From e9dc282f193c4fb6275f8f5a503208fdf71a9472 Mon Sep 17 00:00:00 2001 From: Nikita Kniazev Date: Mon, 20 Feb 2017 19:57:18 +0300 Subject: [PATCH 01/11] Added Windows support --- atari_py/ale_c_wrapper.h | 89 ++++++++++--------- atari_py/ale_interface/CMakeLists.txt | 15 ++-- atari_py/ale_interface/src/ale_interface.cpp | 2 +- atari_py/ale_interface/src/ale_interface.hpp | 11 ++- .../src/common/ColourPalette.cpp | 5 +- .../ale_interface/src/common/misc_tools.h | 4 +- .../src/controllers/fifo_controller.cpp | 2 +- .../src/emucore/m6502/src/bspf/src/bspf.hxx | 25 +++--- .../src/emucore/rsynth/useconfig.h | 8 +- .../src/external/TinyMT/tinymt32.h | 13 ++- atari_py/ale_interface/src/games/Roms.cpp | 2 + .../src/games/supported/FishingDerby.cpp | 7 +- .../src/games/supported/IceHockey.cpp | 9 +- atari_py/ale_interface/src/main.cpp | 4 +- 14 files changed, 117 insertions(+), 79 deletions(-) diff --git a/atari_py/ale_c_wrapper.h b/atari_py/ale_c_wrapper.h index cf01cc1..bda8d1c 100644 --- a/atari_py/ale_c_wrapper.h +++ b/atari_py/ale_c_wrapper.h @@ -3,56 +3,63 @@ #include +#ifdef _WIN32 +# define SYMBOL_EXPORT __declspec(dllexport) +#endif +#ifndef SYMBOL_EXPORT +# define SYMBOL_EXPORT +#endif + extern "C" { // Declares int rgb_palette[256] #include "atari_ntsc_rgb_palette.h" - ALEInterface *ALE_new() {return new ALEInterface();} - void ALE_del(ALEInterface *ale){delete ale;} - const char *getString(ALEInterface *ale, const char *key){return ale->getString(key).c_str();} - int getInt(ALEInterface *ale,const char *key) {return ale->getInt(key);} - bool getBool(ALEInterface *ale,const char *key){return ale->getBool(key);} - float getFloat(ALEInterface *ale,const char *key){return ale->getFloat(key);} - void setString(ALEInterface *ale,const char *key,const char *value){ale->setString(key,value);} - void setInt(ALEInterface *ale,const char *key,int value){ale->setInt(key,value);} - void setBool(ALEInterface *ale,const char *key,bool value){ale->setBool(key,value);} - void setFloat(ALEInterface *ale,const char *key,float value){ale->setFloat(key,value);} - void loadROM(ALEInterface *ale,const char *rom_file){ale->loadROM(rom_file);} - int act(ALEInterface *ale,int action){return ale->act((Action)action);} - bool game_over(ALEInterface *ale){return ale->game_over();} - void reset_game(ALEInterface *ale){ale->reset_game();} - void getLegalActionSet(ALEInterface *ale,int *actions){ + SYMBOL_EXPORT ALEInterface *ALE_new() {return new ALEInterface();} + SYMBOL_EXPORT void ALE_del(ALEInterface *ale){delete ale;} + SYMBOL_EXPORT const char *getString(ALEInterface *ale, const char *key){return ale->getString(key).c_str();} + SYMBOL_EXPORT int getInt(ALEInterface *ale,const char *key) {return ale->getInt(key);} + SYMBOL_EXPORT bool getBool(ALEInterface *ale,const char *key){return ale->getBool(key);} + SYMBOL_EXPORT float getFloat(ALEInterface *ale,const char *key){return ale->getFloat(key);} + SYMBOL_EXPORT void setString(ALEInterface *ale,const char *key,const char *value){ale->setString(key,value);} + SYMBOL_EXPORT void setInt(ALEInterface *ale,const char *key,int value){ale->setInt(key,value);} + SYMBOL_EXPORT void setBool(ALEInterface *ale,const char *key,bool value){ale->setBool(key,value);} + SYMBOL_EXPORT void setFloat(ALEInterface *ale,const char *key,float value){ale->setFloat(key,value);} + SYMBOL_EXPORT void loadROM(ALEInterface *ale,const char *rom_file){ale->loadROM(rom_file);} + SYMBOL_EXPORT int act(ALEInterface *ale,int action){return ale->act((Action)action);} + SYMBOL_EXPORT bool game_over(ALEInterface *ale){return ale->game_over();} + SYMBOL_EXPORT void reset_game(ALEInterface *ale){ale->reset_game();} + SYMBOL_EXPORT void getLegalActionSet(ALEInterface *ale,int *actions){ ActionVect action_vect = ale->getLegalActionSet(); for(unsigned int i = 0;i < ale->getLegalActionSet().size();i++){ actions[i] = action_vect[i]; } } - int getLegalActionSize(ALEInterface *ale){return ale->getLegalActionSet().size();} - void getMinimalActionSet(ALEInterface *ale,int *actions){ + SYMBOL_EXPORT int getLegalActionSize(ALEInterface *ale){return ale->getLegalActionSet().size();} + SYMBOL_EXPORT void getMinimalActionSet(ALEInterface *ale,int *actions){ ActionVect action_vect = ale->getMinimalActionSet(); for(unsigned int i = 0;i < ale->getMinimalActionSet().size();i++){ actions[i] = action_vect[i]; } } - int getMinimalActionSize(ALEInterface *ale){return ale->getMinimalActionSet().size();} - int getFrameNumber(ALEInterface *ale){return ale->getFrameNumber();} - int lives(ALEInterface *ale){return ale->lives();} - int getEpisodeFrameNumber(ALEInterface *ale){return ale->getEpisodeFrameNumber();} - void getScreen(ALEInterface *ale,unsigned char *screen_data){ + SYMBOL_EXPORT int getMinimalActionSize(ALEInterface *ale){return ale->getMinimalActionSet().size();} + SYMBOL_EXPORT int getFrameNumber(ALEInterface *ale){return ale->getFrameNumber();} + SYMBOL_EXPORT int lives(ALEInterface *ale){return ale->lives();} + SYMBOL_EXPORT int getEpisodeFrameNumber(ALEInterface *ale){return ale->getEpisodeFrameNumber();} + SYMBOL_EXPORT void getScreen(ALEInterface *ale,unsigned char *screen_data){ int w = ale->getScreen().width(); int h = ale->getScreen().height(); pixel_t *ale_screen_data = (pixel_t *)ale->getScreen().getArray(); memcpy(screen_data,ale_screen_data,w*h*sizeof(pixel_t)); } - void getRAM(ALEInterface *ale,unsigned char *ram){ + SYMBOL_EXPORT void getRAM(ALEInterface *ale,unsigned char *ram){ unsigned char *ale_ram = ale->getRAM().array(); int size = ale->getRAM().size(); memcpy(ram,ale_ram,size*sizeof(unsigned char)); } - int getRAMSize(ALEInterface *ale){return ale->getRAM().size();} - int getScreenWidth(ALEInterface *ale){return ale->getScreen().width();} - int getScreenHeight(ALEInterface *ale){return ale->getScreen().height();} + SYMBOL_EXPORT int getRAMSize(ALEInterface *ale){return ale->getRAM().size();} + SYMBOL_EXPORT int getScreenWidth(ALEInterface *ale){return ale->getScreen().width();} + SYMBOL_EXPORT int getScreenHeight(ALEInterface *ale){return ale->getScreen().height();} - void getScreenRGB(ALEInterface *ale, unsigned char *output_buffer){ + SYMBOL_EXPORT void getScreenRGB(ALEInterface *ale, unsigned char *output_buffer){ size_t w = ale->getScreen().width(); size_t h = ale->getScreen().height(); size_t screen_size = w*h; @@ -61,7 +68,7 @@ extern "C" { ale->theOSystem->colourPalette().applyPaletteRGB(output_buffer, ale_screen_data, screen_size); } - void getScreenRGB2(ALEInterface *ale, unsigned char *output_buffer){ + SYMBOL_EXPORT void getScreenRGB2(ALEInterface *ale, unsigned char *output_buffer){ size_t w = ale->getScreen().width(); size_t h = ale->getScreen().height(); size_t screen_size = w*h; @@ -76,7 +83,7 @@ extern "C" { } } - void getScreenGrayscale(ALEInterface *ale, unsigned char *output_buffer){ + SYMBOL_EXPORT void getScreenGrayscale(ALEInterface *ale, unsigned char *output_buffer){ size_t w = ale->getScreen().width(); size_t h = ale->getScreen().height(); size_t screen_size = w*h; @@ -85,24 +92,24 @@ extern "C" { ale->theOSystem->colourPalette().applyPaletteGrayscale(output_buffer, ale_screen_data, screen_size); } - void saveState(ALEInterface *ale){ale->saveState();} - void loadState(ALEInterface *ale){ale->loadState();} - ALEState* cloneState(ALEInterface *ale){return new ALEState(ale->cloneState());} - void restoreState(ALEInterface *ale, ALEState* state){ale->restoreState(*state);} - ALEState* cloneSystemState(ALEInterface *ale){return new ALEState(ale->cloneSystemState());} - void restoreSystemState(ALEInterface *ale, ALEState* state){ale->restoreSystemState(*state);} - void deleteState(ALEState* state){delete state;} - void saveScreenPNG(ALEInterface *ale,const char *filename){ale->saveScreenPNG(filename);} + SYMBOL_EXPORT void saveState(ALEInterface *ale){ale->saveState();} + SYMBOL_EXPORT void loadState(ALEInterface *ale){ale->loadState();} + SYMBOL_EXPORT ALEState* cloneState(ALEInterface *ale){return new ALEState(ale->cloneState());} + SYMBOL_EXPORT void restoreState(ALEInterface *ale, ALEState* state){ale->restoreState(*state);} + SYMBOL_EXPORT ALEState* cloneSystemState(ALEInterface *ale){return new ALEState(ale->cloneSystemState());} + SYMBOL_EXPORT void restoreSystemState(ALEInterface *ale, ALEState* state){ale->restoreSystemState(*state);} + SYMBOL_EXPORT void deleteState(ALEState* state){delete state;} + SYMBOL_EXPORT void saveScreenPNG(ALEInterface *ale,const char *filename){ale->saveScreenPNG(filename);} // Encodes the state as a raw bytestream. This may have multiple '\0' characters // and thus should not be treated as a C string. Use encodeStateLen to find the length // of the buffer to pass in, or it will be overrun as this simply memcpys bytes into the buffer. - void encodeState(ALEState *state, char *buf, int buf_len); - int encodeStateLen(ALEState *state); - ALEState *decodeState(const char *serialized, int len); + SYMBOL_EXPORT void encodeState(ALEState *state, char *buf, int buf_len); + SYMBOL_EXPORT int encodeStateLen(ALEState *state); + SYMBOL_EXPORT ALEState *decodeState(const char *serialized, int len); // 0: Info, 1: Warning, 2: Error - void setLoggerMode(int mode) { ale::Logger::setMode(ale::Logger::mode(mode)); } + SYMBOL_EXPORT void setLoggerMode(int mode) { ale::Logger::setMode(ale::Logger::mode(mode)); } } #endif diff --git a/atari_py/ale_interface/CMakeLists.txt b/atari_py/ale_interface/CMakeLists.txt index d8f1906..d29a9a0 100644 --- a/atari_py/ale_interface/CMakeLists.txt +++ b/atari_py/ale_interface/CMakeLists.txt @@ -10,9 +10,11 @@ option(BUILD_CPP_LIB "Build C++ Shared Library" OFF) option(BUILD_CLI "Build ALE Command Line Interface" OFF) option(BUILD_C_LIB "Build ALE C Library (needed for Python interface)" ON) -set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wall -Wunused -fPIC -O3 -fomit-frame-pointer -D__STDC_CONSTANT_MACROS") -add_definitions(-DHAVE_INTTYPES) -set(LINK_LIBS z) +find_package(ZLIB REQUIRED) +if(ZLIB_FOUND) + include_directories(${ZLIB_INCLUDE_DIRS}) + set(LINK_LIBS ${ZLIB_LIBRARIES}) +endif() if(USE_RLGLUE) add_definitions(-D__USE_RLGLUE) @@ -51,13 +53,14 @@ endforeach(module ${MODULES}) # OS-dependent specifics if(APPLE) + add_definitions(-DBSPF_MAC_OSX) include_directories(/System/Library/Frameworks/vecLib.framework/Versions/Current/Headers) set(CMAKE_SHARED_LIBRARY_SUFFIX ".so") -endif() - -if(WINDOWS OR MINGW) +elseif(WIN32 OR MINGW) + add_definitions(-DBSPF_WIN32) list(APPEND SOURCES ${SOURCE_DIR}/os_dependent/SettingsWin32.cxx ${SOURCE_DIR}/os_dependent/OSystemWin32.cxx ${SOURCE_DIR}/os_dependent/FSNodeWin32.cxx) else() + add_definitions(-DBSPF_UNIX) list(APPEND SOURCES ${SOURCE_DIR}/os_dependent/SettingsUNIX.cxx ${SOURCE_DIR}/os_dependent/OSystemUNIX.cxx ${SOURCE_DIR}/os_dependent/FSNodePOSIX.cxx) SET(BIN_INSTALL_DIR "bin") SET(LIB_SUFFIX "" CACHE STRING "Define suffix of directory name (32/64)" ) diff --git a/atari_py/ale_interface/src/ale_interface.cpp b/atari_py/ale_interface/src/ale_interface.cpp index 6218316..7fbff9d 100644 --- a/atari_py/ale_interface/src/ale_interface.cpp +++ b/atari_py/ale_interface/src/ale_interface.cpp @@ -54,7 +54,7 @@ void ALEInterface::disableBufferedIO() { void ALEInterface::createOSystem(std::auto_ptr &theOSystem, std::auto_ptr &theSettings) { -#if (defined(WIN32) || defined(__MINGW32__)) +#if (defined(_WIN32) || defined(__MINGW32__)) theOSystem.reset(new OSystemWin32()); theSettings.reset(new SettingsWin32(theOSystem.get())); #else diff --git a/atari_py/ale_interface/src/ale_interface.hpp b/atari_py/ale_interface/src/ale_interface.hpp index 997a3e4..d9954ec 100644 --- a/atari_py/ale_interface/src/ale_interface.hpp +++ b/atari_py/ale_interface/src/ale_interface.hpp @@ -32,10 +32,13 @@ #include "emucore/FSNode.hxx" #include "emucore/OSystem.hxx" -#include "os_dependent/SettingsWin32.hxx" -#include "os_dependent/OSystemWin32.hxx" -#include "os_dependent/SettingsUNIX.hxx" -#include "os_dependent/OSystemUNIX.hxx" +#if (defined(_WIN32) || defined(__MINGW32__)) +# include "os_dependent/SettingsWin32.hxx" +# include "os_dependent/OSystemWin32.hxx" +#else +# include "os_dependent/SettingsUNIX.hxx" +# include "os_dependent/OSystemUNIX.hxx" +#endif #include "games/Roms.hpp" #include "common/display_screen.h" #include "environment/stella_environment.hpp" diff --git a/atari_py/ale_interface/src/common/ColourPalette.cpp b/atari_py/ale_interface/src/common/ColourPalette.cpp index acf91f3..fde02a0 100644 --- a/atari_py/ale_interface/src/common/ColourPalette.cpp +++ b/atari_py/ale_interface/src/common/ColourPalette.cpp @@ -34,7 +34,10 @@ inline uInt32 convertGrayscale(uInt32 packedRGBValue) double g = (packedRGBValue >> 8) & 0xff; double b = (packedRGBValue >> 0) & 0xff; - uInt8 lum = (uInt8) round(r * 0.2989 + g * 0.5870 + b * 0.1140); + // `round` is the part of c++11, but we have to support c++98 + // because of python2. As we have unsigend values here it is safe + // to replace `round` call with +0.5 which is equal in this case. + uInt8 lum = (uInt8) (r * 0.2989 + g * 0.5870 + b * 0.1140 + 0.5); return packRGB(lum, lum, lum); } diff --git a/atari_py/ale_interface/src/common/misc_tools.h b/atari_py/ale_interface/src/common/misc_tools.h index fe1ddb8..8e34d5a 100644 --- a/atari_py/ale_interface/src/common/misc_tools.h +++ b/atari_py/ale_interface/src/common/misc_tools.h @@ -17,7 +17,7 @@ #include "Constants.h" -#if (defined(WIN32) || defined(__MINGW32__)) +#if (defined(_WIN32) || defined(__MINGW32__)) #include #endif @@ -54,7 +54,7 @@ inline void bound(int& x, int lower_bound, int upper_bound) { /* ***************************************************************************** Return time in milliseconds. **************************************************************************** */ -#if (defined(WIN32) || defined(__MINGW32__)) +#if (defined(_WIN32) || defined(__MINGW32__)) #include inline long timeMillis() { diff --git a/atari_py/ale_interface/src/controllers/fifo_controller.cpp b/atari_py/ale_interface/src/controllers/fifo_controller.cpp index e3da759..bf45984 100644 --- a/atari_py/ale_interface/src/controllers/fifo_controller.cpp +++ b/atari_py/ale_interface/src/controllers/fifo_controller.cpp @@ -89,7 +89,7 @@ void FIFOController::handshake() { // send the width and height of the screen through the pipe char out_buffer [1024]; - snprintf (out_buffer, sizeof(out_buffer), "%d-%d\n", + BSPF_snprintf(out_buffer, sizeof(out_buffer), "%d-%d\n", (int)m_environment.getScreen().width(), (int)m_environment.getScreen().height()); diff --git a/atari_py/ale_interface/src/emucore/m6502/src/bspf/src/bspf.hxx b/atari_py/ale_interface/src/emucore/m6502/src/bspf/src/bspf.hxx index b387051..df174aa 100644 --- a/atari_py/ale_interface/src/emucore/m6502/src/bspf/src/bspf.hxx +++ b/atari_py/ale_interface/src/emucore/m6502/src/bspf/src/bspf.hxx @@ -56,20 +56,23 @@ typedef unsigned int uInt32; #endif // Defines to help with path handling -//ALE #if defined BSPF_UNIX -#define BSPF_PATH_SEPARATOR "/" -//ALE #elif (defined(BSPF_DOS) || defined(BSPF_WIN32) || defined(BSPF_OS2)) -//ALE #define BSPF_PATH_SEPARATOR "\\" -//ALE #elif defined BSPF_MAC_OSX -//ALE #define BSPF_PATH_SEPARATOR "/" -//ALE #elif defined BSPF_GP2X -//ALE #define BSPF_PATH_SEPARATOR "/" -//ALE #endif +#if defined(BSPF_UNIX) + #define BSPF_PATH_SEPARATOR "/" +#elif (defined(BSPF_DOS) || defined(BSPF_WIN32) || defined(BSPF_OS2)) + #define BSPF_PATH_SEPARATOR "\\" +#elif defined(BSPF_MAC_OSX) + #define BSPF_PATH_SEPARATOR "/" +#elif defined(BSPF_GP2X) + #define BSPF_PATH_SEPARATOR "/" +#else + #error "Unsupported platform or misconfigured" +#endif // I wish Windows had a complete POSIX layer #ifdef BSPF_WIN32 - #define BSPF_strcasecmp stricmp - #define BSPF_strncasecmp strnicmp +//#if defined(_MSC_VER) && (_MSC_VER < 1600) + #define BSPF_strcasecmp _stricmp + #define BSPF_strncasecmp _strnicmp #define BSPF_isblank(c) ((c == ' ') || (c == '\t')) #define BSPF_snprintf _snprintf #define BSPF_vsnprintf _vsnprintf diff --git a/atari_py/ale_interface/src/emucore/rsynth/useconfig.h b/atari_py/ale_interface/src/emucore/rsynth/useconfig.h index f58f8af..69747e6 100644 --- a/atari_py/ale_interface/src/emucore/rsynth/useconfig.h +++ b/atari_py/ale_interface/src/emucore/rsynth/useconfig.h @@ -20,8 +20,12 @@ char *strchr (), *strrchr (); #endif #endif /* STDC_HEADERS */ -#if HAVE_UNISTD_H -#include +#ifdef _WIN32 +# include +#else +# if HAVE_UNISTD_H +# include +# endif #endif #if HAVE_LIBC_H diff --git a/atari_py/ale_interface/src/external/TinyMT/tinymt32.h b/atari_py/ale_interface/src/external/TinyMT/tinymt32.h index 942581b..3247d4f 100644 --- a/atari_py/ale_interface/src/external/TinyMT/tinymt32.h +++ b/atari_py/ale_interface/src/external/TinyMT/tinymt32.h @@ -16,8 +16,17 @@ * LICENSE.txt */ -#include -#include +#if defined(_MSC_VER) && (_MSC_VER < 1600) +typedef __int32 int32_t; +typedef unsigned __int32 uint32_t; +typedef __int64 int64_t; +typedef unsigned __int64 uint64_t; +# define UINT32_C(c) c ## UL +# define inline __inline +#else +# include +# include +#endif #define TINYMT32_MEXP 127 #define TINYMT32_SH0 1 diff --git a/atari_py/ale_interface/src/games/Roms.cpp b/atari_py/ale_interface/src/games/Roms.cpp index ad49e44..7e99872 100644 --- a/atari_py/ale_interface/src/games/Roms.cpp +++ b/atari_py/ale_interface/src/games/Roms.cpp @@ -78,6 +78,8 @@ #include "supported/YarsRevenge.hpp" #include "supported/Zaxxon.hpp" +#include + /* list of supported games */ static const RomSettings *roms[] = { diff --git a/atari_py/ale_interface/src/games/supported/FishingDerby.cpp b/atari_py/ale_interface/src/games/supported/FishingDerby.cpp index af87c76..c07addb 100644 --- a/atari_py/ale_interface/src/games/supported/FishingDerby.cpp +++ b/atari_py/ale_interface/src/games/supported/FishingDerby.cpp @@ -12,7 +12,8 @@ #include "FishingDerby.hpp" #include "../RomUtils.hpp" -using namespace std; + +#include FishingDerbySettings::FishingDerbySettings() { @@ -34,8 +35,8 @@ RomSettings* FishingDerbySettings::clone() const { void FishingDerbySettings::step(const System& system) { // update the reward - int my_score = max(getDecimalScore(0xBD, &system), 0); - int oppt_score = max(getDecimalScore(0xBE, &system), 0); + int my_score = (std::max)(getDecimalScore(0xBD, &system), 0); + int oppt_score = (std::max)(getDecimalScore(0xBE, &system), 0); int score = my_score - oppt_score; m_reward = score - m_score; m_score = score; diff --git a/atari_py/ale_interface/src/games/supported/IceHockey.cpp b/atari_py/ale_interface/src/games/supported/IceHockey.cpp index 3cc29bd..694c1ff 100644 --- a/atari_py/ale_interface/src/games/supported/IceHockey.cpp +++ b/atari_py/ale_interface/src/games/supported/IceHockey.cpp @@ -12,7 +12,8 @@ #include "IceHockey.hpp" #include "../RomUtils.hpp" -using namespace std; + +#include IceHockeySettings::IceHockeySettings() { @@ -34,10 +35,10 @@ RomSettings* IceHockeySettings::clone() const { void IceHockeySettings::step(const System& system) { // update the reward - int my_score = max(getDecimalScore(0x8A, &system), 0); - int oppt_score = max(getDecimalScore(0x8B, &system), 0); + int my_score = (std::max)(getDecimalScore(0x8A, &system), 0); + int oppt_score = (std::max)(getDecimalScore(0x8B, &system), 0); int score = my_score - oppt_score; - int reward = min(score - m_score, 1); + int reward = (std::min)(score - m_score, 1); m_reward = reward; m_score = score; diff --git a/atari_py/ale_interface/src/main.cpp b/atari_py/ale_interface/src/main.cpp index f634b55..250c485 100644 --- a/atari_py/ale_interface/src/main.cpp +++ b/atari_py/ale_interface/src/main.cpp @@ -22,7 +22,9 @@ #include "emucore/FSNode.hxx" #include "emucore/OSystem.hxx" -#if (defined(WIN32) || defined(__MINGW32__)) +#include "common/Defaults.hpp" + +#if (defined(_WIN32) || defined(__MINGW32__)) # include "os_dependent/SettingsWin32.hxx" # include "os_dependent/OSystemWin32.hxx" #else From a3c3352eb4498482e216f4a6e518bb358ae81536 Mon Sep 17 00:00:00 2001 From: Nikita Kniazev Date: Mon, 20 Feb 2017 19:58:39 +0300 Subject: [PATCH 02/11] Build C library with distutils (without CMake) --- README.md | 6 +- atari_py/ale_python_interface.py | 16 +++- atari_py/package_data.txt | 2 - setup.py | 154 ++++++++++++++++++++++++++----- 4 files changed, 148 insertions(+), 30 deletions(-) diff --git a/README.md b/README.md index 97f2fb3..33f6a34 100644 --- a/README.md +++ b/README.md @@ -21,5 +21,7 @@ this repo to your `PYTHONPATH`: ### Common issues -- Make sure you have `cmake` installed. On OSX, you probably want - `brew install cmake`. +- If `zlib` cannot be found by compiler - check if it is installed in your + system. You can provide `zlib` path by setting `ZLIB_ROOT` environment + variable or directly to `pip` like this: + `pip install --global-option=build_ext --global-option="-L/path/to/zlib/lib" --global-option="-I/path/to/zlib/include" atari-py` diff --git a/atari_py/ale_python_interface.py b/atari_py/ale_python_interface.py index 72425e0..84b18d0 100644 --- a/atari_py/ale_python_interface.py +++ b/atari_py/ale_python_interface.py @@ -10,8 +10,20 @@ import os import six -ale_lib = cdll.LoadLibrary(os.path.join(os.path.dirname(__file__), - 'ale_interface/build/libale_c.so')) + +def get_shared_lib_path(): + from distutils.ccompiler import get_default_compiler, new_compiler + from distutils.sysconfig import get_config_var + fname = 'ale_c' + ext_suffix = get_config_var('EXT_SUFFIX') + if ext_suffix is not None: + fname += os.path.splitext(ext_suffix)[0] + fname += new_compiler(compiler=get_default_compiler()).shared_lib_extension + path = os.path.join(os.path.dirname(__file__), '..', fname) + return os.path.abspath(path) + + +ale_lib = cdll.LoadLibrary(get_shared_lib_path()) ale_lib.ALE_new.argtypes = None ale_lib.ALE_new.restype = c_void_p diff --git a/atari_py/package_data.txt b/atari_py/package_data.txt index 6d35fff..18d0316 100644 --- a/atari_py/package_data.txt +++ b/atari_py/package_data.txt @@ -1,5 +1,3 @@ -ale_interface/build/*.so -ale_interface/build/ale ale_c_wrapper.cpp ale_c_wrapper.h ale_interface/CMakeLists.txt diff --git a/setup.py b/setup.py index cb962e7..9e1571a 100644 --- a/setup.py +++ b/setup.py @@ -1,26 +1,131 @@ -import multiprocessing +import glob import os -from setuptools import setup -import subprocess import sys -from distutils.command.build import build as DistutilsBuild - -with open(os.path.join(os.path.dirname(__file__), 'atari_py/package_data.txt')) as f: - package_data = [line.rstrip() for line in f.readlines()] - -class Build(DistutilsBuild): - def run(self): - cores_to_use = max(1, multiprocessing.cpu_count() - 1) - cmd = ['make', 'build', '-C', 'atari_py/ale_interface', '-j', str(cores_to_use)] - try: - subprocess.check_call(cmd) - except subprocess.CalledProcessError as e: - sys.stderr.write("Could not build atari-py: %s. (HINT: are you sure cmake is installed? You might also be missing a library. Atari-py requires: zlib [installable as 'apt-get install zlib1g-dev' on Ubuntu].)\n" % e) - raise - except OSError as e: - sys.stderr.write("Unable to execute '{}'. HINT: are you sure `make` is installed?\n".format(' '.join(cmd))) - raise - DistutilsBuild.run(self) +from setuptools import setup +from setuptools.command.build_ext import build_ext as _build_ext +from setuptools.extension import Library + + +class build_ext(_build_ext): + def setup_shlib_compiler(self): + _build_ext.setup_shlib_compiler(self) + if os.name == 'nt': + # Currently setuptools Library linking on Windows is broken + # so we are monkeypatching it to be able to produce dll + from distutils.ccompiler import CCompiler + mtd = CCompiler.link_shared_object.__get__(self.shlib_compiler) + self.shlib_compiler.link_shared_object = mtd + + +def list_files(path): + for root, dirs, files in os.walk(path): + for fname in files: + yield os.path.join(root, fname) + + for dirname in dirs: + for rpath in list_files(os.path.join(root, dirname)): + yield rpath + + +basepath = os.path.normpath(r'atari_py/ale_interface/src') +modules = [os.path.join(basepath, os.path.normpath(path)) + for path in 'common controllers emucore emucore/m6502/src ' + 'emucore/m6502/src/bspf/src environment games ' + 'games/supported external external/TinyMT'.split()] +defines = [] +sources = [os.path.join('atari_py', 'ale_c_wrapper.cpp'), + os.path.join(basepath, 'ale_interface.cpp')] +includes = ['atari_py', basepath, os.path.join(basepath, 'os_dependent')] +includes += modules + +for folder in modules: + sources += glob.glob(os.path.join(folder, '*.c')) + sources += glob.glob(os.path.join(folder, '*.c?[xp]')) + +if sys.platform.startswith('linux'): + defines.append(('BSPF_UNIX', None)) + for fname in 'SettingsUNIX.cxx OSystemUNIX.cxx FSNodePOSIX.cxx'.split(): + sources.append(os.path.join(basepath, 'os_dependent', fname)) +elif sys.platform == "darwin": + defines.append(('BSPF_MAC_OSX', None)) + includes.append( + '/System/Library/Frameworks/vecLib.framework/Versions/Current/Headers') +elif sys.platform == "win32": + defines.append(('BSPF_WIN32', None)) + for fname in 'SettingsWin32.cxx OSystemWin32.cxx FSNodeWin32.cxx'.split(): + sources.append(os.path.join(basepath, 'os_dependent', fname)) + +library_dirs = [] +zlib_root = os.environ.get('ZLIB_ROOT') +if zlib_root is not None: + if not os.path.isfile(os.path.join(zlib_root, 'zlib.h')): + raise ValueError("There is no 'zlib.h' in ZLIB_ROOT folder") + zlib_includes = [zlib_root] + + import fnmatch + zlib_includes += { + os.path.dirname(path) + for path in fnmatch.filter(list_files(zlib_root), '*zconf.h') + } + if not zlib_includes: + raise ValueError("Failed to find 'zconf.h' under ZLIB_ROOT folder. " + "Have you compiled zlib?") + includes += zlib_includes + + zlib_libraries = set() + + # Try to compile a test program against zlib + from distutils.ccompiler import get_default_compiler, new_compiler + compiler = new_compiler(compiler=get_default_compiler()) + ext = compiler.static_lib_extension + + import tempfile + from distutils.ccompiler import CompileError, LinkError + tmp_dir = tempfile.mkdtemp() + src_path = os.path.join(tmp_dir, 'zlibtest.c') + with open(src_path, 'w') as f: + f.write("#include \nint main() { inflate(0, 0); return 0; }") + try: + for i, path in enumerate(fnmatch.filter(list_files(zlib_root), + '*zlib*' + ext)): + tmp_dir_i = os.path.join(tmp_dir, str(i)) + zlib_library = os.path.splitext(os.path.basename(path))[0] + zlib_library_dir = os.path.dirname(path) + try: + objects = compiler.compile([src_path], tmp_dir_i, + include_dirs=zlib_includes) + compiler.link_executable(objects, 'zlibtest', tmp_dir_i, + libraries=[zlib_library], + library_dirs=[zlib_library_dir]) + except (CompileError, LinkError) as e: + pass # skip this library as malformed + else: + zlib_libraries.add((zlib_library, zlib_library_dir)) + finally: + import shutil + shutil.rmtree(tmp_dir, ignore_errors=True) + + if not zlib_libraries: + raise ValueError("Failed to find a suitable library (zlib*%s) under " + "ZLIB_ROOT folder. Have you compiled zlib?" % ext) + + # Priority to static library (Windows) + for zlib_library, zlib_library_dir in zlib_libraries: + if 'static' in zlib_library: + break + library_dirs.append(zlib_library_dir) +else: + zlib_library = 'zlib' + + +ale_c = Library('ale_c', + define_macros=defines, + sources=sources, + include_dirs=includes, + libraries=[zlib_library], + library_dirs=library_dirs, + ) + setup(name='atari-py', version='0.1.1', @@ -30,8 +135,9 @@ def run(self): author_email='info@openai.com', license='', packages=['atari_py'], - package_data={'atari_py': package_data}, - cmdclass={'build': Build}, + package_data={'atari_py': ['atari_roms/*']}, + cmdclass={'build_ext': build_ext}, + ext_modules=[ale_c], install_requires=['numpy', 'six'], tests_require=['nose2'] -) + ) From 4af6cb039576a7550c9524d94453e1a9436a6433 Mon Sep 17 00:00:00 2001 From: Nikita Kniazev Date: Mon, 20 Feb 2017 21:16:32 +0300 Subject: [PATCH 03/11] c++98 compatibility fix --- atari_py/ale_interface/src/emucore/TIA.cxx | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/atari_py/ale_interface/src/emucore/TIA.cxx b/atari_py/ale_interface/src/emucore/TIA.cxx index 43bcffa..535195f 100644 --- a/atari_py/ale_interface/src/emucore/TIA.cxx +++ b/atari_py/ale_interface/src/emucore/TIA.cxx @@ -34,6 +34,15 @@ using namespace std; #define HBLANK 68 +// c++98 compatibility +#if !defined(__intptr_t_defined) && !defined(_UINTPTR_T_DEFINED) && !defined(uintptr_t) +# if __WORDSIZE == 64 +typedef unsigned long int uintptr_t; +# else +typedef unsigned int uintptr_t; +# endif +#endif + // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - TIA::TIA(const Console& console, Settings& settings) : myConsole(console), From d7e81404ea1aa6b2dee15c53635575013ae10c3f Mon Sep 17 00:00:00 2001 From: Nikita Kniazev Date: Mon, 20 Feb 2017 22:58:37 +0300 Subject: [PATCH 04/11] Fixed *nix build --- atari_py/ale_python_interface.py | 5 ++++- setup.py | 30 +++++++++++++++++++++++++----- 2 files changed, 29 insertions(+), 6 deletions(-) diff --git a/atari_py/ale_python_interface.py b/atari_py/ale_python_interface.py index 84b18d0..a6e1133 100644 --- a/atari_py/ale_python_interface.py +++ b/atari_py/ale_python_interface.py @@ -14,7 +14,10 @@ def get_shared_lib_path(): from distutils.ccompiler import get_default_compiler, new_compiler from distutils.sysconfig import get_config_var - fname = 'ale_c' + if os.name == 'nt': + fname = 'ale_c' + else: + fname = 'libale_c' ext_suffix = get_config_var('EXT_SUFFIX') if ext_suffix is not None: fname += os.path.splitext(ext_suffix)[0] diff --git a/setup.py b/setup.py index 9e1571a..d1ff1d1 100644 --- a/setup.py +++ b/setup.py @@ -6,15 +6,27 @@ from setuptools.extension import Library +# Force linker to produce a shared library class build_ext(_build_ext): + if sys.platform.startswith('linux'): + def get_ext_filename(self, fullname): + import setuptools.command.build_ext + tmp = setuptools.command.build_ext.libtype + setuptools.command.build_ext.libtype = 'shared' + ret = _build_ext.get_ext_filename(self, fullname) + setuptools.command.build_ext.libtype = tmp + return ret + def setup_shlib_compiler(self): _build_ext.setup_shlib_compiler(self) - if os.name == 'nt': - # Currently setuptools Library linking on Windows is broken - # so we are monkeypatching it to be able to produce dll + if sys.platform == 'win32': from distutils.ccompiler import CCompiler mtd = CCompiler.link_shared_object.__get__(self.shlib_compiler) self.shlib_compiler.link_shared_object = mtd + elif sys.platform.startswith('linux'): + from functools import partial + c = self.shlib_compiler + c.link_shared_object = partial(c.link, c.SHARED_LIBRARY) def list_files(path): @@ -79,6 +91,11 @@ def list_files(path): compiler = new_compiler(compiler=get_default_compiler()) ext = compiler.static_lib_extension + if os.name == 'nt': + zlib_name = 'zlib' + else: + zlib_name = 'libz' + import tempfile from distutils.ccompiler import CompileError, LinkError tmp_dir = tempfile.mkdtemp() @@ -87,7 +104,7 @@ def list_files(path): f.write("#include \nint main() { inflate(0, 0); return 0; }") try: for i, path in enumerate(fnmatch.filter(list_files(zlib_root), - '*zlib*' + ext)): + '*%s*%s' % (zlib_name, ext))): tmp_dir_i = os.path.join(tmp_dir, str(i)) zlib_library = os.path.splitext(os.path.basename(path))[0] zlib_library_dir = os.path.dirname(path) @@ -115,7 +132,10 @@ def list_files(path): break library_dirs.append(zlib_library_dir) else: - zlib_library = 'zlib' + if os.name == 'nt': + zlib_library = 'zlib' + else: + zlib_library = 'z' ale_c = Library('ale_c', From 95f4e6362cf6dbee4c7b8b54083baf20bb0c2d0a Mon Sep 17 00:00:00 2001 From: Nikita Kniazev Date: Tue, 21 Feb 2017 01:48:08 +0300 Subject: [PATCH 05/11] `tox.ini` cleanup --- tox.ini | 11 ++--------- 1 file changed, 2 insertions(+), 9 deletions(-) diff --git a/tox.ini b/tox.ini index fe17214..43fc845 100644 --- a/tox.ini +++ b/tox.ini @@ -7,26 +7,19 @@ envlist = py27, py35 [testenv:py35] -whitelist_externals=make - echo +whitelist_externals=echo install_command=echo {packages} commands = pip install numpy nose2 - make - python setup.py build pip install -e . nose2 python setup.py clean --all - make clean [testenv:py27] -whitelist_externals=make - echo +whitelist_externals=echo install_command=echo {packages} commands = pip install numpy nose2 - python setup.py build pip install -e . nose2 python setup.py clean --all - make clean From 4f8a883da3741f15673c1e93ef21bd65e6087aa0 Mon Sep 17 00:00:00 2001 From: Nikita Kniazev Date: Tue, 21 Feb 2017 13:27:54 +0300 Subject: [PATCH 06/11] Improved zlib lookup --- setup.py | 32 ++++++++++++++++++++++---------- 1 file changed, 22 insertions(+), 10 deletions(-) diff --git a/setup.py b/setup.py index d1ff1d1..c14059c 100644 --- a/setup.py +++ b/setup.py @@ -67,21 +67,34 @@ def list_files(path): for fname in 'SettingsWin32.cxx OSystemWin32.cxx FSNodeWin32.cxx'.split(): sources.append(os.path.join(basepath, 'os_dependent', fname)) + +def rglob(path, pattern): + return fnmatch.filter(list_files(path), pattern) + + +def find_include_dirs(root, fname): + return {os.path.dirname(path) + for path in rglob(root, '*' + fname)} + + library_dirs = [] zlib_root = os.environ.get('ZLIB_ROOT') if zlib_root is not None: - if not os.path.isfile(os.path.join(zlib_root, 'zlib.h')): - raise ValueError("There is no 'zlib.h' in ZLIB_ROOT folder") - zlib_includes = [zlib_root] - import fnmatch - zlib_includes += { - os.path.dirname(path) - for path in fnmatch.filter(list_files(zlib_root), '*zconf.h') - } + + zlib_includes = [] + + zlib_dirs = find_include_dirs(zlib_root, 'zlib.h') + if not zlib_dirs: + raise ValueError("Failed to find 'zlib.h' under ZLIB_ROOT folder. " + "It looks like there is no zlib in supplied path.") + zlib_includes += zlib_dirs + + zconf_dirs = find_include_dirs(zlib_root, 'zconf.h') if not zlib_includes: raise ValueError("Failed to find 'zconf.h' under ZLIB_ROOT folder. " "Have you compiled zlib?") + zlib_includes += zconf_dirs includes += zlib_includes zlib_libraries = set() @@ -103,8 +116,7 @@ def list_files(path): with open(src_path, 'w') as f: f.write("#include \nint main() { inflate(0, 0); return 0; }") try: - for i, path in enumerate(fnmatch.filter(list_files(zlib_root), - '*%s*%s' % (zlib_name, ext))): + for i, path in enumerate(rglob(zlib_root, '*%s*%s' % (zlib_name, ext))): tmp_dir_i = os.path.join(tmp_dir, str(i)) zlib_library = os.path.splitext(os.path.basename(path))[0] zlib_library_dir = os.path.dirname(path) From 7ba51cc1855e85ec6c4cd65b2b1be1dcd5875e69 Mon Sep 17 00:00:00 2001 From: Nikita Kniazev Date: Tue, 21 Feb 2017 13:46:03 +0300 Subject: [PATCH 07/11] Fix library search pattern in error message --- setup.py | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/setup.py b/setup.py index c14059c..e9b2069 100644 --- a/setup.py +++ b/setup.py @@ -108,6 +108,7 @@ def find_include_dirs(root, fname): zlib_name = 'zlib' else: zlib_name = 'libz' + zlib_lib_pattern = '%s*%s' % (zlib_name, ext) import tempfile from distutils.ccompiler import CompileError, LinkError @@ -116,7 +117,7 @@ def find_include_dirs(root, fname): with open(src_path, 'w') as f: f.write("#include \nint main() { inflate(0, 0); return 0; }") try: - for i, path in enumerate(rglob(zlib_root, '*%s*%s' % (zlib_name, ext))): + for i, path in enumerate(rglob(zlib_root, '*' + zlib_lib_pattern)): tmp_dir_i = os.path.join(tmp_dir, str(i)) zlib_library = os.path.splitext(os.path.basename(path))[0] zlib_library_dir = os.path.dirname(path) @@ -135,8 +136,9 @@ def find_include_dirs(root, fname): shutil.rmtree(tmp_dir, ignore_errors=True) if not zlib_libraries: - raise ValueError("Failed to find a suitable library (zlib*%s) under " - "ZLIB_ROOT folder. Have you compiled zlib?" % ext) + raise ValueError("Failed to find a suitable library (%s) under " + "ZLIB_ROOT folder. Have you compiled zlib?" + % zlib_lib_pattern) # Priority to static library (Windows) for zlib_library, zlib_library_dir in zlib_libraries: From 28afd83f5eaaf4987847669c7a2230dca57127bc Mon Sep 17 00:00:00 2001 From: Nikita Kniazev Date: Thu, 23 Feb 2017 16:22:25 +0300 Subject: [PATCH 08/11] Removed zlib depency --- atari_py/ale_c_wrapper.h | 4 +- atari_py/ale_interface/src/ale_interface.cpp | 25 +- atari_py/ale_interface/src/ale_interface.hpp | 9 +- .../src/common/ScreenExporter.cpp | 200 --- .../src/common/ScreenExporter.hpp | 58 - .../src/controllers/ale_controller.cpp | 2 +- .../ale_interface/src/emucore/OSystem.cxx | 75 +- .../ale_interface/src/emucore/OSystem.hxx | 22 +- .../ale_interface/src/emucore/Settings.cxx | 2 +- atari_py/ale_interface/src/emucore/unzip.c | 1273 ----------------- atari_py/ale_interface/src/emucore/unzip.h | 275 ---- .../src/environment/stella_environment.cpp | 4 +- .../src/environment/stella_environment.hpp | 4 +- atari_py/ale_interface/src/games/Roms.cpp | 11 +- atari_py/ale_interface/src/games/Roms.hpp | 2 +- atari_py/ale_python_interface.py | 18 +- setup.py | 88 +- 17 files changed, 86 insertions(+), 1986 deletions(-) delete mode 100644 atari_py/ale_interface/src/common/ScreenExporter.cpp delete mode 100644 atari_py/ale_interface/src/common/ScreenExporter.hpp delete mode 100644 atari_py/ale_interface/src/emucore/unzip.c delete mode 100644 atari_py/ale_interface/src/emucore/unzip.h diff --git a/atari_py/ale_c_wrapper.h b/atari_py/ale_c_wrapper.h index bda8d1c..8ba04b5 100644 --- a/atari_py/ale_c_wrapper.h +++ b/atari_py/ale_c_wrapper.h @@ -23,7 +23,7 @@ extern "C" { SYMBOL_EXPORT void setInt(ALEInterface *ale,const char *key,int value){ale->setInt(key,value);} SYMBOL_EXPORT void setBool(ALEInterface *ale,const char *key,bool value){ale->setBool(key,value);} SYMBOL_EXPORT void setFloat(ALEInterface *ale,const char *key,float value){ale->setFloat(key,value);} - SYMBOL_EXPORT void loadROM(ALEInterface *ale,const char *rom_file){ale->loadROM(rom_file);} + SYMBOL_EXPORT bool loadROM(ALEInterface *ale,const char *rom,size_t size,const char *name){return ale->loadROM(std::string(rom, size), name);} SYMBOL_EXPORT int act(ALEInterface *ale,int action){return ale->act((Action)action);} SYMBOL_EXPORT bool game_over(ALEInterface *ale){return ale->game_over();} SYMBOL_EXPORT void reset_game(ALEInterface *ale){ale->reset_game();} @@ -99,7 +99,7 @@ extern "C" { SYMBOL_EXPORT ALEState* cloneSystemState(ALEInterface *ale){return new ALEState(ale->cloneSystemState());} SYMBOL_EXPORT void restoreSystemState(ALEInterface *ale, ALEState* state){ale->restoreSystemState(*state);} SYMBOL_EXPORT void deleteState(ALEState* state){delete state;} - SYMBOL_EXPORT void saveScreenPNG(ALEInterface *ale,const char *filename){ale->saveScreenPNG(filename);} + //Kojoley SYMBOL_EXPORT void saveScreenPNG(ALEInterface *ale,const char *filename){ale->saveScreenPNG(filename);} // Encodes the state as a raw bytestream. This may have multiple '\0' characters // and thus should not be treated as a C string. Use encodeStateLen to find the length diff --git a/atari_py/ale_interface/src/ale_interface.cpp b/atari_py/ale_interface/src/ale_interface.cpp index 7fbff9d..a9f3c0d 100644 --- a/atari_py/ale_interface/src/ale_interface.cpp +++ b/atari_py/ale_interface/src/ale_interface.cpp @@ -65,7 +65,7 @@ void ALEInterface::createOSystem(std::auto_ptr &theOSystem, theOSystem->settings().loadConfig(); } -void ALEInterface::loadSettings(const string& romfile, +void ALEInterface::loadSettings(const string& rom, const string& name, std::auto_ptr &theOSystem) { // Load the configuration from a config file (passed on the command // line), if provided @@ -78,13 +78,13 @@ void ALEInterface::loadSettings(const string& romfile, theOSystem->create(); // Attempt to load the ROM - if (romfile == "" || !FilesystemNode::fileExists(romfile)) { - Logger::Error << "No ROM File specified or the ROM file was not found." + if (rom.empty()) { + Logger::Error << "Empty ROM File specified" << std::endl; exit(1); - } else if (theOSystem->createConsole(romfile)) { - Logger::Info << "Running ROM file..." << std::endl; - theOSystem->settings().setString("rom_file", romfile); + } else if (theOSystem->createConsole(rom, name)) { + Logger::Info << "Running ROM " << name << "..." << std::endl; + theOSystem->settings().setString("rom_name", name); } else { exit(1); } @@ -117,13 +117,11 @@ ALEInterface::~ALEInterface() {} // ready to play. Resets the OSystem/Console/Environment/etc. This is // necessary after changing a setting. Optionally specify a new rom to // load. -void ALEInterface::loadROM(string rom_file = "") { +bool ALEInterface::loadROM(string rom_file, string name) { assert(theOSystem.get()); - if (rom_file.empty()) { - rom_file = theOSystem->romFile(); - } - loadSettings(rom_file, theOSystem); - romSettings.reset(buildRomRLWrapper(rom_file)); + loadSettings(rom_file, name, theOSystem); + romSettings.reset(buildRomRLWrapper(name)); + if (romSettings.get() == NULL) return false; environment.reset(new StellaEnvironment(theOSystem.get(), romSettings.get())); max_num_frames = theOSystem->settings().getInt("max_num_frames_per_episode"); environment->reset(); @@ -135,6 +133,7 @@ void ALEInterface::loadROM(string rom_file = "") { exit(1); } #endif + return true; } // Get the value of a setting. @@ -305,6 +304,7 @@ void ALEInterface::restoreSystemState(const ALEState& state) { return environment->restoreSystemState(state); } +/* Kojoley void ALEInterface::saveScreenPNG(const string& filename) { ScreenExporter exporter(theOSystem->colourPalette()); @@ -314,3 +314,4 @@ void ALEInterface::saveScreenPNG(const string& filename) { ScreenExporter *ALEInterface::createScreenExporter(const std::string &filename) const { return new ScreenExporter(theOSystem->colourPalette(), filename); } +Kojoley */ diff --git a/atari_py/ale_interface/src/ale_interface.hpp b/atari_py/ale_interface/src/ale_interface.hpp index d9954ec..f249df6 100644 --- a/atari_py/ale_interface/src/ale_interface.hpp +++ b/atari_py/ale_interface/src/ale_interface.hpp @@ -42,7 +42,7 @@ #include "games/Roms.hpp" #include "common/display_screen.h" #include "environment/stella_environment.hpp" -#include "common/ScreenExporter.hpp" +//Kojoley #include "common/ScreenExporter.hpp" #include "common/Log.hpp" #include @@ -76,7 +76,7 @@ class ALEInterface { // Resets the Atari and loads a game. After this call the game // should be ready to play. This is necessary after changing a // setting for the setting to take effect. - void loadROM(std::string rom_file); + bool loadROM(std::string rom = "", std::string name = ""); // Applies an action to the game and returns the reward. It is the // user's responsibility to check if the game has ended and reset @@ -145,12 +145,12 @@ class ALEInterface { void restoreSystemState(const ALEState& state); // Save the current screen as a png file - void saveScreenPNG(const std::string& filename); + //Kojoley void saveScreenPNG(const std::string& filename); // Creates a ScreenExporter object which can be used to save a sequence of frames. Ownership // said object is passed to the caller. Frames are saved in the directory 'path', which needs // to exists. - ScreenExporter *createScreenExporter(const std::string &path) const; + //Kojoley ScreenExporter *createScreenExporter(const std::string &path) const; public: std::auto_ptr theOSystem; @@ -166,6 +166,7 @@ class ALEInterface { static void createOSystem(std::auto_ptr &theOSystem, std::auto_ptr &theSettings); static void loadSettings(const std::string& romfile, + const std::string& name, std::auto_ptr &theOSystem); }; diff --git a/atari_py/ale_interface/src/common/ScreenExporter.cpp b/atari_py/ale_interface/src/common/ScreenExporter.cpp deleted file mode 100644 index c2fb30a..0000000 --- a/atari_py/ale_interface/src/common/ScreenExporter.cpp +++ /dev/null @@ -1,200 +0,0 @@ -/* ***************************************************************************** - * A.L.E (Arcade Learning Environment) - * Copyright (c) 2009-2013 by Yavar Naddaf, Joel Veness, Marc G. Bellemare and - * the Reinforcement Learning and Artificial Intelligence Laboratory - * Released under the GNU General Public License; see License.txt for details. - * - * Based on: Stella -- "An Atari 2600 VCS Emulator" - * Copyright (c) 1995-2007 by Bradford W. Mott and the Stella team - * - * ***************************************************************************** - * ScreenExporter.hpp - * - * A class for exporting Atari 2600 frames as PNGs. - * - **************************************************************************** */ - -#include "ScreenExporter.hpp" -#include -#include -#include -#include "Log.hpp" - -// MGB: These methods originally belonged to ExportScreen. Possibly these should be returned to -// their own class, rather than be static methods. They are here to avoid exposing the gritty -// details of PNG generation. -static void writePNGChunk(std::ofstream& out, const char* type, uInt8* data, int size) { - - // Stuff the length/type into the buffer - uInt8 temp[8]; - temp[0] = size >> 24; - temp[1] = size >> 16; - temp[2] = size >> 8; - temp[3] = size; - temp[4] = type[0]; - temp[5] = type[1]; - temp[6] = type[2]; - temp[7] = type[3]; - - // Write the header - out.write((const char*)temp, 8); - - // Append the actual data - uInt32 crc = crc32(0, temp + 4, 4); - if(size > 0) - { - out.write((const char*)data, size); - crc = crc32(crc, data, size); - } - - // Write the CRC - temp[0] = crc >> 24; - temp[1] = crc >> 16; - temp[2] = crc >> 8; - temp[3] = crc; - out.write((const char*)temp, 4); -} - - -static void writePNGHeader(std::ofstream& out, const ALEScreen &screen, bool doubleWidth = true) { - - int width = doubleWidth ? screen.width() * 2: screen.width(); - int height = screen.height(); - // PNG file header - uInt8 header[8] = { 137, 80, 78, 71, 13, 10, 26, 10 }; - out.write((const char*)header, sizeof(header)); - - // PNG IHDR - uInt8 ihdr[13]; - ihdr[0] = (width >> 24) & 0xFF; // width - ihdr[1] = (width >> 16) & 0xFF; - ihdr[2] = (width >> 8) & 0xFF; - ihdr[3] = (width >> 0) & 0xFF; - ihdr[4] = (height >> 24) & 0xFF; // height - ihdr[5] = (height >> 16) & 0xFF; - ihdr[6] = (height >> 8) & 0xFF; - ihdr[7] = (height >> 0) & 0xFF; - ihdr[8] = 8; // 8 bits per sample (24 bits per pixel) - ihdr[9] = 2; // PNG_COLOR_TYPE_RGB - ihdr[10] = 0; // PNG_COMPRESSION_TYPE_DEFAULT - ihdr[11] = 0; // PNG_FILTER_TYPE_DEFAULT - ihdr[12] = 0; // PNG_INTERLACE_NONE - writePNGChunk(out, "IHDR", ihdr, sizeof(ihdr)); -} - - -static void writePNGData(std::ofstream &out, const ALEScreen &screen, const ColourPalette &palette, bool doubleWidth = true) { - - int dataWidth = screen.width(); - int width = doubleWidth ? dataWidth * 2 : dataWidth; - int height = screen.height(); - - // If so desired, double the width - - // Fill the buffer with scanline data - int rowbytes = width * 3; - - std::vector buffer((rowbytes + 1) * height, 0); - uInt8* buf_ptr = &buffer[0]; - - for(int i = 0; i < height; i++) { - *buf_ptr++ = 0; // first byte of row is filter type - for(int j = 0; j < dataWidth; j++) { - int r, g, b; - - palette.getRGB(screen.getArray()[i * dataWidth + j], r, g, b); - // Double the pixel width, if so desired - int jj = doubleWidth ? 2 * j : j; - - buf_ptr[jj * 3 + 0] = r; - buf_ptr[jj * 3 + 1] = g; - buf_ptr[jj * 3 + 2] = b; - - if (doubleWidth) { - - jj = jj + 1; - - buf_ptr[jj * 3 + 0] = r; - buf_ptr[jj * 3 + 1] = g; - buf_ptr[jj * 3 + 2] = b; - } - } - buf_ptr += rowbytes; // add pitch - } - - // Compress the data with zlib - uLongf compmemsize = (uLongf)((height * (width + 1) * 3 + 1) + 12); - std::vector compmem(compmemsize, 0); - - if((compress(&compmem[0], &compmemsize, &buffer[0], height * (width * 3 + 1)) != Z_OK)) { - - // @todo -- throw a proper exception - ale::Logger::Error << "Error: Couldn't compress PNG" << std::endl; - return; - } - - // Write the compressed framebuffer data - writePNGChunk(out, "IDAT", &compmem[0], compmemsize); -} - - -static void writePNGEnd(std::ofstream &out) { - - // Finish up - writePNGChunk(out, "IEND", 0, 0); -} - -ScreenExporter::ScreenExporter(ColourPalette &palette): - m_palette(palette), - m_frame_number(0), - m_frame_field_width(6) { -} - - -ScreenExporter::ScreenExporter(ColourPalette &palette, const std::string &path): - m_palette(palette), - m_frame_number(0), - m_frame_field_width(6), - m_path(path) { -} - - -void ScreenExporter::save(const ALEScreen &screen, const std::string &filename) const { - - // Open file for writing - std::ofstream out(filename.c_str(), std::ios_base::binary); - if (!out.good()) { - - // @todo exception - ale::Logger::Error << "Could not open " << filename << " for writing" << std::endl; - return; - } - - // Now write the PNG proper - writePNGHeader(out, screen, true); - writePNGData(out, screen, m_palette, true); - writePNGEnd(out); - - out.close(); -} - -void ScreenExporter::saveNext(const ALEScreen &screen) { - - // Must have specified a directory. - assert(m_path.size() > 0); - - // MGB: It would be nice here to automagically create paths, but the only way I know of - // doing this cleanly is via boost, which we don't include. - - // Construct the filename from basepath & current frame number - std::ostringstream oss; - oss << m_path << "/" << - std::setw(m_frame_field_width) << std::setfill('0') << m_frame_number << ".png"; - - // Save the png - save(screen, oss.str()); - - m_frame_number++; -} - - diff --git a/atari_py/ale_interface/src/common/ScreenExporter.hpp b/atari_py/ale_interface/src/common/ScreenExporter.hpp deleted file mode 100644 index 91f0d0c..0000000 --- a/atari_py/ale_interface/src/common/ScreenExporter.hpp +++ /dev/null @@ -1,58 +0,0 @@ -/* ***************************************************************************** - * A.L.E (Arcade Learning Environment) - * Copyright (c) 2009-2013 by Yavar Naddaf, Joel Veness, Marc G. Bellemare and - * the Reinforcement Learning and Artificial Intelligence Laboratory - * Released under the GNU General Public License; see License.txt for details. - * - * Based on: Stella -- "An Atari 2600 VCS Emulator" - * Copyright (c) 1995-2007 by Bradford W. Mott and the Stella team - * - * ***************************************************************************** - * ScreenExporter.hpp - * - * A class for exporting Atari 2600 frames as PNGs. - * - **************************************************************************** */ - -#ifndef __SCREEN_EXPORTER_HPP__ -#define __SCREEN_EXPORTER_HPP__ - -#include -#include "display_screen.h" -#include "../environment/ale_screen.hpp" - -class ScreenExporter { - - public: - - /** Creates a new ScreenExporter which can be used to save screens using save(filename). */ - ScreenExporter(ColourPalette &palette); - - /** Creates a new ScreenExporter which will save frames successively in the directory provided. - Frames are sequentially named with 6 digits, starting at 000000. */ - ScreenExporter(ColourPalette &palette, const std::string &path); - - /** Save the given screen to the given filename. No paths are created. */ - void save(const ALEScreen &screen, const std::string &filename) const; - - /** Save the given screen according to our own internal numbering. */ - void saveNext(const ALEScreen &screen); - - private: - - ColourPalette &m_palette; - - /** The next frame number. */ - int m_frame_number; - - /** The width of the frame number when constructing filenames (set to 6). */ - int m_frame_field_width; - - /** The directory where we save successive frames. */ - std::string m_path; -}; - -#endif // __SCREEN_EXPORTER_HPP__ - - - diff --git a/atari_py/ale_interface/src/controllers/ale_controller.cpp b/atari_py/ale_interface/src/controllers/ale_controller.cpp index 17e70db..12ed061 100644 --- a/atari_py/ale_interface/src/controllers/ale_controller.cpp +++ b/atari_py/ale_interface/src/controllers/ale_controller.cpp @@ -24,7 +24,7 @@ ALEController::ALEController(OSystem* osystem): m_osystem(osystem), - m_settings(buildRomRLWrapper(m_osystem->settings().getString("rom_file"))), + m_settings(buildRomRLWrapper(m_osystem->settings().getString("rom_name"))), m_environment(m_osystem, m_settings.get()) { if (m_settings.get() == NULL) { diff --git a/atari_py/ale_interface/src/emucore/OSystem.cxx b/atari_py/ale_interface/src/emucore/OSystem.cxx index 6ef3740..69c770d 100644 --- a/atari_py/ale_interface/src/emucore/OSystem.cxx +++ b/atari_py/ale_interface/src/emucore/OSystem.cxx @@ -20,7 +20,7 @@ #include #include #include -#include +//Kojoley #include #include using namespace std; @@ -57,7 +57,7 @@ OSystem::OSystem() myConsole(NULL), myQuitLoop(false), mySkipEmulation(false), - myRomFile(""), + //Kojoley myRomFile(""), myFeatures(""), p_display_screen(NULL) { @@ -348,7 +348,7 @@ void OSystem::createSound() // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -bool OSystem::createConsole(const string& romfile) +bool OSystem::createConsole(const string& rom, const string& name) { // Do a little error checking; it shouldn't be necessary if(myConsole) deleteConsole(); @@ -356,27 +356,20 @@ bool OSystem::createConsole(const string& romfile) bool retval = false; // If a blank ROM has been given, we reload the current one (assuming one exists) - if(romfile == "") + if(rom.empty()) { - if(myRomFile == "") - { - ale::Logger::Error << "ERROR: Rom file not specified ..." << endl; - return false; - } + ale::Logger::Error << "ERROR: Rom not specified ..." << endl; + return false; } - else - myRomFile = romfile; // Open the cartridge image and read it in - uInt8* image; - int size = -1; string md5; - if(openROM(myRomFile, md5, &image, &size)) + if(openROM(rom, name, md5)) { // Get all required info for creating a valid console Cartridge* cart = (Cartridge*) NULL; Properties props; - if(queryConsoleInfo(image, size, md5, &cart, props)) + if(queryConsoleInfo((const uInt8 *)rom.data(), rom.size(), md5, &cart, props)) { // Create an instance of the 2600 game console myConsole = new Console(this, cart, props); @@ -395,11 +388,9 @@ bool OSystem::createConsole(const string& romfile) if(mySettings->getBool("showinfo")) cerr << "Game console created:" << endl - << " ROM file: " << myRomFile << endl << myConsole->about() << endl; else ale::Logger::Info << "Game console created:" << endl - << " ROM file: " << myRomFile << endl << myConsole->about() << endl; // Update the timing info for a new console run @@ -410,20 +401,16 @@ bool OSystem::createConsole(const string& romfile) } else { - ale::Logger::Error << "ERROR: Couldn't create console for " << myRomFile << " ..." << endl; + ale::Logger::Error << "ERROR: Couldn't create console for rom ..." << endl; retval = false; } } else { - ale::Logger::Error << "ERROR: Couldn't open " << myRomFile << " ..." << endl; + ale::Logger::Error << "ERROR: Couldn't open rom ..." << endl; retval = false; } - // Free the image since we don't need it any longer - if(size != -1) { - delete[] image; - } if (mySettings->getBool("display_screen", true)) { #ifndef __USE_SDL ale::Logger::Error << "Screen display requires directive __USE_SDL to be defined." @@ -483,8 +470,9 @@ void OSystem::createLauncher() ALE */ // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -bool OSystem::openROM(const string& rom, string& md5, uInt8** image, int* size) +bool OSystem::openROM(const string& rom, const string& name, string& md5) { + /* Kojoley // Assume the file is either gzip'ed or not compressed at all gzFile f = gzopen(rom.c_str(), "rb"); if(!f) @@ -493,25 +481,21 @@ bool OSystem::openROM(const string& rom, string& md5, uInt8** image, int* size) *image = new uInt8[MAX_ROM_SIZE]; *size = gzread(f, *image, MAX_ROM_SIZE); gzclose(f); + Kojoley */ // If we get to this point, we know we have a valid file to open // Now we make sure that the file has a valid properties entry - md5 = MD5(*image, *size); + md5 = MD5((const uInt8 *)rom.data(), rom.size()); - // Some games may not have a name, since there may not - // be an entry in stella.pro. In that case, we use the rom name - // and reinsert the properties object - Properties props; - myPropSet->getMD5(md5, props); - - string name = props.get(Cartridge_Name); - if(name == "Untitled") - { - // Get the filename from the rom pathname - string::size_type pos = rom.find_last_of(BSPF_PATH_SEPARATOR); - if(pos+1 != string::npos) + if (!name.empty()) { + // Some games may not have a name, since there may not + // be an entry in stella.pro. In that case, we use the rom name + // and reinsert the properties object + Properties props; + myPropSet->getMD5(md5, props); + + if(props.get(Cartridge_Name) == "Untitled") { - name = rom.substr(pos+1); props.set(Cartridge_MD5, md5); props.set(Cartridge_Name, name); myPropSet->insert(props, false); @@ -522,35 +506,30 @@ bool OSystem::openROM(const string& rom, string& md5, uInt8** image, int* size) } // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -string OSystem::getROMInfo(const string& romfile) +string OSystem::getROMInfo(const string& rom, const string& name) { ostringstream buf; // Open the cartridge image and read it in - uInt8* image; - int size = -1; string md5; - if(openROM(romfile, md5, &image, &size)) + if(openROM(rom, name, md5)) { // Get all required info for creating a temporary console Cartridge* cart = (Cartridge*) NULL; Properties props; - if(queryConsoleInfo(image, size, md5, &cart, props)) + if(queryConsoleInfo((const uInt8 *)rom.data(), rom.size(), md5, &cart, props)) { Console* console = new Console(this, cart, props); if(console) buf << console->about(); else - buf << "ERROR: Couldn't get ROM info for " << romfile << " ..." << endl; + buf << "ERROR: Couldn't get ROM info for rom ..." << endl; delete console; } else - buf << "ERROR: Couldn't open " << romfile << " ..." << endl; + buf << "ERROR: Couldn't open rom ..." << endl; } - // Free the image and console since we don't need it any longer - if(size != -1) - delete[] image; return buf.str(); } diff --git a/atari_py/ale_interface/src/emucore/OSystem.hxx b/atari_py/ale_interface/src/emucore/OSystem.hxx index 4eca7d6..d5d669f 100644 --- a/atari_py/ale_interface/src/emucore/OSystem.hxx +++ b/atari_py/ale_interface/src/emucore/OSystem.hxx @@ -39,7 +39,7 @@ class VideoDialog; #include "m6502/src/bspf/src/bspf.hxx" #include "../common/display_screen.h" #include "../common/ColourPalette.hpp" -#include "../common/ScreenExporter.hpp" +//Kojoley #include "../common/ScreenExporter.hpp" #include "../common/Log.hpp" struct Resolution { @@ -282,7 +282,7 @@ class OSystem @return String representing the full path of the ROM file. */ - const std::string& romFile() const { return myRomFile; } + //Kojoley const std::string& romFile() const { return myRomFile; } /** Switches between software and OpenGL framebuffer modes. @@ -293,9 +293,11 @@ class OSystem Creates a new game console from the specified romfile. @param romfile The full pathname of the ROM to use + @param name The ROM name @return True on successful creation, otherwise false */ - bool createConsole(const std::string& romfile = ""); + bool createConsole(const std::string& romfile = "", + const std::string& name = ""); /** Deletes the currently defined console, if it exists. @@ -313,9 +315,11 @@ class OSystem Console object and querying it. @param romfile The full pathname of the ROM to use + @param name The ROM name @return Some information about this ROM */ - std::string getROMInfo(const std::string& romfile); + std::string getROMInfo(const std::string& romfile, + const std::string& name = ""); /** The features which are conditionally compiled into Stella. @@ -328,13 +332,13 @@ class OSystem Open the given ROM and return an array containing its contents. @param rom The absolute pathname of the ROM file + @param name The ROM name @param md5 The md5 calculated from the ROM file - @param image A pointer to store the ROM data - Note, the calling method is responsible for deleting this - @param size The amount of data read into the image array @return False on any errors, else true */ - bool openROM(const std::string& rom, std::string& md5, uInt8** image, int* size); + bool openROM(const std::string& rom, + const std::string& name, + std::string& md5); /** Issue a quit event to the OSystem. @@ -503,7 +507,7 @@ class OSystem std::string myPropertiesFile; std::string myGameListCacheFile; - std::string myRomFile; + //Kojoley std::string myRomFile; std::string myFeatures; diff --git a/atari_py/ale_interface/src/emucore/Settings.cxx b/atari_py/ale_interface/src/emucore/Settings.cxx index fe1224c..b5c14e8 100644 --- a/atari_py/ale_interface/src/emucore/Settings.cxx +++ b/atari_py/ale_interface/src/emucore/Settings.cxx @@ -708,7 +708,7 @@ void Settings::setDefaultSettings() { boolSettings.insert(pair("send_rgb", false)); intSettings.insert(pair("frame_skip", 1)); floatSettings.insert(pair("repeat_action_probability", 0.25)); - stringSettings.insert(pair("rom_file", "")); + stringSettings.insert(pair("rom_name", "")); // Record settings intSettings.insert(pair("fragsize", 64)); // fragsize to 64 ensures proper sound sync diff --git a/atari_py/ale_interface/src/emucore/unzip.c b/atari_py/ale_interface/src/emucore/unzip.c deleted file mode 100644 index 7e4344e..0000000 --- a/atari_py/ale_interface/src/emucore/unzip.c +++ /dev/null @@ -1,1273 +0,0 @@ -/* unzip.c -- IO on .zip files using zlib - Version 0.15 beta, Mar 19th, 1998, - - Read unzip.h for more info -*/ - - -#include -#include -#include -#include - -#include "unzip.h" - -#ifdef STDC -# include -# include -# include -#endif -#ifdef NO_ERRNO_H - extern int errno; -#else -# include -#endif - -#ifndef local -# define local static -#endif -/* compile with -Dlocal if your debugger can't find static symbols */ - - - -#if !defined(unix) && !defined(CASESENSITIVITYDEFAULT_YES) && \ - !defined(CASESENSITIVITYDEFAULT_NO) -#define CASESENSITIVITYDEFAULT_NO -#endif - - -#ifndef UNZ_BUFSIZE -#define UNZ_BUFSIZE (16384) -#endif - -#ifndef UNZ_MAXFILENAMEINZIP -#define UNZ_MAXFILENAMEINZIP (256) -#endif - -#ifndef ALLOC -# define ALLOC(size) (malloc(size)) -#endif -#ifndef TRYFREE -# define TRYFREE(p) {if (p) free(p);} -#endif - -#define SIZECENTRALDIRITEM (0x2e) -#define SIZEZIPLOCALHEADER (0x1e) - - -/* I've found an old Unix (a SunOS 4.1.3_U1) without all SEEK_* defined.... */ - -#ifndef SEEK_CUR -#define SEEK_CUR 1 -#endif - -#ifndef SEEK_END -#define SEEK_END 2 -#endif - -#ifndef SEEK_SET -#define SEEK_SET 0 -#endif - -const char unz_copyright[] = - " unzip 0.15 Copyright 1998 Gilles Vollant "; - -/* unz_file_info_interntal contain internal info about a file in zipfile*/ -typedef struct unz_file_info_internal_s -{ - uLong offset_curfile;/* relative offset of local header 4 bytes */ -} unz_file_info_internal; - - -/* file_in_zip_read_info_s contain internal information about a file in zipfile, - when reading and decompress it */ -typedef struct -{ - char *read_buffer; /* internal buffer for compressed data */ - z_stream stream; /* zLib stream structure for inflate */ - - uLong pos_in_zipfile; /* position in byte on the zipfile, for fseek*/ - uLong stream_initialised; /* flag set if stream structure is initialised*/ - - uLong offset_local_extrafield;/* offset of the local extra field */ - uInt size_local_extrafield;/* size of the local extra field */ - uLong pos_local_extrafield; /* position in the local extra field in read*/ - - uLong crc32; /* crc32 of all data uncompressed */ - uLong crc32_wait; /* crc32 we must obtain after decompress all */ - uLong rest_read_compressed; /* number of byte to be decompressed */ - uLong rest_read_uncompressed;/*number of byte to be obtained after decomp*/ - FILE* file; /* io structore of the zipfile */ - uLong compression_method; /* compression method (0==store) */ - uLong byte_before_the_zipfile;/* byte before the zipfile, (>0 for sfx)*/ -} file_in_zip_read_info_s; - - -/* unz_s contain internal information about the zipfile -*/ -typedef struct -{ - FILE* file; /* io structore of the zipfile */ - unz_global_info gi; /* public global information */ - uLong byte_before_the_zipfile;/* byte before the zipfile, (>0 for sfx)*/ - uLong num_file; /* number of the current file in the zipfile*/ - uLong pos_in_central_dir; /* pos of the current file in the central dir*/ - uLong current_file_ok; /* flag about the usability of the current file*/ - uLong central_pos; /* position of the beginning of the central dir*/ - - uLong size_central_dir; /* size of the central directory */ - uLong offset_central_dir; /* offset of start of central directory with - respect to the starting disk number */ - - unz_file_info cur_file_info; /* public info about the current file in zip*/ - unz_file_info_internal cur_file_info_internal; /* private info about it*/ - file_in_zip_read_info_s* pfile_in_zip_read; /* structure about the current - file if we are decompressing it */ -} unz_s; - - -/* =========================================================================== - Read a byte from a gz_stream; update next_in and avail_in. Return EOF - for end of file. - IN assertion: the stream s has been sucessfully opened for reading. -*/ - - -local int unzlocal_getByte(FILE* fin, int* pi) -{ - unsigned char c; - int err = fread(&c, 1, 1, fin); - if (err==1) - { - *pi = (int)c; - return UNZ_OK; - } - else - { - if (ferror(fin)) - return UNZ_ERRNO; - else - return UNZ_EOF; - } -} - - -/* =========================================================================== - Reads a long in LSB order from the given gz_stream. Sets -*/ -local int unzlocal_getShort (FILE* fin,uLong* pX) -{ - uLong x ; - int i = 0; - int err; - - err = unzlocal_getByte(fin,&i); - x = (uLong)i; - - if (err==UNZ_OK) - err = unzlocal_getByte(fin,&i); - x += ((uLong)i)<<8; - - if (err==UNZ_OK) - *pX = x; - else - *pX = 0; - return err; -} - -local int unzlocal_getLong (FILE* fin,uLong* pX) -{ - uLong x ; - int i = 0; - int err; - - err = unzlocal_getByte(fin,&i); - x = (uLong)i; - - if (err==UNZ_OK) - err = unzlocal_getByte(fin,&i); - x += ((uLong)i)<<8; - - if (err==UNZ_OK) - err = unzlocal_getByte(fin,&i); - x += ((uLong)i)<<16; - - if (err==UNZ_OK) - err = unzlocal_getByte(fin,&i); - x += ((uLong)i)<<24; - - if (err==UNZ_OK) - *pX = x; - else - *pX = 0; - return err; -} - - -/* My own strcmpi / strcasecmp */ -local int strcmpcasenosensitive_internal (const char* fileName1, const char* fileName2) -{ - for (;;) - { - char c1=*(fileName1++); - char c2=*(fileName2++); - if ((c1>='a') && (c1<='z')) - c1 -= 0x20; - if ((c2>='a') && (c2<='z')) - c2 -= 0x20; - if (c1=='\0') - return ((c2=='\0') ? 0 : -1); - if (c2=='\0') - return 1; - if (c1c2) - return 1; - } -} - - -#ifdef CASESENSITIVITYDEFAULT_NO -#define CASESENSITIVITYDEFAULTVALUE 2 -#else -#define CASESENSITIVITYDEFAULTVALUE 1 -#endif - -#ifndef STRCMPCASENOSENTIVEFUNCTION -#define STRCMPCASENOSENTIVEFUNCTION strcmpcasenosensitive_internal -#endif - -/* - Compare two filename (fileName1,fileName2). - If iCaseSenisivity = 1, comparision is case sensitivity (like strcmp) - If iCaseSenisivity = 2, comparision is not case sensitivity (like strcmpi - or strcasecmp) - If iCaseSenisivity = 0, case sensitivity is defaut of your operating system - (like 1 on Unix, 2 on Windows) - -*/ -extern int ZEXPORT unzStringFileNameCompare - (const char* fileName1, const char* fileName2, int iCaseSensitivity) -{ - if (iCaseSensitivity==0) - iCaseSensitivity=CASESENSITIVITYDEFAULTVALUE; - - if (iCaseSensitivity==1) - return strcmp(fileName1,fileName2); - - return STRCMPCASENOSENTIVEFUNCTION(fileName1,fileName2); -} - -#define BUFREADCOMMENT (0x400) - -/* - Locate the Central directory of a zipfile (at the end, just before - the global comment) -*/ -local uLong unzlocal_SearchCentralDir(FILE* fin) -{ - unsigned char* buf; - uLong uSizeFile; - uLong uBackRead; - uLong uMaxBack=0xffff; /* maximum size of global comment */ - uLong uPosFound=0; - - if (fseek(fin,0,SEEK_END) != 0) - return 0; - - - uSizeFile = ftell( fin ); - - if (uMaxBack>uSizeFile) - uMaxBack = uSizeFile; - - buf = (unsigned char*)ALLOC(BUFREADCOMMENT+4); - if (buf==NULL) - return 0; - - uBackRead = 4; - while (uBackReaduMaxBack) - uBackRead = uMaxBack; - else - uBackRead+=BUFREADCOMMENT; - uReadPos = uSizeFile-uBackRead ; - - uReadSize = ((BUFREADCOMMENT+4) < (uSizeFile-uReadPos)) ? - (BUFREADCOMMENT+4) : (uSizeFile-uReadPos); - if (fseek(fin,uReadPos,SEEK_SET)!=0) - break; - - if (fread(buf,(uInt)uReadSize,1,fin)!=1) - break; - - for (i=(int)uReadSize-3; (i--)>0;) - if (((*(buf+i))==0x50) && ((*(buf+i+1))==0x4b) && - ((*(buf+i+2))==0x05) && ((*(buf+i+3))==0x06)) - { - uPosFound = uReadPos+i; - break; - } - - if (uPosFound!=0) - break; - } - TRYFREE(buf); - return uPosFound; -} - -/* - Open a Zip file. path contain the full pathname (by example, - on a Windows NT computer "c:\\test\\zlib109.zip" or on an Unix computer - "zlib/zlib109.zip". - If the zipfile cannot be opened (file don't exist or in not valid), the - return value is NULL. - Else, the return value is a unzFile Handle, usable with other function - of this unzip package. -*/ -extern unzFile ZEXPORT unzOpen(const char *path) -{ - unz_s us; - unz_s *s; - uLong central_pos,uL; - FILE * fin ; - - uLong number_disk; /* number of the current dist, used for - spaning ZIP, unsupported, always 0*/ - uLong number_disk_with_CD; /* number the the disk with central dir, used - for spaning ZIP, unsupported, always 0*/ - uLong number_entry_CD; /* total number of entries in - the central dir - (same than number_entry on nospan) */ - - int err=UNZ_OK; - - if (unz_copyright[0]!=' ') - return NULL; - - fin=fopen(path,"rb"); - if (fin==NULL) - return NULL; - - central_pos = unzlocal_SearchCentralDir(fin); - if (central_pos==0) - err=UNZ_ERRNO; - - if (fseek(fin,central_pos,SEEK_SET)!=0) - err=UNZ_ERRNO; - - /* the signature, already checked */ - if (unzlocal_getLong(fin,&uL)!=UNZ_OK) - err=UNZ_ERRNO; - - /* number of this disk */ - if (unzlocal_getShort(fin,&number_disk)!=UNZ_OK) - err=UNZ_ERRNO; - - /* number of the disk with the start of the central directory */ - if (unzlocal_getShort(fin,&number_disk_with_CD)!=UNZ_OK) - err=UNZ_ERRNO; - - /* total number of entries in the central dir on this disk */ - if (unzlocal_getShort(fin,&us.gi.number_entry)!=UNZ_OK) - err=UNZ_ERRNO; - - /* total number of entries in the central dir */ - if (unzlocal_getShort(fin,&number_entry_CD)!=UNZ_OK) - err=UNZ_ERRNO; - - if ((number_entry_CD!=us.gi.number_entry) || - (number_disk_with_CD!=0) || - (number_disk!=0)) - err=UNZ_BADZIPFILE; - - /* size of the central directory */ - if (unzlocal_getLong(fin,&us.size_central_dir)!=UNZ_OK) - err=UNZ_ERRNO; - - /* offset of start of central directory with respect to the - starting disk number */ - if (unzlocal_getLong(fin,&us.offset_central_dir)!=UNZ_OK) - err=UNZ_ERRNO; - - /* zipfile comment length */ - if (unzlocal_getShort(fin,&us.gi.size_comment)!=UNZ_OK) - err=UNZ_ERRNO; - - if ((central_pospfile_in_zip_read!=NULL) - unzCloseCurrentFile(file); - - fclose(s->file); - TRYFREE(s); - return UNZ_OK; -} - - -/* - Write info about the ZipFile in the *pglobal_info structure. - No preparation of the structure is needed - return UNZ_OK if there is no problem. */ -extern int ZEXPORT unzGetGlobalInfo (unzFile file, unz_global_info* pglobal_info) -{ - unz_s* s; - if (file==NULL) - return UNZ_PARAMERROR; - s=(unz_s*)file; - *pglobal_info=s->gi; - return UNZ_OK; -} - - -/* - Translate date/time from Dos format to tm_unz (readable more easilty) -*/ -local void unzlocal_DosDateToTmuDate (uLong ulDosDate, tm_unz* ptm) -{ - uLong uDate; - uDate = (uLong)(ulDosDate>>16); - ptm->tm_mday = (uInt)(uDate&0x1f) ; - ptm->tm_mon = (uInt)((((uDate)&0x1E0)/0x20)-1) ; - ptm->tm_year = (uInt)(((uDate&0x0FE00)/0x0200)+1980) ; - - ptm->tm_hour = (uInt) ((ulDosDate &0xF800)/0x800); - ptm->tm_min = (uInt) ((ulDosDate&0x7E0)/0x20) ; - ptm->tm_sec = (uInt) (2*(ulDosDate&0x1f)) ; -} - -/* - Get Info about the current file in the zipfile, with internal only info -*/ -local int unzlocal_GetCurrentFileInfoInternal OF((unzFile file, - unz_file_info *pfile_info, - unz_file_info_internal - *pfile_info_internal, - char *szFileName, - uLong fileNameBufferSize, - void *extraField, - uLong extraFieldBufferSize, - char *szComment, - uLong commentBufferSize)); - -local int unzlocal_GetCurrentFileInfoInternal - ( unzFile file, - unz_file_info *pfile_info, - unz_file_info_internal *pfile_info_internal, - char *szFileName, - uLong fileNameBufferSize, - void *extraField, - uLong extraFieldBufferSize, - char *szComment, - uLong commentBufferSize) -{ - unz_s* s; - unz_file_info file_info; - unz_file_info_internal file_info_internal; - int err=UNZ_OK; - uLong uMagic; - long lSeek=0; - - if (file==NULL) - return UNZ_PARAMERROR; - s=(unz_s*)file; - if (fseek(s->file,s->pos_in_central_dir+s->byte_before_the_zipfile,SEEK_SET)!=0) - err=UNZ_ERRNO; - - - /* we check the magic */ - if (err==UNZ_OK) - { - if (unzlocal_getLong(s->file,&uMagic) != UNZ_OK) - err=UNZ_ERRNO; - else if (uMagic!=0x02014b50) - err=UNZ_BADZIPFILE; - } - - if (unzlocal_getShort(s->file,&file_info.version) != UNZ_OK) - err=UNZ_ERRNO; - - if (unzlocal_getShort(s->file,&file_info.version_needed) != UNZ_OK) - err=UNZ_ERRNO; - - if (unzlocal_getShort(s->file,&file_info.flag) != UNZ_OK) - err=UNZ_ERRNO; - - if (unzlocal_getShort(s->file,&file_info.compression_method) != UNZ_OK) - err=UNZ_ERRNO; - - if (unzlocal_getLong(s->file,&file_info.dosDate) != UNZ_OK) - err=UNZ_ERRNO; - - unzlocal_DosDateToTmuDate(file_info.dosDate,&file_info.tmu_date); - - if (unzlocal_getLong(s->file,&file_info.crc) != UNZ_OK) - err=UNZ_ERRNO; - - if (unzlocal_getLong(s->file,&file_info.compressed_size) != UNZ_OK) - err=UNZ_ERRNO; - - if (unzlocal_getLong(s->file,&file_info.uncompressed_size) != UNZ_OK) - err=UNZ_ERRNO; - - if (unzlocal_getShort(s->file,&file_info.size_filename) != UNZ_OK) - err=UNZ_ERRNO; - - if (unzlocal_getShort(s->file,&file_info.size_file_extra) != UNZ_OK) - err=UNZ_ERRNO; - - if (unzlocal_getShort(s->file,&file_info.size_file_comment) != UNZ_OK) - err=UNZ_ERRNO; - - if (unzlocal_getShort(s->file,&file_info.disk_num_start) != UNZ_OK) - err=UNZ_ERRNO; - - if (unzlocal_getShort(s->file,&file_info.internal_fa) != UNZ_OK) - err=UNZ_ERRNO; - - if (unzlocal_getLong(s->file,&file_info.external_fa) != UNZ_OK) - err=UNZ_ERRNO; - - if (unzlocal_getLong(s->file,&file_info_internal.offset_curfile) != UNZ_OK) - err=UNZ_ERRNO; - - lSeek+=file_info.size_filename; - if ((err==UNZ_OK) && (szFileName!=NULL)) - { - uLong uSizeRead ; - if (file_info.size_filename0) && (fileNameBufferSize>0)) - if (fread(szFileName,(uInt)uSizeRead,1,s->file)!=1) - err=UNZ_ERRNO; - lSeek -= uSizeRead; - } - - - if ((err==UNZ_OK) && (extraField!=NULL)) - { - uLong uSizeRead ; - if (file_info.size_file_extrafile,lSeek,SEEK_CUR)==0) - lSeek=0; - else - err=UNZ_ERRNO; - } - if ((file_info.size_file_extra>0) && (extraFieldBufferSize>0)) - if (fread(extraField,(uInt)uSizeRead,1,s->file)!=1) - err=UNZ_ERRNO; - lSeek += file_info.size_file_extra - uSizeRead; - } - else - lSeek+=file_info.size_file_extra; - - - if ((err==UNZ_OK) && (szComment!=NULL)) - { - uLong uSizeRead ; - if (file_info.size_file_commentfile,lSeek,SEEK_CUR)==0) - lSeek=0; - else - err=UNZ_ERRNO; - } - if ((file_info.size_file_comment>0) && (commentBufferSize>0)) - if (fread(szComment,(uInt)uSizeRead,1,s->file)!=1) - err=UNZ_ERRNO; - lSeek+=file_info.size_file_comment - uSizeRead; - } - else - lSeek+=file_info.size_file_comment; - - if ((err==UNZ_OK) && (pfile_info!=NULL)) - *pfile_info=file_info; - - if ((err==UNZ_OK) && (pfile_info_internal!=NULL)) - *pfile_info_internal=file_info_internal; - - return err; -} - - - -/* - Write info about the ZipFile in the *pglobal_info structure. - No preparation of the structure is needed - return UNZ_OK if there is no problem. -*/ -extern int ZEXPORT unzGetCurrentFileInfo - ( unzFile file, - unz_file_info *pfile_info, - char *szFileName, - uLong fileNameBufferSize, - void *extraField, - uLong extraFieldBufferSize, - char *szComment, - uLong commentBufferSize - ) -{ - return unzlocal_GetCurrentFileInfoInternal(file,pfile_info,NULL, - szFileName,fileNameBufferSize, - extraField,extraFieldBufferSize, - szComment,commentBufferSize); -} - -/* - Set the current file of the zipfile to the first file. - return UNZ_OK if there is no problem -*/ -extern int ZEXPORT unzGoToFirstFile (unzFile file) -{ - int err=UNZ_OK; - unz_s* s; - if (file==NULL) - return UNZ_PARAMERROR; - s=(unz_s*)file; - s->pos_in_central_dir=s->offset_central_dir; - s->num_file=0; - err=unzlocal_GetCurrentFileInfoInternal(file,&s->cur_file_info, - &s->cur_file_info_internal, - NULL,0,NULL,0,NULL,0); - s->current_file_ok = (err == UNZ_OK); - return err; -} - - -/* - Set the current file of the zipfile to the next file. - return UNZ_OK if there is no problem - return UNZ_END_OF_LIST_OF_FILE if the actual file was the latest. -*/ -extern int ZEXPORT unzGoToNextFile (unzFile file) -{ - unz_s* s; - int err; - - if (file==NULL) - return UNZ_PARAMERROR; - s=(unz_s*)file; - if (!s->current_file_ok) - return UNZ_END_OF_LIST_OF_FILE; - if (s->num_file+1==s->gi.number_entry) - return UNZ_END_OF_LIST_OF_FILE; - - s->pos_in_central_dir += SIZECENTRALDIRITEM + s->cur_file_info.size_filename + - s->cur_file_info.size_file_extra + s->cur_file_info.size_file_comment ; - s->num_file++; - err = unzlocal_GetCurrentFileInfoInternal(file,&s->cur_file_info, - &s->cur_file_info_internal, - NULL,0,NULL,0,NULL,0); - s->current_file_ok = (err == UNZ_OK); - return err; -} - - -/* - Try locate the file szFileName in the zipfile. - For the iCaseSensitivity signification, see unzipStringFileNameCompare - - return value : - UNZ_OK if the file is found. It becomes the current file. - UNZ_END_OF_LIST_OF_FILE if the file is not found -*/ -extern int ZEXPORT unzLocateFile - ( unzFile file, - const char *szFileName, - int iCaseSensitivity - ) -{ - unz_s* s; - int err; - - - uLong num_fileSaved; - uLong pos_in_central_dirSaved; - - - if (file==NULL) - return UNZ_PARAMERROR; - - if (strlen(szFileName)>=UNZ_MAXFILENAMEINZIP) - return UNZ_PARAMERROR; - - s=(unz_s*)file; - if (!s->current_file_ok) - return UNZ_END_OF_LIST_OF_FILE; - - num_fileSaved = s->num_file; - pos_in_central_dirSaved = s->pos_in_central_dir; - - err = unzGoToFirstFile(file); - - while (err == UNZ_OK) - { - char szCurrentFileName[UNZ_MAXFILENAMEINZIP+1]; - unzGetCurrentFileInfo(file,NULL, - szCurrentFileName,sizeof(szCurrentFileName)-1, - NULL,0,NULL,0); - if (unzStringFileNameCompare(szCurrentFileName, - szFileName,iCaseSensitivity)==0) - return UNZ_OK; - err = unzGoToNextFile(file); - } - - s->num_file = num_fileSaved ; - s->pos_in_central_dir = pos_in_central_dirSaved ; - return err; -} - - -/* - Read the local header of the current zipfile - Check the coherency of the local header and info in the end of central - directory about this file - store in *piSizeVar the size of extra info in local header - (filename and size of extra field data) -*/ -local int unzlocal_CheckCurrentFileCoherencyHeader - ( unz_s* s, - uInt* piSizeVar, - uLong *poffset_local_extrafield, - uInt *psize_local_extrafield - ) -{ - uLong uMagic,uData,uFlags; - uLong size_filename; - uLong size_extra_field; - int err=UNZ_OK; - - *piSizeVar = 0; - *poffset_local_extrafield = 0; - *psize_local_extrafield = 0; - - if (fseek(s->file,s->cur_file_info_internal.offset_curfile + - s->byte_before_the_zipfile,SEEK_SET)!=0) - return UNZ_ERRNO; - - - if (err==UNZ_OK) - { - if (unzlocal_getLong(s->file,&uMagic) != UNZ_OK) - err=UNZ_ERRNO; - else if (uMagic!=0x04034b50) - err=UNZ_BADZIPFILE; - } - - if (unzlocal_getShort(s->file,&uData) != UNZ_OK) - err=UNZ_ERRNO; -/* - else if ((err==UNZ_OK) && (uData!=s->cur_file_info.wVersion)) - err=UNZ_BADZIPFILE; -*/ - if (unzlocal_getShort(s->file,&uFlags) != UNZ_OK) - err=UNZ_ERRNO; - - if (unzlocal_getShort(s->file,&uData) != UNZ_OK) - err=UNZ_ERRNO; - else if ((err==UNZ_OK) && (uData!=s->cur_file_info.compression_method)) - err=UNZ_BADZIPFILE; - - if ((err==UNZ_OK) && (s->cur_file_info.compression_method!=0) && - (s->cur_file_info.compression_method!=Z_DEFLATED)) - err=UNZ_BADZIPFILE; - - if (unzlocal_getLong(s->file,&uData) != UNZ_OK) /* date/time */ - err=UNZ_ERRNO; - - if (unzlocal_getLong(s->file,&uData) != UNZ_OK) /* crc */ - err=UNZ_ERRNO; - else if ((err==UNZ_OK) && (uData!=s->cur_file_info.crc) && - ((uFlags & 8)==0)) - err=UNZ_BADZIPFILE; - - if (unzlocal_getLong(s->file,&uData) != UNZ_OK) /* size compr */ - err=UNZ_ERRNO; - else if ((err==UNZ_OK) && (uData!=s->cur_file_info.compressed_size) && - ((uFlags & 8)==0)) - err=UNZ_BADZIPFILE; - - if (unzlocal_getLong(s->file,&uData) != UNZ_OK) /* size uncompr */ - err=UNZ_ERRNO; - else if ((err==UNZ_OK) && (uData!=s->cur_file_info.uncompressed_size) && - ((uFlags & 8)==0)) - err=UNZ_BADZIPFILE; - - - if (unzlocal_getShort(s->file,&size_filename) != UNZ_OK) - err=UNZ_ERRNO; - else if ((err==UNZ_OK) && (size_filename!=s->cur_file_info.size_filename)) - err=UNZ_BADZIPFILE; - - *piSizeVar += (uInt)size_filename; - - if (unzlocal_getShort(s->file,&size_extra_field) != UNZ_OK) - err=UNZ_ERRNO; - *poffset_local_extrafield= s->cur_file_info_internal.offset_curfile + - SIZEZIPLOCALHEADER + size_filename; - *psize_local_extrafield = (uInt)size_extra_field; - - *piSizeVar += (uInt)size_extra_field; - - return err; -} - -/* - Open for reading data the current file in the zipfile. - If there is no error and the file is opened, the return value is UNZ_OK. -*/ -extern int ZEXPORT unzOpenCurrentFile (unzFile file) -{ - int err=UNZ_OK; - int Store; - uInt iSizeVar; - unz_s* s; - file_in_zip_read_info_s* pfile_in_zip_read_info; - uLong offset_local_extrafield; /* offset of the local extra field */ - uInt size_local_extrafield; /* size of the local extra field */ - - if (file==NULL) - return UNZ_PARAMERROR; - s=(unz_s*)file; - if (!s->current_file_ok) - return UNZ_PARAMERROR; - - if (s->pfile_in_zip_read != NULL) - unzCloseCurrentFile(file); - - if (unzlocal_CheckCurrentFileCoherencyHeader(s,&iSizeVar, - &offset_local_extrafield,&size_local_extrafield)!=UNZ_OK) - return UNZ_BADZIPFILE; - - pfile_in_zip_read_info = (file_in_zip_read_info_s*) - ALLOC(sizeof(file_in_zip_read_info_s)); - if (pfile_in_zip_read_info==NULL) - return UNZ_INTERNALERROR; - - pfile_in_zip_read_info->read_buffer=(char*)ALLOC(UNZ_BUFSIZE); - pfile_in_zip_read_info->offset_local_extrafield = offset_local_extrafield; - pfile_in_zip_read_info->size_local_extrafield = size_local_extrafield; - pfile_in_zip_read_info->pos_local_extrafield=0; - - if (pfile_in_zip_read_info->read_buffer==NULL) - { - TRYFREE(pfile_in_zip_read_info); - return UNZ_INTERNALERROR; - } - - pfile_in_zip_read_info->stream_initialised=0; - - if ((s->cur_file_info.compression_method!=0) && - (s->cur_file_info.compression_method!=Z_DEFLATED)) - err=UNZ_BADZIPFILE; - Store = s->cur_file_info.compression_method==0; - - pfile_in_zip_read_info->crc32_wait=s->cur_file_info.crc; - pfile_in_zip_read_info->crc32=0; - pfile_in_zip_read_info->compression_method = - s->cur_file_info.compression_method; - pfile_in_zip_read_info->file=s->file; - pfile_in_zip_read_info->byte_before_the_zipfile=s->byte_before_the_zipfile; - - pfile_in_zip_read_info->stream.total_out = 0; - - if (!Store) - { - pfile_in_zip_read_info->stream.zalloc = (alloc_func)0; - pfile_in_zip_read_info->stream.zfree = (free_func)0; - pfile_in_zip_read_info->stream.opaque = (voidpf)0; - - err=inflateInit2(&pfile_in_zip_read_info->stream, -MAX_WBITS); - if (err == Z_OK) - pfile_in_zip_read_info->stream_initialised=1; - /* windowBits is passed < 0 to tell that there is no zlib header. - * Note that in this case inflate *requires* an extra "dummy" byte - * after the compressed stream in order to complete decompression and - * return Z_STREAM_END. - * In unzip, i don't wait absolutely Z_STREAM_END because I known the - * size of both compressed and uncompressed data - */ - } - pfile_in_zip_read_info->rest_read_compressed = - s->cur_file_info.compressed_size ; - pfile_in_zip_read_info->rest_read_uncompressed = - s->cur_file_info.uncompressed_size ; - - - pfile_in_zip_read_info->pos_in_zipfile = - s->cur_file_info_internal.offset_curfile + SIZEZIPLOCALHEADER + - iSizeVar; - - pfile_in_zip_read_info->stream.avail_in = (uInt)0; - - - s->pfile_in_zip_read = pfile_in_zip_read_info; - return UNZ_OK; -} - - -/* - Read bytes from the current file. - buf contain buffer where data must be copied - len the size of buf. - - return the number of byte copied if somes bytes are copied - return 0 if the end of file was reached - return <0 with error code if there is an error - (UNZ_ERRNO for IO error, or zLib error for uncompress error) -*/ -extern int ZEXPORT unzReadCurrentFile - ( unzFile file, - voidp buf, - unsigned len - ) -{ - int err=UNZ_OK; - uInt iRead = 0; - unz_s* s; - file_in_zip_read_info_s* pfile_in_zip_read_info; - if (file==NULL) - return UNZ_PARAMERROR; - s=(unz_s*)file; - pfile_in_zip_read_info=s->pfile_in_zip_read; - - if (pfile_in_zip_read_info==NULL) - return UNZ_PARAMERROR; - - - if (pfile_in_zip_read_info->read_buffer == NULL) - return UNZ_END_OF_LIST_OF_FILE; - if (len==0) - return 0; - - pfile_in_zip_read_info->stream.next_out = (Bytef*)buf; - - pfile_in_zip_read_info->stream.avail_out = (uInt)len; - - if (len>pfile_in_zip_read_info->rest_read_uncompressed) - pfile_in_zip_read_info->stream.avail_out = - (uInt)pfile_in_zip_read_info->rest_read_uncompressed; - - while (pfile_in_zip_read_info->stream.avail_out>0) - { - if ((pfile_in_zip_read_info->stream.avail_in==0) && - (pfile_in_zip_read_info->rest_read_compressed>0)) - { - uInt uReadThis = UNZ_BUFSIZE; - if (pfile_in_zip_read_info->rest_read_compressedrest_read_compressed; - if (uReadThis == 0) - return UNZ_EOF; - if (fseek(pfile_in_zip_read_info->file, - pfile_in_zip_read_info->pos_in_zipfile + - pfile_in_zip_read_info->byte_before_the_zipfile,SEEK_SET)!=0) - return UNZ_ERRNO; - if (fread(pfile_in_zip_read_info->read_buffer,uReadThis,1, - pfile_in_zip_read_info->file)!=1) - return UNZ_ERRNO; - pfile_in_zip_read_info->pos_in_zipfile += uReadThis; - - pfile_in_zip_read_info->rest_read_compressed-=uReadThis; - - pfile_in_zip_read_info->stream.next_in = - (Bytef*)pfile_in_zip_read_info->read_buffer; - pfile_in_zip_read_info->stream.avail_in = (uInt)uReadThis; - } - - if (pfile_in_zip_read_info->compression_method==0) - { - uInt uDoCopy,i ; - if (pfile_in_zip_read_info->stream.avail_out < - pfile_in_zip_read_info->stream.avail_in) - uDoCopy = pfile_in_zip_read_info->stream.avail_out ; - else - uDoCopy = pfile_in_zip_read_info->stream.avail_in ; - - for (i=0;istream.next_out+i) = - *(pfile_in_zip_read_info->stream.next_in+i); - - pfile_in_zip_read_info->crc32 = crc32(pfile_in_zip_read_info->crc32, - pfile_in_zip_read_info->stream.next_out, - uDoCopy); - pfile_in_zip_read_info->rest_read_uncompressed-=uDoCopy; - pfile_in_zip_read_info->stream.avail_in -= uDoCopy; - pfile_in_zip_read_info->stream.avail_out -= uDoCopy; - pfile_in_zip_read_info->stream.next_out += uDoCopy; - pfile_in_zip_read_info->stream.next_in += uDoCopy; - pfile_in_zip_read_info->stream.total_out += uDoCopy; - iRead += uDoCopy; - } - else - { - uLong uTotalOutBefore,uTotalOutAfter; - const Bytef *bufBefore; - uLong uOutThis; - int flush=Z_SYNC_FLUSH; - - uTotalOutBefore = pfile_in_zip_read_info->stream.total_out; - bufBefore = pfile_in_zip_read_info->stream.next_out; - - /* - if ((pfile_in_zip_read_info->rest_read_uncompressed == - pfile_in_zip_read_info->stream.avail_out) && - (pfile_in_zip_read_info->rest_read_compressed == 0)) - flush = Z_FINISH; - */ - err=inflate(&pfile_in_zip_read_info->stream,flush); - - uTotalOutAfter = pfile_in_zip_read_info->stream.total_out; - uOutThis = uTotalOutAfter-uTotalOutBefore; - - pfile_in_zip_read_info->crc32 = - crc32(pfile_in_zip_read_info->crc32,bufBefore, - (uInt)(uOutThis)); - - pfile_in_zip_read_info->rest_read_uncompressed -= - uOutThis; - - iRead += (uInt)(uTotalOutAfter - uTotalOutBefore); - - if (err==Z_STREAM_END) - return (iRead==0) ? UNZ_EOF : iRead; - if (err!=Z_OK) - break; - } - } - - if (err==Z_OK) - return iRead; - return err; -} - - -/* - Give the current position in uncompressed data -*/ -extern z_off_t ZEXPORT unztell (unzFile file) -{ - unz_s* s; - file_in_zip_read_info_s* pfile_in_zip_read_info; - if (file==NULL) - return UNZ_PARAMERROR; - s=(unz_s*)file; - pfile_in_zip_read_info=s->pfile_in_zip_read; - - if (pfile_in_zip_read_info==NULL) - return UNZ_PARAMERROR; - - return (z_off_t)pfile_in_zip_read_info->stream.total_out; -} - - -/* - return 1 if the end of file was reached, 0 elsewhere -*/ -extern int ZEXPORT unzeof (unzFile file) -{ - unz_s* s; - file_in_zip_read_info_s* pfile_in_zip_read_info; - if (file==NULL) - return UNZ_PARAMERROR; - s=(unz_s*)file; - pfile_in_zip_read_info=s->pfile_in_zip_read; - - if (pfile_in_zip_read_info==NULL) - return UNZ_PARAMERROR; - - if (pfile_in_zip_read_info->rest_read_uncompressed == 0) - return 1; - else - return 0; -} - - - -/* - Read extra field from the current file (opened by unzOpenCurrentFile) - This is the local-header version of the extra field (sometimes, there is - more info in the local-header version than in the central-header) - - if buf==NULL, it return the size of the local extra field that can be read - - if buf!=NULL, len is the size of the buffer, the extra header is copied in - buf. - the return value is the number of bytes copied in buf, or (if <0) - the error code -*/ -extern int ZEXPORT unzGetLocalExtrafield - ( unzFile file, - voidp buf, - unsigned len - ) -{ - unz_s* s; - file_in_zip_read_info_s* pfile_in_zip_read_info; - uInt read_now; - uLong size_to_read; - - if (file==NULL) - return UNZ_PARAMERROR; - s=(unz_s*)file; - pfile_in_zip_read_info=s->pfile_in_zip_read; - - if (pfile_in_zip_read_info==NULL) - return UNZ_PARAMERROR; - - size_to_read = (pfile_in_zip_read_info->size_local_extrafield - - pfile_in_zip_read_info->pos_local_extrafield); - - if (buf==NULL) - return (int)size_to_read; - - if (len>size_to_read) - read_now = (uInt)size_to_read; - else - read_now = (uInt)len ; - - if (read_now==0) - return 0; - - if (fseek(pfile_in_zip_read_info->file, - pfile_in_zip_read_info->offset_local_extrafield + - pfile_in_zip_read_info->pos_local_extrafield,SEEK_SET)!=0) - return UNZ_ERRNO; - - if (fread(buf,(uInt)size_to_read,1,pfile_in_zip_read_info->file)!=1) - return UNZ_ERRNO; - - return (int)read_now; -} - -/* - Close the file in zip opened with unzipOpenCurrentFile - Return UNZ_CRCERROR if all the file was read but the CRC is not good -*/ -extern int ZEXPORT unzCloseCurrentFile (unzFile file) -{ - int err=UNZ_OK; - - unz_s* s; - file_in_zip_read_info_s* pfile_in_zip_read_info; - if (file==NULL) - return UNZ_PARAMERROR; - s=(unz_s*)file; - pfile_in_zip_read_info=s->pfile_in_zip_read; - - if (pfile_in_zip_read_info==NULL) - return UNZ_PARAMERROR; - - - if (pfile_in_zip_read_info->rest_read_uncompressed == 0) - { - if (pfile_in_zip_read_info->crc32 != pfile_in_zip_read_info->crc32_wait) - err=UNZ_CRCERROR; - } - - - TRYFREE(pfile_in_zip_read_info->read_buffer); - pfile_in_zip_read_info->read_buffer = NULL; - if (pfile_in_zip_read_info->stream_initialised) - inflateEnd(&pfile_in_zip_read_info->stream); - - pfile_in_zip_read_info->stream_initialised = 0; - TRYFREE(pfile_in_zip_read_info); - - s->pfile_in_zip_read=NULL; - - return err; -} - - -/* - Get the global comment string of the ZipFile, in the szComment buffer. - uSizeBuf is the size of the szComment buffer. - return the number of byte copied or an error code <0 -*/ -extern int ZEXPORT unzGetGlobalComment - ( unzFile file, - char *szComment, - uLong uSizeBuf - ) -{ - unz_s* s; - uLong uReadThis ; - if (file==NULL) - return UNZ_PARAMERROR; - s=(unz_s*)file; - - uReadThis = uSizeBuf; - if (uReadThis>s->gi.size_comment) - uReadThis = s->gi.size_comment; - - if (fseek(s->file,s->central_pos+22,SEEK_SET)!=0) - return UNZ_ERRNO; - - if (uReadThis>0) - { - *szComment='\0'; - if (fread(szComment,(uInt)uReadThis,1,s->file)!=1) - return UNZ_ERRNO; - } - - if ((szComment != NULL) && (uSizeBuf > s->gi.size_comment)) - *(szComment+s->gi.size_comment)='\0'; - return (int)uReadThis; -} diff --git a/atari_py/ale_interface/src/emucore/unzip.h b/atari_py/ale_interface/src/emucore/unzip.h deleted file mode 100644 index 2c8ae7f..0000000 --- a/atari_py/ale_interface/src/emucore/unzip.h +++ /dev/null @@ -1,275 +0,0 @@ -/* unzip.h -- IO for uncompress .zip files using zlib - Version 0.15 beta, Mar 19th, 1998, - - Copyright (C) 1998 Gilles Vollant - - This unzip package allow extract file from .ZIP file, compatible with PKZip 2.04g - WinZip, InfoZip tools and compatible. - Encryption and multi volume ZipFile (span) are not supported. - Old compressions used by old PKZip 1.x are not supported - - THIS IS AN ALPHA VERSION. AT THIS STAGE OF DEVELOPPEMENT, SOMES API OR STRUCTURE - CAN CHANGE IN FUTURE VERSION !! - I WAIT FEEDBACK at mail info@winimage.com - Visit also http://www.winimage.com/zLibDll/unzip.htm for evolution - - Condition of use and distribution are the same than zlib : - - This software is provided 'as-is', without any express or implied - warranty. In no event will the authors be held liable for any damages - arising from the use of this software. - - Permission is granted to anyone to use this software for any purpose, - including commercial applications, and to alter it and redistribute it - freely, subject to the following restrictions: - - 1. The origin of this software must not be misrepresented; you must not - claim that you wrote the original software. If you use this software - in a product, an acknowledgment in the product documentation would be - appreciated but is not required. - 2. Altered source versions must be plainly marked as such, and must not be - misrepresented as being the original software. - 3. This notice may not be removed or altered from any source distribution. - - -*/ -/* for more info about .ZIP format, see - ftp://ftp.cdrom.com/pub/infozip/doc/appnote-970311-iz.zip - PkWare has also a specification at : - ftp://ftp.pkware.com/probdesc.zip */ - -#ifndef _unz_H -#define _unz_H - -#ifdef __cplusplus -extern "C" { -#endif - -#ifndef _ZLIB_H -#include -#endif - -#if defined(STRICTUNZIP) || defined(STRICTZIPUNZIP) -/* like the STRICT of WIN32, we define a pointer that cannot be converted - from (void*) without cast */ -typedef struct TagunzFile__ { int unused; } unzFile__; -typedef unzFile__ *unzFile; -#else -typedef voidp unzFile; -#endif - - -#define UNZ_OK (0) -#define UNZ_END_OF_LIST_OF_FILE (-100) -#define UNZ_ERRNO (Z_ERRNO) -#define UNZ_EOF (0) -#define UNZ_PARAMERROR (-102) -#define UNZ_BADZIPFILE (-103) -#define UNZ_INTERNALERROR (-104) -#define UNZ_CRCERROR (-105) - -/* tm_unz contain date/time info */ -typedef struct tm_unz_s -{ - uInt tm_sec; /* seconds after the minute - [0,59] */ - uInt tm_min; /* minutes after the hour - [0,59] */ - uInt tm_hour; /* hours since midnight - [0,23] */ - uInt tm_mday; /* day of the month - [1,31] */ - uInt tm_mon; /* months since January - [0,11] */ - uInt tm_year; /* years - [1980..2044] */ -} tm_unz; - -/* unz_global_info structure contain global data about the ZIPfile - These data comes from the end of central dir */ -typedef struct unz_global_info_s -{ - uLong number_entry; /* total number of entries in - the central dir on this disk */ - uLong size_comment; /* size of the global comment of the zipfile */ -} unz_global_info; - - -/* unz_file_info contain information about a file in the zipfile */ -typedef struct unz_file_info_s -{ - uLong version; /* version made by 2 bytes */ - uLong version_needed; /* version needed to extract 2 bytes */ - uLong flag; /* general purpose bit flag 2 bytes */ - uLong compression_method; /* compression method 2 bytes */ - uLong dosDate; /* last mod file date in Dos fmt 4 bytes */ - uLong crc; /* crc-32 4 bytes */ - uLong compressed_size; /* compressed size 4 bytes */ - uLong uncompressed_size; /* uncompressed size 4 bytes */ - uLong size_filename; /* filename length 2 bytes */ - uLong size_file_extra; /* extra field length 2 bytes */ - uLong size_file_comment; /* file comment length 2 bytes */ - - uLong disk_num_start; /* disk number start 2 bytes */ - uLong internal_fa; /* internal file attributes 2 bytes */ - uLong external_fa; /* external file attributes 4 bytes */ - - tm_unz tmu_date; -} unz_file_info; - -extern int ZEXPORT unzStringFileNameCompare OF ((const char* fileName1, - const char* fileName2, - int iCaseSensitivity)); -/* - Compare two filename (fileName1,fileName2). - If iCaseSenisivity = 1, comparision is case sensitivity (like strcmp) - If iCaseSenisivity = 2, comparision is not case sensitivity (like strcmpi - or strcasecmp) - If iCaseSenisivity = 0, case sensitivity is defaut of your operating system - (like 1 on Unix, 2 on Windows) -*/ - - -extern unzFile ZEXPORT unzOpen OF((const char *path)); -/* - Open a Zip file. path contain the full pathname (by example, - on a Windows NT computer "c:\\zlib\\zlib111.zip" or on an Unix computer - "zlib/zlib111.zip". - If the zipfile cannot be opened (file don't exist or in not valid), the - return value is NULL. - Else, the return value is a unzFile Handle, usable with other function - of this unzip package. -*/ - -extern int ZEXPORT unzClose OF((unzFile file)); -/* - Close a ZipFile opened with unzipOpen. - If there is files inside the .Zip opened with unzOpenCurrentFile (see later), - these files MUST be closed with unzipCloseCurrentFile before call unzipClose. - return UNZ_OK if there is no problem. */ - -extern int ZEXPORT unzGetGlobalInfo OF((unzFile file, - unz_global_info *pglobal_info)); -/* - Write info about the ZipFile in the *pglobal_info structure. - No preparation of the structure is needed - return UNZ_OK if there is no problem. */ - - -extern int ZEXPORT unzGetGlobalComment OF((unzFile file, - char *szComment, - uLong uSizeBuf)); -/* - Get the global comment string of the ZipFile, in the szComment buffer. - uSizeBuf is the size of the szComment buffer. - return the number of byte copied or an error code <0 -*/ - - -/***************************************************************************/ -/* Unzip package allow you browse the directory of the zipfile */ - -extern int ZEXPORT unzGoToFirstFile OF((unzFile file)); -/* - Set the current file of the zipfile to the first file. - return UNZ_OK if there is no problem -*/ - -extern int ZEXPORT unzGoToNextFile OF((unzFile file)); -/* - Set the current file of the zipfile to the next file. - return UNZ_OK if there is no problem - return UNZ_END_OF_LIST_OF_FILE if the actual file was the latest. -*/ - -extern int ZEXPORT unzLocateFile OF((unzFile file, - const char *szFileName, - int iCaseSensitivity)); -/* - Try locate the file szFileName in the zipfile. - For the iCaseSensitivity signification, see unzStringFileNameCompare - - return value : - UNZ_OK if the file is found. It becomes the current file. - UNZ_END_OF_LIST_OF_FILE if the file is not found -*/ - - -extern int ZEXPORT unzGetCurrentFileInfo OF((unzFile file, - unz_file_info *pfile_info, - char *szFileName, - uLong fileNameBufferSize, - void *extraField, - uLong extraFieldBufferSize, - char *szComment, - uLong commentBufferSize)); -/* - Get Info about the current file - if pfile_info!=NULL, the *pfile_info structure will contain somes info about - the current file - if szFileName!=NULL, the filemane string will be copied in szFileName - (fileNameBufferSize is the size of the buffer) - if extraField!=NULL, the extra field information will be copied in extraField - (extraFieldBufferSize is the size of the buffer). - This is the Central-header version of the extra field - if szComment!=NULL, the comment string of the file will be copied in szComment - (commentBufferSize is the size of the buffer) -*/ - -/***************************************************************************/ -/* for reading the content of the current zipfile, you can open it, read data - from it, and close it (you can close it before reading all the file) - */ - -extern int ZEXPORT unzOpenCurrentFile OF((unzFile file)); -/* - Open for reading data the current file in the zipfile. - If there is no error, the return value is UNZ_OK. -*/ - -extern int ZEXPORT unzCloseCurrentFile OF((unzFile file)); -/* - Close the file in zip opened with unzOpenCurrentFile - Return UNZ_CRCERROR if all the file was read but the CRC is not good -*/ - - -extern int ZEXPORT unzReadCurrentFile OF((unzFile file, - voidp buf, - unsigned len)); -/* - Read bytes from the current file (opened by unzOpenCurrentFile) - buf contain buffer where data must be copied - len the size of buf. - - return the number of byte copied if somes bytes are copied - return 0 if the end of file was reached - return <0 with error code if there is an error - (UNZ_ERRNO for IO error, or zLib error for uncompress error) -*/ - -extern z_off_t ZEXPORT unztell OF((unzFile file)); -/* - Give the current position in uncompressed data -*/ - -extern int ZEXPORT unzeof OF((unzFile file)); -/* - return 1 if the end of file was reached, 0 elsewhere -*/ - -extern int ZEXPORT unzGetLocalExtrafield OF((unzFile file, - voidp buf, - unsigned len)); -/* - Read extra field from the current file (opened by unzOpenCurrentFile) - This is the local-header version of the extra field (sometimes, there is - more info in the local-header version than in the central-header) - - if buf==NULL, it return the size of the local extra field - - if buf!=NULL, len is the size of the buffer, the extra header is copied in - buf. - the return value is the number of bytes copied in buf, or (if <0) - the error code -*/ - -#ifdef __cplusplus -} -#endif - -#endif /* _unz_H */ diff --git a/atari_py/ale_interface/src/environment/stella_environment.cpp b/atari_py/ale_interface/src/environment/stella_environment.cpp index 83a065a..dce0a2e 100644 --- a/atari_py/ale_interface/src/environment/stella_environment.cpp +++ b/atari_py/ale_interface/src/environment/stella_environment.cpp @@ -56,7 +56,7 @@ StellaEnvironment::StellaEnvironment(OSystem* osystem, RomSettings* settings): ale::Logger::Info << "Recording screens to directory: " << recordDir << std::endl; // Create the screen exporter - m_screen_exporter.reset(new ScreenExporter(m_osystem->colourPalette(), recordDir)); + //Kojoley m_screen_exporter.reset(new ScreenExporter(m_osystem->colourPalette(), recordDir)); } } @@ -158,9 +158,11 @@ reward_t StellaEnvironment::act(Action player_a_action, Action player_b_action) // is not enabled) m_osystem->sound().recordNextFrame(); + /* Kojoley // Similarly record screen as needed if (m_screen_exporter.get() != NULL) m_screen_exporter->saveNext(m_screen); + Kojoley*/ // Use the stored actions, which may or may not have changed this frame sum_rewards += oneStepAct(m_player_a_action, m_player_b_action); diff --git a/atari_py/ale_interface/src/environment/stella_environment.hpp b/atari_py/ale_interface/src/environment/stella_environment.hpp index 9125d80..b5efb88 100644 --- a/atari_py/ale_interface/src/environment/stella_environment.hpp +++ b/atari_py/ale_interface/src/environment/stella_environment.hpp @@ -25,7 +25,7 @@ #include "../emucore/OSystem.hxx" #include "../emucore/Event.hxx" #include "../games/RomSettings.hpp" -#include "../common/ScreenExporter.hpp" +//Kojoley #include "../common/ScreenExporter.hpp" #include "../common/Log.hpp" #include @@ -114,7 +114,7 @@ class StellaEnvironment { int m_max_num_frames_per_episode; // Maxmimum number of frames per episode size_t m_frame_skip; // How many frames to emulate per act() float m_repeat_action_probability; // Stochasticity of the environment - std::auto_ptr m_screen_exporter; // Automatic screen recorder + //Kojoley std::auto_ptr m_screen_exporter; // Automatic screen recorder // The last actions taken by our players Action m_player_a_action, m_player_b_action; diff --git a/atari_py/ale_interface/src/games/Roms.cpp b/atari_py/ale_interface/src/games/Roms.cpp index 7e99872..2d35200 100644 --- a/atari_py/ale_interface/src/games/Roms.cpp +++ b/atari_py/ale_interface/src/games/Roms.cpp @@ -150,16 +150,9 @@ static const RomSettings *roms[] = { /* looks for the RL wrapper corresponding to a particular rom title */ -RomSettings *buildRomRLWrapper(const std::string &rom) { - - size_t slash_ind = rom.find_last_of("/\\"); - std::string rom_str = rom.substr(slash_ind + 1); - size_t dot_idx = rom_str.find_first_of("."); - rom_str = rom_str.substr(0, dot_idx); - std::transform(rom_str.begin(), rom_str.end(), rom_str.begin(), ::tolower); - +RomSettings *buildRomRLWrapper(const std::string &rom_name) { for (size_t i=0; i < sizeof(roms)/sizeof(roms[0]); i++) { - if (rom_str == roms[i]->rom()) return roms[i]->clone(); + if (rom_name == roms[i]->rom()) return roms[i]->clone(); } return NULL; diff --git a/atari_py/ale_interface/src/games/Roms.hpp b/atari_py/ale_interface/src/games/Roms.hpp index 056906d..25bb28d 100644 --- a/atari_py/ale_interface/src/games/Roms.hpp +++ b/atari_py/ale_interface/src/games/Roms.hpp @@ -18,7 +18,7 @@ struct RomSettings; // looks for the RL wrapper corresponding to a particular rom title -extern RomSettings *buildRomRLWrapper(const std::string &rom); +extern RomSettings *buildRomRLWrapper(const std::string &rom_name); #endif // __ROMS_HPP__ diff --git a/atari_py/ale_python_interface.py b/atari_py/ale_python_interface.py index a6e1133..dfde8cd 100644 --- a/atari_py/ale_python_interface.py +++ b/atari_py/ale_python_interface.py @@ -48,8 +48,8 @@ def get_shared_lib_path(): ale_lib.setBool.restype = None ale_lib.setFloat.argtypes = [c_void_p, c_char_p, c_float] ale_lib.setFloat.restype = None -ale_lib.loadROM.argtypes = [c_void_p, c_char_p] -ale_lib.loadROM.restype = None +ale_lib.loadROM.argtypes = [c_void_p, c_char_p, c_int, c_char_p] +ale_lib.loadROM.restype = c_bool ale_lib.act.argtypes = [c_void_p, c_int] ale_lib.act.restype = c_int ale_lib.game_over.argtypes = [c_void_p] @@ -100,8 +100,10 @@ def get_shared_lib_path(): ale_lib.restoreSystemState.restype = None ale_lib.deleteState.argtypes = [c_void_p] ale_lib.deleteState.restype = None +'''Kojoley ale_lib.saveScreenPNG.argtypes = [c_void_p, c_char_p] ale_lib.saveScreenPNG.restype = None +Kojoley''' ale_lib.encodeState.argtypes = [c_void_p, c_void_p, c_int] ale_lib.encodeState.restype = None ale_lib.encodeStateLen.argtypes = [c_void_p] @@ -145,7 +147,13 @@ def setFloat(self, key, value): ale_lib.setFloat(self.obj, _as_bytes(key), float(value)) def loadROM(self, rom_file): - ale_lib.loadROM(self.obj, _as_bytes(rom_file)) + name, _ = os.path.splitext(os.path.basename(rom_file)) + if not isinstance(name, bytes): + name = name.encode('utf-8') + with open(rom_file, 'rb') as f: + data = f.read() + if not ale_lib.loadROM(self.obj, data, len(data), name): + raise ValueError("Failed to load ROM") def act(self, action): return ale_lib.act(self.obj, int(action)) @@ -267,7 +275,9 @@ def getRAM(self, ram=None): def saveScreenPNG(self, filename): """Save the current screen as a png file""" - return ale_lib.saveScreenPNG(self.obj, _as_bytes(filename)) + from PIL import Image + im = Image.fromarray(self.getScreenRGB()) + im.save(filename, 'png') def saveState(self): """Saves the state of the system""" diff --git a/setup.py b/setup.py index e9b2069..1a4f0b9 100644 --- a/setup.py +++ b/setup.py @@ -66,98 +66,14 @@ def list_files(path): defines.append(('BSPF_WIN32', None)) for fname in 'SettingsWin32.cxx OSystemWin32.cxx FSNodeWin32.cxx'.split(): sources.append(os.path.join(basepath, 'os_dependent', fname)) - - -def rglob(path, pattern): - return fnmatch.filter(list_files(path), pattern) - - -def find_include_dirs(root, fname): - return {os.path.dirname(path) - for path in rglob(root, '*' + fname)} - - -library_dirs = [] -zlib_root = os.environ.get('ZLIB_ROOT') -if zlib_root is not None: - import fnmatch - - zlib_includes = [] - - zlib_dirs = find_include_dirs(zlib_root, 'zlib.h') - if not zlib_dirs: - raise ValueError("Failed to find 'zlib.h' under ZLIB_ROOT folder. " - "It looks like there is no zlib in supplied path.") - zlib_includes += zlib_dirs - - zconf_dirs = find_include_dirs(zlib_root, 'zconf.h') - if not zlib_includes: - raise ValueError("Failed to find 'zconf.h' under ZLIB_ROOT folder. " - "Have you compiled zlib?") - zlib_includes += zconf_dirs - includes += zlib_includes - - zlib_libraries = set() - - # Try to compile a test program against zlib - from distutils.ccompiler import get_default_compiler, new_compiler - compiler = new_compiler(compiler=get_default_compiler()) - ext = compiler.static_lib_extension - - if os.name == 'nt': - zlib_name = 'zlib' - else: - zlib_name = 'libz' - zlib_lib_pattern = '%s*%s' % (zlib_name, ext) - - import tempfile - from distutils.ccompiler import CompileError, LinkError - tmp_dir = tempfile.mkdtemp() - src_path = os.path.join(tmp_dir, 'zlibtest.c') - with open(src_path, 'w') as f: - f.write("#include \nint main() { inflate(0, 0); return 0; }") - try: - for i, path in enumerate(rglob(zlib_root, '*' + zlib_lib_pattern)): - tmp_dir_i = os.path.join(tmp_dir, str(i)) - zlib_library = os.path.splitext(os.path.basename(path))[0] - zlib_library_dir = os.path.dirname(path) - try: - objects = compiler.compile([src_path], tmp_dir_i, - include_dirs=zlib_includes) - compiler.link_executable(objects, 'zlibtest', tmp_dir_i, - libraries=[zlib_library], - library_dirs=[zlib_library_dir]) - except (CompileError, LinkError) as e: - pass # skip this library as malformed - else: - zlib_libraries.add((zlib_library, zlib_library_dir)) - finally: - import shutil - shutil.rmtree(tmp_dir, ignore_errors=True) - - if not zlib_libraries: - raise ValueError("Failed to find a suitable library (%s) under " - "ZLIB_ROOT folder. Have you compiled zlib?" - % zlib_lib_pattern) - - # Priority to static library (Windows) - for zlib_library, zlib_library_dir in zlib_libraries: - if 'static' in zlib_library: - break - library_dirs.append(zlib_library_dir) -else: - if os.name == 'nt': - zlib_library = 'zlib' - else: - zlib_library = 'z' + # disable msvc secure warnings + defines.append(('_CRT_SECURE_NO_WARNINGS', None)) ale_c = Library('ale_c', define_macros=defines, sources=sources, include_dirs=includes, - libraries=[zlib_library], - library_dirs=library_dirs, ) From 7c31864d92615e86a34852d0b0d43ef8052f7945 Mon Sep 17 00:00:00 2001 From: Nikita Kniazev Date: Fri, 24 Feb 2017 01:37:37 +0300 Subject: [PATCH 09/11] Update readme --- README.md | 12 ------------ 1 file changed, 12 deletions(-) diff --git a/README.md b/README.md index 33f6a34..1ec182b 100644 --- a/README.md +++ b/README.md @@ -13,15 +13,3 @@ To install via pip, run: Alternatively, you can install using setuptools using: ```python setup.py install``` - -You can also trigger a build of the C++ code via `make`, and then add -this repo to your `PYTHONPATH`: - -```export PYTHONPATH=/path/to/atari-py:$PYTHONPATH``` - -### Common issues - -- If `zlib` cannot be found by compiler - check if it is installed in your - system. You can provide `zlib` path by setting `ZLIB_ROOT` environment - variable or directly to `pip` like this: - `pip install --global-option=build_ext --global-option="-L/path/to/zlib/lib" --global-option="-I/path/to/zlib/include" atari-py` From ca6f1089e8344906b52482038a33b7a75b7a868c Mon Sep 17 00:00:00 2001 From: Nikita Kniazev Date: Sun, 23 Jul 2017 17:51:20 +0300 Subject: [PATCH 10/11] Fix non-C var declaration coming from 72acda257230b5259fb616a85bf70d97a9a01ea5 --- atari_py/ale_interface/src/external/TinyMT/tinymt32.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/atari_py/ale_interface/src/external/TinyMT/tinymt32.c b/atari_py/ale_interface/src/external/TinyMT/tinymt32.c index 4f69fd3..ab8d0ea 100644 --- a/atari_py/ale_interface/src/external/TinyMT/tinymt32.c +++ b/atari_py/ale_interface/src/external/TinyMT/tinymt32.c @@ -60,13 +60,14 @@ static void period_certification(tinymt32_t * random) { * @param seed a 32-bit unsigned integer used as a seed. */ void tinymt32_init(tinymt32_t * random, uint32_t seed) { + int i; + // MGB: These values were apparently drawn from the aether. This isn't good for reproducibility. // I will set them to some bunk values. random->mat1 = 4753849; random->mat2 = 3231259923; random->tmat = 614784120; - int i; random->status[0] = seed; random->status[1] = random->mat1; random->status[2] = random->mat2; From 4c1dd729fd3c0de270c468c82ffe5d3be029a044 Mon Sep 17 00:00:00 2001 From: Nikita Kniazev Date: Sun, 23 Jul 2017 19:34:05 +0300 Subject: [PATCH 11/11] AppVeyor setup --- .appveyor.yml | 36 ++++++++++++++++++++++++++++++++++++ 1 file changed, 36 insertions(+) create mode 100644 .appveyor.yml diff --git a/.appveyor.yml b/.appveyor.yml new file mode 100644 index 0000000..cd0adfd --- /dev/null +++ b/.appveyor.yml @@ -0,0 +1,36 @@ +environment: + matrix: + - PYTHON: "C:\\Python27" + - PYTHON: "C:\\Python35" + - PYTHON: "C:\\Python36" + - PYTHON: "C:\\Python27-x64" + - PYTHON: "C:\\Python35-x64" + - PYTHON: "C:\\Python36-x64" + +install: + - "%PYTHON%\\python.exe -m pip install wheel" + +build: off + +before_test: + - "%PYTHON%\\python.exe setup.py bdist_wheel" + - "cd dist" + - "%PYTHON%\\python.exe -m pip install --find-links=. atari-py" + - "%PYTHON%\\python.exe -m pip install gym" + +test_script: + - "%PYTHON%\\python.exe -c \"import gym; env = gym.make('Enduro-v0'); env.reset(); [env.step(env.action_space.sample()) for i in range(1000)]\"" + +artifacts: + - path: dist\*.whl + name: Releases + +deploy: + provider: GitHub + auth_token: + secure: "Weh3LepGE4k174U43zSHYAiM1pUCUSlQ+wjwpmUI2X3SsZqTpdRKzDUwkLnHjp23" + artifact: /.*\.whl/ + draft: false + prerelease: false + on: + appveyor_repo_tag: true