Add PNaCl build of VBA-M.
This CL adds a PNaCl target for VBA-M which builds a Chrome App into the src/pnacl/app directory.
This commit is contained in:
parent
8b46072ca3
commit
27243323fd
|
@ -34,6 +34,13 @@ if( NOT ENABLE_DEBUGGER AND ENABLE_SDL )
|
||||||
message( SEND_ERROR "The SDL port can't be built without debugging support" )
|
message( SEND_ERROR "The SDL port can't be built without debugging support" )
|
||||||
endif( NOT ENABLE_DEBUGGER AND ENABLE_SDL )
|
endif( NOT ENABLE_DEBUGGER AND ENABLE_SDL )
|
||||||
|
|
||||||
|
if ( PNACL )
|
||||||
|
set ( ENABLE_SDL ON )
|
||||||
|
set ( ENABLE_GTK OFF )
|
||||||
|
set ( ENABLE_LINK OFF )
|
||||||
|
set ( ENABLE_WX OFF )
|
||||||
|
endif ( PNACL )
|
||||||
|
|
||||||
# Set the version number with -DVERSION=X.X.X-uber
|
# Set the version number with -DVERSION=X.X.X-uber
|
||||||
IF( NOT VERSION )
|
IF( NOT VERSION )
|
||||||
SET( VERSION "https://github.com/EmperorArthur/VBA-M" )
|
SET( VERSION "https://github.com/EmperorArthur/VBA-M" )
|
||||||
|
@ -71,7 +78,7 @@ endif( ENABLE_ASM_SCALERS )
|
||||||
# Look for some dependencies using CMake scripts
|
# Look for some dependencies using CMake scripts
|
||||||
FIND_PACKAGE ( ZLIB REQUIRED )
|
FIND_PACKAGE ( ZLIB REQUIRED )
|
||||||
FIND_PACKAGE ( PNG REQUIRED )
|
FIND_PACKAGE ( PNG REQUIRED )
|
||||||
FIND_PACKAGE ( OpenGL REQUIRED )
|
FIND_PACKAGE ( OpenGL )
|
||||||
FIND_PACKAGE ( SDL REQUIRED )
|
FIND_PACKAGE ( SDL REQUIRED )
|
||||||
|
|
||||||
if( ENABLE_LINK )
|
if( ENABLE_LINK )
|
||||||
|
@ -87,7 +94,10 @@ SET(VBAMCORE_LIBS
|
||||||
${ZLIB_LIBRARY}
|
${ZLIB_LIBRARY}
|
||||||
${PNG_LIBRARY})
|
${PNG_LIBRARY})
|
||||||
|
|
||||||
|
if ( PNACL )
|
||||||
|
# Add core NaCl libraries.
|
||||||
|
SET(VBAMCORE_LIBS ${VBAMCORE_LIBS} ppapi ppapi_cpp nacl_io)
|
||||||
|
endif ( PNACL )
|
||||||
|
|
||||||
# Disable looking for GTK if not going to build the GTK frontend
|
# Disable looking for GTK if not going to build the GTK frontend
|
||||||
# so that pkg-config is not required
|
# so that pkg-config is not required
|
||||||
|
@ -131,8 +141,12 @@ IF( NOT SYSCONFDIR )
|
||||||
SET( SYSCONFDIR "/etc" )
|
SET( SYSCONFDIR "/etc" )
|
||||||
ENDIF( NOT SYSCONFDIR )
|
ENDIF( NOT SYSCONFDIR )
|
||||||
|
|
||||||
|
if ( OpenGL_FOUND )
|
||||||
|
set( USE_OPENGL_FLAG "-DUSE_OPENGL " )
|
||||||
|
endif ( OpenGL_FOUND )
|
||||||
|
|
||||||
# C defines
|
# C defines
|
||||||
ADD_DEFINITIONS (-DHAVE_NETINET_IN_H -DHAVE_ARPA_INET_H -DHAVE_ZLIB_H -DFINAL_VERSION -DSDL -DUSE_OPENGL -DSYSCONFDIR='"${SYSCONFDIR}"' -DWITH_LIRC='${WITHLIRC}')
|
ADD_DEFINITIONS (-DHAVE_NETINET_IN_H -DHAVE_ARPA_INET_H -DHAVE_ZLIB_H -DFINAL_VERSION -DSDL ${USE_OPENGL_FLAG} -DSYSCONFDIR='"${SYSCONFDIR}"' -DWITH_LIRC='${WITHLIRC}')
|
||||||
ADD_DEFINITIONS (-DVERSION='"${VERSION}"' -DPKGDATADIR='"${PKGDATADIR}"' -DPACKAGE='')
|
ADD_DEFINITIONS (-DVERSION='"${VERSION}"' -DPKGDATADIR='"${PKGDATADIR}"' -DPACKAGE='')
|
||||||
|
|
||||||
if( ENABLE_LINK )
|
if( ENABLE_LINK )
|
||||||
|
@ -142,13 +156,13 @@ if( ENABLE_LINK )
|
||||||
SET(CMAKE_REQUIRED_LIBRARIES ${CMAKE_REQUIRED_LIBRARIES} ${RT_LIB})
|
SET(CMAKE_REQUIRED_LIBRARIES ${CMAKE_REQUIRED_LIBRARIES} ${RT_LIB})
|
||||||
SET(VBAMCORE_LIBS ${VBAMCORE_LIBS} ${RT_LIB})
|
SET(VBAMCORE_LIBS ${VBAMCORE_LIBS} ${RT_LIB})
|
||||||
ENDIF(RT_LIB)
|
ENDIF(RT_LIB)
|
||||||
|
|
||||||
FIND_LIBRARY(PTHREAD_LIB pthread)
|
FIND_LIBRARY(PTHREAD_LIB pthread)
|
||||||
IF(PTHREAD_LIB)
|
IF(PTHREAD_LIB)
|
||||||
SET(CMAKE_REQUIRED_LIBRARIES ${CMAKE_REQUIRED_LIBRARIES} ${PTHREAD_LIB})
|
SET(CMAKE_REQUIRED_LIBRARIES ${CMAKE_REQUIRED_LIBRARIES} ${PTHREAD_LIB})
|
||||||
SET(VBAMCORE_LIBS ${VBAMCORE_LIBS} ${PTHREAD_LIB})
|
SET(VBAMCORE_LIBS ${VBAMCORE_LIBS} ${PTHREAD_LIB})
|
||||||
ENDIF(PTHREAD_LIB)
|
ENDIF(PTHREAD_LIB)
|
||||||
|
|
||||||
INCLUDE(CheckFunctionExists)
|
INCLUDE(CheckFunctionExists)
|
||||||
CHECK_FUNCTION_EXISTS(sem_timedwait SEM_TIMEDWAIT)
|
CHECK_FUNCTION_EXISTS(sem_timedwait SEM_TIMEDWAIT)
|
||||||
IF( SEM_TIMEDWAIT)
|
IF( SEM_TIMEDWAIT)
|
||||||
|
@ -304,6 +318,10 @@ SET(SRC_SDL
|
||||||
src/sdl/expr-lex.cpp
|
src/sdl/expr-lex.cpp
|
||||||
)
|
)
|
||||||
|
|
||||||
|
SET(SRC_PNACL
|
||||||
|
src/pnacl/nacl_glue.cpp
|
||||||
|
)
|
||||||
|
|
||||||
SET(SRC_FILTERS
|
SET(SRC_FILTERS
|
||||||
src/filters/2xSaI.cpp
|
src/filters/2xSaI.cpp
|
||||||
src/filters/admame.cpp
|
src/filters/admame.cpp
|
||||||
|
@ -376,8 +394,8 @@ IF( ENABLE_SDL )
|
||||||
vbam
|
vbam
|
||||||
WIN32
|
WIN32
|
||||||
${SRC_SDL}
|
${SRC_SDL}
|
||||||
|
${SRC_PNACL}
|
||||||
)
|
)
|
||||||
|
|
||||||
IF( WIN32 )
|
IF( WIN32 )
|
||||||
SET( WIN32_LIBRARIES wsock32 )
|
SET( WIN32_LIBRARIES wsock32 )
|
||||||
ENDIF( WIN32 )
|
ENDIF( WIN32 )
|
||||||
|
@ -392,11 +410,14 @@ IF( ENABLE_SDL )
|
||||||
${WIN32_LIBRARIES}
|
${WIN32_LIBRARIES}
|
||||||
${LIRC_CLIENT_LIBRARY}
|
${LIRC_CLIENT_LIBRARY}
|
||||||
)
|
)
|
||||||
|
IF ( PNACL )
|
||||||
INSTALL(PROGRAMS ${CMAKE_CURRENT_BINARY_DIR}/vbam DESTINATION bin)
|
build_to_app( vbam )
|
||||||
INSTALL(FILES ${CMAKE_CURRENT_SOURCE_DIR}/src/sdl/vbam.cfg-example
|
ELSE ( PNACL )
|
||||||
DESTINATION ${SYSCONFDIR}
|
INSTALL(PROGRAMS ${CMAKE_CURRENT_BINARY_DIR}/vbam DESTINATION bin)
|
||||||
RENAME vbam.cfg)
|
INSTALL(FILES ${CMAKE_CURRENT_SOURCE_DIR}/src/sdl/vbam.cfg-example
|
||||||
|
DESTINATION ${SYSCONFDIR}
|
||||||
|
RENAME vbam.cfg)
|
||||||
|
ENDIF ( PNACL )
|
||||||
ENDIF( ENABLE_SDL )
|
ENDIF( ENABLE_SDL )
|
||||||
|
|
||||||
IF( ENABLE_GTK )
|
IF( ENABLE_GTK )
|
||||||
|
|
|
@ -0,0 +1,56 @@
|
||||||
|
# How to build for PNaCl on Linux.
|
||||||
|
#
|
||||||
|
# Download the Native Client SDK.
|
||||||
|
# Run naclsdk update pepper_XX. The pepper version must be pepper_37.
|
||||||
|
# Set NACL_SDK_ROOT in your environment to nacl_sdk/pepper_XX.
|
||||||
|
#
|
||||||
|
# Check out the naclports repository. This was built with
|
||||||
|
# naclports@b0aaa9899316e157883ee4b54f70affbebd2c3e1.
|
||||||
|
# Set NACL_ARCH to 'pnacl' in your environment and run 'make sdl'
|
||||||
|
# from the naclports root.
|
||||||
|
#
|
||||||
|
# Come back to the root of vba-m and run
|
||||||
|
# cmake -DCMAKE_TOOLCHAIN_FILE=CMakeScripts/PNaCl.Toolchain.cmake CMakeLists.txt
|
||||||
|
# make
|
||||||
|
#
|
||||||
|
# This will build a non-finalized PNaCl port to ./vbam and a finalized version
|
||||||
|
# to src/pnacl/app/vbam.pexe.
|
||||||
|
#
|
||||||
|
# The src/pnacl/app folder can be loaded as an unpacked extension into Chrome
|
||||||
|
# which will run vba-m as a packaged app.
|
||||||
|
|
||||||
|
include( CMakeForceCompiler )
|
||||||
|
|
||||||
|
set( PNACL ON )
|
||||||
|
set( PLATFORM_PREFIX "$ENV{NACL_SDK_ROOT}/toolchain/linux_pnacl" )
|
||||||
|
set( FINALIZED_TARGET "src/pnacl/app/vbam.pexe" )
|
||||||
|
|
||||||
|
set( CMAKE_SYSTEM_NAME "Linux" CACHE STRING "Target system." )
|
||||||
|
set( CMAKE_SYSTEM_PROCESSOR "LLVM-IR" CACHE STRING "Target processor." )
|
||||||
|
set( CMAKE_FIND_ROOT_PATH "${PLATFORM_PREFIX}/usr" )
|
||||||
|
set( CMAKE_AR "${PLATFORM_PREFIX}/bin64/pnacl-ar" CACHE STRING "")
|
||||||
|
set( CMAKE_RANLIB "${PLATFORM_PREFIX}/bin64/pnacl-ranlib" CACHE STRING "")
|
||||||
|
set( CMAKE_C_COMPILER "${PLATFORM_PREFIX}/bin64/pnacl-clang" )
|
||||||
|
set( CMAKE_CXX_COMPILER "${PLATFORM_PREFIX}/bin64/pnacl-clang++" )
|
||||||
|
set( CMAKE_C_FLAGS "-Wno-non-literal-null-conversion -Wno-deprecated-writable-strings -U__STRICT_ANSI__" CACHE STRING "" )
|
||||||
|
set( CMAKE_CXX_FLAGS "-Wno-non-literal-null-conversion -Wno-deprecated-writable-strings -U__STRICT_ANSI__" CACHE STRING "" )
|
||||||
|
|
||||||
|
cmake_force_c_compiler( ${CMAKE_C_COMPILER} Clang )
|
||||||
|
cmake_force_cxx_compiler( ${CMAKE_CXX_COMPILER} Clang )
|
||||||
|
|
||||||
|
set( CMAKE_FIND_ROOT_PATH_MODE_PROGRAM NEVER )
|
||||||
|
set( CMAKE_FIND_ROOT_PATH_MODE_LIBRARY ONLY )
|
||||||
|
set( CMAKE_FIND_ROOT_PATH_MODE_INCLUDE ONLY )
|
||||||
|
set( CMAKE_FIND_ROOT_PATH_MODE_PACKAGE ONLY )
|
||||||
|
|
||||||
|
macro( build_to_app _target )
|
||||||
|
add_custom_command( TARGET ${_target}
|
||||||
|
POST_BUILD
|
||||||
|
COMMAND "${PLATFORM_PREFIX}/bin64/pnacl-finalize"
|
||||||
|
"-o" "${FINALIZED_TARGET}"
|
||||||
|
"$<TARGET_FILE:${_target}>" )
|
||||||
|
endmacro()
|
||||||
|
|
||||||
|
set( ENV{SDLDIR} "${PLATFORM_PREFIX}/usr" )
|
||||||
|
include_directories( SYSTEM $ENV{NACL_SDK_ROOT}/include )
|
||||||
|
link_directories( $ENV{NACL_SDK_ROOT}/lib/pnacl/Release )
|
|
@ -7,13 +7,13 @@
|
||||||
|
|
||||||
|
|
||||||
#ifdef __GNUC__
|
#ifdef __GNUC__
|
||||||
#if defined(__APPLE__) || defined (BSD) || defined (__NetBSD__)
|
#if defined(__APPLE__) || defined (BSD) || defined (__NetBSD__) || defined (__native_client__)
|
||||||
typedef off_t __off64_t; /* off_t is 64 bits on BSD. */
|
typedef off_t __off64_t; /* off_t is 64 bits on BSD. */
|
||||||
#define fseeko64 fseeko
|
#define fseeko64 fseeko
|
||||||
#define ftello64 ftello
|
#define ftello64 ftello
|
||||||
#else
|
#else
|
||||||
typedef off64_t __off64_t;
|
typedef off64_t __off64_t;
|
||||||
#endif /* __APPLE__ || BSD */
|
#endif /* __APPLE__ || BSD || __native_client__ */
|
||||||
#endif /* __GNUC__ */
|
#endif /* __GNUC__ */
|
||||||
|
|
||||||
#ifndef _MSC_VER
|
#ifndef _MSC_VER
|
||||||
|
|
|
@ -5,7 +5,7 @@ extern int armExecute();
|
||||||
extern int thumbExecute();
|
extern int thumbExecute();
|
||||||
|
|
||||||
#ifdef __GNUC__
|
#ifdef __GNUC__
|
||||||
#ifndef __APPLE__
|
#if !defined(__APPLE__) && !defined(__native_client__)
|
||||||
# define INSN_REGPARM __attribute__((regparm(1)))
|
# define INSN_REGPARM __attribute__((regparm(1)))
|
||||||
#else
|
#else
|
||||||
# define INSN_REGPARM /*nothing*/
|
# define INSN_REGPARM /*nothing*/
|
||||||
|
|
|
@ -0,0 +1,11 @@
|
||||||
|
chrome.app.runtime.onLaunched.addListener(function() {
|
||||||
|
chrome.app.window.create('game.html', {
|
||||||
|
bounds: {
|
||||||
|
width: 480,
|
||||||
|
height: 320
|
||||||
|
},
|
||||||
|
resizable: true,
|
||||||
|
minWidth: 480,
|
||||||
|
minHeight: 320
|
||||||
|
});
|
||||||
|
});
|
|
@ -0,0 +1,63 @@
|
||||||
|
<!DOCTYPE html>
|
||||||
|
<html>
|
||||||
|
<head>
|
||||||
|
<link rel="stylesheet" href="style.css">
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
<div id="listener">
|
||||||
|
<embed name="nacl_module"
|
||||||
|
id="naclModule"
|
||||||
|
width=480 height=320
|
||||||
|
src="game.nmf"
|
||||||
|
type="application/x-pnacl" />
|
||||||
|
</div>
|
||||||
|
<div id="loadingMessage" class="centered">
|
||||||
|
<div>Translating PNaCl to Native Architecture</div>
|
||||||
|
<div id="loadingBar">
|
||||||
|
<div id="progress"></div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div id="openMessage" class="centered helptext">
|
||||||
|
<div>Press Ctrl+O to open a rom</div>
|
||||||
|
<div id="filenameErrorMessage" class="errorMessage">
|
||||||
|
The filename cannot have spaces. Please rename the file and try again.
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div id="topLeftHelptext" class="helptext">
|
||||||
|
</div>
|
||||||
|
<div id="topRightHelptext" class="helptext">
|
||||||
|
<div><a href='#' id="advancedButton">Advanced</a></div>
|
||||||
|
<div class="advancedSetting">
|
||||||
|
<div><a href="#" id="importSaveButton">Import save</a></div>
|
||||||
|
<div>
|
||||||
|
<label>
|
||||||
|
<input type="checkbox" id="gamepadCheckbox">
|
||||||
|
Use gamepad
|
||||||
|
</label>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div id="leftHelptext" class="helptext">
|
||||||
|
<div>A: Z</div>
|
||||||
|
<div>B: X</div>
|
||||||
|
<div>L: A</div>
|
||||||
|
<div>R: S</div>
|
||||||
|
<div>D-pad: Arrow keys</div>
|
||||||
|
</div>
|
||||||
|
<div id="rightHelptext" class="helptext">
|
||||||
|
<div>Start: Enter</div>
|
||||||
|
<div>Select: Backspace</div>
|
||||||
|
<div id="normalSaveStateKeys">
|
||||||
|
<div>Save state: Shift + F1-9</div>
|
||||||
|
<div>Load state: F1-9</div>
|
||||||
|
</div>
|
||||||
|
<div id="crosSaveStateKeys">
|
||||||
|
<div>Save state: Shift + Search(🔍) + 1-9</div>
|
||||||
|
<div>Load state: Search(🔍) + 1-9</div>
|
||||||
|
</div>
|
||||||
|
<div>Vol down/up: -/=</div>
|
||||||
|
</div>
|
||||||
|
<script src="index.js"></script>
|
||||||
|
</body>
|
||||||
|
</html>
|
||||||
|
|
|
@ -0,0 +1,10 @@
|
||||||
|
{
|
||||||
|
"program": {
|
||||||
|
"portable" : {
|
||||||
|
"pnacl-translate" : {
|
||||||
|
"url" : "vbam.pexe",
|
||||||
|
"optlevel": 2
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
Binary file not shown.
After Width: | Height: | Size: 21 KiB |
|
@ -0,0 +1,237 @@
|
||||||
|
var plugin = document.getElementById('naclModule');
|
||||||
|
var firstLoad = false;
|
||||||
|
var naclVisible = false;
|
||||||
|
var localfs = null;
|
||||||
|
var syncfs = null;
|
||||||
|
var saveDirEntry = null;
|
||||||
|
var gamepadCheckbox = document.getElementById('gamepadCheckbox');
|
||||||
|
|
||||||
|
var postFileCallback = function() {};
|
||||||
|
|
||||||
|
function setFilenameErrorVisible(visible) {
|
||||||
|
document.getElementById('filenameErrorMessage').style.display =
|
||||||
|
visible ? 'block' : 'none';
|
||||||
|
}
|
||||||
|
|
||||||
|
function setHelptextsVisible(visible) {
|
||||||
|
var helptexts = document.getElementsByClassName('helptext');
|
||||||
|
for (var i = 0; i < helptexts.length; i++) {
|
||||||
|
helptexts[i].style.display = visible ? 'block' : 'none';
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function setNaclVisible(visible) {
|
||||||
|
naclVisible = visible;
|
||||||
|
document.getElementsByTagName('body')[0].className =
|
||||||
|
visible ? 'lightsOff' : 'lightsOn';
|
||||||
|
setHelptextsVisible(!visible);
|
||||||
|
scaleNacl();
|
||||||
|
}
|
||||||
|
|
||||||
|
function scaleNacl() {
|
||||||
|
var bounds = chrome.app.window.current().getBounds();
|
||||||
|
var scaleX = bounds.width / plugin.width;
|
||||||
|
var scaleY = bounds.height / plugin.height;
|
||||||
|
var scale = naclVisible ? Math.min(scaleX, scaleY) : 0;
|
||||||
|
plugin.style.webkitTransform = 'scale(' + scale + ')';
|
||||||
|
}
|
||||||
|
|
||||||
|
function makeNewPlugin() {
|
||||||
|
var newNode = plugin.cloneNode(true);
|
||||||
|
plugin.parentNode.appendChild(newNode);
|
||||||
|
plugin.parentNode.removeChild(plugin);
|
||||||
|
plugin = document.getElementById('naclModule');
|
||||||
|
setNaclVisible(false);
|
||||||
|
}
|
||||||
|
|
||||||
|
function showOpenFileDialog() {
|
||||||
|
setFilenameErrorVisible(false);
|
||||||
|
chrome.fileSystem.chooseEntry({
|
||||||
|
'type': 'openFile',
|
||||||
|
'accepts': [{'description': 'GBA Roms', 'extensions': ['zip', 'gba']}]
|
||||||
|
},
|
||||||
|
function(entry) {
|
||||||
|
if (!entry)
|
||||||
|
return;
|
||||||
|
|
||||||
|
if (entry.fullPath.indexOf(' ') != -1) {
|
||||||
|
setFilenameErrorVisible(true);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
postFileCallback = function() {
|
||||||
|
setNaclVisible(true);
|
||||||
|
plugin.postMessage({
|
||||||
|
'path': entry.fullPath,
|
||||||
|
'filesystem': entry.filesystem,
|
||||||
|
'gamepad' : gamepadCheckbox.checked
|
||||||
|
});
|
||||||
|
postFileCallback = function() {};
|
||||||
|
};
|
||||||
|
makeNewPlugin();
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
function copyToSyncFileSystem() {
|
||||||
|
if (!syncfs || !localfs) {
|
||||||
|
setTimeout(copyToSyncFileSystem, 1000);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
reader = saveDirEntry.createReader();
|
||||||
|
var copyIfNewer = function(entries) {
|
||||||
|
if (entries.length == 0)
|
||||||
|
return;
|
||||||
|
|
||||||
|
for (i in entries) {
|
||||||
|
var entry = entries[i];
|
||||||
|
if (!entry.isFile)
|
||||||
|
return;
|
||||||
|
(function() {
|
||||||
|
var e = entry;
|
||||||
|
var doCopy = function() {
|
||||||
|
console.log('Upsyncing ' + e.name);
|
||||||
|
e.copyTo(syncfs.root);
|
||||||
|
};
|
||||||
|
e.getMetadata(function(localMeta) {
|
||||||
|
syncfs.root.getFile(e.name, {}, function(syncEntry) {
|
||||||
|
syncEntry.getMetadata(function(syncMeta) {
|
||||||
|
// syncEntry.remove(function() {
|
||||||
|
if (syncMeta.modificationTime < localMeta.modificationTime)
|
||||||
|
doCopy();
|
||||||
|
// });
|
||||||
|
}, doCopy);
|
||||||
|
}, doCopy);
|
||||||
|
});
|
||||||
|
})();
|
||||||
|
}
|
||||||
|
reader.readEntries(copyIfNewer);
|
||||||
|
};
|
||||||
|
reader.readEntries(copyIfNewer);
|
||||||
|
|
||||||
|
setTimeout(copyToSyncFileSystem, 30000);
|
||||||
|
}
|
||||||
|
|
||||||
|
function initSyncFileSystem() {
|
||||||
|
syncfs = null;
|
||||||
|
chrome.syncFileSystem.getServiceStatus(function(status) {
|
||||||
|
if (status == 'running') {
|
||||||
|
chrome.syncFileSystem.requestFileSystem(function(fs) {
|
||||||
|
syncfs = fs;
|
||||||
|
});
|
||||||
|
} else {
|
||||||
|
setTimeout(initSyncFileSystem, 5000);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
window.webkitRequestFileSystem(window.PERSISTENT, 0, function(fs) {
|
||||||
|
localfs = fs;
|
||||||
|
fs.root.getDirectory(
|
||||||
|
'states', { create: true }, function(d) { saveDirEntry = d; });
|
||||||
|
});
|
||||||
|
|
||||||
|
initSyncFileSystem();
|
||||||
|
copyToSyncFileSystem();
|
||||||
|
chrome.syncFileSystem.onServiceStatusChanged.addListener(initSyncFileSystem);
|
||||||
|
chrome.syncFileSystem.onFileStatusChanged.addListener(function(detail) {
|
||||||
|
/*
|
||||||
|
if (saveDirEntry && detail.status == 'synced' &&
|
||||||
|
detail.direction == 'remote_to_local') {
|
||||||
|
if (detail.action == 'deleted') {
|
||||||
|
saveDirEntry.getFile(detail.fileEntry.name, {}, function(entry) {
|
||||||
|
console.log('Deleting' + detail.fileEntry.name);
|
||||||
|
entry.remove(function() {});
|
||||||
|
});
|
||||||
|
detail.fileEntry.remove(function() {});
|
||||||
|
} else {
|
||||||
|
detail.fileEntry.copyTo(saveDirEntry);
|
||||||
|
console.log('Downsyncing ' + detail.fileEntry.name);
|
||||||
|
}
|
||||||
|
}*/
|
||||||
|
});
|
||||||
|
|
||||||
|
var is_cros = window.navigator.userAgent.toLowerCase().indexOf('cros') != -1;
|
||||||
|
document.getElementById('normalSaveStateKeys').style.display = is_cros ? 'none' : 'block';
|
||||||
|
document.getElementById('crosSaveStateKeys').style.display = is_cros ? 'block' : 'none';
|
||||||
|
|
||||||
|
document.getElementById('importSaveButton').onclick = function() {
|
||||||
|
chrome.fileSystem.chooseEntry({
|
||||||
|
'type': 'openFile',
|
||||||
|
'accepts': [{'description': 'VBA-M Save Files', 'extensions': ['sav', 'sgm']}]
|
||||||
|
},
|
||||||
|
function(entry) {
|
||||||
|
if (!entry)
|
||||||
|
return;
|
||||||
|
|
||||||
|
if (entry.fullPath.indexOf(' ') != -1) {
|
||||||
|
setFilenameErrorVisible(true);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
entry.copyTo(saveDirEntry);
|
||||||
|
console.log('Copied ' + entry.name + ' to HTML5fs');
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
// Gamepad checkbox.
|
||||||
|
gamepadCheckbox.onclick = function() {
|
||||||
|
chrome.storage.local.set({'gamepad': gamepadCheckbox.checked});
|
||||||
|
}
|
||||||
|
chrome.storage.local.get('gamepad', function(items) {
|
||||||
|
gamepadCheckbox.checked = items['gamepad'];
|
||||||
|
});
|
||||||
|
|
||||||
|
// Advanced settings
|
||||||
|
document.getElementById('advancedButton').onclick = function() {
|
||||||
|
document.getElementById('advancedButton').style.display = 'none';
|
||||||
|
var advancedSettings = document.getElementsByClassName('advancedSetting');
|
||||||
|
for (var i = 0; i < advancedSettings.length; i++)
|
||||||
|
advancedSettings[i].style.display = 'block';
|
||||||
|
};
|
||||||
|
|
||||||
|
// Add window scaling.
|
||||||
|
chrome.app.window.current().onBoundsChanged.addListener(scaleNacl);
|
||||||
|
|
||||||
|
// NaCl plugin listener
|
||||||
|
var listener = document.getElementById('listener');
|
||||||
|
listener.addEventListener(
|
||||||
|
'message',
|
||||||
|
function(e) {
|
||||||
|
console.log(e);
|
||||||
|
}, true);
|
||||||
|
|
||||||
|
listener.addEventListener(
|
||||||
|
'crash',
|
||||||
|
function(e) {
|
||||||
|
makeNewPlugin();
|
||||||
|
}, true);
|
||||||
|
|
||||||
|
listener.addEventListener(
|
||||||
|
'load',
|
||||||
|
function(e) {
|
||||||
|
setHelptextsVisible(true);
|
||||||
|
document.getElementById('loadingMessage').style.display = 'none';
|
||||||
|
postFileCallback();
|
||||||
|
firstLoad = true;
|
||||||
|
scaleNacl();
|
||||||
|
}, true);
|
||||||
|
|
||||||
|
listener.addEventListener(
|
||||||
|
'progress',
|
||||||
|
function(e) {
|
||||||
|
var percent = e.loaded / e.total;
|
||||||
|
document.getElementById('progress').style.width = (percent * 100) + '%';
|
||||||
|
}, true);
|
||||||
|
|
||||||
|
document.addEventListener('keydown', function(e) {
|
||||||
|
// Ctrl + o
|
||||||
|
if (firstLoad && e.ctrlKey && e.keyCode == 79) {
|
||||||
|
showOpenFileDialog();
|
||||||
|
}
|
||||||
|
// ESC
|
||||||
|
if (e.keyCode == 27) {
|
||||||
|
// makeNewPlugin();
|
||||||
|
e.preventDefault();
|
||||||
|
}
|
||||||
|
}, true);
|
|
@ -0,0 +1,22 @@
|
||||||
|
{
|
||||||
|
"name": "VBA-M",
|
||||||
|
"description": "A native GBA emulator for Chrome",
|
||||||
|
"version": "1.3.6",
|
||||||
|
"manifest_version": 2,
|
||||||
|
"minimum_chrome_version": "34",
|
||||||
|
"offline_enabled": true,
|
||||||
|
"icons": {
|
||||||
|
"128": "icon.png"
|
||||||
|
},
|
||||||
|
"app": {
|
||||||
|
"background": {
|
||||||
|
"scripts": ["background.js"]
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"permissions": [
|
||||||
|
"syncFileSystem",
|
||||||
|
"fileSystem",
|
||||||
|
"storage",
|
||||||
|
"unlimitedStorage"
|
||||||
|
]
|
||||||
|
}
|
|
@ -0,0 +1,89 @@
|
||||||
|
/* Structure */
|
||||||
|
|
||||||
|
html {
|
||||||
|
height: 100%;
|
||||||
|
}
|
||||||
|
|
||||||
|
body {
|
||||||
|
align-items: center;
|
||||||
|
display: flex;
|
||||||
|
height: 100%;
|
||||||
|
justify-content: center;
|
||||||
|
margin: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.lightsOn {
|
||||||
|
background-color: rgb(251, 251, 251);
|
||||||
|
}
|
||||||
|
|
||||||
|
.lightsOff {
|
||||||
|
background-color: black;
|
||||||
|
}
|
||||||
|
|
||||||
|
.centered {
|
||||||
|
left: 0;
|
||||||
|
position: absolute;
|
||||||
|
text-align: center;
|
||||||
|
top: 40%;
|
||||||
|
width: 100%;
|
||||||
|
z-index: -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
.helptext {
|
||||||
|
display: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
.errorMessage {
|
||||||
|
display: none;
|
||||||
|
color: red;
|
||||||
|
}
|
||||||
|
|
||||||
|
#loadingBar {
|
||||||
|
background-color: black;
|
||||||
|
border-radius: 13px;
|
||||||
|
margin: 0 auto;
|
||||||
|
padding: 3px;
|
||||||
|
width: 200px;
|
||||||
|
}
|
||||||
|
|
||||||
|
#loadingBar > div {
|
||||||
|
background-color: blue;
|
||||||
|
border-radius: 10px;
|
||||||
|
height: 10px;
|
||||||
|
width: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
#naclModule {
|
||||||
|
-webkit-transform-origin: 50% 50%;
|
||||||
|
}
|
||||||
|
|
||||||
|
#leftHelptext {
|
||||||
|
bottom: 5px;
|
||||||
|
left: 5px;
|
||||||
|
position: fixed;
|
||||||
|
}
|
||||||
|
|
||||||
|
#rightHelptext {
|
||||||
|
bottom: 5px;
|
||||||
|
position: fixed;
|
||||||
|
right: 5px;
|
||||||
|
text-align: right;
|
||||||
|
}
|
||||||
|
|
||||||
|
#topLeftHelptext {
|
||||||
|
left: 5px;
|
||||||
|
position: fixed;
|
||||||
|
text-align: left;
|
||||||
|
top: 5px;
|
||||||
|
}
|
||||||
|
|
||||||
|
#topRightHelptext {
|
||||||
|
top: 5px;
|
||||||
|
position: fixed;
|
||||||
|
right: 5px;
|
||||||
|
text-align: right;
|
||||||
|
}
|
||||||
|
|
||||||
|
.advancedSetting {
|
||||||
|
display: none;
|
||||||
|
}
|
|
@ -0,0 +1,5 @@
|
||||||
|
captureDir=/store/states
|
||||||
|
saveDir=/store/states
|
||||||
|
batteryDir=/store/states
|
||||||
|
showSpeed=2
|
||||||
|
rtcEnabled=1
|
|
@ -0,0 +1,300 @@
|
||||||
|
#include <unistd.h>
|
||||||
|
|
||||||
|
#include <SDL/SDL.h>
|
||||||
|
#include <SDL/SDL_events.h>
|
||||||
|
#include <SDL/SDL_nacl.h>
|
||||||
|
#include <nacl_io/nacl_io.h>
|
||||||
|
#include <ppapi/c/pp_errors.h>
|
||||||
|
#include <ppapi/c/pp_instance.h>
|
||||||
|
#include <ppapi/c/ppb_gamepad.h>
|
||||||
|
#include <ppapi/c/ppb_instance.h>
|
||||||
|
#include <ppapi/cpp/completion_callback.h>
|
||||||
|
#include <ppapi/cpp/file_system.h>
|
||||||
|
#include <ppapi/cpp/input_event.h>
|
||||||
|
#include <ppapi/cpp/instance.h>
|
||||||
|
#include <ppapi/cpp/module.h>
|
||||||
|
#include <ppapi/cpp/var.h>
|
||||||
|
#include <ppapi/cpp/var_dictionary.h>
|
||||||
|
#include <ppapi/utility/completion_callback_factory.h>
|
||||||
|
#include <sys/mount.h>
|
||||||
|
#include <sys/stat.h>
|
||||||
|
|
||||||
|
#define NUM_BUTTONS 17
|
||||||
|
#define AXIS_MAX 32767
|
||||||
|
|
||||||
|
extern int SDL_main(int argc, char **argv);
|
||||||
|
|
||||||
|
class GameInstance : public pp::Instance {
|
||||||
|
public:
|
||||||
|
explicit GameInstance(PP_Instance instance)
|
||||||
|
: pp::Instance(instance),
|
||||||
|
game_main_thread_(NULL),
|
||||||
|
num_changed_view_(0),
|
||||||
|
width_(0),
|
||||||
|
height_(0),
|
||||||
|
gamepad_enabled_(false),
|
||||||
|
cc_factory_(this) {
|
||||||
|
// Game requires mouse and keyboard events; add more if necessary.
|
||||||
|
nacl_io_init_ppapi(instance, pp::Module::Get()->get_browser_interface());
|
||||||
|
RequestInputEvents(PP_INPUTEVENT_CLASS_MOUSE |
|
||||||
|
PP_INPUTEVENT_CLASS_KEYBOARD);
|
||||||
|
++num_instances_;
|
||||||
|
assert(num_instances_ == 1);
|
||||||
|
|
||||||
|
gamepad_ = static_cast<const PPB_Gamepad*>(
|
||||||
|
pp::Module::Get()->GetBrowserInterface(PPB_GAMEPAD_INTERFACE));
|
||||||
|
assert(gamepad_);
|
||||||
|
}
|
||||||
|
|
||||||
|
virtual ~GameInstance() {
|
||||||
|
// Wait for game thread to finish.
|
||||||
|
if (game_main_thread_) {
|
||||||
|
pthread_join(game_main_thread_, NULL);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// This function is called with the HTML attributes of the embed tag,
|
||||||
|
// which can be used in lieu of command line arguments.
|
||||||
|
virtual bool Init(uint32_t argc, const char* argn[], const char* argv[]) {
|
||||||
|
for (uint32_t i = 0; i < argc; ++i) {
|
||||||
|
if (argn[i] == std::string("width")) {
|
||||||
|
width_ = strtol(argv[i], 0, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (argn[i] == std::string("height")) {
|
||||||
|
height_ = strtol(argv[i], 0, 0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
// This crucial function forwards PPAPI events to SDL.
|
||||||
|
virtual bool HandleInputEvent(const pp::InputEvent& event) {
|
||||||
|
SDL_NACL_PushEvent(event.pp_resource());
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
virtual void HandleMessage(const pp::Var& message) {
|
||||||
|
pp::VarDictionary args(message);
|
||||||
|
pp::Var filesystem_var = args.Get("filesystem");
|
||||||
|
if (!filesystem_var.is_resource())
|
||||||
|
return;
|
||||||
|
|
||||||
|
pp::Resource filesystem_resource = filesystem_var.AsResource();
|
||||||
|
if (!pp::FileSystem::IsFileSystem(filesystem_resource))
|
||||||
|
return;
|
||||||
|
|
||||||
|
PP_Resource filesystem_id = filesystem_resource.pp_resource();
|
||||||
|
if (!filesystem_id)
|
||||||
|
return;
|
||||||
|
|
||||||
|
char buf[BUFSIZ];
|
||||||
|
if (snprintf(buf, BUFSIZ, "type=PERSISTENT,filesystem_resource=%d", filesystem_id) > BUFSIZ)
|
||||||
|
return;
|
||||||
|
|
||||||
|
rom_mount_string_ = buf;
|
||||||
|
|
||||||
|
pp::Var path_var = args.Get("path");
|
||||||
|
if (!path_var.is_string())
|
||||||
|
return;
|
||||||
|
|
||||||
|
rom_path_string_ = path_var.AsString();
|
||||||
|
|
||||||
|
pp::Var gamepad_var = args.Get("gamepad");
|
||||||
|
if (!gamepad_var.is_bool())
|
||||||
|
return;
|
||||||
|
|
||||||
|
gamepad_enabled_ = gamepad_var.AsBool();
|
||||||
|
}
|
||||||
|
|
||||||
|
// This function is called for various reasons, e.g. visibility and page
|
||||||
|
// size changes. We ignore these calls except for the first
|
||||||
|
// invocation, which we use to start the game.
|
||||||
|
virtual void DidChangeView(const pp::Rect& position, const pp::Rect& clip) {
|
||||||
|
++num_changed_view_;
|
||||||
|
if (num_changed_view_ > 1) return;
|
||||||
|
// NOTE: It is crucial that the two calls below are run here
|
||||||
|
// and not in a thread.
|
||||||
|
SDL_NACL_SetInstance(pp_instance(),
|
||||||
|
pp::Module::Get()->get_browser_interface(),
|
||||||
|
width_,
|
||||||
|
height_);
|
||||||
|
// This is SDL_Init call which used to be in game_main()
|
||||||
|
int flags = SDL_INIT_VIDEO | SDL_INIT_AUDIO | SDL_INIT_TIMER |
|
||||||
|
SDL_INIT_NOPARACHUTE | SDL_INIT_JOYSTICK;
|
||||||
|
if(SDL_Init(flags))
|
||||||
|
exit(-1);
|
||||||
|
|
||||||
|
StartGameInNewThread(0);
|
||||||
|
}
|
||||||
|
private:
|
||||||
|
static int num_instances_; // Ensure we only create one instance.
|
||||||
|
static bool old_pressed_[NUM_BUTTONS];
|
||||||
|
|
||||||
|
pthread_t game_main_thread_; // This thread will run game_main().
|
||||||
|
int num_changed_view_; // Ensure we initialize an instance only once.
|
||||||
|
// Dimension of the SDL video screen.
|
||||||
|
int width_;
|
||||||
|
int height_;
|
||||||
|
pp::CompletionCallbackFactory<GameInstance> cc_factory_;
|
||||||
|
bool gamepad_enabled_;
|
||||||
|
const PPB_Gamepad* gamepad_;
|
||||||
|
|
||||||
|
std::string rom_mount_string_;
|
||||||
|
std::string rom_path_string_;
|
||||||
|
|
||||||
|
static SDL_Event *copyEvent(SDL_Event& event) {
|
||||||
|
SDL_Event *event_copy = (SDL_Event*)malloc(sizeof(SDL_Event));
|
||||||
|
*event_copy = event;
|
||||||
|
return event_copy;
|
||||||
|
}
|
||||||
|
|
||||||
|
int GetSDLButton(int i) {
|
||||||
|
switch (i) {
|
||||||
|
case 2:
|
||||||
|
return 1;
|
||||||
|
case 3:
|
||||||
|
return 0;
|
||||||
|
case 4:
|
||||||
|
return 6;
|
||||||
|
case 5:
|
||||||
|
return 7;
|
||||||
|
}
|
||||||
|
return i;
|
||||||
|
}
|
||||||
|
|
||||||
|
void GamepadInputLoop(int32_t dummy) {
|
||||||
|
PP_GamepadsSampleData gamepad_data;
|
||||||
|
gamepad_->Sample(pp_instance(), &gamepad_data);
|
||||||
|
if (gamepad_data.length) {
|
||||||
|
PP_GamepadSampleData& pad = gamepad_data.items[0];
|
||||||
|
if (pad.connected) {
|
||||||
|
// Draw axes.
|
||||||
|
SDL_Event e;
|
||||||
|
bool pressed[NUM_BUTTONS] = {0};
|
||||||
|
for (int i = 0; i < pad.buttons_length; i++)
|
||||||
|
pressed[i] = pad.buttons[i] > 0.3 || pressed[i];
|
||||||
|
|
||||||
|
if (old_pressed_[16] != pressed[16]) {
|
||||||
|
}
|
||||||
|
for (int i = 0; i < NUM_BUTTONS; i++) {
|
||||||
|
if (pressed[i] != old_pressed_[i]) {
|
||||||
|
e.type = SDL_JOYBUTTONDOWN;
|
||||||
|
e.jbutton.which = 0;
|
||||||
|
e.jbutton.button = GetSDLButton(i);
|
||||||
|
e.jbutton.state = pressed[i] ? SDL_PRESSED : SDL_RELEASED;
|
||||||
|
SDL_PushEvent(copyEvent(e));
|
||||||
|
old_pressed_[i] = pressed[i];
|
||||||
|
// Send keyboard SPACE instead of button 16.
|
||||||
|
if (i == 16) {
|
||||||
|
e.type = pressed[i] ? SDL_KEYDOWN : SDL_KEYUP;
|
||||||
|
e.key.type = pressed[i] ? SDL_KEYDOWN : SDL_KEYUP;
|
||||||
|
e.key.which = 1;
|
||||||
|
e.key.state = pressed[i] ? SDL_PRESSED : SDL_RELEASED;
|
||||||
|
e.key.keysym.scancode = SDLK_SPACE;
|
||||||
|
e.key.keysym.sym = SDLK_SPACE;
|
||||||
|
SDL_PushEvent(copyEvent(e));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
e.type = SDL_JOYAXISMOTION;
|
||||||
|
e.jaxis.which = 0;
|
||||||
|
for (int i = 0; i < pad.axes_length; i++) {
|
||||||
|
e.jaxis.type = SDL_JOYAXISMOTION;
|
||||||
|
e.jaxis.axis = i;
|
||||||
|
e.jaxis.value = pad.axes[i] * AXIS_MAX;
|
||||||
|
SDL_PushEvent(copyEvent(e));
|
||||||
|
}
|
||||||
|
if (pressed[12]) {
|
||||||
|
e.jaxis.axis = 1;
|
||||||
|
e.jaxis.value = -AXIS_MAX;
|
||||||
|
SDL_PushEvent(copyEvent(e));
|
||||||
|
}
|
||||||
|
if (pressed[14]) {
|
||||||
|
e.jaxis.axis = 0;
|
||||||
|
e.jaxis.value = -AXIS_MAX;
|
||||||
|
SDL_PushEvent(copyEvent(e));
|
||||||
|
}
|
||||||
|
if (pressed[13]) {
|
||||||
|
e.jaxis.axis = 1;
|
||||||
|
e.jaxis.value = AXIS_MAX;
|
||||||
|
SDL_PushEvent(copyEvent(e));
|
||||||
|
}
|
||||||
|
if (pressed[15]) {
|
||||||
|
e.jaxis.axis = 0;
|
||||||
|
e.jaxis.value = AXIS_MAX;
|
||||||
|
SDL_PushEvent(copyEvent(e));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
pp::Module::Get()->core()->CallOnMainThread(
|
||||||
|
100, cc_factory_.NewCallback(&GameInstance::GamepadInputLoop), 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
void StartGameInNewThread(int32_t dummy) {
|
||||||
|
if (!rom_mount_string_.empty() && !rom_path_string_.empty()) {
|
||||||
|
fprintf(stderr, "Mounting %s with %s\n", rom_path_string_.c_str(),
|
||||||
|
rom_mount_string_.c_str());
|
||||||
|
pthread_create(&game_main_thread_, NULL, &LaunchGame, this);
|
||||||
|
if (gamepad_enabled_) {
|
||||||
|
pp::Module::Get()->core()->CallOnMainThread(
|
||||||
|
100, cc_factory_.NewCallback(&GameInstance::GamepadInputLoop), 0);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
// Wait some more (here: 100ms).
|
||||||
|
pp::Module::Get()->core()->CallOnMainThread(
|
||||||
|
100, cc_factory_.NewCallback(&GameInstance::StartGameInNewThread), 0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void* LaunchGame(void* data) {
|
||||||
|
// Use "thiz" to get access to instance object.
|
||||||
|
GameInstance* thiz = reinterpret_cast<GameInstance*>(data);
|
||||||
|
umount("/");
|
||||||
|
mount("", "/", "memfs", 0, "");
|
||||||
|
|
||||||
|
mkdir("/config", 0777);
|
||||||
|
fprintf(stderr, "mount httpfs = %d\n", mount("/", "/config", "httpfs", 0, ""));
|
||||||
|
|
||||||
|
mkdir("/games", 0777);
|
||||||
|
fprintf(stderr, "mount rom = %d\n", mount("/", "/games", "html5fs", 0, thiz->rom_mount_string_.c_str()));
|
||||||
|
|
||||||
|
mkdir("/store", 0777);
|
||||||
|
fprintf(stderr, "mount html5fs = %d\n", mount("/", "/store", "html5fs", 0, ""));
|
||||||
|
mkdir("/store/states", 0777);
|
||||||
|
mkdir("/store/captures", 0777);
|
||||||
|
// Craft a fake command line.
|
||||||
|
char rom_path[BUFSIZ];
|
||||||
|
strncpy(rom_path, ("/games" + thiz->rom_path_string_).c_str(), BUFSIZ);
|
||||||
|
std::string config_string("--config=/config/vbam.cfg");
|
||||||
|
if (thiz->gamepad_enabled_)
|
||||||
|
config_string = "--config=/config/vbam-gamepad.cfg";
|
||||||
|
|
||||||
|
char config[BUFSIZ];
|
||||||
|
strncpy(config, config_string.c_str(), BUFSIZ);
|
||||||
|
char* argv[] = { "vbam", config, rom_path, NULL};
|
||||||
|
SDL_main(3, argv);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
int GameInstance::num_instances_;
|
||||||
|
bool GameInstance::old_pressed_[];
|
||||||
|
|
||||||
|
class GameModule : public pp::Module {
|
||||||
|
public:
|
||||||
|
GameModule() : pp::Module() {}
|
||||||
|
virtual ~GameModule() {}
|
||||||
|
|
||||||
|
virtual pp::Instance* CreateInstance(PP_Instance instance) {
|
||||||
|
return new GameInstance(instance);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
namespace pp {
|
||||||
|
Module* CreateModule() {
|
||||||
|
return new GameModule();
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace pp
|
|
@ -23,6 +23,7 @@
|
||||||
#include <sys/types.h>
|
#include <sys/types.h>
|
||||||
#include <sys/stat.h>
|
#include <sys/stat.h>
|
||||||
#include <cmath>
|
#include <cmath>
|
||||||
|
#ifdef USE_OPENGL
|
||||||
#ifdef __APPLE__
|
#ifdef __APPLE__
|
||||||
#include <OpenGL/glu.h>
|
#include <OpenGL/glu.h>
|
||||||
#include <OpenGL/glext.h>
|
#include <OpenGL/glext.h>
|
||||||
|
@ -30,6 +31,7 @@
|
||||||
#include <GL/glu.h>
|
#include <GL/glu.h>
|
||||||
#include <GL/glext.h>
|
#include <GL/glext.h>
|
||||||
#endif
|
#endif
|
||||||
|
#endif
|
||||||
|
|
||||||
#include <time.h>
|
#include <time.h>
|
||||||
|
|
||||||
|
@ -134,9 +136,13 @@ int sdlPrintUsage = 0;
|
||||||
int cartridgeType = 3;
|
int cartridgeType = 3;
|
||||||
int captureFormat = 0;
|
int captureFormat = 0;
|
||||||
|
|
||||||
int openGL = 1;
|
|
||||||
int textureSize = 256;
|
int textureSize = 256;
|
||||||
|
#ifdef USE_OPENGL
|
||||||
|
int openGL = 1;
|
||||||
GLuint screenTexture = 0;
|
GLuint screenTexture = 0;
|
||||||
|
#else
|
||||||
|
int openGL = 0;
|
||||||
|
#endif
|
||||||
u8 *filterPix = 0;
|
u8 *filterPix = 0;
|
||||||
|
|
||||||
int pauseWhenInactive = 0;
|
int pauseWhenInactive = 0;
|
||||||
|
@ -810,6 +816,7 @@ void sdlReadPreferences(FILE *f)
|
||||||
|
|
||||||
void sdlOpenGLInit(int w, int h)
|
void sdlOpenGLInit(int w, int h)
|
||||||
{
|
{
|
||||||
|
#ifdef USE_OPENGL
|
||||||
float screenAspect = (float) srcWidth / srcHeight,
|
float screenAspect = (float) srcWidth / srcHeight,
|
||||||
windowAspect = (float) w / h;
|
windowAspect = (float) w / h;
|
||||||
|
|
||||||
|
@ -861,6 +868,7 @@ void sdlOpenGLInit(int w, int h)
|
||||||
|
|
||||||
glClearColor(0.0,0.0,0.0,1.0);
|
glClearColor(0.0,0.0,0.0,1.0);
|
||||||
glClear( GL_COLOR_BUFFER_BIT );
|
glClear( GL_COLOR_BUFFER_BIT );
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
void sdlReadPreferences()
|
void sdlReadPreferences()
|
||||||
|
@ -1277,6 +1285,9 @@ static void sdlHandleSavestateKey(int num, int shifted)
|
||||||
// 0: load
|
// 0: load
|
||||||
// 1: save
|
// 1: save
|
||||||
int backuping = 1; // controls whether we are doing savestate backups
|
int backuping = 1; // controls whether we are doing savestate backups
|
||||||
|
#ifdef __native_client__
|
||||||
|
backuping = 0;
|
||||||
|
#endif
|
||||||
|
|
||||||
if ( sdlSaveKeysSwitch == 2 )
|
if ( sdlSaveKeysSwitch == 2 )
|
||||||
{
|
{
|
||||||
|
@ -1475,9 +1486,11 @@ void sdlPollEvents()
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case SDLK_KP_DIVIDE:
|
case SDLK_KP_DIVIDE:
|
||||||
|
case SDLK_MINUS:
|
||||||
sdlChangeVolume(-0.1);
|
sdlChangeVolume(-0.1);
|
||||||
break;
|
break;
|
||||||
case SDLK_KP_MULTIPLY:
|
case SDLK_KP_MULTIPLY:
|
||||||
|
case SDLK_EQUALS:
|
||||||
sdlChangeVolume(0.1);
|
sdlChangeVolume(0.1);
|
||||||
break;
|
break;
|
||||||
case SDLK_KP_MINUS:
|
case SDLK_KP_MINUS:
|
||||||
|
@ -1543,15 +1556,19 @@ void sdlPollEvents()
|
||||||
case SDLK_g:
|
case SDLK_g:
|
||||||
if(!(event.key.keysym.mod & MOD_NOCTRL) &&
|
if(!(event.key.keysym.mod & MOD_NOCTRL) &&
|
||||||
(event.key.keysym.mod & KMOD_CTRL)) {
|
(event.key.keysym.mod & KMOD_CTRL)) {
|
||||||
filterFunction = 0;
|
filterFunction = 0;
|
||||||
while (!filterFunction)
|
while (!filterFunction) {
|
||||||
{
|
filter = (Filter)((filter + 1) % kInvalidFilter);
|
||||||
filter = (Filter)((filter + 1) % kInvalidFilter);
|
#ifdef __native_client__
|
||||||
filterFunction = initFilter(filter, systemColorDepth, srcWidth);
|
if (getFilterEnlargeFactor(filter) != filter_enlarge)
|
||||||
}
|
continue;
|
||||||
if (getFilterEnlargeFactor(filter) != filter_enlarge)
|
#endif
|
||||||
sdlInitVideo();
|
filterFunction = initFilter(filter, systemColorDepth, srcWidth);
|
||||||
systemScreenMessage(getFilterName(filter));
|
}
|
||||||
|
if (getFilterEnlargeFactor(filter) != filter_enlarge) {
|
||||||
|
sdlInitVideo();
|
||||||
|
}
|
||||||
|
systemScreenMessage(getFilterName(filter));
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case SDLK_F11:
|
case SDLK_F11:
|
||||||
|
@ -2486,6 +2503,7 @@ void systemDrawScreen()
|
||||||
drawSpeed(screen, destPitch, 10, 20);
|
drawSpeed(screen, destPitch, 10, 20);
|
||||||
|
|
||||||
if (openGL) {
|
if (openGL) {
|
||||||
|
#ifdef USE_OPENGL
|
||||||
glClear( GL_COLOR_BUFFER_BIT );
|
glClear( GL_COLOR_BUFFER_BIT );
|
||||||
glPixelStorei(GL_UNPACK_ROW_LENGTH, destWidth);
|
glPixelStorei(GL_UNPACK_ROW_LENGTH, destWidth);
|
||||||
if (systemColorDepth == 16)
|
if (systemColorDepth == 16)
|
||||||
|
@ -2508,6 +2526,7 @@ void systemDrawScreen()
|
||||||
glEnd();
|
glEnd();
|
||||||
|
|
||||||
SDL_GL_SwapBuffers();
|
SDL_GL_SwapBuffers();
|
||||||
|
#endif
|
||||||
} else {
|
} else {
|
||||||
SDL_UnlockSurface(surface);
|
SDL_UnlockSurface(surface);
|
||||||
SDL_Flip(surface);
|
SDL_Flip(surface);
|
||||||
|
|
|
@ -85,7 +85,7 @@ static int sensorY = 2047;
|
||||||
static uint32_t sdlGetHatCode(const SDL_Event &event)
|
static uint32_t sdlGetHatCode(const SDL_Event &event)
|
||||||
{
|
{
|
||||||
if (!event.jhat.value) return 0;
|
if (!event.jhat.value) return 0;
|
||||||
|
|
||||||
return (
|
return (
|
||||||
((event.jhat.which + 1) << 16) |
|
((event.jhat.which + 1) << 16) |
|
||||||
32 |
|
32 |
|
||||||
|
@ -249,7 +249,6 @@ static void sdlUpdateJoyButton(int which,
|
||||||
int b = joypad[j][i] & 0xffff;
|
int b = joypad[j][i] & 0xffff;
|
||||||
if(dev) {
|
if(dev) {
|
||||||
dev--;
|
dev--;
|
||||||
|
|
||||||
if((dev == which) && (b >= 128) && (b == (button+128))) {
|
if((dev == which) && (b >= 128) && (b == (button+128))) {
|
||||||
sdlButtons[j][i] = pressed;
|
sdlButtons[j][i] = pressed;
|
||||||
}
|
}
|
||||||
|
@ -399,7 +398,11 @@ void inputInitJoysticks()
|
||||||
joypad[PAD_MAIN][i] = joypad[PAD_DEFAULT][i];
|
joypad[PAD_MAIN][i] = joypad[PAD_DEFAULT][i];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#if defined (__native_client__)
|
||||||
|
sdlNumDevices = 1;
|
||||||
|
#else
|
||||||
sdlNumDevices = SDL_NumJoysticks();
|
sdlNumDevices = SDL_NumJoysticks();
|
||||||
|
#endif
|
||||||
|
|
||||||
if(sdlNumDevices)
|
if(sdlNumDevices)
|
||||||
sdlDevices = (SDL_Joystick **)calloc(1,sdlNumDevices *
|
sdlDevices = (SDL_Joystick **)calloc(1,sdlNumDevices *
|
||||||
|
@ -418,8 +421,11 @@ void inputInitJoysticks()
|
||||||
if(sdlDevices[dev] == NULL) {
|
if(sdlDevices[dev] == NULL) {
|
||||||
sdlDevices[dev] = SDL_JoystickOpen(dev);
|
sdlDevices[dev] = SDL_JoystickOpen(dev);
|
||||||
}
|
}
|
||||||
|
#if defined (__native_client__)
|
||||||
|
ok = true; // Force gamepad to be useable.
|
||||||
|
#else
|
||||||
ok = sdlCheckJoyKey(joypad[j][i]);
|
ok = sdlCheckJoyKey(joypad[j][i]);
|
||||||
|
#endif
|
||||||
} else
|
} else
|
||||||
ok = false;
|
ok = false;
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue