From 578447fcf0e5742d062b7f8fbfddfa5e500dcde1 Mon Sep 17 00:00:00 2001 From: Anthony Platanios Date: Thu, 4 Apr 2019 14:03:53 -0400 Subject: [PATCH 01/33] Started working on a C API. --- CMakeLists.txt | 15 ++++ src/retro-c.cpp | 187 ++++++++++++++++++++++++++++++++++++++++++++++++ src/retro-c.h | 75 +++++++++++++++++++ 3 files changed, 277 insertions(+) create mode 100644 src/retro-c.cpp create mode 100644 src/retro-c.h diff --git a/CMakeLists.txt b/CMakeLists.txt index f71b1ef5a..d293c2588 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -37,6 +37,7 @@ option(BUILD_TESTS "Should tests be built" ON) option(BUILD_UI "Should integration UI be built" OFF) option(BUILD_LUAJIT "Should static LuaJIT be used instead of system Lua" ON) option(BUILD_MANYLINUX "Should use static libraries compatible with manylinux1" OFF) +option(BUILD_C "Build C API" OFF) set(BUILD_PYTHON ON CACHE BOOL "Build Python module") mark_as_advanced(BUILD_PYTHON) @@ -285,6 +286,20 @@ if(BUILD_PYTHON) target_link_libraries(retro retro-base ${PYBIND_LIBS} ${STATIC_LDFLAGS}) endif() +if(BUILD_C) + add_library(retro-c SHARED src/retro-c.cpp) + set_target_properties(retro-c PROPERTIES OUTPUT_NAME retro) + if(APPLE) + set(C_LIBS "-undefined dynamic_lookup") + elseif(WIN32) + if(CMAKE_SYSTEM_PROCESSOR STREQUAL "x86_64" OR CMAKE_SYSTEM_PROCESSOR STREQUAL "AMD64") + add_definitions(-DMS_WIN64) + endif() + set(C_LIBS "") + endif() + target_link_libraries(retro-c retro-base ${C_LIBS} ${STATIC_LDFLAGS}) +endif() + if(BUILD_TESTS) enable_testing() add_subdirectory(third-party/gtest/googlemock) diff --git a/src/retro-c.cpp b/src/retro-c.cpp new file mode 100644 index 000000000..26097cae2 --- /dev/null +++ b/src/retro-c.cpp @@ -0,0 +1,187 @@ +#include "retro-c.h" + +#include +#ifdef _WIN32 +// pyconfig.h doesn't seem to like hypot, so we need to work around it. +namespace std { +template +static inline T _hypot(T x, T y) { + return hypot(x, y); +} +} +#endif + +#include "coreinfo.h" +#include "data.h" +#include "emulator.h" +#include "imageops.h" +#include "memory.h" +#include "search.h" +#include "script.h" +#include "movie.h" +#include "movie-bk2.h" + +#include +#include +#include + +using std::string; +using namespace Retro; + +const char* retroCorePath(const char* hint) { + return Retro::corePath(hint).c_str(); +} + +const char* retroDataPath(const char* hint) { + return Retro::GameData::dataPath(hint).c_str(); +} + +CGameData gameDataCreate() { + auto* data = new Retro::GameData(); + auto* scenario = new Retro::Scenario(*data); + return {data, scenario}; +} + +void gameDataDelete(CGameData* gameData) { + delete gameData->data; + delete gameData->scenario; + delete gameData; +} + +bool gameDataLoad(CGameData* gameData, const char* dataFilename, const char* scenarioFilename) { + ScriptContext::reset(); + + bool success = true; + if (dataFilename != nullptr) { + success = success && gameData->data->load(dataFilename); + } + if (scenarioFilename != nullptr) { + success = success && gameData->scenario->load(scenarioFilename); + } + return success; +} + +bool gameDataSave(CGameData* gameData, const char* dataFilename, const char* scenarioFilename) { + ScriptContext::reset(); + + bool success = true; + if (dataFilename != nullptr) { + success = success && gameData->data->save(dataFilename); + } + if (scenarioFilename != nullptr) { + success = success && gameData->scenario->save(scenarioFilename); + } + return success; +} + +void gameDataReset(CGameData* gameData) { + gameData->scenario->restart(); + gameData->scenario->reloadScripts(); +} + +uint16_t gameDataFilterAction(CGameData* gameData, uint16_t action) { + return gameData->scenario->filterAction(action); +} + +// TODO: gameDataValidActions + +void gameDataUpdateRam(CGameData* gameData) { + gameData->data->updateRam(); + gameData->scenario->update(); +} + +// TODO: lookupValue, setValue, lookupAll +// TODO: getVariable, setVariable, removeVariable, listVariables + +float gameDataCurrentReward(CGameData* gameData, unsigned int player) { + return gameData->scenario->currentReward(player); +} + +float gameDataTotalReward(CGameData* gameData, unsigned int player) { + return gameData->scenario->totalReward(player); +} + +bool gameDataIsDone(CGameData* gameData) { + return gameData->scenario->isDone(); +} + +CCropInfo gameDataCropInfo(CGameData* gameData, unsigned int player) { + size_t x = 0; + size_t y = 0; + size_t width = 0; + size_t height = 0; + gameData->scenario->getCrop(&x, &y, &width, &height, player); + return {x, y, width, height}; +} + +// TODO: gameDataMemory + +void gameDataSearch(CGameData* gameData, const char* name, int64_t value) { + gameData->data->search(name, value); +} + +void gameDataDeltaSearch(CGameData* gameData, const char* name, const char* op, int64_t ref) { + gameData->data->deltaSearch(name, Retro::Scenario::op(op), ref); +} + +// TODO: gameDataGetSearch + +void gameDataRemoveSearch(CGameData* gameData, const char* name) { + gameData->data->removeSearch(name); +} + +// TODO: gameDataListSearches + +CMovie movieCreate(const char* name, bool record, unsigned int players) { + Retro::Movie* movie; + if (record) { + movie = new MovieBK2(name, true, players); + } else { + movie = Movie::load(name).get(); + } + if (!movie) { + throw std::runtime_error("Could not load movie"); + } + return {movie, record}; +} + +void movieDelete(CMovie* movie) { + delete movie->movie; + delete movie; +} + +// TODO: movieConfigure + +const char* movieGetGameName(CMovie* movie) { + return movie->movie->getGameName().c_str(); +} + +bool movieStep(CMovie* movie) { + return movie->movie->step(); +} + +void movieClose(CMovie* movie) { + movie->movie->close(); +} + +unsigned int moviePlayers(CMovie* movie) { + return movie->movie->players(); +} + +bool movieGetKey(CMovie* movie, int key, unsigned int player) { + return movie->movie->getKey(key, player); +} + +void movieSetKey(CMovie* movie, int key, bool set, unsigned int player) { + movie->movie->setKey(key, set, player); +} + +CMovieState movieGetState(CMovie* movie) { + std::vector data; + movie->movie->getState(&data); + return {reinterpret_cast(data.data()), data.size()}; +} + +void movieSetState(CMovie* movie, CMovieState* state) { + movie->movie->setState(reinterpret_cast(state->bytes), state->numBytes); +} diff --git a/src/retro-c.h b/src/retro-c.h new file mode 100644 index 000000000..8ec2eaa58 --- /dev/null +++ b/src/retro-c.h @@ -0,0 +1,75 @@ +#include "data.h" +#include "movie.h" + +using namespace Retro; + +#ifdef __cplusplus +extern "C" { +#endif + +typedef struct CSearch { + Retro::Search* search; + bool managed; +} CSearch; + +typedef struct CGameData { + Retro::GameData* data; + Retro::Scenario* scenario; +} CGameData; + +typedef struct CMovie { + Retro::Movie* movie; + bool recording; +} CMovie; + +typedef struct CMovieState { + char* bytes; + size_t numBytes; +} CMovieState; + +typedef struct CCropInfo { + size_t x; + size_t y; + size_t width; + size_t height; +} CCropInfo; + +CGameData gameDataCreate(); +void gameDataDelete(CGameData* gameData); +bool gameDataLoad(CGameData* gameData, const char* dataFilename, const char* scenarioFilename); +bool gameDataSave(CGameData* gameData, const char* dataFilename, const char* scenarioFilename); +void gameDataReset(CGameData* gameData); +uint16_t gameDataFilterAction(CGameData* gameData, uint16_t action); +// TODO: validActions +void gameDataUpdateRam(CGameData* gameData); +// TODO: lookupValue, setValue, lookupAll +// TODO: getVariable, setVariable, removeVariable, listVariables +float gameDataCurrentReward(CGameData* gameData, unsigned int player); +float gameDataTotalReward(CGameData* gameData, unsigned int player); +bool gameDataIsDone(CGameData* gameData); +CCropInfo gameDataCropInfo(CGameData* gameData, unsigned int player); +// TODO: memory +void gameDataSearch(CGameData* gameData, const char* name, int64_t value); +void gameDataDeltaSearch(CGameData* gameData, const char* name, const char* op, int64_t ref); +// TODO: getSearch +void gameDataRemoveSearch(CGameData* gameData, const char* name); +// TODO: listSearches + +CMovie movieCreate(const char* name, bool record, unsigned int players); +void movieDelete(CMovie* movie); +// TODO: movieConfigure +const char* movieGetGameName(CMovie* movie); +bool movieStep(CMovie* movie); +void movieClose(CMovie* movie); +unsigned int moviePlayers(CMovie* movie); +bool movieGetKey(CMovie* movie, int key, unsigned int player); +void movieSetKey(CMovie* movie, int key, bool set, unsigned int player); +CMovieState movieGetState(CMovie* movie); +void movieSetState(CMovie* movie, CMovieState* state); + +const char* retroCorePath(const char* hint); +const char* retroDataPath(const char* hint); + +#ifdef __cplusplus +} /* extern "C" */ +#endif From da13cf854d200e9c26749096c892affaa0d912a1 Mon Sep 17 00:00:00 2001 From: Anthony Platanios Date: Thu, 4 Apr 2019 14:18:48 -0400 Subject: [PATCH 02/33] Added support for search structs to the C API. --- src/retro-c.cpp | 40 ++++++++++++++++++++++++++++++++++++++++ src/retro-c.h | 13 +++++++++++++ 2 files changed, 53 insertions(+) diff --git a/src/retro-c.cpp b/src/retro-c.cpp index 26097cae2..5e70b0b99 100644 --- a/src/retro-c.cpp +++ b/src/retro-c.cpp @@ -185,3 +185,43 @@ CMovieState movieGetState(CMovie* movie) { void movieSetState(CMovie* movie, CMovieState* state) { movie->movie->setState(reinterpret_cast(state->bytes), state->numBytes); } + +CSearch searchCreate(const char** types, size_t numTypes) { + Retro::Search* search; + if (numTypes > 0) { + std::vector dtypes; + for (int i = 0; i < numTypes; i++) { + dtypes.emplace_back(types[i]); + } + search = new Retro::Search(dtypes); + } else { + search = nullptr; + } + return {search, true}; +} + +CSearch searchCreate(Retro::Search* search) { + return {search, false}; +} + +void searchDelete(CSearch* search) { + if (search->managed) { + delete search->search; + } + delete search; +} + +int searchNumResults(CSearch* search) { + return search->search->numResults(); +} + +bool searchHasUniqueResult(CSearch* search) { + return search->search->hasUniqueResult(); +} + +CSearchResult searchUniqueResult(CSearch* search) { + TypedSearchResult result = search->search->uniqueResult(); + return {result.address, result.type.type}; +} + +// TODO: searchTypedResults diff --git a/src/retro-c.h b/src/retro-c.h index 8ec2eaa58..5b94cd219 100644 --- a/src/retro-c.h +++ b/src/retro-c.h @@ -12,6 +12,11 @@ typedef struct CSearch { bool managed; } CSearch; +typedef struct CSearchResult { + size_t address; + const char* type; +} CSearchResult; + typedef struct CGameData { Retro::GameData* data; Retro::Scenario* scenario; @@ -34,6 +39,14 @@ typedef struct CCropInfo { size_t height; } CCropInfo; +CSearch searchCreate(const char** types, size_t numTypes); +CSearch searchCreate(Retro::Search* search); +void searchDelete(CSearch* search); +int searchNumResults(CSearch* search); +bool searchHasUniqueResult(CSearch* search); +CSearchResult searchUniqueResult(CSearch* search); +// TODO: searchTypedResults + CGameData gameDataCreate(); void gameDataDelete(CGameData* gameData); bool gameDataLoad(CGameData* gameData, const char* dataFilename, const char* scenarioFilename); From beff4ca245284fe2a164ec70017701e63134bee5 Mon Sep 17 00:00:00 2001 From: Anthony Platanios Date: Thu, 4 Apr 2019 14:30:33 -0400 Subject: [PATCH 03/33] Added support for some missing GameData functions to the C API. --- src/retro-c.cpp | 108 ++++++++++++++++++++++++++++++------------------ src/retro-c.h | 18 +++++++- 2 files changed, 83 insertions(+), 43 deletions(-) diff --git a/src/retro-c.cpp b/src/retro-c.cpp index 5e70b0b99..940426a4e 100644 --- a/src/retro-c.cpp +++ b/src/retro-c.cpp @@ -28,14 +28,46 @@ static inline T _hypot(T x, T y) { using std::string; using namespace Retro; -const char* retroCorePath(const char* hint) { - return Retro::corePath(hint).c_str(); +CSearch searchCreate(const char** types, size_t numTypes) { + Retro::Search* search; + if (numTypes > 0) { + std::vector dtypes; + for (int i = 0; i < numTypes; i++) { + dtypes.emplace_back(types[i]); + } + search = new Retro::Search(dtypes); + } else { + search = nullptr; + } + return {search, true}; } -const char* retroDataPath(const char* hint) { - return Retro::GameData::dataPath(hint).c_str(); +CSearch searchCreateUnmanaged(Retro::Search* search) { + return {search, false}; +} + +void searchDelete(CSearch* search) { + if (search->managed) { + delete search->search; + } + delete search; +} + +int searchNumResults(CSearch* search) { + return search->search->numResults(); +} + +bool searchHasUniqueResult(CSearch* search) { + return search->search->hasUniqueResult(); +} + +CSearchResult searchUniqueResult(CSearch* search) { + TypedSearchResult result = search->search->uniqueResult(); + return {result.address, result.type.type}; } +// TODO: searchTypedResults + CGameData gameDataCreate() { auto* data = new Retro::GameData(); auto* scenario = new Retro::Scenario(*data); @@ -91,7 +123,33 @@ void gameDataUpdateRam(CGameData* gameData) { } // TODO: lookupValue, setValue, lookupAll -// TODO: getVariable, setVariable, removeVariable, listVariables + +CVariable gameDataGetVariable(CGameData* gameData, const char* name) { + Retro::Variable var = gameData->data->getVariable(name); + return {name, var.address, var.type.type}; +} + +void gameDataSetVariable(CGameData* gameData, const char* name, CVariable* value) { + Retro::Variable var { value->type, value->address }; + gameData->data->setVariable(name, var); +} + +void gameDataRemoveVariable(CGameData* gameData, const char* name) { + gameData->data->removeVariable(name); +} + +CVariables gameDataListVariables(CGameData* gameData) { + const auto& vars = gameData->data->listVariables(); + auto numVariables = vars.size(); + auto* variables = new CVariable[numVariables]; + auto i = 0; + for (const auto& var : vars) { + const auto& v = var.second; + variables[i] = {var.first.c_str(), v.address, v.type.type}; + i++; + } + return {variables, numVariables}; +} float gameDataCurrentReward(CGameData* gameData, unsigned int player) { return gameData->scenario->currentReward(player); @@ -186,42 +244,10 @@ void movieSetState(CMovie* movie, CMovieState* state) { movie->movie->setState(reinterpret_cast(state->bytes), state->numBytes); } -CSearch searchCreate(const char** types, size_t numTypes) { - Retro::Search* search; - if (numTypes > 0) { - std::vector dtypes; - for (int i = 0; i < numTypes; i++) { - dtypes.emplace_back(types[i]); - } - search = new Retro::Search(dtypes); - } else { - search = nullptr; - } - return {search, true}; -} - -CSearch searchCreate(Retro::Search* search) { - return {search, false}; -} - -void searchDelete(CSearch* search) { - if (search->managed) { - delete search->search; - } - delete search; -} - -int searchNumResults(CSearch* search) { - return search->search->numResults(); -} - -bool searchHasUniqueResult(CSearch* search) { - return search->search->hasUniqueResult(); +const char* retroCorePath(const char* hint) { + return Retro::corePath(hint).c_str(); } -CSearchResult searchUniqueResult(CSearch* search) { - TypedSearchResult result = search->search->uniqueResult(); - return {result.address, result.type.type}; +const char* retroDataPath(const char* hint) { + return Retro::GameData::dataPath(hint).c_str(); } - -// TODO: searchTypedResults diff --git a/src/retro-c.h b/src/retro-c.h index 5b94cd219..0687a41a7 100644 --- a/src/retro-c.h +++ b/src/retro-c.h @@ -22,6 +22,17 @@ typedef struct CGameData { Retro::Scenario* scenario; } CGameData; +typedef struct CVariable { + const char* name; + size_t address; + const char* type; +} CVariable; + +typedef struct CVariables { + CVariable* variables; + size_t numVariables; +} CVariables; + typedef struct CMovie { Retro::Movie* movie; bool recording; @@ -40,7 +51,7 @@ typedef struct CCropInfo { } CCropInfo; CSearch searchCreate(const char** types, size_t numTypes); -CSearch searchCreate(Retro::Search* search); +CSearch searchCreateUnmanaged(Retro::Search* search); void searchDelete(CSearch* search); int searchNumResults(CSearch* search); bool searchHasUniqueResult(CSearch* search); @@ -56,7 +67,10 @@ uint16_t gameDataFilterAction(CGameData* gameData, uint16_t action); // TODO: validActions void gameDataUpdateRam(CGameData* gameData); // TODO: lookupValue, setValue, lookupAll -// TODO: getVariable, setVariable, removeVariable, listVariables +CVariable gameDataGetVariable(CGameData* gameData, const char* name); +void gameDataSetVariable(CGameData* gameData, const char* name, CVariable* value); +void gameDataRemoveVariable(CGameData* gameData, const char* name); +CVariables gameDataListVariables(CGameData* gameData); float gameDataCurrentReward(CGameData* gameData, unsigned int player); float gameDataTotalReward(CGameData* gameData, unsigned int player); bool gameDataIsDone(CGameData* gameData); From 132e1aa322b7fe9ca53bcd3561ffe5cdbd2f6cc5 Mon Sep 17 00:00:00 2001 From: Anthony Platanios Date: Thu, 4 Apr 2019 14:43:14 -0400 Subject: [PATCH 04/33] Added support for memory view structs to the C API. --- src/retro-c.cpp | 28 ++++++++++++++++++++++++++++ src/retro-c.h | 21 +++++++++++++++++++++ 2 files changed, 49 insertions(+) diff --git a/src/retro-c.cpp b/src/retro-c.cpp index 940426a4e..a521dab03 100644 --- a/src/retro-c.cpp +++ b/src/retro-c.cpp @@ -28,6 +28,34 @@ static inline T _hypot(T x, T y) { using std::string; using namespace Retro; +CMemoryView memoryViewCreate(Retro::AddressSpace* addressSpace) { + return { addressSpace }; +} + +void memoryViewDelete(CMemoryView* memoryView) { + delete memoryView; +} + +int64_t memoryViewExtract(CMemoryView* memoryView, size_t address, const char* type) { + return (*memoryView->addressSpace)[Variable{ type, address }]; +} + +void memoryViewAssign(CMemoryView* memoryView, size_t address, const char* type, int64_t value) { + (*memoryView->addressSpace)[Variable{ type, address }] = value; +} + +CMemoryBlocks memoryViewBlocks(CMemoryView* memoryView) { + auto& internalBlocks = memoryView->addressSpace->blocks(); + auto numBlocks = internalBlocks.size(); + auto* blocks = new CMemoryBlock[numBlocks]; + auto i = 0; + for (const auto& iter : internalBlocks) { + blocks[i] = {iter.first, static_cast(iter.second.offset(0)), iter.second.size()}; + i++; + } + return {blocks, numBlocks}; +} + CSearch searchCreate(const char** types, size_t numTypes) { Retro::Search* search; if (numTypes > 0) { diff --git a/src/retro-c.h b/src/retro-c.h index 0687a41a7..8dfb9ece5 100644 --- a/src/retro-c.h +++ b/src/retro-c.h @@ -7,6 +7,21 @@ using namespace Retro; extern "C" { #endif +typedef struct CMemoryView { + Retro::AddressSpace* addressSpace; +} CMemoryView; + +typedef struct CMemoryBlock { + size_t address; + const char* bytes; + size_t numBytes; +} CMemoryBlock; + +typedef struct CMemoryBlocks { + CMemoryBlock* blocks; + size_t numBlocks; +} CMemoryBlocks; + typedef struct CSearch { Retro::Search* search; bool managed; @@ -50,6 +65,12 @@ typedef struct CCropInfo { size_t height; } CCropInfo; +CMemoryView memoryViewCreate(Retro::AddressSpace* addressSpace); +void memoryViewDelete(CMemoryView* memoryView); +int64_t memoryViewExtract(CMemoryView* memoryView, size_t address, const char* type); +void memoryViewAssign(CMemoryView* memoryView, size_t address, const char* type, int64_t value); +CMemoryBlocks memoryViewBlocks(CMemoryView* memoryView); + CSearch searchCreate(const char** types, size_t numTypes); CSearch searchCreateUnmanaged(Retro::Search* search); void searchDelete(CSearch* search); From 3f858d200a5144b0ea0dbda3883e9e2e0c2b5b7b Mon Sep 17 00:00:00 2001 From: Anthony Platanios Date: Thu, 4 Apr 2019 16:21:38 -0400 Subject: [PATCH 05/33] Added most of the missing functionality to the C API. --- src/retro-c.cpp | 150 +++++++++++++++++++++++++++++++++++++++++++++--- src/retro-c.h | 69 ++++++++++++++++++---- 2 files changed, 202 insertions(+), 17 deletions(-) diff --git a/src/retro-c.cpp b/src/retro-c.cpp index a521dab03..8653b172a 100644 --- a/src/retro-c.cpp +++ b/src/retro-c.cpp @@ -28,6 +28,105 @@ static inline T _hypot(T x, T y) { using std::string; using namespace Retro; +CEmulator emulatorCreate(const char* romPath) { + Retro::Emulator emulator; + if (Emulator::isLoaded()) { + throw std::runtime_error( + "Cannot create multiple emulator instances per process, make sure to call " + "'env.close()' on each environment before creating a new one."); + } + if (!emulator.loadRom(romPath)) { + throw std::runtime_error("Could not load ROM."); + } + // The following is necessary because otherwise, you get a segfault + // when you try to get the screen for the first time. + emulator.run(); + return {&emulator, 0}; +} + +void emulatorDelete(CEmulator* emulator) { + delete emulator->emulator; + delete emulator; +} + +void emulatorStep(CEmulator* emulator) { + emulator->emulator->run(); +} + +CBytes emulatorGetState(CEmulator* emulator) { + size_t numBytes = emulator->emulator->serializeSize(); + void* bytes = malloc(numBytes); + emulator->emulator->serialize(bytes, numBytes); + return {bytes, numBytes}; +} + +bool emulatorSetState(CEmulator* emulator, CBytes* state) { + return emulator->emulator->unserialize(state->bytes, state->numBytes); +} + +CEmulatorScreen emulatorGetScreen(CEmulator* emulator) { + auto* emu = emulator->emulator; + long w = emu->getImageWidth(); + long h = emu->getImageHeight(); + uint8_t* data = new uint8_t[w * h * 3]; + Image out(Image::Format::RGB888, data, w, h, w); + Image in; + if (emu->getImageDepth() == 16) { + in = Image(Image::Format::RGB565, emu->getImageData(), w, h, emu->getImagePitch()); + } else if (emu->getImageDepth() == 32) { + in = Image(Image::Format::RGBX888, emu->getImageData(), w, h, emu->getImagePitch()); + } + in.copyTo(&out); + return {data, (int) w, (int) h, 3}; +} + +double emulatorGetScreenRate(CEmulator* emulator) { + return emulator->emulator->getFrameRate(); +} + +CEmulatorAudio emulatorGetAudio(CEmulator* emulator) { + size_t numSamples = emulator->emulator->getAudioSamples() * 2; + int16_t* samples = new int16_t[numSamples]; + memcpy(samples, emulator->emulator->getAudioData(), numSamples * 2); + return {samples, numSamples}; +} + +double emulatorGetAudioRate(CEmulator* emulator) { + return emulator->emulator->getAudioRate(); +} + +CEmulatorResolution emulatorGetResolution(CEmulator* emulator) { + auto w = emulator->emulator->getImageWidth(); + auto h = emulator->emulator->getImageHeight(); + return {w, h}; +} + +void emulatorSetButtonMask(CEmulator* emulator, uint8_t* mask, size_t maskSize, unsigned int player) { + if (maskSize > N_BUTTONS) { + throw std::runtime_error("mask.size() > N_BUTTONS."); + } + if (player >= MAX_PLAYERS) { + throw std::runtime_error("player >= MAX_PLAYERS."); + } + for (int key = 0; key < maskSize; key++) { + emulator->emulator->setKey(player, key, mask[key]); + } +} + +void emulatorAddCheat(CEmulator* emulator, const char* code) { + emulator->emulator->setCheat(emulator->cheats, true, code); + emulator->cheats++; +} + +void emulatorClearCheats(CEmulator* emulator) { + emulator->emulator->clearCheats(); + emulator->cheats = 0; +} + +void emulatorConfigureData(CEmulator* emulator, CGameData* gameData) { + emulator->emulator->configureData(gameData->data); +} + CMemoryView memoryViewCreate(Retro::AddressSpace* addressSpace) { return { addressSpace }; } @@ -143,7 +242,24 @@ uint16_t gameDataFilterAction(CGameData* gameData, uint16_t action) { return gameData->scenario->filterAction(action); } -// TODO: gameDataValidActions +CValidActions gameDataValidActions(CGameData* gameData) { + std::map> validActions = gameData->scenario->validActions(); + size_t numActionsOuter = validActions.size(); + int** actions = new int*[numActionsOuter]; + size_t* numActionsInner = new size_t[numActionsOuter]; + int i = 0; + for (const auto& action : validActions) { + numActionsInner[i] = action.second.size(); + actions[i] = new int[numActionsInner[i]]; + int j = 0; + for (const auto& act : action.second) { + actions[i][j] = act; + j++; + } + i++; + } + return {actions, numActionsInner, numActionsOuter}; +} void gameDataUpdateRam(CGameData* gameData) { gameData->data->updateRam(); @@ -200,7 +316,9 @@ CCropInfo gameDataCropInfo(CGameData* gameData, unsigned int player) { return {x, y, width, height}; } -// TODO: gameDataMemory +CMemoryView gameDataMemory(CGameData* gameData) { + return memoryViewCreate(&gameData->data->addressSpace()); +} void gameDataSearch(CGameData* gameData, const char* name, int64_t value) { gameData->data->search(name, value); @@ -210,13 +328,22 @@ void gameDataDeltaSearch(CGameData* gameData, const char* name, const char* op, gameData->data->deltaSearch(name, Retro::Scenario::op(op), ref); } -// TODO: gameDataGetSearch +CSearch gameDataGetSearch(CGameData* gameData, const char* name) { + return searchCreateUnmanaged(gameData->data->getSearch(name)); +} void gameDataRemoveSearch(CGameData* gameData, const char* name) { gameData->data->removeSearch(name); } -// TODO: gameDataListSearches +CSearchList gameDataListSearches(CGameData* gameData) { + std::vector names = gameData->data->listSearches(); + const char** cNames = new const char*[names.size()]; + for (int i = 0; i < names.size(); i++) { + cNames[i] = names[i].c_str(); + } + return {cNames, names.size()}; +} CMovie movieCreate(const char* name, bool record, unsigned int players) { Retro::Movie* movie; @@ -236,7 +363,12 @@ void movieDelete(CMovie* movie) { delete movie; } -// TODO: movieConfigure +void movieConfigure(CMovie* movie, const char* name, CEmulator* emulator) { + if (movie->recording) { + static_cast(movie->movie)->setGameName(name); + static_cast(movie->movie)->loadKeymap(emulator->emulator->core()); + } +} const char* movieGetGameName(CMovie* movie) { return movie->movie->getGameName().c_str(); @@ -262,16 +394,20 @@ void movieSetKey(CMovie* movie, int key, bool set, unsigned int player) { movie->movie->setKey(key, set, player); } -CMovieState movieGetState(CMovie* movie) { +CBytes movieGetState(CMovie* movie) { std::vector data; movie->movie->getState(&data); return {reinterpret_cast(data.data()), data.size()}; } -void movieSetState(CMovie* movie, CMovieState* state) { +void movieSetState(CMovie* movie, CBytes* state) { movie->movie->setState(reinterpret_cast(state->bytes), state->numBytes); } +bool retroLoadCoreInfo(const char* json) { + return Retro::loadCoreInfo(json); +} + const char* retroCorePath(const char* hint) { return Retro::corePath(hint).c_str(); } diff --git a/src/retro-c.h b/src/retro-c.h index 8dfb9ece5..dcbb81e72 100644 --- a/src/retro-c.h +++ b/src/retro-c.h @@ -7,6 +7,28 @@ using namespace Retro; extern "C" { #endif +typedef struct CEmulator { + Retro::Emulator* emulator; + int cheats; +} CEmulator; + +typedef struct CEmulatorScreen { + uint8_t* values; + int width; + int height; + int channels; +} CEmulatorScreen; + +typedef struct CEmulatorAudio { + int16_t* samples; + size_t numSamples; +} CEmulatorAudio; + +typedef struct CEmulatorResolution { + int width; + int height; +} CEmulatorResolution; + typedef struct CMemoryView { Retro::AddressSpace* addressSpace; } CMemoryView; @@ -27,6 +49,11 @@ typedef struct CSearch { bool managed; } CSearch; +typedef struct CSearchList { + const char** names; + size_t numNames; +} CSearchList; + typedef struct CSearchResult { size_t address; const char* type; @@ -48,15 +75,21 @@ typedef struct CVariables { size_t numVariables; } CVariables; +typedef struct CValidActions { + int** actions; + size_t* numActionsInner; + size_t numActionsOuter; +} CValidActions; + typedef struct CMovie { Retro::Movie* movie; bool recording; } CMovie; -typedef struct CMovieState { - char* bytes; +typedef struct CBytes { + void* bytes; size_t numBytes; -} CMovieState; +} CBytes; typedef struct CCropInfo { size_t x; @@ -65,6 +98,21 @@ typedef struct CCropInfo { size_t height; } CCropInfo; +CEmulator emulatorCreate(const char* romPath); +void emulatorDelete(CEmulator* emulator); +void emulatorStep(CEmulator* emulator); +CBytes emulatorGetState(CEmulator* emulator); +bool emulatorSetState(CEmulator* emulator, CBytes* state); +CEmulatorScreen emulatorGetScreen(CEmulator* emulator); +double emulatorGetScreenRate(CEmulator* emulator); +CEmulatorAudio emulatorGetAudio(CEmulator* emulator); +double emulatorGetAudioRate(CEmulator* emulator); +CEmulatorResolution emulatorGetResolution(CEmulator* emulator); +void emulatorSetButtonMask(CEmulator* emulator, uint8_t* mask, size_t maskSize, unsigned int player); +void emulatorAddCheat(CEmulator* emulator, const char* code); +void emulatorClearCheats(CEmulator* emulator); +void emulatorConfigureData(CEmulator* emulator, CGameData* gameData); + CMemoryView memoryViewCreate(Retro::AddressSpace* addressSpace); void memoryViewDelete(CMemoryView* memoryView); int64_t memoryViewExtract(CMemoryView* memoryView, size_t address, const char* type); @@ -85,7 +133,7 @@ bool gameDataLoad(CGameData* gameData, const char* dataFilename, const char* sce bool gameDataSave(CGameData* gameData, const char* dataFilename, const char* scenarioFilename); void gameDataReset(CGameData* gameData); uint16_t gameDataFilterAction(CGameData* gameData, uint16_t action); -// TODO: validActions +CValidActions gameDataValidActions(CGameData* gameData); void gameDataUpdateRam(CGameData* gameData); // TODO: lookupValue, setValue, lookupAll CVariable gameDataGetVariable(CGameData* gameData, const char* name); @@ -96,25 +144,26 @@ float gameDataCurrentReward(CGameData* gameData, unsigned int player); float gameDataTotalReward(CGameData* gameData, unsigned int player); bool gameDataIsDone(CGameData* gameData); CCropInfo gameDataCropInfo(CGameData* gameData, unsigned int player); -// TODO: memory +CMemoryView gameDataMemory(CGameData* gameData); void gameDataSearch(CGameData* gameData, const char* name, int64_t value); void gameDataDeltaSearch(CGameData* gameData, const char* name, const char* op, int64_t ref); -// TODO: getSearch +CSearch gameDataGetSearch(CGameData* gameData, const char* name); void gameDataRemoveSearch(CGameData* gameData, const char* name); -// TODO: listSearches +CSearchList gameDataListSearches(CGameData* gameData); CMovie movieCreate(const char* name, bool record, unsigned int players); void movieDelete(CMovie* movie); -// TODO: movieConfigure +void movieConfigure(CMovie* movie, const char* name, CEmulator* emulator); const char* movieGetGameName(CMovie* movie); bool movieStep(CMovie* movie); void movieClose(CMovie* movie); unsigned int moviePlayers(CMovie* movie); bool movieGetKey(CMovie* movie, int key, unsigned int player); void movieSetKey(CMovie* movie, int key, bool set, unsigned int player); -CMovieState movieGetState(CMovie* movie); -void movieSetState(CMovie* movie, CMovieState* state); +CBytes movieGetState(CMovie* movie); +void movieSetState(CMovie* movie, CBytes* state); +bool retroLoadCoreInfo(const char* json); const char* retroCorePath(const char* hint); const char* retroDataPath(const char* hint); From feb950920965228dd13689ec37176b959e1bb25e Mon Sep 17 00:00:00 2001 From: Anthony Platanios Date: Thu, 4 Apr 2019 16:24:25 -0400 Subject: [PATCH 06/33] Switched to using spaces for indentation. --- src/retro-c.cpp | 398 ++++++++++++++++++++++++------------------------ src/retro-c.h | 16 +- 2 files changed, 207 insertions(+), 207 deletions(-) diff --git a/src/retro-c.cpp b/src/retro-c.cpp index 8653b172a..e541662f8 100644 --- a/src/retro-c.cpp +++ b/src/retro-c.cpp @@ -6,7 +6,7 @@ namespace std { template static inline T _hypot(T x, T y) { - return hypot(x, y); + return hypot(x, y); } } #endif @@ -29,389 +29,389 @@ using std::string; using namespace Retro; CEmulator emulatorCreate(const char* romPath) { - Retro::Emulator emulator; - if (Emulator::isLoaded()) { - throw std::runtime_error( - "Cannot create multiple emulator instances per process, make sure to call " - "'env.close()' on each environment before creating a new one."); - } - if (!emulator.loadRom(romPath)) { - throw std::runtime_error("Could not load ROM."); - } - // The following is necessary because otherwise, you get a segfault - // when you try to get the screen for the first time. - emulator.run(); - return {&emulator, 0}; + Retro::Emulator emulator; + if (Emulator::isLoaded()) { + throw std::runtime_error( + "Cannot create multiple emulator instances per process, make sure to call " + "'env.close()' on each environment before creating a new one."); + } + if (!emulator.loadRom(romPath)) { + throw std::runtime_error("Could not load ROM."); + } + // The following is necessary because otherwise, you get a segfault + // when you try to get the screen for the first time. + emulator.run(); + return {&emulator, 0}; } void emulatorDelete(CEmulator* emulator) { - delete emulator->emulator; - delete emulator; + delete emulator->emulator; + delete emulator; } void emulatorStep(CEmulator* emulator) { - emulator->emulator->run(); + emulator->emulator->run(); } CBytes emulatorGetState(CEmulator* emulator) { - size_t numBytes = emulator->emulator->serializeSize(); - void* bytes = malloc(numBytes); - emulator->emulator->serialize(bytes, numBytes); - return {bytes, numBytes}; + size_t numBytes = emulator->emulator->serializeSize(); + void* bytes = malloc(numBytes); + emulator->emulator->serialize(bytes, numBytes); + return {bytes, numBytes}; } bool emulatorSetState(CEmulator* emulator, CBytes* state) { - return emulator->emulator->unserialize(state->bytes, state->numBytes); + return emulator->emulator->unserialize(state->bytes, state->numBytes); } CEmulatorScreen emulatorGetScreen(CEmulator* emulator) { - auto* emu = emulator->emulator; - long w = emu->getImageWidth(); - long h = emu->getImageHeight(); - uint8_t* data = new uint8_t[w * h * 3]; - Image out(Image::Format::RGB888, data, w, h, w); - Image in; - if (emu->getImageDepth() == 16) { - in = Image(Image::Format::RGB565, emu->getImageData(), w, h, emu->getImagePitch()); - } else if (emu->getImageDepth() == 32) { - in = Image(Image::Format::RGBX888, emu->getImageData(), w, h, emu->getImagePitch()); - } - in.copyTo(&out); - return {data, (int) w, (int) h, 3}; + auto* emu = emulator->emulator; + long w = emu->getImageWidth(); + long h = emu->getImageHeight(); + uint8_t* data = new uint8_t[w * h * 3]; + Image out(Image::Format::RGB888, data, w, h, w); + Image in; + if (emu->getImageDepth() == 16) { + in = Image(Image::Format::RGB565, emu->getImageData(), w, h, emu->getImagePitch()); + } else if (emu->getImageDepth() == 32) { + in = Image(Image::Format::RGBX888, emu->getImageData(), w, h, emu->getImagePitch()); + } + in.copyTo(&out); + return {data, (int) w, (int) h, 3}; } double emulatorGetScreenRate(CEmulator* emulator) { - return emulator->emulator->getFrameRate(); + return emulator->emulator->getFrameRate(); } CEmulatorAudio emulatorGetAudio(CEmulator* emulator) { - size_t numSamples = emulator->emulator->getAudioSamples() * 2; - int16_t* samples = new int16_t[numSamples]; - memcpy(samples, emulator->emulator->getAudioData(), numSamples * 2); - return {samples, numSamples}; + size_t numSamples = emulator->emulator->getAudioSamples() * 2; + int16_t* samples = new int16_t[numSamples]; + memcpy(samples, emulator->emulator->getAudioData(), numSamples * 2); + return {samples, numSamples}; } double emulatorGetAudioRate(CEmulator* emulator) { - return emulator->emulator->getAudioRate(); + return emulator->emulator->getAudioRate(); } CEmulatorResolution emulatorGetResolution(CEmulator* emulator) { - auto w = emulator->emulator->getImageWidth(); - auto h = emulator->emulator->getImageHeight(); - return {w, h}; + auto w = emulator->emulator->getImageWidth(); + auto h = emulator->emulator->getImageHeight(); + return {w, h}; } void emulatorSetButtonMask(CEmulator* emulator, uint8_t* mask, size_t maskSize, unsigned int player) { - if (maskSize > N_BUTTONS) { - throw std::runtime_error("mask.size() > N_BUTTONS."); - } - if (player >= MAX_PLAYERS) { - throw std::runtime_error("player >= MAX_PLAYERS."); - } - for (int key = 0; key < maskSize; key++) { - emulator->emulator->setKey(player, key, mask[key]); - } + if (maskSize > N_BUTTONS) { + throw std::runtime_error("mask.size() > N_BUTTONS."); + } + if (player >= MAX_PLAYERS) { + throw std::runtime_error("player >= MAX_PLAYERS."); + } + for (int key = 0; key < maskSize; key++) { + emulator->emulator->setKey(player, key, mask[key]); + } } void emulatorAddCheat(CEmulator* emulator, const char* code) { - emulator->emulator->setCheat(emulator->cheats, true, code); - emulator->cheats++; + emulator->emulator->setCheat(emulator->cheats, true, code); + emulator->cheats++; } void emulatorClearCheats(CEmulator* emulator) { - emulator->emulator->clearCheats(); - emulator->cheats = 0; + emulator->emulator->clearCheats(); + emulator->cheats = 0; } void emulatorConfigureData(CEmulator* emulator, CGameData* gameData) { - emulator->emulator->configureData(gameData->data); + emulator->emulator->configureData(gameData->data); } CMemoryView memoryViewCreate(Retro::AddressSpace* addressSpace) { - return { addressSpace }; + return { addressSpace }; } void memoryViewDelete(CMemoryView* memoryView) { - delete memoryView; + delete memoryView; } int64_t memoryViewExtract(CMemoryView* memoryView, size_t address, const char* type) { - return (*memoryView->addressSpace)[Variable{ type, address }]; + return (*memoryView->addressSpace)[Variable{ type, address }]; } void memoryViewAssign(CMemoryView* memoryView, size_t address, const char* type, int64_t value) { - (*memoryView->addressSpace)[Variable{ type, address }] = value; + (*memoryView->addressSpace)[Variable{ type, address }] = value; } CMemoryBlocks memoryViewBlocks(CMemoryView* memoryView) { - auto& internalBlocks = memoryView->addressSpace->blocks(); - auto numBlocks = internalBlocks.size(); - auto* blocks = new CMemoryBlock[numBlocks]; - auto i = 0; - for (const auto& iter : internalBlocks) { - blocks[i] = {iter.first, static_cast(iter.second.offset(0)), iter.second.size()}; - i++; - } - return {blocks, numBlocks}; + auto& internalBlocks = memoryView->addressSpace->blocks(); + auto numBlocks = internalBlocks.size(); + auto* blocks = new CMemoryBlock[numBlocks]; + auto i = 0; + for (const auto& iter : internalBlocks) { + blocks[i] = {iter.first, static_cast(iter.second.offset(0)), iter.second.size()}; + i++; + } + return {blocks, numBlocks}; } CSearch searchCreate(const char** types, size_t numTypes) { - Retro::Search* search; - if (numTypes > 0) { - std::vector dtypes; - for (int i = 0; i < numTypes; i++) { - dtypes.emplace_back(types[i]); - } - search = new Retro::Search(dtypes); - } else { - search = nullptr; - } - return {search, true}; + Retro::Search* search; + if (numTypes > 0) { + std::vector dtypes; + for (int i = 0; i < numTypes; i++) { + dtypes.emplace_back(types[i]); + } + search = new Retro::Search(dtypes); + } else { + search = nullptr; + } + return {search, true}; } CSearch searchCreateUnmanaged(Retro::Search* search) { - return {search, false}; + return {search, false}; } void searchDelete(CSearch* search) { - if (search->managed) { - delete search->search; - } - delete search; + if (search->managed) { + delete search->search; + } + delete search; } int searchNumResults(CSearch* search) { - return search->search->numResults(); + return search->search->numResults(); } bool searchHasUniqueResult(CSearch* search) { - return search->search->hasUniqueResult(); + return search->search->hasUniqueResult(); } CSearchResult searchUniqueResult(CSearch* search) { - TypedSearchResult result = search->search->uniqueResult(); - return {result.address, result.type.type}; + TypedSearchResult result = search->search->uniqueResult(); + return {result.address, result.type.type}; } // TODO: searchTypedResults CGameData gameDataCreate() { - auto* data = new Retro::GameData(); - auto* scenario = new Retro::Scenario(*data); - return {data, scenario}; + auto* data = new Retro::GameData(); + auto* scenario = new Retro::Scenario(*data); + return {data, scenario}; } void gameDataDelete(CGameData* gameData) { - delete gameData->data; - delete gameData->scenario; - delete gameData; + delete gameData->data; + delete gameData->scenario; + delete gameData; } bool gameDataLoad(CGameData* gameData, const char* dataFilename, const char* scenarioFilename) { - ScriptContext::reset(); + ScriptContext::reset(); - bool success = true; - if (dataFilename != nullptr) { - success = success && gameData->data->load(dataFilename); - } - if (scenarioFilename != nullptr) { - success = success && gameData->scenario->load(scenarioFilename); - } - return success; + bool success = true; + if (dataFilename != nullptr) { + success = success && gameData->data->load(dataFilename); + } + if (scenarioFilename != nullptr) { + success = success && gameData->scenario->load(scenarioFilename); + } + return success; } bool gameDataSave(CGameData* gameData, const char* dataFilename, const char* scenarioFilename) { - ScriptContext::reset(); + ScriptContext::reset(); - bool success = true; - if (dataFilename != nullptr) { - success = success && gameData->data->save(dataFilename); - } - if (scenarioFilename != nullptr) { - success = success && gameData->scenario->save(scenarioFilename); - } - return success; + bool success = true; + if (dataFilename != nullptr) { + success = success && gameData->data->save(dataFilename); + } + if (scenarioFilename != nullptr) { + success = success && gameData->scenario->save(scenarioFilename); + } + return success; } void gameDataReset(CGameData* gameData) { - gameData->scenario->restart(); - gameData->scenario->reloadScripts(); + gameData->scenario->restart(); + gameData->scenario->reloadScripts(); } uint16_t gameDataFilterAction(CGameData* gameData, uint16_t action) { - return gameData->scenario->filterAction(action); + return gameData->scenario->filterAction(action); } CValidActions gameDataValidActions(CGameData* gameData) { - std::map> validActions = gameData->scenario->validActions(); - size_t numActionsOuter = validActions.size(); - int** actions = new int*[numActionsOuter]; + std::map> validActions = gameData->scenario->validActions(); + size_t numActionsOuter = validActions.size(); + int** actions = new int*[numActionsOuter]; size_t* numActionsInner = new size_t[numActionsOuter]; - int i = 0; - for (const auto& action : validActions) { - numActionsInner[i] = action.second.size(); - actions[i] = new int[numActionsInner[i]]; - int j = 0; - for (const auto& act : action.second) { - actions[i][j] = act; - j++; - } - i++; - } - return {actions, numActionsInner, numActionsOuter}; + int i = 0; + for (const auto& action : validActions) { + numActionsInner[i] = action.second.size(); + actions[i] = new int[numActionsInner[i]]; + int j = 0; + for (const auto& act : action.second) { + actions[i][j] = act; + j++; + } + i++; + } + return {actions, numActionsInner, numActionsOuter}; } void gameDataUpdateRam(CGameData* gameData) { - gameData->data->updateRam(); - gameData->scenario->update(); + gameData->data->updateRam(); + gameData->scenario->update(); } // TODO: lookupValue, setValue, lookupAll CVariable gameDataGetVariable(CGameData* gameData, const char* name) { - Retro::Variable var = gameData->data->getVariable(name); - return {name, var.address, var.type.type}; + Retro::Variable var = gameData->data->getVariable(name); + return {name, var.address, var.type.type}; } void gameDataSetVariable(CGameData* gameData, const char* name, CVariable* value) { - Retro::Variable var { value->type, value->address }; - gameData->data->setVariable(name, var); + Retro::Variable var { value->type, value->address }; + gameData->data->setVariable(name, var); } void gameDataRemoveVariable(CGameData* gameData, const char* name) { - gameData->data->removeVariable(name); + gameData->data->removeVariable(name); } CVariables gameDataListVariables(CGameData* gameData) { - const auto& vars = gameData->data->listVariables(); - auto numVariables = vars.size(); - auto* variables = new CVariable[numVariables]; - auto i = 0; - for (const auto& var : vars) { - const auto& v = var.second; - variables[i] = {var.first.c_str(), v.address, v.type.type}; - i++; - } - return {variables, numVariables}; + const auto& vars = gameData->data->listVariables(); + auto numVariables = vars.size(); + auto* variables = new CVariable[numVariables]; + auto i = 0; + for (const auto& var : vars) { + const auto& v = var.second; + variables[i] = {var.first.c_str(), v.address, v.type.type}; + i++; + } + return {variables, numVariables}; } float gameDataCurrentReward(CGameData* gameData, unsigned int player) { - return gameData->scenario->currentReward(player); + return gameData->scenario->currentReward(player); } float gameDataTotalReward(CGameData* gameData, unsigned int player) { - return gameData->scenario->totalReward(player); + return gameData->scenario->totalReward(player); } bool gameDataIsDone(CGameData* gameData) { - return gameData->scenario->isDone(); + return gameData->scenario->isDone(); } CCropInfo gameDataCropInfo(CGameData* gameData, unsigned int player) { - size_t x = 0; - size_t y = 0; - size_t width = 0; - size_t height = 0; - gameData->scenario->getCrop(&x, &y, &width, &height, player); - return {x, y, width, height}; + size_t x = 0; + size_t y = 0; + size_t width = 0; + size_t height = 0; + gameData->scenario->getCrop(&x, &y, &width, &height, player); + return {x, y, width, height}; } CMemoryView gameDataMemory(CGameData* gameData) { - return memoryViewCreate(&gameData->data->addressSpace()); + return memoryViewCreate(&gameData->data->addressSpace()); } void gameDataSearch(CGameData* gameData, const char* name, int64_t value) { - gameData->data->search(name, value); + gameData->data->search(name, value); } void gameDataDeltaSearch(CGameData* gameData, const char* name, const char* op, int64_t ref) { - gameData->data->deltaSearch(name, Retro::Scenario::op(op), ref); + gameData->data->deltaSearch(name, Retro::Scenario::op(op), ref); } CSearch gameDataGetSearch(CGameData* gameData, const char* name) { - return searchCreateUnmanaged(gameData->data->getSearch(name)); + return searchCreateUnmanaged(gameData->data->getSearch(name)); } void gameDataRemoveSearch(CGameData* gameData, const char* name) { - gameData->data->removeSearch(name); + gameData->data->removeSearch(name); } CSearchList gameDataListSearches(CGameData* gameData) { - std::vector names = gameData->data->listSearches(); - const char** cNames = new const char*[names.size()]; - for (int i = 0; i < names.size(); i++) { - cNames[i] = names[i].c_str(); - } - return {cNames, names.size()}; + std::vector names = gameData->data->listSearches(); + const char** cNames = new const char*[names.size()]; + for (int i = 0; i < names.size(); i++) { + cNames[i] = names[i].c_str(); + } + return {cNames, names.size()}; } CMovie movieCreate(const char* name, bool record, unsigned int players) { - Retro::Movie* movie; - if (record) { - movie = new MovieBK2(name, true, players); - } else { - movie = Movie::load(name).get(); - } - if (!movie) { - throw std::runtime_error("Could not load movie"); - } - return {movie, record}; + Retro::Movie* movie; + if (record) { + movie = new MovieBK2(name, true, players); + } else { + movie = Movie::load(name).get(); + } + if (!movie) { + throw std::runtime_error("Could not load movie"); + } + return {movie, record}; } void movieDelete(CMovie* movie) { - delete movie->movie; - delete movie; + delete movie->movie; + delete movie; } void movieConfigure(CMovie* movie, const char* name, CEmulator* emulator) { - if (movie->recording) { - static_cast(movie->movie)->setGameName(name); - static_cast(movie->movie)->loadKeymap(emulator->emulator->core()); - } + if (movie->recording) { + static_cast(movie->movie)->setGameName(name); + static_cast(movie->movie)->loadKeymap(emulator->emulator->core()); + } } const char* movieGetGameName(CMovie* movie) { - return movie->movie->getGameName().c_str(); + return movie->movie->getGameName().c_str(); } bool movieStep(CMovie* movie) { - return movie->movie->step(); + return movie->movie->step(); } void movieClose(CMovie* movie) { - movie->movie->close(); + movie->movie->close(); } unsigned int moviePlayers(CMovie* movie) { - return movie->movie->players(); + return movie->movie->players(); } bool movieGetKey(CMovie* movie, int key, unsigned int player) { - return movie->movie->getKey(key, player); + return movie->movie->getKey(key, player); } void movieSetKey(CMovie* movie, int key, bool set, unsigned int player) { - movie->movie->setKey(key, set, player); + movie->movie->setKey(key, set, player); } CBytes movieGetState(CMovie* movie) { - std::vector data; - movie->movie->getState(&data); - return {reinterpret_cast(data.data()), data.size()}; + std::vector data; + movie->movie->getState(&data); + return {reinterpret_cast(data.data()), data.size()}; } void movieSetState(CMovie* movie, CBytes* state) { - movie->movie->setState(reinterpret_cast(state->bytes), state->numBytes); + movie->movie->setState(reinterpret_cast(state->bytes), state->numBytes); } bool retroLoadCoreInfo(const char* json) { - return Retro::loadCoreInfo(json); + return Retro::loadCoreInfo(json); } const char* retroCorePath(const char* hint) { - return Retro::corePath(hint).c_str(); + return Retro::corePath(hint).c_str(); } const char* retroDataPath(const char* hint) { - return Retro::GameData::dataPath(hint).c_str(); + return Retro::GameData::dataPath(hint).c_str(); } diff --git a/src/retro-c.h b/src/retro-c.h index dcbb81e72..b4962a4e2 100644 --- a/src/retro-c.h +++ b/src/retro-c.h @@ -9,7 +9,7 @@ extern "C" { typedef struct CEmulator { Retro::Emulator* emulator; - int cheats; + int cheats; } CEmulator; typedef struct CEmulatorScreen { @@ -46,7 +46,7 @@ typedef struct CMemoryBlocks { typedef struct CSearch { Retro::Search* search; - bool managed; + bool managed; } CSearch; typedef struct CSearchList { @@ -56,18 +56,18 @@ typedef struct CSearchList { typedef struct CSearchResult { size_t address; - const char* type; + const char* type; } CSearchResult; typedef struct CGameData { Retro::GameData* data; - Retro::Scenario* scenario; + Retro::Scenario* scenario; } CGameData; typedef struct CVariable { const char* name; size_t address; - const char* type; + const char* type; } CVariable; typedef struct CVariables { @@ -83,17 +83,17 @@ typedef struct CValidActions { typedef struct CMovie { Retro::Movie* movie; - bool recording; + bool recording; } CMovie; typedef struct CBytes { void* bytes; - size_t numBytes; + size_t numBytes; } CBytes; typedef struct CCropInfo { size_t x; - size_t y; + size_t y; size_t width; size_t height; } CCropInfo; From d0881e9d378716f17b72cee70da5ef1b26062c50 Mon Sep 17 00:00:00 2001 From: Anthony Platanios Date: Thu, 4 Apr 2019 20:55:25 -0400 Subject: [PATCH 07/33] Added support for some more of the missing functions to the C API. --- src/retro-c.cpp | 26 +++++++++++++++++++++++++- src/retro-c.h | 8 +++++++- 2 files changed, 32 insertions(+), 2 deletions(-) diff --git a/src/retro-c.cpp b/src/retro-c.cpp index e541662f8..a95a56f84 100644 --- a/src/retro-c.cpp +++ b/src/retro-c.cpp @@ -266,7 +266,31 @@ void gameDataUpdateRam(CGameData* gameData) { gameData->scenario->update(); } -// TODO: lookupValue, setValue, lookupAll +bool gameDataLookupBoolValue(CGameData* gameData, const char* name) { + return bool(gameData->data->lookupValue(name)); +} + +int64_t gameDataLookupIntValue(CGameData* gameData, const char* name) { + return int64_t(gameData->data->lookupValue(name)); +} + +double gameDataLookupDoubleValue(CGameData* gameData, const char* name) { + return double(gameData->data->lookupValue(name)); +} + +void gameDataSetBoolValue(CGameData* gameData, const char* name, bool value) { + gameData->data->setValue(name, Variant(value)); +} + +void gameDataSetIntValue(CGameData* gameData, const char* name, int64_t value) { + gameData->data->setValue(name, Variant(value)); +} + +void gameDataSetDoubleValue(CGameData* gameData, const char* name, double value) { + gameData->data->setValue(name, Variant(value)); +} + +// TODO: lookupAll CVariable gameDataGetVariable(CGameData* gameData, const char* name) { Retro::Variable var = gameData->data->getVariable(name); diff --git a/src/retro-c.h b/src/retro-c.h index b4962a4e2..d95935c6e 100644 --- a/src/retro-c.h +++ b/src/retro-c.h @@ -135,7 +135,13 @@ void gameDataReset(CGameData* gameData); uint16_t gameDataFilterAction(CGameData* gameData, uint16_t action); CValidActions gameDataValidActions(CGameData* gameData); void gameDataUpdateRam(CGameData* gameData); -// TODO: lookupValue, setValue, lookupAll +bool gameDataLookupBoolValue(CGameData* gameData, const char* name); +int64_t gameDataLookupIntValue(CGameData* gameData, const char* name); +double gameDataLookupDoubleValue(CGameData* gameData, const char* name); +void gameDataSetBoolValue(CGameData* gameData, const char* name, bool value); +void gameDataSetIntValue(CGameData* gameData, const char* name, int64_t value); +void gameDataSetDoubleValue(CGameData* gameData, const char* name, double value); +// TODO: lookupAll CVariable gameDataGetVariable(CGameData* gameData, const char* name); void gameDataSetVariable(CGameData* gameData, const char* name, CVariable* value); void gameDataRemoveVariable(CGameData* gameData, const char* name); From fb4e05d6ee9dea9606429344d8f92bfb1e737901 Mon Sep 17 00:00:00 2001 From: Anthony Platanios Date: Thu, 4 Apr 2019 21:03:07 -0400 Subject: [PATCH 08/33] Added support for one more of the missing functions to the C API. --- src/retro-c.cpp | 13 +++++++++++-- src/retro-c.h | 8 ++++---- 2 files changed, 15 insertions(+), 6 deletions(-) diff --git a/src/retro-c.cpp b/src/retro-c.cpp index a95a56f84..74db31ca3 100644 --- a/src/retro-c.cpp +++ b/src/retro-c.cpp @@ -290,7 +290,16 @@ void gameDataSetDoubleValue(CGameData* gameData, const char* name, double value) gameData->data->setValue(name, Variant(value)); } -// TODO: lookupAll +CNames gameDataLookupKeys(CGameData* gameData) { + std::unordered_map allValues = gameData->data->lookupAll(); + const char** cNames = new const char*[allValues.size()]; + auto i = 0; + for (const auto& var : allValues) { + cNames[i] = var.first.c_str(); + i++; + } + return {cNames, allValues.size()}; +} CVariable gameDataGetVariable(CGameData* gameData, const char* name) { Retro::Variable var = gameData->data->getVariable(name); @@ -360,7 +369,7 @@ void gameDataRemoveSearch(CGameData* gameData, const char* name) { gameData->data->removeSearch(name); } -CSearchList gameDataListSearches(CGameData* gameData) { +CNames gameDataListSearchNames(CGameData* gameData) { std::vector names = gameData->data->listSearches(); const char** cNames = new const char*[names.size()]; for (int i = 0; i < names.size(); i++) { diff --git a/src/retro-c.h b/src/retro-c.h index d95935c6e..0038b3354 100644 --- a/src/retro-c.h +++ b/src/retro-c.h @@ -49,10 +49,10 @@ typedef struct CSearch { bool managed; } CSearch; -typedef struct CSearchList { +typedef struct CNames { const char** names; size_t numNames; -} CSearchList; +} CNames; typedef struct CSearchResult { size_t address; @@ -141,7 +141,7 @@ double gameDataLookupDoubleValue(CGameData* gameData, const char* name); void gameDataSetBoolValue(CGameData* gameData, const char* name, bool value); void gameDataSetIntValue(CGameData* gameData, const char* name, int64_t value); void gameDataSetDoubleValue(CGameData* gameData, const char* name, double value); -// TODO: lookupAll +CNames gameDataLookupKeys(CGameData* gameData); CVariable gameDataGetVariable(CGameData* gameData, const char* name); void gameDataSetVariable(CGameData* gameData, const char* name, CVariable* value); void gameDataRemoveVariable(CGameData* gameData, const char* name); @@ -155,7 +155,7 @@ void gameDataSearch(CGameData* gameData, const char* name, int64_t value); void gameDataDeltaSearch(CGameData* gameData, const char* name, const char* op, int64_t ref); CSearch gameDataGetSearch(CGameData* gameData, const char* name); void gameDataRemoveSearch(CGameData* gameData, const char* name); -CSearchList gameDataListSearches(CGameData* gameData); +CNames gameDataListSearchNames(CGameData* gameData); CMovie movieCreate(const char* name, bool record, unsigned int players); void movieDelete(CMovie* movie); From e45dea1623c17d1e4214712351870c30de4e8d10 Mon Sep 17 00:00:00 2001 From: Anthony Platanios Date: Thu, 4 Apr 2019 21:14:34 -0400 Subject: [PATCH 09/33] Added the last missing functions to the C API. --- src/retro-c.cpp | 26 +++++++++++++++++++++++++- src/retro-c.h | 16 +++++++++++++++- 2 files changed, 40 insertions(+), 2 deletions(-) diff --git a/src/retro-c.cpp b/src/retro-c.cpp index 74db31ca3..981af04c5 100644 --- a/src/retro-c.cpp +++ b/src/retro-c.cpp @@ -193,7 +193,31 @@ CSearchResult searchUniqueResult(CSearch* search) { return {result.address, result.type.type}; } -// TODO: searchTypedResults +CSearchTypedResults searchTypedResults(CSearch* search) { + std::map> results; + for (const auto& result : search->search->typedResults()) { + results[static_cast(result)].emplace(result.type); + } + CSearchTypedResult* cResults = new CSearchTypedResult[results.size()]; + int i = 0; + for (const auto& result : results) { + const char** types = new const char*[result.second.size()]; + int j = 0; + for (const auto& type : result.second) { + types[j] = type.type; + j++; + } + cResults[i] = { + result.first.address, + result.first.mult, + result.first.div, + result.first.bias, + types, + result.second.size()}; + i++; + } + return {cResults, results.size()}; +} CGameData gameDataCreate() { auto* data = new Retro::GameData(); diff --git a/src/retro-c.h b/src/retro-c.h index 0038b3354..4e43cea8f 100644 --- a/src/retro-c.h +++ b/src/retro-c.h @@ -59,6 +59,20 @@ typedef struct CSearchResult { const char* type; } CSearchResult; +typedef struct CSearchTypedResult { + size_t address; + uint64_t mult; + uint64_t div; + int64_t bias; + const char** types; + size_t numTypes; +} CSearchTypedResult; + +typedef struct CSearchTypedResults { + CSearchTypedResult* results; + size_t numResults; +} CSearchTypedResults; + typedef struct CGameData { Retro::GameData* data; Retro::Scenario* scenario; @@ -125,7 +139,7 @@ void searchDelete(CSearch* search); int searchNumResults(CSearch* search); bool searchHasUniqueResult(CSearch* search); CSearchResult searchUniqueResult(CSearch* search); -// TODO: searchTypedResults +CSearchTypedResults searchTypedResults(CSearch* search); CGameData gameDataCreate(); void gameDataDelete(CGameData* gameData); From c994fb46111d510b9a89da3af78c253afcb1f4a4 Mon Sep 17 00:00:00 2001 From: Anthony Platanios Date: Thu, 4 Apr 2019 23:05:35 -0400 Subject: [PATCH 10/33] Made some fixes. --- src/retro-c.cpp | 138 ++++++++++++++++++++++++------------------------ src/retro-c.h | 23 ++++---- 2 files changed, 80 insertions(+), 81 deletions(-) diff --git a/src/retro-c.cpp b/src/retro-c.cpp index 981af04c5..e8fa0f54f 100644 --- a/src/retro-c.cpp +++ b/src/retro-c.cpp @@ -45,27 +45,27 @@ CEmulator emulatorCreate(const char* romPath) { } void emulatorDelete(CEmulator* emulator) { - delete emulator->emulator; + delete ((Retro::Emulator*) emulator->emulator); delete emulator; } void emulatorStep(CEmulator* emulator) { - emulator->emulator->run(); + ((Retro::Emulator*) emulator->emulator)->run(); } CBytes emulatorGetState(CEmulator* emulator) { - size_t numBytes = emulator->emulator->serializeSize(); + size_t numBytes = ((Retro::Emulator*) emulator->emulator)->serializeSize(); void* bytes = malloc(numBytes); - emulator->emulator->serialize(bytes, numBytes); + ((Retro::Emulator*) emulator->emulator)->serialize(bytes, numBytes); return {bytes, numBytes}; } bool emulatorSetState(CEmulator* emulator, CBytes* state) { - return emulator->emulator->unserialize(state->bytes, state->numBytes); + return ((Retro::Emulator*) emulator->emulator)->unserialize(state->bytes, state->numBytes); } CEmulatorScreen emulatorGetScreen(CEmulator* emulator) { - auto* emu = emulator->emulator; + auto* emu = ((Retro::Emulator*) emulator->emulator); long w = emu->getImageWidth(); long h = emu->getImageHeight(); uint8_t* data = new uint8_t[w * h * 3]; @@ -81,23 +81,23 @@ CEmulatorScreen emulatorGetScreen(CEmulator* emulator) { } double emulatorGetScreenRate(CEmulator* emulator) { - return emulator->emulator->getFrameRate(); + return ((Retro::Emulator*) emulator->emulator)->getFrameRate(); } CEmulatorAudio emulatorGetAudio(CEmulator* emulator) { - size_t numSamples = emulator->emulator->getAudioSamples() * 2; + size_t numSamples = ((Retro::Emulator*) emulator->emulator)->getAudioSamples() * 2; int16_t* samples = new int16_t[numSamples]; - memcpy(samples, emulator->emulator->getAudioData(), numSamples * 2); + memcpy(samples, ((Retro::Emulator*) emulator->emulator)->getAudioData(), numSamples * 2); return {samples, numSamples}; } double emulatorGetAudioRate(CEmulator* emulator) { - return emulator->emulator->getAudioRate(); + return ((Retro::Emulator*) emulator->emulator)->getAudioRate(); } CEmulatorResolution emulatorGetResolution(CEmulator* emulator) { - auto w = emulator->emulator->getImageWidth(); - auto h = emulator->emulator->getImageHeight(); + auto w = ((Retro::Emulator*) emulator->emulator)->getImageWidth(); + auto h = ((Retro::Emulator*) emulator->emulator)->getImageHeight(); return {w, h}; } @@ -109,26 +109,26 @@ void emulatorSetButtonMask(CEmulator* emulator, uint8_t* mask, size_t maskSize, throw std::runtime_error("player >= MAX_PLAYERS."); } for (int key = 0; key < maskSize; key++) { - emulator->emulator->setKey(player, key, mask[key]); + ((Retro::Emulator*) emulator->emulator)->setKey(player, key, mask[key]); } } void emulatorAddCheat(CEmulator* emulator, const char* code) { - emulator->emulator->setCheat(emulator->cheats, true, code); + ((Retro::Emulator*) emulator->emulator)->setCheat(emulator->cheats, true, code); emulator->cheats++; } void emulatorClearCheats(CEmulator* emulator) { - emulator->emulator->clearCheats(); + ((Retro::Emulator*) emulator->emulator)->clearCheats(); emulator->cheats = 0; } void emulatorConfigureData(CEmulator* emulator, CGameData* gameData) { - emulator->emulator->configureData(gameData->data); + ((Retro::Emulator*) emulator->emulator)->configureData(((Retro::GameData*) gameData->data)); } -CMemoryView memoryViewCreate(Retro::AddressSpace* addressSpace) { - return { addressSpace }; +CMemoryView memoryViewCreate(void* addressSpace) { + return { (Retro::AddressSpace*) addressSpace }; } void memoryViewDelete(CMemoryView* memoryView) { @@ -136,15 +136,15 @@ void memoryViewDelete(CMemoryView* memoryView) { } int64_t memoryViewExtract(CMemoryView* memoryView, size_t address, const char* type) { - return (*memoryView->addressSpace)[Variable{ type, address }]; + return (*((Retro::AddressSpace*) memoryView->addressSpace))[Variable{ type, address }]; } void memoryViewAssign(CMemoryView* memoryView, size_t address, const char* type, int64_t value) { - (*memoryView->addressSpace)[Variable{ type, address }] = value; + (*((Retro::AddressSpace*) memoryView->addressSpace))[Variable{ type, address }] = value; } CMemoryBlocks memoryViewBlocks(CMemoryView* memoryView) { - auto& internalBlocks = memoryView->addressSpace->blocks(); + auto& internalBlocks = ((Retro::AddressSpace*) memoryView->addressSpace)->blocks(); auto numBlocks = internalBlocks.size(); auto* blocks = new CMemoryBlock[numBlocks]; auto i = 0; @@ -175,27 +175,27 @@ CSearch searchCreateUnmanaged(Retro::Search* search) { void searchDelete(CSearch* search) { if (search->managed) { - delete search->search; + delete ((Retro::Search*) search->search); } delete search; } int searchNumResults(CSearch* search) { - return search->search->numResults(); + return ((Retro::Search*) search->search)->numResults(); } bool searchHasUniqueResult(CSearch* search) { - return search->search->hasUniqueResult(); + return ((Retro::Search*) search->search)->hasUniqueResult(); } CSearchResult searchUniqueResult(CSearch* search) { - TypedSearchResult result = search->search->uniqueResult(); + TypedSearchResult result = ((Retro::Search*) search->search)->uniqueResult(); return {result.address, result.type.type}; } CSearchTypedResults searchTypedResults(CSearch* search) { std::map> results; - for (const auto& result : search->search->typedResults()) { + for (const auto& result : ((Retro::Search*) search->search)->typedResults()) { results[static_cast(result)].emplace(result.type); } CSearchTypedResult* cResults = new CSearchTypedResult[results.size()]; @@ -226,8 +226,8 @@ CGameData gameDataCreate() { } void gameDataDelete(CGameData* gameData) { - delete gameData->data; - delete gameData->scenario; + delete ((Retro::GameData*) gameData->data); + delete ((Retro::Scenario*) gameData->scenario); delete gameData; } @@ -236,10 +236,10 @@ bool gameDataLoad(CGameData* gameData, const char* dataFilename, const char* sce bool success = true; if (dataFilename != nullptr) { - success = success && gameData->data->load(dataFilename); + success = success && ((Retro::GameData*) gameData->data)->load(dataFilename); } if (scenarioFilename != nullptr) { - success = success && gameData->scenario->load(scenarioFilename); + success = success && ((Retro::Scenario*) gameData->scenario)->load(scenarioFilename); } return success; } @@ -249,25 +249,25 @@ bool gameDataSave(CGameData* gameData, const char* dataFilename, const char* sce bool success = true; if (dataFilename != nullptr) { - success = success && gameData->data->save(dataFilename); + success = success && ((Retro::GameData*) gameData->data)->save(dataFilename); } if (scenarioFilename != nullptr) { - success = success && gameData->scenario->save(scenarioFilename); + success = success && ((Retro::Scenario*) gameData->scenario)->save(scenarioFilename); } return success; } void gameDataReset(CGameData* gameData) { - gameData->scenario->restart(); - gameData->scenario->reloadScripts(); + ((Retro::Scenario*) gameData->scenario)->restart(); + ((Retro::Scenario*) gameData->scenario)->reloadScripts(); } uint16_t gameDataFilterAction(CGameData* gameData, uint16_t action) { - return gameData->scenario->filterAction(action); + return ((Retro::Scenario*) gameData->scenario)->filterAction(action); } CValidActions gameDataValidActions(CGameData* gameData) { - std::map> validActions = gameData->scenario->validActions(); + std::map> validActions = ((Retro::Scenario*) gameData->scenario)->validActions(); size_t numActionsOuter = validActions.size(); int** actions = new int*[numActionsOuter]; size_t* numActionsInner = new size_t[numActionsOuter]; @@ -286,36 +286,36 @@ CValidActions gameDataValidActions(CGameData* gameData) { } void gameDataUpdateRam(CGameData* gameData) { - gameData->data->updateRam(); - gameData->scenario->update(); + ((Retro::GameData*) gameData->data)->updateRam(); + ((Retro::Scenario*) gameData->scenario)->update(); } bool gameDataLookupBoolValue(CGameData* gameData, const char* name) { - return bool(gameData->data->lookupValue(name)); + return bool(((Retro::GameData*) gameData->data)->lookupValue(name)); } int64_t gameDataLookupIntValue(CGameData* gameData, const char* name) { - return int64_t(gameData->data->lookupValue(name)); + return int64_t(((Retro::GameData*) gameData->data)->lookupValue(name)); } double gameDataLookupDoubleValue(CGameData* gameData, const char* name) { - return double(gameData->data->lookupValue(name)); + return double(((Retro::GameData*) gameData->data)->lookupValue(name)); } void gameDataSetBoolValue(CGameData* gameData, const char* name, bool value) { - gameData->data->setValue(name, Variant(value)); + ((Retro::GameData*) gameData->data)->setValue(name, Variant(value)); } void gameDataSetIntValue(CGameData* gameData, const char* name, int64_t value) { - gameData->data->setValue(name, Variant(value)); + ((Retro::GameData*) gameData->data)->setValue(name, Variant(value)); } void gameDataSetDoubleValue(CGameData* gameData, const char* name, double value) { - gameData->data->setValue(name, Variant(value)); + ((Retro::GameData*) gameData->data)->setValue(name, Variant(value)); } CNames gameDataLookupKeys(CGameData* gameData) { - std::unordered_map allValues = gameData->data->lookupAll(); + std::unordered_map allValues = ((Retro::GameData*) gameData->data)->lookupAll(); const char** cNames = new const char*[allValues.size()]; auto i = 0; for (const auto& var : allValues) { @@ -326,21 +326,21 @@ CNames gameDataLookupKeys(CGameData* gameData) { } CVariable gameDataGetVariable(CGameData* gameData, const char* name) { - Retro::Variable var = gameData->data->getVariable(name); + Retro::Variable var = ((Retro::GameData*) gameData->data)->getVariable(name); return {name, var.address, var.type.type}; } void gameDataSetVariable(CGameData* gameData, const char* name, CVariable* value) { Retro::Variable var { value->type, value->address }; - gameData->data->setVariable(name, var); + ((Retro::GameData*) gameData->data)->setVariable(name, var); } void gameDataRemoveVariable(CGameData* gameData, const char* name) { - gameData->data->removeVariable(name); + ((Retro::GameData*) gameData->data)->removeVariable(name); } CVariables gameDataListVariables(CGameData* gameData) { - const auto& vars = gameData->data->listVariables(); + const auto& vars = ((Retro::GameData*) gameData->data)->listVariables(); auto numVariables = vars.size(); auto* variables = new CVariable[numVariables]; auto i = 0; @@ -353,15 +353,15 @@ CVariables gameDataListVariables(CGameData* gameData) { } float gameDataCurrentReward(CGameData* gameData, unsigned int player) { - return gameData->scenario->currentReward(player); + return ((Retro::Scenario*) gameData->scenario)->currentReward(player); } float gameDataTotalReward(CGameData* gameData, unsigned int player) { - return gameData->scenario->totalReward(player); + return ((Retro::Scenario*) gameData->scenario)->totalReward(player); } bool gameDataIsDone(CGameData* gameData) { - return gameData->scenario->isDone(); + return ((Retro::Scenario*) gameData->scenario)->isDone(); } CCropInfo gameDataCropInfo(CGameData* gameData, unsigned int player) { @@ -369,32 +369,32 @@ CCropInfo gameDataCropInfo(CGameData* gameData, unsigned int player) { size_t y = 0; size_t width = 0; size_t height = 0; - gameData->scenario->getCrop(&x, &y, &width, &height, player); + ((Retro::Scenario*) gameData->scenario)->getCrop(&x, &y, &width, &height, player); return {x, y, width, height}; } CMemoryView gameDataMemory(CGameData* gameData) { - return memoryViewCreate(&gameData->data->addressSpace()); + return memoryViewCreate(&((Retro::GameData*) gameData->data)->addressSpace()); } void gameDataSearch(CGameData* gameData, const char* name, int64_t value) { - gameData->data->search(name, value); + ((Retro::GameData*) gameData->data)->search(name, value); } void gameDataDeltaSearch(CGameData* gameData, const char* name, const char* op, int64_t ref) { - gameData->data->deltaSearch(name, Retro::Scenario::op(op), ref); + ((Retro::GameData*) gameData->data)->deltaSearch(name, Retro::Scenario::op(op), ref); } CSearch gameDataGetSearch(CGameData* gameData, const char* name) { - return searchCreateUnmanaged(gameData->data->getSearch(name)); + return searchCreateUnmanaged(((Retro::GameData*) gameData->data)->getSearch(name)); } void gameDataRemoveSearch(CGameData* gameData, const char* name) { - gameData->data->removeSearch(name); + ((Retro::GameData*) gameData->data)->removeSearch(name); } CNames gameDataListSearchNames(CGameData* gameData) { - std::vector names = gameData->data->listSearches(); + std::vector names = ((Retro::GameData*) gameData->data)->listSearches(); const char** cNames = new const char*[names.size()]; for (int i = 0; i < names.size(); i++) { cNames[i] = names[i].c_str(); @@ -416,49 +416,49 @@ CMovie movieCreate(const char* name, bool record, unsigned int players) { } void movieDelete(CMovie* movie) { - delete movie->movie; + delete (Retro::Movie*) movie->movie; delete movie; } void movieConfigure(CMovie* movie, const char* name, CEmulator* emulator) { if (movie->recording) { static_cast(movie->movie)->setGameName(name); - static_cast(movie->movie)->loadKeymap(emulator->emulator->core()); + static_cast(movie->movie)->loadKeymap(((Retro::Emulator*) ((Retro::Emulator*) emulator->emulator))->core()); } } const char* movieGetGameName(CMovie* movie) { - return movie->movie->getGameName().c_str(); + return ((Retro::Movie*) movie->movie)->getGameName().c_str(); } bool movieStep(CMovie* movie) { - return movie->movie->step(); + return ((Retro::Movie*) movie->movie)->step(); } void movieClose(CMovie* movie) { - movie->movie->close(); + ((Retro::Movie*) movie->movie)->close(); } unsigned int moviePlayers(CMovie* movie) { - return movie->movie->players(); + return ((Retro::Movie*) movie->movie)->players(); } bool movieGetKey(CMovie* movie, int key, unsigned int player) { - return movie->movie->getKey(key, player); + return ((Retro::Movie*) movie->movie)->getKey(key, player); } void movieSetKey(CMovie* movie, int key, bool set, unsigned int player) { - movie->movie->setKey(key, set, player); + ((Retro::Movie*) movie->movie)->setKey(key, set, player); } CBytes movieGetState(CMovie* movie) { std::vector data; - movie->movie->getState(&data); + ((Retro::Movie*) movie->movie)->getState(&data); return {reinterpret_cast(data.data()), data.size()}; } void movieSetState(CMovie* movie, CBytes* state) { - movie->movie->setState(reinterpret_cast(state->bytes), state->numBytes); + ((Retro::Movie*) movie->movie)->setState(reinterpret_cast(state->bytes), state->numBytes); } bool retroLoadCoreInfo(const char* json) { diff --git a/src/retro-c.h b/src/retro-c.h index 4e43cea8f..1f9e8de69 100644 --- a/src/retro-c.h +++ b/src/retro-c.h @@ -1,14 +1,13 @@ -#include "data.h" -#include "movie.h" - -using namespace Retro; +#include +#include +#include #ifdef __cplusplus extern "C" { #endif typedef struct CEmulator { - Retro::Emulator* emulator; + void* emulator; int cheats; } CEmulator; @@ -30,7 +29,7 @@ typedef struct CEmulatorResolution { } CEmulatorResolution; typedef struct CMemoryView { - Retro::AddressSpace* addressSpace; + void* addressSpace; } CMemoryView; typedef struct CMemoryBlock { @@ -45,7 +44,7 @@ typedef struct CMemoryBlocks { } CMemoryBlocks; typedef struct CSearch { - Retro::Search* search; + void* search; bool managed; } CSearch; @@ -74,8 +73,8 @@ typedef struct CSearchTypedResults { } CSearchTypedResults; typedef struct CGameData { - Retro::GameData* data; - Retro::Scenario* scenario; + void* data; + void* scenario; } CGameData; typedef struct CVariable { @@ -96,7 +95,7 @@ typedef struct CValidActions { } CValidActions; typedef struct CMovie { - Retro::Movie* movie; + void* movie; bool recording; } CMovie; @@ -127,14 +126,14 @@ void emulatorAddCheat(CEmulator* emulator, const char* code); void emulatorClearCheats(CEmulator* emulator); void emulatorConfigureData(CEmulator* emulator, CGameData* gameData); -CMemoryView memoryViewCreate(Retro::AddressSpace* addressSpace); +CMemoryView memoryViewCreate(void* addressSpace); void memoryViewDelete(CMemoryView* memoryView); int64_t memoryViewExtract(CMemoryView* memoryView, size_t address, const char* type); void memoryViewAssign(CMemoryView* memoryView, size_t address, const char* type, int64_t value); CMemoryBlocks memoryViewBlocks(CMemoryView* memoryView); CSearch searchCreate(const char** types, size_t numTypes); -CSearch searchCreateUnmanaged(Retro::Search* search); +CSearch searchCreateUnmanaged(void* search); void searchDelete(CSearch* search); int searchNumResults(CSearch* search); bool searchHasUniqueResult(CSearch* search); From 485cbe60ff24f664af0fe0cf1e8c948c88b52828 Mon Sep 17 00:00:00 2001 From: Anthony Platanios Date: Fri, 5 Apr 2019 11:08:08 -0400 Subject: [PATCH 11/33] Avoided copies. --- src/retro-c.cpp | 104 +++++++++++++++++++++--------------------------- src/retro-c.h | 44 ++++++++++---------- 2 files changed, 68 insertions(+), 80 deletions(-) diff --git a/src/retro-c.cpp b/src/retro-c.cpp index e8fa0f54f..6fae08bb9 100644 --- a/src/retro-c.cpp +++ b/src/retro-c.cpp @@ -1,16 +1,5 @@ #include "retro-c.h" -#include -#ifdef _WIN32 -// pyconfig.h doesn't seem to like hypot, so we need to work around it. -namespace std { -template -static inline T _hypot(T x, T y) { - return hypot(x, y); -} -} -#endif - #include "coreinfo.h" #include "data.h" #include "emulator.h" @@ -25,10 +14,9 @@ static inline T _hypot(T x, T y) { #include #include -using std::string; using namespace Retro; -CEmulator emulatorCreate(const char* romPath) { +CEmulator* emulatorCreate(const char* romPath) { Retro::Emulator emulator; if (Emulator::isLoaded()) { throw std::runtime_error( @@ -41,7 +29,7 @@ CEmulator emulatorCreate(const char* romPath) { // The following is necessary because otherwise, you get a segfault // when you try to get the screen for the first time. emulator.run(); - return {&emulator, 0}; + return new CEmulator {&emulator, 0}; } void emulatorDelete(CEmulator* emulator) { @@ -53,18 +41,18 @@ void emulatorStep(CEmulator* emulator) { ((Retro::Emulator*) emulator->emulator)->run(); } -CBytes emulatorGetState(CEmulator* emulator) { +CBytes* emulatorGetState(CEmulator* emulator) { size_t numBytes = ((Retro::Emulator*) emulator->emulator)->serializeSize(); void* bytes = malloc(numBytes); ((Retro::Emulator*) emulator->emulator)->serialize(bytes, numBytes); - return {bytes, numBytes}; + return new CBytes {bytes, numBytes}; } bool emulatorSetState(CEmulator* emulator, CBytes* state) { return ((Retro::Emulator*) emulator->emulator)->unserialize(state->bytes, state->numBytes); } -CEmulatorScreen emulatorGetScreen(CEmulator* emulator) { +CEmulatorScreen* emulatorGetScreen(CEmulator* emulator) { auto* emu = ((Retro::Emulator*) emulator->emulator); long w = emu->getImageWidth(); long h = emu->getImageHeight(); @@ -77,28 +65,28 @@ CEmulatorScreen emulatorGetScreen(CEmulator* emulator) { in = Image(Image::Format::RGBX888, emu->getImageData(), w, h, emu->getImagePitch()); } in.copyTo(&out); - return {data, (int) w, (int) h, 3}; + return new CEmulatorScreen {data, (int) w, (int) h, 3}; } double emulatorGetScreenRate(CEmulator* emulator) { return ((Retro::Emulator*) emulator->emulator)->getFrameRate(); } -CEmulatorAudio emulatorGetAudio(CEmulator* emulator) { +CEmulatorAudio* emulatorGetAudio(CEmulator* emulator) { size_t numSamples = ((Retro::Emulator*) emulator->emulator)->getAudioSamples() * 2; int16_t* samples = new int16_t[numSamples]; memcpy(samples, ((Retro::Emulator*) emulator->emulator)->getAudioData(), numSamples * 2); - return {samples, numSamples}; + return new CEmulatorAudio {samples, numSamples}; } double emulatorGetAudioRate(CEmulator* emulator) { return ((Retro::Emulator*) emulator->emulator)->getAudioRate(); } -CEmulatorResolution emulatorGetResolution(CEmulator* emulator) { +CEmulatorResolution* emulatorGetResolution(CEmulator* emulator) { auto w = ((Retro::Emulator*) emulator->emulator)->getImageWidth(); auto h = ((Retro::Emulator*) emulator->emulator)->getImageHeight(); - return {w, h}; + return new CEmulatorResolution {w, h}; } void emulatorSetButtonMask(CEmulator* emulator, uint8_t* mask, size_t maskSize, unsigned int player) { @@ -127,8 +115,8 @@ void emulatorConfigureData(CEmulator* emulator, CGameData* gameData) { ((Retro::Emulator*) emulator->emulator)->configureData(((Retro::GameData*) gameData->data)); } -CMemoryView memoryViewCreate(void* addressSpace) { - return { (Retro::AddressSpace*) addressSpace }; +CMemoryView* memoryViewCreate(void* addressSpace) { + return new CMemoryView { (Retro::AddressSpace*) addressSpace }; } void memoryViewDelete(CMemoryView* memoryView) { @@ -143,7 +131,7 @@ void memoryViewAssign(CMemoryView* memoryView, size_t address, const char* type, (*((Retro::AddressSpace*) memoryView->addressSpace))[Variable{ type, address }] = value; } -CMemoryBlocks memoryViewBlocks(CMemoryView* memoryView) { +CMemoryBlocks* memoryViewBlocks(CMemoryView* memoryView) { auto& internalBlocks = ((Retro::AddressSpace*) memoryView->addressSpace)->blocks(); auto numBlocks = internalBlocks.size(); auto* blocks = new CMemoryBlock[numBlocks]; @@ -152,10 +140,10 @@ CMemoryBlocks memoryViewBlocks(CMemoryView* memoryView) { blocks[i] = {iter.first, static_cast(iter.second.offset(0)), iter.second.size()}; i++; } - return {blocks, numBlocks}; + return new CMemoryBlocks {blocks, numBlocks}; } -CSearch searchCreate(const char** types, size_t numTypes) { +CSearch* searchCreate(const char** types, size_t numTypes) { Retro::Search* search; if (numTypes > 0) { std::vector dtypes; @@ -166,11 +154,11 @@ CSearch searchCreate(const char** types, size_t numTypes) { } else { search = nullptr; } - return {search, true}; + return new CSearch {search, true}; } -CSearch searchCreateUnmanaged(Retro::Search* search) { - return {search, false}; +CSearch* searchCreateUnmanaged(Retro::Search* search) { + return new CSearch {search, false}; } void searchDelete(CSearch* search) { @@ -188,12 +176,12 @@ bool searchHasUniqueResult(CSearch* search) { return ((Retro::Search*) search->search)->hasUniqueResult(); } -CSearchResult searchUniqueResult(CSearch* search) { +CSearchResult* searchUniqueResult(CSearch* search) { TypedSearchResult result = ((Retro::Search*) search->search)->uniqueResult(); - return {result.address, result.type.type}; + return new CSearchResult {result.address, result.type.type}; } -CSearchTypedResults searchTypedResults(CSearch* search) { +CSearchTypedResults* searchTypedResults(CSearch* search) { std::map> results; for (const auto& result : ((Retro::Search*) search->search)->typedResults()) { results[static_cast(result)].emplace(result.type); @@ -216,13 +204,13 @@ CSearchTypedResults searchTypedResults(CSearch* search) { result.second.size()}; i++; } - return {cResults, results.size()}; + return new CSearchTypedResults {cResults, results.size()}; } -CGameData gameDataCreate() { +CGameData* gameDataCreate() { auto* data = new Retro::GameData(); auto* scenario = new Retro::Scenario(*data); - return {data, scenario}; + return new CGameData {data, scenario}; } void gameDataDelete(CGameData* gameData) { @@ -266,7 +254,7 @@ uint16_t gameDataFilterAction(CGameData* gameData, uint16_t action) { return ((Retro::Scenario*) gameData->scenario)->filterAction(action); } -CValidActions gameDataValidActions(CGameData* gameData) { +CValidActions* gameDataValidActions(CGameData* gameData) { std::map> validActions = ((Retro::Scenario*) gameData->scenario)->validActions(); size_t numActionsOuter = validActions.size(); int** actions = new int*[numActionsOuter]; @@ -282,7 +270,7 @@ CValidActions gameDataValidActions(CGameData* gameData) { } i++; } - return {actions, numActionsInner, numActionsOuter}; + return new CValidActions {actions, numActionsInner, numActionsOuter}; } void gameDataUpdateRam(CGameData* gameData) { @@ -314,20 +302,20 @@ void gameDataSetDoubleValue(CGameData* gameData, const char* name, double value) ((Retro::GameData*) gameData->data)->setValue(name, Variant(value)); } -CNames gameDataLookupKeys(CGameData* gameData) { +CNames* gameDataLookupKeys(CGameData* gameData) { std::unordered_map allValues = ((Retro::GameData*) gameData->data)->lookupAll(); - const char** cNames = new const char*[allValues.size()]; + const char** namesArray = new const char*[allValues.size()]; auto i = 0; for (const auto& var : allValues) { - cNames[i] = var.first.c_str(); + namesArray[i] = var.first.c_str(); i++; } - return {cNames, allValues.size()}; + return new CNames {namesArray, allValues.size()}; } -CVariable gameDataGetVariable(CGameData* gameData, const char* name) { +CVariable* gameDataGetVariable(CGameData* gameData, const char* name) { Retro::Variable var = ((Retro::GameData*) gameData->data)->getVariable(name); - return {name, var.address, var.type.type}; + return new CVariable {name, var.address, var.type.type}; } void gameDataSetVariable(CGameData* gameData, const char* name, CVariable* value) { @@ -339,7 +327,7 @@ void gameDataRemoveVariable(CGameData* gameData, const char* name) { ((Retro::GameData*) gameData->data)->removeVariable(name); } -CVariables gameDataListVariables(CGameData* gameData) { +CVariables* gameDataListVariables(CGameData* gameData) { const auto& vars = ((Retro::GameData*) gameData->data)->listVariables(); auto numVariables = vars.size(); auto* variables = new CVariable[numVariables]; @@ -349,7 +337,7 @@ CVariables gameDataListVariables(CGameData* gameData) { variables[i] = {var.first.c_str(), v.address, v.type.type}; i++; } - return {variables, numVariables}; + return new CVariables {variables, numVariables}; } float gameDataCurrentReward(CGameData* gameData, unsigned int player) { @@ -364,16 +352,16 @@ bool gameDataIsDone(CGameData* gameData) { return ((Retro::Scenario*) gameData->scenario)->isDone(); } -CCropInfo gameDataCropInfo(CGameData* gameData, unsigned int player) { +CCropInfo* gameDataCropInfo(CGameData* gameData, unsigned int player) { size_t x = 0; size_t y = 0; size_t width = 0; size_t height = 0; ((Retro::Scenario*) gameData->scenario)->getCrop(&x, &y, &width, &height, player); - return {x, y, width, height}; + return new CCropInfo {x, y, width, height}; } -CMemoryView gameDataMemory(CGameData* gameData) { +CMemoryView* gameDataMemory(CGameData* gameData) { return memoryViewCreate(&((Retro::GameData*) gameData->data)->addressSpace()); } @@ -385,7 +373,7 @@ void gameDataDeltaSearch(CGameData* gameData, const char* name, const char* op, ((Retro::GameData*) gameData->data)->deltaSearch(name, Retro::Scenario::op(op), ref); } -CSearch gameDataGetSearch(CGameData* gameData, const char* name) { +CSearch* gameDataGetSearch(CGameData* gameData, const char* name) { return searchCreateUnmanaged(((Retro::GameData*) gameData->data)->getSearch(name)); } @@ -393,16 +381,16 @@ void gameDataRemoveSearch(CGameData* gameData, const char* name) { ((Retro::GameData*) gameData->data)->removeSearch(name); } -CNames gameDataListSearchNames(CGameData* gameData) { +CNames* gameDataListSearchNames(CGameData* gameData) { std::vector names = ((Retro::GameData*) gameData->data)->listSearches(); - const char** cNames = new const char*[names.size()]; + const char** namesArray = new const char*[names.size()]; for (int i = 0; i < names.size(); i++) { - cNames[i] = names[i].c_str(); + namesArray[i] = names[i].c_str(); } - return {cNames, names.size()}; + return new CNames {namesArray, names.size()}; } -CMovie movieCreate(const char* name, bool record, unsigned int players) { +CMovie* movieCreate(const char* name, bool record, unsigned int players) { Retro::Movie* movie; if (record) { movie = new MovieBK2(name, true, players); @@ -412,7 +400,7 @@ CMovie movieCreate(const char* name, bool record, unsigned int players) { if (!movie) { throw std::runtime_error("Could not load movie"); } - return {movie, record}; + return new CMovie {movie, record}; } void movieDelete(CMovie* movie) { @@ -451,10 +439,10 @@ void movieSetKey(CMovie* movie, int key, bool set, unsigned int player) { ((Retro::Movie*) movie->movie)->setKey(key, set, player); } -CBytes movieGetState(CMovie* movie) { +CBytes* movieGetState(CMovie* movie) { std::vector data; ((Retro::Movie*) movie->movie)->getState(&data); - return {reinterpret_cast(data.data()), data.size()}; + return new CBytes {reinterpret_cast(data.data()), data.size()}; } void movieSetState(CMovie* movie, CBytes* state) { diff --git a/src/retro-c.h b/src/retro-c.h index 1f9e8de69..dc5aeea90 100644 --- a/src/retro-c.h +++ b/src/retro-c.h @@ -111,42 +111,42 @@ typedef struct CCropInfo { size_t height; } CCropInfo; -CEmulator emulatorCreate(const char* romPath); +CEmulator* emulatorCreate(const char* romPath); void emulatorDelete(CEmulator* emulator); void emulatorStep(CEmulator* emulator); -CBytes emulatorGetState(CEmulator* emulator); +CBytes* emulatorGetState(CEmulator* emulator); bool emulatorSetState(CEmulator* emulator, CBytes* state); -CEmulatorScreen emulatorGetScreen(CEmulator* emulator); +CEmulatorScreen* emulatorGetScreen(CEmulator* emulator); double emulatorGetScreenRate(CEmulator* emulator); -CEmulatorAudio emulatorGetAudio(CEmulator* emulator); +CEmulatorAudio* emulatorGetAudio(CEmulator* emulator); double emulatorGetAudioRate(CEmulator* emulator); -CEmulatorResolution emulatorGetResolution(CEmulator* emulator); +CEmulatorResolution* emulatorGetResolution(CEmulator* emulator); void emulatorSetButtonMask(CEmulator* emulator, uint8_t* mask, size_t maskSize, unsigned int player); void emulatorAddCheat(CEmulator* emulator, const char* code); void emulatorClearCheats(CEmulator* emulator); void emulatorConfigureData(CEmulator* emulator, CGameData* gameData); -CMemoryView memoryViewCreate(void* addressSpace); +CMemoryView* memoryViewCreate(void* addressSpace); void memoryViewDelete(CMemoryView* memoryView); int64_t memoryViewExtract(CMemoryView* memoryView, size_t address, const char* type); void memoryViewAssign(CMemoryView* memoryView, size_t address, const char* type, int64_t value); -CMemoryBlocks memoryViewBlocks(CMemoryView* memoryView); +CMemoryBlocks* memoryViewBlocks(CMemoryView* memoryView); -CSearch searchCreate(const char** types, size_t numTypes); -CSearch searchCreateUnmanaged(void* search); +CSearch* searchCreate(const char** types, size_t numTypes); +CSearch* searchCreateUnmanaged(void* search); void searchDelete(CSearch* search); int searchNumResults(CSearch* search); bool searchHasUniqueResult(CSearch* search); -CSearchResult searchUniqueResult(CSearch* search); -CSearchTypedResults searchTypedResults(CSearch* search); +CSearchResult* searchUniqueResult(CSearch* search); +CSearchTypedResults* searchTypedResults(CSearch* search); -CGameData gameDataCreate(); +CGameData* gameDataCreate(); void gameDataDelete(CGameData* gameData); bool gameDataLoad(CGameData* gameData, const char* dataFilename, const char* scenarioFilename); bool gameDataSave(CGameData* gameData, const char* dataFilename, const char* scenarioFilename); void gameDataReset(CGameData* gameData); uint16_t gameDataFilterAction(CGameData* gameData, uint16_t action); -CValidActions gameDataValidActions(CGameData* gameData); +CValidActions* gameDataValidActions(CGameData* gameData); void gameDataUpdateRam(CGameData* gameData); bool gameDataLookupBoolValue(CGameData* gameData, const char* name); int64_t gameDataLookupIntValue(CGameData* gameData, const char* name); @@ -154,23 +154,23 @@ double gameDataLookupDoubleValue(CGameData* gameData, const char* name); void gameDataSetBoolValue(CGameData* gameData, const char* name, bool value); void gameDataSetIntValue(CGameData* gameData, const char* name, int64_t value); void gameDataSetDoubleValue(CGameData* gameData, const char* name, double value); -CNames gameDataLookupKeys(CGameData* gameData); -CVariable gameDataGetVariable(CGameData* gameData, const char* name); +CNames* gameDataLookupKeys(CGameData* gameData); +CVariable* gameDataGetVariable(CGameData* gameData, const char* name); void gameDataSetVariable(CGameData* gameData, const char* name, CVariable* value); void gameDataRemoveVariable(CGameData* gameData, const char* name); -CVariables gameDataListVariables(CGameData* gameData); +CVariables* gameDataListVariables(CGameData* gameData); float gameDataCurrentReward(CGameData* gameData, unsigned int player); float gameDataTotalReward(CGameData* gameData, unsigned int player); bool gameDataIsDone(CGameData* gameData); -CCropInfo gameDataCropInfo(CGameData* gameData, unsigned int player); -CMemoryView gameDataMemory(CGameData* gameData); +CCropInfo* gameDataCropInfo(CGameData* gameData, unsigned int player); +CMemoryView* gameDataMemory(CGameData* gameData); void gameDataSearch(CGameData* gameData, const char* name, int64_t value); void gameDataDeltaSearch(CGameData* gameData, const char* name, const char* op, int64_t ref); -CSearch gameDataGetSearch(CGameData* gameData, const char* name); +CSearch* gameDataGetSearch(CGameData* gameData, const char* name); void gameDataRemoveSearch(CGameData* gameData, const char* name); -CNames gameDataListSearchNames(CGameData* gameData); +CNames* gameDataListSearchNames(CGameData* gameData); -CMovie movieCreate(const char* name, bool record, unsigned int players); +CMovie* movieCreate(const char* name, bool record, unsigned int players); void movieDelete(CMovie* movie); void movieConfigure(CMovie* movie, const char* name, CEmulator* emulator); const char* movieGetGameName(CMovie* movie); @@ -179,7 +179,7 @@ void movieClose(CMovie* movie); unsigned int moviePlayers(CMovie* movie); bool movieGetKey(CMovie* movie, int key, unsigned int player); void movieSetKey(CMovie* movie, int key, bool set, unsigned int player); -CBytes movieGetState(CMovie* movie); +CBytes* movieGetState(CMovie* movie); void movieSetState(CMovie* movie, CBytes* state); bool retroLoadCoreInfo(const char* json); From 4510dc9c39ebbe5e544392c7fb2e2bb005afe1bc Mon Sep 17 00:00:00 2001 From: Anthony Platanios Date: Fri, 5 Apr 2019 11:27:21 -0400 Subject: [PATCH 12/33] Exported the C API symbols. --- CMakeLists.txt | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index d293c2588..d9dfd16c1 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -288,7 +288,10 @@ endif() if(BUILD_C) add_library(retro-c SHARED src/retro-c.cpp) - set_target_properties(retro-c PROPERTIES OUTPUT_NAME retro) + set_target_properties(retro-c PROPERTIES + OUTPUT_NAME retro + CXX_VISIBILITY_PRESET default + POSITION_INDEPENDENT_CODE ON) if(APPLE) set(C_LIBS "-undefined dynamic_lookup") elseif(WIN32) @@ -297,7 +300,7 @@ if(BUILD_C) endif() set(C_LIBS "") endif() - target_link_libraries(retro-c retro-base ${C_LIBS} ${STATIC_LDFLAGS}) + target_link_libraries(retro-c PUBLIC retro-base ${C_LIBS} ${STATIC_LDFLAGS}) endif() if(BUILD_TESTS) From 5ade2119c4b7e471ce8cf255b9ba8fdaf7a837e3 Mon Sep 17 00:00:00 2001 From: Anthony Platanios Date: Fri, 5 Apr 2019 12:20:15 -0400 Subject: [PATCH 13/33] Changed exception handling in the C API (more principled approaching is coming soon). --- CMakeLists.txt | 2 +- src/retro-c.cpp | 16 +++++++++++----- 2 files changed, 12 insertions(+), 6 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index d9dfd16c1..9ed62eb6f 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -300,7 +300,7 @@ if(BUILD_C) endif() set(C_LIBS "") endif() - target_link_libraries(retro-c PUBLIC retro-base ${C_LIBS} ${STATIC_LDFLAGS}) + target_link_libraries(retro-c retro-base ${C_LIBS} ${STATIC_LDFLAGS}) endif() if(BUILD_TESTS) diff --git a/src/retro-c.cpp b/src/retro-c.cpp index 6fae08bb9..165d9e185 100644 --- a/src/retro-c.cpp +++ b/src/retro-c.cpp @@ -19,12 +19,15 @@ using namespace Retro; CEmulator* emulatorCreate(const char* romPath) { Retro::Emulator emulator; if (Emulator::isLoaded()) { - throw std::runtime_error( + fprintf( + stderr, "Cannot create multiple emulator instances per process, make sure to call " "'env.close()' on each environment before creating a new one."); + return nullptr; } if (!emulator.loadRom(romPath)) { - throw std::runtime_error("Could not load ROM."); + fprintf(stderr, "Could not load ROM."); + return nullptr; } // The following is necessary because otherwise, you get a segfault // when you try to get the screen for the first time. @@ -91,10 +94,12 @@ CEmulatorResolution* emulatorGetResolution(CEmulator* emulator) { void emulatorSetButtonMask(CEmulator* emulator, uint8_t* mask, size_t maskSize, unsigned int player) { if (maskSize > N_BUTTONS) { - throw std::runtime_error("mask.size() > N_BUTTONS."); + fprintf(stderr, "mask.size() > N_BUTTONS."); + return; } if (player >= MAX_PLAYERS) { - throw std::runtime_error("player >= MAX_PLAYERS."); + fprintf(stderr, "player >= MAX_PLAYERS."); + return; } for (int key = 0; key < maskSize; key++) { ((Retro::Emulator*) emulator->emulator)->setKey(player, key, mask[key]); @@ -398,7 +403,8 @@ CMovie* movieCreate(const char* name, bool record, unsigned int players) { movie = Movie::load(name).get(); } if (!movie) { - throw std::runtime_error("Could not load movie"); + fprintf(stderr, "Could not load movie."); + return nullptr; } return new CMovie {movie, record}; } From a1d2e7302fa41e43d32ac22979f9d4aceedb976b Mon Sep 17 00:00:00 2001 From: Anthony Platanios Date: Sat, 6 Apr 2019 11:55:38 -0400 Subject: [PATCH 14/33] Minor edits. --- src/retro-c.cpp | 8 ++++---- src/retro-c.h | 12 ++++++------ 2 files changed, 10 insertions(+), 10 deletions(-) diff --git a/src/retro-c.cpp b/src/retro-c.cpp index 165d9e185..1f3428cb2 100644 --- a/src/retro-c.cpp +++ b/src/retro-c.cpp @@ -68,7 +68,7 @@ CEmulatorScreen* emulatorGetScreen(CEmulator* emulator) { in = Image(Image::Format::RGBX888, emu->getImageData(), w, h, emu->getImagePitch()); } in.copyTo(&out); - return new CEmulatorScreen {data, (int) w, (int) h, 3}; + return new CEmulatorScreen {data, (size_t) w, (size_t) h, 3}; } double emulatorGetScreenRate(CEmulator* emulator) { @@ -87,8 +87,8 @@ double emulatorGetAudioRate(CEmulator* emulator) { } CEmulatorResolution* emulatorGetResolution(CEmulator* emulator) { - auto w = ((Retro::Emulator*) emulator->emulator)->getImageWidth(); - auto h = ((Retro::Emulator*) emulator->emulator)->getImageHeight(); + auto w = (size_t) ((Retro::Emulator*) emulator->emulator)->getImageWidth(); + auto h = (size_t) ((Retro::Emulator*) emulator->emulator)->getImageHeight(); return new CEmulatorResolution {w, h}; } @@ -378,7 +378,7 @@ void gameDataDeltaSearch(CGameData* gameData, const char* name, const char* op, ((Retro::GameData*) gameData->data)->deltaSearch(name, Retro::Scenario::op(op), ref); } -CSearch* gameDataGetSearch(CGameData* gameData, const char* name) { +CSearch* gameDataSearch(CGameData* gameData, const char* name) { return searchCreateUnmanaged(((Retro::GameData*) gameData->data)->getSearch(name)); } diff --git a/src/retro-c.h b/src/retro-c.h index dc5aeea90..98a3b7bdd 100644 --- a/src/retro-c.h +++ b/src/retro-c.h @@ -8,14 +8,14 @@ extern "C" { typedef struct CEmulator { void* emulator; - int cheats; + size_t cheats; } CEmulator; typedef struct CEmulatorScreen { uint8_t* values; - int width; - int height; - int channels; + size_t width; + size_t height; + size_t channels; } CEmulatorScreen; typedef struct CEmulatorAudio { @@ -24,8 +24,8 @@ typedef struct CEmulatorAudio { } CEmulatorAudio; typedef struct CEmulatorResolution { - int width; - int height; + size_t width; + size_t height; } CEmulatorResolution; typedef struct CMemoryView { From b9642febbcfe73f257be7d5f7ebd923c3c0cc1b9 Mon Sep 17 00:00:00 2001 From: Anthony Platanios Date: Sat, 6 Apr 2019 12:00:04 -0400 Subject: [PATCH 15/33] Minor edits. --- src/retro-c.cpp | 2 +- src/retro-c.h | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/retro-c.cpp b/src/retro-c.cpp index 1f3428cb2..ce441ebef 100644 --- a/src/retro-c.cpp +++ b/src/retro-c.cpp @@ -142,7 +142,7 @@ CMemoryBlocks* memoryViewBlocks(CMemoryView* memoryView) { auto* blocks = new CMemoryBlock[numBlocks]; auto i = 0; for (const auto& iter : internalBlocks) { - blocks[i] = {iter.first, static_cast(iter.second.offset(0)), iter.second.size()}; + blocks[i] = {iter.first, static_cast(iter.second.offset(0)), iter.second.size()}; i++; } return new CMemoryBlocks {blocks, numBlocks}; diff --git a/src/retro-c.h b/src/retro-c.h index 98a3b7bdd..658393223 100644 --- a/src/retro-c.h +++ b/src/retro-c.h @@ -34,7 +34,7 @@ typedef struct CMemoryView { typedef struct CMemoryBlock { size_t address; - const char* bytes; + const uint8_t* bytes; size_t numBytes; } CMemoryBlock; From 3c12301c947c68570e9c9665f3fe0b025346de39 Mon Sep 17 00:00:00 2001 From: Anthony Platanios Date: Sat, 6 Apr 2019 18:43:00 -0400 Subject: [PATCH 16/33] Minor edit. --- src/retro-c.cpp | 2 +- src/retro-c.h | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/retro-c.cpp b/src/retro-c.cpp index ce441ebef..c190a1f99 100644 --- a/src/retro-c.cpp +++ b/src/retro-c.cpp @@ -92,7 +92,7 @@ CEmulatorResolution* emulatorGetResolution(CEmulator* emulator) { return new CEmulatorResolution {w, h}; } -void emulatorSetButtonMask(CEmulator* emulator, uint8_t* mask, size_t maskSize, unsigned int player) { +void emulatorSetButtonMask(CEmulator* emulator, const uint8_t* mask, size_t maskSize, unsigned int player) { if (maskSize > N_BUTTONS) { fprintf(stderr, "mask.size() > N_BUTTONS."); return; diff --git a/src/retro-c.h b/src/retro-c.h index 658393223..c24621f90 100644 --- a/src/retro-c.h +++ b/src/retro-c.h @@ -121,7 +121,7 @@ double emulatorGetScreenRate(CEmulator* emulator); CEmulatorAudio* emulatorGetAudio(CEmulator* emulator); double emulatorGetAudioRate(CEmulator* emulator); CEmulatorResolution* emulatorGetResolution(CEmulator* emulator); -void emulatorSetButtonMask(CEmulator* emulator, uint8_t* mask, size_t maskSize, unsigned int player); +void emulatorSetButtonMask(CEmulator* emulator, const uint8_t* mask, size_t maskSize, unsigned int player); void emulatorAddCheat(CEmulator* emulator, const char* code); void emulatorClearCheats(CEmulator* emulator); void emulatorConfigureData(CEmulator* emulator, CGameData* gameData); From 82250d6d3e1852487ad75aacc53527df3f7d58f1 Mon Sep 17 00:00:00 2001 From: Anthony Platanios Date: Sat, 6 Apr 2019 19:06:02 -0400 Subject: [PATCH 17/33] Another small update. --- src/retro-c.cpp | 6 +++--- src/retro-c.h | 2 +- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/src/retro-c.cpp b/src/retro-c.cpp index c190a1f99..5ec7fe7c3 100644 --- a/src/retro-c.cpp +++ b/src/retro-c.cpp @@ -48,7 +48,7 @@ CBytes* emulatorGetState(CEmulator* emulator) { size_t numBytes = ((Retro::Emulator*) emulator->emulator)->serializeSize(); void* bytes = malloc(numBytes); ((Retro::Emulator*) emulator->emulator)->serialize(bytes, numBytes); - return new CBytes {bytes, numBytes}; + return new CBytes {reinterpret_cast(bytes), numBytes}; } bool emulatorSetState(CEmulator* emulator, CBytes* state) { @@ -448,11 +448,11 @@ void movieSetKey(CMovie* movie, int key, bool set, unsigned int player) { CBytes* movieGetState(CMovie* movie) { std::vector data; ((Retro::Movie*) movie->movie)->getState(&data); - return new CBytes {reinterpret_cast(data.data()), data.size()}; + return new CBytes {reinterpret_cast(data.data()), data.size()}; } void movieSetState(CMovie* movie, CBytes* state) { - ((Retro::Movie*) movie->movie)->setState(reinterpret_cast(state->bytes), state->numBytes); + ((Retro::Movie*) movie->movie)->setState(state->bytes, state->numBytes); } bool retroLoadCoreInfo(const char* json) { diff --git a/src/retro-c.h b/src/retro-c.h index c24621f90..9260c725e 100644 --- a/src/retro-c.h +++ b/src/retro-c.h @@ -100,7 +100,7 @@ typedef struct CMovie { } CMovie; typedef struct CBytes { - void* bytes; + const uint8_t* bytes; size_t numBytes; } CBytes; From be16d35c013909764aba5d258395068062fca8d5 Mon Sep 17 00:00:00 2001 From: Anthony Platanios Date: Sat, 6 Apr 2019 21:38:45 -0400 Subject: [PATCH 18/33] Reproducible bug. --- src/emulator.cpp | 8 ++++++++ src/memory.cpp | 2 ++ src/retro-c.cpp | 4 +++- 3 files changed, 13 insertions(+), 1 deletion(-) diff --git a/src/emulator.cpp b/src/emulator.cpp index b16b2f7f0..38777f234 100644 --- a/src/emulator.cpp +++ b/src/emulator.cpp @@ -410,13 +410,21 @@ int16_t Emulator::cbInputState(unsigned port, unsigned, unsigned, unsigned id) { } void Emulator::configureData(GameData* data) { + fprintf(stderr, "%s", "\n##################### - 5.0"); m_addressSpace = &data->addressSpace(); + fprintf(stderr, "\nAfter: %lu", m_addressSpace); + fprintf(stderr, "%s", "\n##################### - 5.1"); m_addressSpace->reset(); + fprintf(stderr, "%s", "\n##################### - 5.2"); Retro::configureData(data, m_core); + fprintf(stderr, "%s", "\n##################### - 5.3"); reconfigureAddressSpace(); + fprintf(stderr, "%s", "\n##################### - 5.4"); if (m_addressSpace->blocks().empty() && retro_get_memory_size(RETRO_MEMORY_SYSTEM_RAM)) { + fprintf(stderr, "%s", "\n##################### - 5.5"); m_addressSpace->addBlock(Retro::ramBase(m_core), retro_get_memory_size(RETRO_MEMORY_SYSTEM_RAM), retro_get_memory_data(RETRO_MEMORY_SYSTEM_RAM)); } + fprintf(stderr, "%s", "\n##################### - 5.6"); } vector Emulator::buttons() const { diff --git a/src/memory.cpp b/src/memory.cpp index 689724b42..e3d49153f 100644 --- a/src/memory.cpp +++ b/src/memory.cpp @@ -396,7 +396,9 @@ bool AddressSpace::ok() const { } void AddressSpace::reset() { + fprintf(stderr, "\nBefore: %lu", this); m_blocks.clear(); + fprintf(stderr, "%s", "\n##################### - 5.1.1"); } void AddressSpace::clone(const AddressSpace& as) { diff --git a/src/retro-c.cpp b/src/retro-c.cpp index 5ec7fe7c3..91d13eb3e 100644 --- a/src/retro-c.cpp +++ b/src/retro-c.cpp @@ -117,7 +117,7 @@ void emulatorClearCheats(CEmulator* emulator) { } void emulatorConfigureData(CEmulator* emulator, CGameData* gameData) { - ((Retro::Emulator*) emulator->emulator)->configureData(((Retro::GameData*) gameData->data)); + ((Retro::Emulator*) emulator->emulator)->configureData((Retro::GameData*) gameData->data); } CMemoryView* memoryViewCreate(void* addressSpace) { @@ -215,6 +215,8 @@ CSearchTypedResults* searchTypedResults(CSearch* search) { CGameData* gameDataCreate() { auto* data = new Retro::GameData(); auto* scenario = new Retro::Scenario(*data); + fprintf(stderr, "\nAfter: %lu", &data->addressSpace()); + (&data->addressSpace())->reset(); return new CGameData {data, scenario}; } From 2b0413e22f9361ea6a86ce8a5f16d2da6eb89555 Mon Sep 17 00:00:00 2001 From: Anthony Platanios Date: Sun, 7 Apr 2019 00:05:58 -0400 Subject: [PATCH 19/33] Made some memory bug fixes. --- src/emulator.cpp | 8 -------- src/memory.cpp | 2 -- src/retro-c.cpp | 34 ++++++++++++++++++++++------------ 3 files changed, 22 insertions(+), 22 deletions(-) diff --git a/src/emulator.cpp b/src/emulator.cpp index 38777f234..b16b2f7f0 100644 --- a/src/emulator.cpp +++ b/src/emulator.cpp @@ -410,21 +410,13 @@ int16_t Emulator::cbInputState(unsigned port, unsigned, unsigned, unsigned id) { } void Emulator::configureData(GameData* data) { - fprintf(stderr, "%s", "\n##################### - 5.0"); m_addressSpace = &data->addressSpace(); - fprintf(stderr, "\nAfter: %lu", m_addressSpace); - fprintf(stderr, "%s", "\n##################### - 5.1"); m_addressSpace->reset(); - fprintf(stderr, "%s", "\n##################### - 5.2"); Retro::configureData(data, m_core); - fprintf(stderr, "%s", "\n##################### - 5.3"); reconfigureAddressSpace(); - fprintf(stderr, "%s", "\n##################### - 5.4"); if (m_addressSpace->blocks().empty() && retro_get_memory_size(RETRO_MEMORY_SYSTEM_RAM)) { - fprintf(stderr, "%s", "\n##################### - 5.5"); m_addressSpace->addBlock(Retro::ramBase(m_core), retro_get_memory_size(RETRO_MEMORY_SYSTEM_RAM), retro_get_memory_data(RETRO_MEMORY_SYSTEM_RAM)); } - fprintf(stderr, "%s", "\n##################### - 5.6"); } vector Emulator::buttons() const { diff --git a/src/memory.cpp b/src/memory.cpp index e3d49153f..689724b42 100644 --- a/src/memory.cpp +++ b/src/memory.cpp @@ -396,9 +396,7 @@ bool AddressSpace::ok() const { } void AddressSpace::reset() { - fprintf(stderr, "\nBefore: %lu", this); m_blocks.clear(); - fprintf(stderr, "%s", "\n##################### - 5.1.1"); } void AddressSpace::clone(const AddressSpace& as) { diff --git a/src/retro-c.cpp b/src/retro-c.cpp index 91d13eb3e..3093f8903 100644 --- a/src/retro-c.cpp +++ b/src/retro-c.cpp @@ -16,8 +16,16 @@ using namespace Retro; +const char* newCString(std::string value) { + auto* cValue = value.c_str(); + auto size = sizeof(char) * (value.length() + 1); + auto* copy = malloc(size); + memcpy(copy, cValue, size); + return reinterpret_cast(copy); +} + CEmulator* emulatorCreate(const char* romPath) { - Retro::Emulator emulator; + Retro::Emulator* emulator = new Retro::Emulator(); if (Emulator::isLoaded()) { fprintf( stderr, @@ -25,14 +33,14 @@ CEmulator* emulatorCreate(const char* romPath) { "'env.close()' on each environment before creating a new one."); return nullptr; } - if (!emulator.loadRom(romPath)) { + if (!emulator->loadRom(romPath)) { fprintf(stderr, "Could not load ROM."); return nullptr; } // The following is necessary because otherwise, you get a segfault // when you try to get the screen for the first time. - emulator.run(); - return new CEmulator {&emulator, 0}; + emulator->run(); + return new CEmulator {emulator, 0}; } void emulatorDelete(CEmulator* emulator) { @@ -200,6 +208,7 @@ CSearchTypedResults* searchTypedResults(CSearch* search) { types[j] = type.type; j++; } + // TODO: Allocated on stack. cResults[i] = { result.first.address, result.first.mult, @@ -215,8 +224,6 @@ CSearchTypedResults* searchTypedResults(CSearch* search) { CGameData* gameDataCreate() { auto* data = new Retro::GameData(); auto* scenario = new Retro::Scenario(*data); - fprintf(stderr, "\nAfter: %lu", &data->addressSpace()); - (&data->addressSpace())->reset(); return new CGameData {data, scenario}; } @@ -314,6 +321,7 @@ CNames* gameDataLookupKeys(CGameData* gameData) { const char** namesArray = new const char*[allValues.size()]; auto i = 0; for (const auto& var : allValues) { + // TODO: Allocated on stack. namesArray[i] = var.first.c_str(); i++; } @@ -322,6 +330,7 @@ CNames* gameDataLookupKeys(CGameData* gameData) { CVariable* gameDataGetVariable(CGameData* gameData, const char* name) { Retro::Variable var = ((Retro::GameData*) gameData->data)->getVariable(name); + // TODO: Allocated on stack. return new CVariable {name, var.address, var.type.type}; } @@ -341,7 +350,7 @@ CVariables* gameDataListVariables(CGameData* gameData) { auto i = 0; for (const auto& var : vars) { const auto& v = var.second; - variables[i] = {var.first.c_str(), v.address, v.type.type}; + variables[i] = {newCString(var.first), v.address, v.type.type}; i++; } return new CVariables {variables, numVariables}; @@ -392,7 +401,7 @@ CNames* gameDataListSearchNames(CGameData* gameData) { std::vector names = ((Retro::GameData*) gameData->data)->listSearches(); const char** namesArray = new const char*[names.size()]; for (int i = 0; i < names.size(); i++) { - namesArray[i] = names[i].c_str(); + namesArray[i] = newCString(names[i]); } return new CNames {namesArray, names.size()}; } @@ -402,7 +411,7 @@ CMovie* movieCreate(const char* name, bool record, unsigned int players) { if (record) { movie = new MovieBK2(name, true, players); } else { - movie = Movie::load(name).get(); + movie = Movie::load(name).release(); } if (!movie) { fprintf(stderr, "Could not load movie."); @@ -424,7 +433,7 @@ void movieConfigure(CMovie* movie, const char* name, CEmulator* emulator) { } const char* movieGetGameName(CMovie* movie) { - return ((Retro::Movie*) movie->movie)->getGameName().c_str(); + return newCString(((Retro::Movie*) movie->movie)->getGameName()); } bool movieStep(CMovie* movie) { @@ -448,6 +457,7 @@ void movieSetKey(CMovie* movie, int key, bool set, unsigned int player) { } CBytes* movieGetState(CMovie* movie) { + // TODO: Allocated on stack? std::vector data; ((Retro::Movie*) movie->movie)->getState(&data); return new CBytes {reinterpret_cast(data.data()), data.size()}; @@ -462,9 +472,9 @@ bool retroLoadCoreInfo(const char* json) { } const char* retroCorePath(const char* hint) { - return Retro::corePath(hint).c_str(); + return newCString(Retro::corePath(hint)); } const char* retroDataPath(const char* hint) { - return Retro::GameData::dataPath(hint).c_str(); + return newCString(Retro::GameData::dataPath(hint)); } From ab5a27272a9455c89518beeb27669c62c629d4fa Mon Sep 17 00:00:00 2001 From: Anthony Platanios Date: Sun, 7 Apr 2019 00:11:04 -0400 Subject: [PATCH 20/33] Fixed another memory issue. --- src/retro-c.cpp | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/src/retro-c.cpp b/src/retro-c.cpp index 3093f8903..839ab1e8a 100644 --- a/src/retro-c.cpp +++ b/src/retro-c.cpp @@ -321,8 +321,7 @@ CNames* gameDataLookupKeys(CGameData* gameData) { const char** namesArray = new const char*[allValues.size()]; auto i = 0; for (const auto& var : allValues) { - // TODO: Allocated on stack. - namesArray[i] = var.first.c_str(); + namesArray[i] = newCString(var.first); i++; } return new CNames {namesArray, allValues.size()}; From c8a1b5f5ac3b4f15826da1a1ca041c1052c0d3bb Mon Sep 17 00:00:00 2001 From: Anthony Platanios Date: Sun, 7 Apr 2019 00:13:30 -0400 Subject: [PATCH 21/33] Fixed yet another memory issue. --- src/retro-c.cpp | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/src/retro-c.cpp b/src/retro-c.cpp index 839ab1e8a..4adfbdc83 100644 --- a/src/retro-c.cpp +++ b/src/retro-c.cpp @@ -329,8 +329,11 @@ CNames* gameDataLookupKeys(CGameData* gameData) { CVariable* gameDataGetVariable(CGameData* gameData, const char* name) { Retro::Variable var = ((Retro::GameData*) gameData->data)->getVariable(name); - // TODO: Allocated on stack. - return new CVariable {name, var.address, var.type.type}; + auto size = sizeof(char) * 5; + auto* typeCopy = malloc(size); + memcpy(typeCopy, var.type.type, size); + auto* type = reinterpret_cast(typeCopy); + return new CVariable {name, var.address, type}; } void gameDataSetVariable(CGameData* gameData, const char* name, CVariable* value) { From 592ef22892318d4414cb474490e383612d88b2de Mon Sep 17 00:00:00 2001 From: Anthony Platanios Date: Sun, 7 Apr 2019 00:17:13 -0400 Subject: [PATCH 22/33] Fixed yet another memory issue. --- src/retro-c.cpp | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/src/retro-c.cpp b/src/retro-c.cpp index 4adfbdc83..0a9f7dd35 100644 --- a/src/retro-c.cpp +++ b/src/retro-c.cpp @@ -459,10 +459,13 @@ void movieSetKey(CMovie* movie, int key, bool set, unsigned int player) { } CBytes* movieGetState(CMovie* movie) { - // TODO: Allocated on stack? std::vector data; ((Retro::Movie*) movie->movie)->getState(&data); - return new CBytes {reinterpret_cast(data.data()), data.size()}; + auto* cData = data.data(); + auto size = sizeof(uint8_t) * data.size(); + auto* copy = malloc(size); + memcpy(copy, cData, size); + return new CBytes {reinterpret_cast(copy), data.size()}; } void movieSetState(CMovie* movie, CBytes* state) { From 91512db4e1610b48df339ebed7e28c167a5b150e Mon Sep 17 00:00:00 2001 From: Anthony Platanios Date: Sun, 7 Apr 2019 00:23:01 -0400 Subject: [PATCH 23/33] Fixed some more memory errors. --- src/emulator.cpp | 3 ++- src/retro-c.cpp | 9 +-------- src/utils.cpp | 8 ++++++++ src/utils.h | 2 ++ 4 files changed, 13 insertions(+), 9 deletions(-) diff --git a/src/emulator.cpp b/src/emulator.cpp index b16b2f7f0..4110707e9 100644 --- a/src/emulator.cpp +++ b/src/emulator.cpp @@ -12,6 +12,7 @@ #include "data.h" #include "emulator.h" #include "libretro.h" +#include "utils.h" #ifndef _WIN32 #define GETSYM dlsym @@ -360,7 +361,7 @@ bool Emulator::cbEnvironment(unsigned cmd, void* data) { return false; } case RETRO_ENVIRONMENT_GET_SYSTEM_DIRECTORY: - *reinterpret_cast(data) = corePath().c_str(); + *reinterpret_cast(data) = newCString(corePath()); return true; case RETRO_ENVIRONMENT_GET_CAN_DUPE: *reinterpret_cast(data) = true; diff --git a/src/retro-c.cpp b/src/retro-c.cpp index 0a9f7dd35..b33d28b4d 100644 --- a/src/retro-c.cpp +++ b/src/retro-c.cpp @@ -9,6 +9,7 @@ #include "script.h" #include "movie.h" #include "movie-bk2.h" +#include "utils.h" #include #include @@ -16,14 +17,6 @@ using namespace Retro; -const char* newCString(std::string value) { - auto* cValue = value.c_str(); - auto size = sizeof(char) * (value.length() + 1); - auto* copy = malloc(size); - memcpy(copy, cValue, size); - return reinterpret_cast(copy); -} - CEmulator* emulatorCreate(const char* romPath) { Retro::Emulator* emulator = new Retro::Emulator(); if (Emulator::isLoaded()) { diff --git a/src/utils.cpp b/src/utils.cpp index 66e1b2dcc..7fccf615a 100644 --- a/src/utils.cpp +++ b/src/utils.cpp @@ -80,4 +80,12 @@ string drillUp(const vector& targets, const string& fail, const string& } return {}; } + +const char* newCString(std::string value) { + auto* cValue = value.c_str(); + auto size = sizeof(char) * (value.length() + 1); + auto* copy = malloc(size); + memcpy(copy, cValue, size); + return reinterpret_cast(copy); +} } diff --git a/src/utils.h b/src/utils.h index 580d5495d..c9062c6cb 100644 --- a/src/utils.h +++ b/src/utils.h @@ -24,4 +24,6 @@ enum class Operation { int64_t calculate(Operation op, int64_t reference, int64_t value); std::string drillUp(const std::vector& targets, const std::string& fail = {}, const std::string& hint = "."); + +const char* newCString(std::string value); } From 672e24437fbda39fa1f2e3e4d3fda9333e0cfbf7 Mon Sep 17 00:00:00 2001 From: Anthony Platanios Date: Sun, 7 Apr 2019 00:25:33 -0400 Subject: [PATCH 24/33] Fixed Linux compilation error. --- src/utils.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/src/utils.cpp b/src/utils.cpp index 7fccf615a..890d0dfaa 100644 --- a/src/utils.cpp +++ b/src/utils.cpp @@ -2,6 +2,7 @@ #include #include +#include #include using namespace std; From 8fd553bab55adc2a8dfd3a109ffd14eebe2f423b Mon Sep 17 00:00:00 2001 From: Anthony Platanios Date: Sun, 7 Apr 2019 00:42:10 -0400 Subject: [PATCH 25/33] Minor edit. --- src/retro-c.cpp | 1 - 1 file changed, 1 deletion(-) diff --git a/src/retro-c.cpp b/src/retro-c.cpp index b33d28b4d..a13e4e7be 100644 --- a/src/retro-c.cpp +++ b/src/retro-c.cpp @@ -201,7 +201,6 @@ CSearchTypedResults* searchTypedResults(CSearch* search) { types[j] = type.type; j++; } - // TODO: Allocated on stack. cResults[i] = { result.first.address, result.first.mult, From 9f9b7d4df19462f39e5619083f8775b084d47040 Mon Sep 17 00:00:00 2001 From: Anthony Platanios Date: Mon, 8 Apr 2019 14:06:56 -0400 Subject: [PATCH 26/33] Some more minor edits. --- CMakeLists.txt | 10 +++------- src/coreinfo.cpp | 2 +- 2 files changed, 4 insertions(+), 8 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 9ed62eb6f..5d0b621c1 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -290,17 +290,13 @@ if(BUILD_C) add_library(retro-c SHARED src/retro-c.cpp) set_target_properties(retro-c PROPERTIES OUTPUT_NAME retro - CXX_VISIBILITY_PRESET default - POSITION_INDEPENDENT_CODE ON) - if(APPLE) - set(C_LIBS "-undefined dynamic_lookup") - elseif(WIN32) + CXX_VISIBILITY_PRESET default) + if(WIN32) if(CMAKE_SYSTEM_PROCESSOR STREQUAL "x86_64" OR CMAKE_SYSTEM_PROCESSOR STREQUAL "AMD64") add_definitions(-DMS_WIN64) endif() - set(C_LIBS "") endif() - target_link_libraries(retro-c retro-base ${C_LIBS} ${STATIC_LDFLAGS}) + target_link_libraries(retro-c retro-base ${STATIC_LDFLAGS}) endif() if(BUILD_TESTS) diff --git a/src/coreinfo.cpp b/src/coreinfo.cpp index 1246bf985..5ea954a42 100644 --- a/src/coreinfo.cpp +++ b/src/coreinfo.cpp @@ -108,7 +108,7 @@ bool loadCoreInfo(const string& jsonData) { for (auto ext = core->at("ext").cbegin(); ext != core->at("ext").cend(); ++ext) { s_extensionToCore[*ext] = core.key(); } - s_coreToLib[core.key()] = core->at("lib"); + s_coreToLib[core.key()] = core->at("lib").get(); } return true; } From d2b063f6323d3974968a0d13b951b75225e0f35b Mon Sep 17 00:00:00 2001 From: Anthony Platanios Date: Mon, 8 Apr 2019 20:58:09 -0400 Subject: [PATCH 27/33] Switched to using 'strdup'. --- src/emulator.cpp | 3 +-- src/retro-c.cpp | 13 ++++++------- src/utils.cpp | 7 ------- src/utils.h | 2 -- 4 files changed, 7 insertions(+), 18 deletions(-) diff --git a/src/emulator.cpp b/src/emulator.cpp index 4110707e9..5cd2b27b4 100644 --- a/src/emulator.cpp +++ b/src/emulator.cpp @@ -12,7 +12,6 @@ #include "data.h" #include "emulator.h" #include "libretro.h" -#include "utils.h" #ifndef _WIN32 #define GETSYM dlsym @@ -361,7 +360,7 @@ bool Emulator::cbEnvironment(unsigned cmd, void* data) { return false; } case RETRO_ENVIRONMENT_GET_SYSTEM_DIRECTORY: - *reinterpret_cast(data) = newCString(corePath()); + *reinterpret_cast(data) = strdup(corePath().c_str()); return true; case RETRO_ENVIRONMENT_GET_CAN_DUPE: *reinterpret_cast(data) = true; diff --git a/src/retro-c.cpp b/src/retro-c.cpp index a13e4e7be..5f8371004 100644 --- a/src/retro-c.cpp +++ b/src/retro-c.cpp @@ -9,7 +9,6 @@ #include "script.h" #include "movie.h" #include "movie-bk2.h" -#include "utils.h" #include #include @@ -313,7 +312,7 @@ CNames* gameDataLookupKeys(CGameData* gameData) { const char** namesArray = new const char*[allValues.size()]; auto i = 0; for (const auto& var : allValues) { - namesArray[i] = newCString(var.first); + namesArray[i] = strdup(var.first.c_str()); i++; } return new CNames {namesArray, allValues.size()}; @@ -344,7 +343,7 @@ CVariables* gameDataListVariables(CGameData* gameData) { auto i = 0; for (const auto& var : vars) { const auto& v = var.second; - variables[i] = {newCString(var.first), v.address, v.type.type}; + variables[i] = {strdup(var.first.c_str()), v.address, v.type.type}; i++; } return new CVariables {variables, numVariables}; @@ -395,7 +394,7 @@ CNames* gameDataListSearchNames(CGameData* gameData) { std::vector names = ((Retro::GameData*) gameData->data)->listSearches(); const char** namesArray = new const char*[names.size()]; for (int i = 0; i < names.size(); i++) { - namesArray[i] = newCString(names[i]); + namesArray[i] = strdup(names[i].c_str()); } return new CNames {namesArray, names.size()}; } @@ -427,7 +426,7 @@ void movieConfigure(CMovie* movie, const char* name, CEmulator* emulator) { } const char* movieGetGameName(CMovie* movie) { - return newCString(((Retro::Movie*) movie->movie)->getGameName()); + return strdup(((Retro::Movie*) movie->movie)->getGameName().c_str()); } bool movieStep(CMovie* movie) { @@ -469,9 +468,9 @@ bool retroLoadCoreInfo(const char* json) { } const char* retroCorePath(const char* hint) { - return newCString(Retro::corePath(hint)); + return strdup(Retro::corePath(hint).c_str()); } const char* retroDataPath(const char* hint) { - return newCString(Retro::GameData::dataPath(hint)); + return strdup(Retro::GameData::dataPath(hint).c_str()); } diff --git a/src/utils.cpp b/src/utils.cpp index 890d0dfaa..a4b08952b 100644 --- a/src/utils.cpp +++ b/src/utils.cpp @@ -82,11 +82,4 @@ string drillUp(const vector& targets, const string& fail, const string& return {}; } -const char* newCString(std::string value) { - auto* cValue = value.c_str(); - auto size = sizeof(char) * (value.length() + 1); - auto* copy = malloc(size); - memcpy(copy, cValue, size); - return reinterpret_cast(copy); -} } diff --git a/src/utils.h b/src/utils.h index c9062c6cb..580d5495d 100644 --- a/src/utils.h +++ b/src/utils.h @@ -24,6 +24,4 @@ enum class Operation { int64_t calculate(Operation op, int64_t reference, int64_t value); std::string drillUp(const std::vector& targets, const std::string& fail = {}, const std::string& hint = "."); - -const char* newCString(std::string value); } From a3a075f178da45327a1a326f15e62913d00617f8 Mon Sep 17 00:00:00 2001 From: Anthony Platanios Date: Sat, 13 Apr 2019 11:29:38 -0400 Subject: [PATCH 28/33] Made the 'add_definitions' shared across BUILD_PYTHON and BUILD_C. --- CMakeLists.txt | 14 ++++++-------- 1 file changed, 6 insertions(+), 8 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 5d0b621c1..2bd3aff4a 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -266,6 +266,12 @@ if(CapnProto_FOUND) target_link_libraries(retro-capnp retro-base CapnProto::capnp) endif() +if(WIN32) + if(CMAKE_SYSTEM_PROCESSOR STREQUAL "x86_64" OR CMAKE_SYSTEM_PROCESSOR STREQUAL "AMD64") + add_definitions(-DMS_WIN64) + endif() +endif() + include_directories(src retro third-party/pybind11/include third-party third-party/gtest/googletest/include ${PYTHON_INCLUDE_DIRS}) if(BUILD_PYTHON) add_library(retro SHARED src/retro.cpp) @@ -278,9 +284,6 @@ if(BUILD_PYTHON) if(APPLE) set(PYBIND_LIBS "-undefined dynamic_lookup") elseif(WIN32) - if(CMAKE_SYSTEM_PROCESSOR STREQUAL "x86_64" OR CMAKE_SYSTEM_PROCESSOR STREQUAL "AMD64") - add_definitions(-DMS_WIN64) - endif() set(PYBIND_LIBS "${PYTHON_LIBRARY}") endif() target_link_libraries(retro retro-base ${PYBIND_LIBS} ${STATIC_LDFLAGS}) @@ -291,11 +294,6 @@ if(BUILD_C) set_target_properties(retro-c PROPERTIES OUTPUT_NAME retro CXX_VISIBILITY_PRESET default) - if(WIN32) - if(CMAKE_SYSTEM_PROCESSOR STREQUAL "x86_64" OR CMAKE_SYSTEM_PROCESSOR STREQUAL "AMD64") - add_definitions(-DMS_WIN64) - endif() - endif() target_link_libraries(retro-c retro-base ${STATIC_LDFLAGS}) endif() From 706c23841a44d1154b87d74b7c089c34f01c666a Mon Sep 17 00:00:00 2001 From: Anthony Platanios Date: Sat, 13 Apr 2019 12:11:56 -0400 Subject: [PATCH 29/33] Addressed some of @endrift's comments. --- src/retro-c.cpp | 201 +++++++++++++++++++++++++++--------------------- src/retro-c.h | 7 +- src/utils.cpp | 2 - 3 files changed, 117 insertions(+), 93 deletions(-) diff --git a/src/retro-c.cpp b/src/retro-c.cpp index 5f8371004..699e8a109 100644 --- a/src/retro-c.cpp +++ b/src/retro-c.cpp @@ -17,7 +17,6 @@ using namespace Retro; CEmulator* emulatorCreate(const char* romPath) { - Retro::Emulator* emulator = new Retro::Emulator(); if (Emulator::isLoaded()) { fprintf( stderr, @@ -25,70 +24,75 @@ CEmulator* emulatorCreate(const char* romPath) { "'env.close()' on each environment before creating a new one."); return nullptr; } - if (!emulator->loadRom(romPath)) { + Emulator* m_re = new Emulator(); + if (!m_re->loadRom(romPath)) { fprintf(stderr, "Could not load ROM."); + delete m_re; return nullptr; } // The following is necessary because otherwise, you get a segfault // when you try to get the screen for the first time. - emulator->run(); - return new CEmulator {emulator, 0}; + m_re->run(); + return new CEmulator {m_re, 0}; } void emulatorDelete(CEmulator* emulator) { - delete ((Retro::Emulator*) emulator->emulator); + delete static_cast(emulator->emulator); delete emulator; } void emulatorStep(CEmulator* emulator) { - ((Retro::Emulator*) emulator->emulator)->run(); + static_cast(emulator->emulator)->run(); } CBytes* emulatorGetState(CEmulator* emulator) { - size_t numBytes = ((Retro::Emulator*) emulator->emulator)->serializeSize(); + auto* m_re = static_cast(emulator->emulator); + size_t numBytes = m_re->serializeSize(); void* bytes = malloc(numBytes); - ((Retro::Emulator*) emulator->emulator)->serialize(bytes, numBytes); + m_re->serialize(bytes, numBytes); return new CBytes {reinterpret_cast(bytes), numBytes}; } bool emulatorSetState(CEmulator* emulator, CBytes* state) { - return ((Retro::Emulator*) emulator->emulator)->unserialize(state->bytes, state->numBytes); + return static_cast(emulator->emulator)->unserialize(state->bytes, state->numBytes); } CEmulatorScreen* emulatorGetScreen(CEmulator* emulator) { - auto* emu = ((Retro::Emulator*) emulator->emulator); - long w = emu->getImageWidth(); - long h = emu->getImageHeight(); + auto* m_re = static_cast(emulator->emulator); + long w = m_re->getImageWidth(); + long h = m_re->getImageHeight(); uint8_t* data = new uint8_t[w * h * 3]; Image out(Image::Format::RGB888, data, w, h, w); Image in; - if (emu->getImageDepth() == 16) { - in = Image(Image::Format::RGB565, emu->getImageData(), w, h, emu->getImagePitch()); - } else if (emu->getImageDepth() == 32) { - in = Image(Image::Format::RGBX888, emu->getImageData(), w, h, emu->getImagePitch()); + if (m_re->getImageDepth() == 16) { + in = Image(Image::Format::RGB565, m_re->getImageData(), w, h, m_re->getImagePitch()); + } else if (m_re->getImageDepth() == 32) { + in = Image(Image::Format::RGBX888, m_re->getImageData(), w, h, m_re->getImagePitch()); } in.copyTo(&out); return new CEmulatorScreen {data, (size_t) w, (size_t) h, 3}; } double emulatorGetScreenRate(CEmulator* emulator) { - return ((Retro::Emulator*) emulator->emulator)->getFrameRate(); + return static_cast(emulator->emulator)->getFrameRate(); } CEmulatorAudio* emulatorGetAudio(CEmulator* emulator) { - size_t numSamples = ((Retro::Emulator*) emulator->emulator)->getAudioSamples() * 2; + auto* m_re = static_cast(emulator->emulator); + size_t numSamples = m_re->getAudioSamples() * 2; int16_t* samples = new int16_t[numSamples]; - memcpy(samples, ((Retro::Emulator*) emulator->emulator)->getAudioData(), numSamples * 2); + memcpy(samples, m_re->getAudioData(), numSamples * 2); return new CEmulatorAudio {samples, numSamples}; } double emulatorGetAudioRate(CEmulator* emulator) { - return ((Retro::Emulator*) emulator->emulator)->getAudioRate(); + return static_cast(emulator->emulator)->getAudioRate(); } CEmulatorResolution* emulatorGetResolution(CEmulator* emulator) { - auto w = (size_t) ((Retro::Emulator*) emulator->emulator)->getImageWidth(); - auto h = (size_t) ((Retro::Emulator*) emulator->emulator)->getImageHeight(); + auto* m_re = static_cast(emulator->emulator); + auto w = m_re->getImageWidth(); + auto h = m_re->getImageHeight(); return new CEmulatorResolution {w, h}; } @@ -102,26 +106,26 @@ void emulatorSetButtonMask(CEmulator* emulator, const uint8_t* mask, size_t mask return; } for (int key = 0; key < maskSize; key++) { - ((Retro::Emulator*) emulator->emulator)->setKey(player, key, mask[key]); + static_cast(emulator->emulator)->setKey(player, key, mask[key]); } } void emulatorAddCheat(CEmulator* emulator, const char* code) { - ((Retro::Emulator*) emulator->emulator)->setCheat(emulator->cheats, true, code); + static_cast(emulator->emulator)->setCheat(emulator->cheats, true, code); emulator->cheats++; } void emulatorClearCheats(CEmulator* emulator) { - ((Retro::Emulator*) emulator->emulator)->clearCheats(); + static_cast(emulator->emulator)->clearCheats(); emulator->cheats = 0; } void emulatorConfigureData(CEmulator* emulator, CGameData* gameData) { - ((Retro::Emulator*) emulator->emulator)->configureData((Retro::GameData*) gameData->data); + static_cast(emulator->emulator)->configureData(static_cast(gameData->data)); } CMemoryView* memoryViewCreate(void* addressSpace) { - return new CMemoryView { (Retro::AddressSpace*) addressSpace }; + return new CMemoryView { static_cast(addressSpace) }; } void memoryViewDelete(CMemoryView* memoryView) { @@ -129,15 +133,15 @@ void memoryViewDelete(CMemoryView* memoryView) { } int64_t memoryViewExtract(CMemoryView* memoryView, size_t address, const char* type) { - return (*((Retro::AddressSpace*) memoryView->addressSpace))[Variable{ type, address }]; + return (*static_cast(memoryView->addressSpace))[Variable{ type, address }]; } void memoryViewAssign(CMemoryView* memoryView, size_t address, const char* type, int64_t value) { - (*((Retro::AddressSpace*) memoryView->addressSpace))[Variable{ type, address }] = value; + (*static_cast(memoryView->addressSpace))[Variable{ type, address }] = value; } CMemoryBlocks* memoryViewBlocks(CMemoryView* memoryView) { - auto& internalBlocks = ((Retro::AddressSpace*) memoryView->addressSpace)->blocks(); + auto& internalBlocks = static_cast(memoryView->addressSpace)->blocks(); auto numBlocks = internalBlocks.size(); auto* blocks = new CMemoryBlock[numBlocks]; auto i = 0; @@ -148,16 +152,19 @@ CMemoryBlocks* memoryViewBlocks(CMemoryView* memoryView) { return new CMemoryBlocks {blocks, numBlocks}; } +void memoryViewBlocksDelete(CMemoryBlocks* memoryBlocks) { + delete memoryBlocks->blocks; + delete memoryBlocks; +} + CSearch* searchCreate(const char** types, size_t numTypes) { - Retro::Search* search; + Search* search = nullptr; if (numTypes > 0) { - std::vector dtypes; + std::vector dtypes; for (int i = 0; i < numTypes; i++) { dtypes.emplace_back(types[i]); } - search = new Retro::Search(dtypes); - } else { - search = nullptr; + search = new Search(dtypes); } return new CSearch {search, true}; } @@ -168,27 +175,32 @@ CSearch* searchCreateUnmanaged(Retro::Search* search) { void searchDelete(CSearch* search) { if (search->managed) { - delete ((Retro::Search*) search->search); + delete static_cast(search->search); } delete search; } int searchNumResults(CSearch* search) { - return ((Retro::Search*) search->search)->numResults(); + return static_cast(search->search)->numResults(); } bool searchHasUniqueResult(CSearch* search) { - return ((Retro::Search*) search->search)->hasUniqueResult(); + return static_cast(search->search)->hasUniqueResult(); } CSearchResult* searchUniqueResult(CSearch* search) { - TypedSearchResult result = ((Retro::Search*) search->search)->uniqueResult(); - return new CSearchResult {result.address, result.type.type}; + TypedSearchResult result = static_cast(search->search)->uniqueResult(); + return new CSearchResult {result.address, strdup(result.type.type)}; +} + +void searchResultDelete(CSearchResult* searchResult) { + delete searchResult->type; + delete searchResult; } CSearchTypedResults* searchTypedResults(CSearch* search) { std::map> results; - for (const auto& result : ((Retro::Search*) search->search)->typedResults()) { + for (const auto& result : static_cast(search->search)->typedResults()) { results[static_cast(result)].emplace(result.type); } CSearchTypedResult* cResults = new CSearchTypedResult[results.size()]; @@ -212,15 +224,25 @@ CSearchTypedResults* searchTypedResults(CSearch* search) { return new CSearchTypedResults {cResults, results.size()}; } +void searchTypedResultsDelete(CSearchTypedResults* searchTypedResults) { + for (int i = 0; i < searchTypedResults->numResults; i++) { + for (int j = 0; j < searchTypedResults->results[i].numTypes; j++) { + delete searchTypedResults->results[i].types[j]; + } + } + delete searchTypedResults->results; + delete searchTypedResults; +} + CGameData* gameDataCreate() { - auto* data = new Retro::GameData(); - auto* scenario = new Retro::Scenario(*data); + auto* data = new GameData(); + auto* scenario = new Scenario(*data); return new CGameData {data, scenario}; } void gameDataDelete(CGameData* gameData) { - delete ((Retro::GameData*) gameData->data); - delete ((Retro::Scenario*) gameData->scenario); + delete static_cast(gameData->data); + delete static_cast(gameData->scenario); delete gameData; } @@ -229,38 +251,38 @@ bool gameDataLoad(CGameData* gameData, const char* dataFilename, const char* sce bool success = true; if (dataFilename != nullptr) { - success = success && ((Retro::GameData*) gameData->data)->load(dataFilename); + success = success && static_cast(gameData->data)->load(dataFilename); } if (scenarioFilename != nullptr) { - success = success && ((Retro::Scenario*) gameData->scenario)->load(scenarioFilename); + success = success && static_cast(gameData->scenario)->load(scenarioFilename); } return success; } bool gameDataSave(CGameData* gameData, const char* dataFilename, const char* scenarioFilename) { - ScriptContext::reset(); - bool success = true; if (dataFilename != nullptr) { - success = success && ((Retro::GameData*) gameData->data)->save(dataFilename); + success = success && static_cast(gameData->data)->save(dataFilename); } if (scenarioFilename != nullptr) { - success = success && ((Retro::Scenario*) gameData->scenario)->save(scenarioFilename); + success = success && static_cast(gameData->scenario)->save(scenarioFilename); } return success; } void gameDataReset(CGameData* gameData) { - ((Retro::Scenario*) gameData->scenario)->restart(); - ((Retro::Scenario*) gameData->scenario)->reloadScripts(); + auto* m_scen = static_cast(gameData->scenario); + m_scen->restart(); + m_scen->reloadScripts(); } uint16_t gameDataFilterAction(CGameData* gameData, uint16_t action) { - return ((Retro::Scenario*) gameData->scenario)->filterAction(action); + return static_cast(gameData->scenario)->filterAction(action); } CValidActions* gameDataValidActions(CGameData* gameData) { - std::map> validActions = ((Retro::Scenario*) gameData->scenario)->validActions(); + auto* m_scen = static_cast(gameData->scenario); + std::map> validActions = m_scen->validActions(); size_t numActionsOuter = validActions.size(); int** actions = new int*[numActionsOuter]; size_t* numActionsInner = new size_t[numActionsOuter]; @@ -279,36 +301,37 @@ CValidActions* gameDataValidActions(CGameData* gameData) { } void gameDataUpdateRam(CGameData* gameData) { - ((Retro::GameData*) gameData->data)->updateRam(); - ((Retro::Scenario*) gameData->scenario)->update(); + static_cast(gameData->data)->updateRam(); + static_cast(gameData->scenario)->update(); } bool gameDataLookupBoolValue(CGameData* gameData, const char* name) { - return bool(((Retro::GameData*) gameData->data)->lookupValue(name)); + return bool(static_cast(gameData->data)->lookupValue(name)); } int64_t gameDataLookupIntValue(CGameData* gameData, const char* name) { - return int64_t(((Retro::GameData*) gameData->data)->lookupValue(name)); + return int64_t(static_cast(gameData->data)->lookupValue(name)); } double gameDataLookupDoubleValue(CGameData* gameData, const char* name) { - return double(((Retro::GameData*) gameData->data)->lookupValue(name)); + return double(static_cast(gameData->data)->lookupValue(name)); } void gameDataSetBoolValue(CGameData* gameData, const char* name, bool value) { - ((Retro::GameData*) gameData->data)->setValue(name, Variant(value)); + static_cast(gameData->data)->setValue(name, Variant(value)); } void gameDataSetIntValue(CGameData* gameData, const char* name, int64_t value) { - ((Retro::GameData*) gameData->data)->setValue(name, Variant(value)); + static_cast(gameData->data)->setValue(name, Variant(value)); } void gameDataSetDoubleValue(CGameData* gameData, const char* name, double value) { - ((Retro::GameData*) gameData->data)->setValue(name, Variant(value)); + static_cast(gameData->data)->setValue(name, Variant(value)); } CNames* gameDataLookupKeys(CGameData* gameData) { - std::unordered_map allValues = ((Retro::GameData*) gameData->data)->lookupAll(); + auto* m_data = static_cast(gameData->data); + std::unordered_map allValues = m_data->lookupAll(); const char** namesArray = new const char*[allValues.size()]; auto i = 0; for (const auto& var : allValues) { @@ -319,7 +342,7 @@ CNames* gameDataLookupKeys(CGameData* gameData) { } CVariable* gameDataGetVariable(CGameData* gameData, const char* name) { - Retro::Variable var = ((Retro::GameData*) gameData->data)->getVariable(name); + Retro::Variable var = static_cast(gameData->data)->getVariable(name); auto size = sizeof(char) * 5; auto* typeCopy = malloc(size); memcpy(typeCopy, var.type.type, size); @@ -329,15 +352,15 @@ CVariable* gameDataGetVariable(CGameData* gameData, const char* name) { void gameDataSetVariable(CGameData* gameData, const char* name, CVariable* value) { Retro::Variable var { value->type, value->address }; - ((Retro::GameData*) gameData->data)->setVariable(name, var); + static_cast(gameData->data)->setVariable(name, var); } void gameDataRemoveVariable(CGameData* gameData, const char* name) { - ((Retro::GameData*) gameData->data)->removeVariable(name); + static_cast(gameData->data)->removeVariable(name); } CVariables* gameDataListVariables(CGameData* gameData) { - const auto& vars = ((Retro::GameData*) gameData->data)->listVariables(); + const auto& vars = static_cast(gameData->data)->listVariables(); auto numVariables = vars.size(); auto* variables = new CVariable[numVariables]; auto i = 0; @@ -350,15 +373,15 @@ CVariables* gameDataListVariables(CGameData* gameData) { } float gameDataCurrentReward(CGameData* gameData, unsigned int player) { - return ((Retro::Scenario*) gameData->scenario)->currentReward(player); + return static_cast(gameData->scenario)->currentReward(player); } float gameDataTotalReward(CGameData* gameData, unsigned int player) { - return ((Retro::Scenario*) gameData->scenario)->totalReward(player); + return static_cast(gameData->scenario)->totalReward(player); } bool gameDataIsDone(CGameData* gameData) { - return ((Retro::Scenario*) gameData->scenario)->isDone(); + return static_cast(gameData->scenario)->isDone(); } CCropInfo* gameDataCropInfo(CGameData* gameData, unsigned int player) { @@ -366,32 +389,32 @@ CCropInfo* gameDataCropInfo(CGameData* gameData, unsigned int player) { size_t y = 0; size_t width = 0; size_t height = 0; - ((Retro::Scenario*) gameData->scenario)->getCrop(&x, &y, &width, &height, player); + static_cast(gameData->scenario)->getCrop(&x, &y, &width, &height, player); return new CCropInfo {x, y, width, height}; } CMemoryView* gameDataMemory(CGameData* gameData) { - return memoryViewCreate(&((Retro::GameData*) gameData->data)->addressSpace()); + return memoryViewCreate(&static_cast(gameData->data)->addressSpace()); } void gameDataSearch(CGameData* gameData, const char* name, int64_t value) { - ((Retro::GameData*) gameData->data)->search(name, value); + static_cast(gameData->data)->search(name, value); } void gameDataDeltaSearch(CGameData* gameData, const char* name, const char* op, int64_t ref) { - ((Retro::GameData*) gameData->data)->deltaSearch(name, Retro::Scenario::op(op), ref); + static_cast(gameData->data)->deltaSearch(name, Scenario::op(op), ref); } CSearch* gameDataSearch(CGameData* gameData, const char* name) { - return searchCreateUnmanaged(((Retro::GameData*) gameData->data)->getSearch(name)); + return searchCreateUnmanaged(static_cast(gameData->data)->getSearch(name)); } void gameDataRemoveSearch(CGameData* gameData, const char* name) { - ((Retro::GameData*) gameData->data)->removeSearch(name); + static_cast(gameData->data)->removeSearch(name); } CNames* gameDataListSearchNames(CGameData* gameData) { - std::vector names = ((Retro::GameData*) gameData->data)->listSearches(); + std::vector names = static_cast(gameData->data)->listSearches(); const char** namesArray = new const char*[names.size()]; for (int i = 0; i < names.size(); i++) { namesArray[i] = strdup(names[i].c_str()); @@ -400,7 +423,7 @@ CNames* gameDataListSearchNames(CGameData* gameData) { } CMovie* movieCreate(const char* name, bool record, unsigned int players) { - Retro::Movie* movie; + Movie* movie; if (record) { movie = new MovieBK2(name, true, players); } else { @@ -414,44 +437,44 @@ CMovie* movieCreate(const char* name, bool record, unsigned int players) { } void movieDelete(CMovie* movie) { - delete (Retro::Movie*) movie->movie; + delete static_cast(movie->movie); delete movie; } void movieConfigure(CMovie* movie, const char* name, CEmulator* emulator) { if (movie->recording) { static_cast(movie->movie)->setGameName(name); - static_cast(movie->movie)->loadKeymap(((Retro::Emulator*) ((Retro::Emulator*) emulator->emulator))->core()); + static_cast(movie->movie)->loadKeymap(static_cast(emulator->emulator)->core()); } } const char* movieGetGameName(CMovie* movie) { - return strdup(((Retro::Movie*) movie->movie)->getGameName().c_str()); + return strdup(static_cast(movie->movie)->getGameName().c_str()); } bool movieStep(CMovie* movie) { - return ((Retro::Movie*) movie->movie)->step(); + return static_cast(movie->movie)->step(); } void movieClose(CMovie* movie) { - ((Retro::Movie*) movie->movie)->close(); + static_cast(movie->movie)->close(); } unsigned int moviePlayers(CMovie* movie) { - return ((Retro::Movie*) movie->movie)->players(); + return static_cast(movie->movie)->players(); } bool movieGetKey(CMovie* movie, int key, unsigned int player) { - return ((Retro::Movie*) movie->movie)->getKey(key, player); + return static_cast(movie->movie)->getKey(key, player); } void movieSetKey(CMovie* movie, int key, bool set, unsigned int player) { - ((Retro::Movie*) movie->movie)->setKey(key, set, player); + static_cast(movie->movie)->setKey(key, set, player); } CBytes* movieGetState(CMovie* movie) { std::vector data; - ((Retro::Movie*) movie->movie)->getState(&data); + static_cast(movie->movie)->getState(&data); auto* cData = data.data(); auto size = sizeof(uint8_t) * data.size(); auto* copy = malloc(size); @@ -460,7 +483,7 @@ CBytes* movieGetState(CMovie* movie) { } void movieSetState(CMovie* movie, CBytes* state) { - ((Retro::Movie*) movie->movie)->setState(state->bytes, state->numBytes); + static_cast(movie->movie)->setState(state->bytes, state->numBytes); } bool retroLoadCoreInfo(const char* json) { diff --git a/src/retro-c.h b/src/retro-c.h index 9260c725e..a4d76d78f 100644 --- a/src/retro-c.h +++ b/src/retro-c.h @@ -24,8 +24,8 @@ typedef struct CEmulatorAudio { } CEmulatorAudio; typedef struct CEmulatorResolution { - size_t width; - size_t height; + int width; + int height; } CEmulatorResolution; typedef struct CMemoryView { @@ -131,6 +131,7 @@ void memoryViewDelete(CMemoryView* memoryView); int64_t memoryViewExtract(CMemoryView* memoryView, size_t address, const char* type); void memoryViewAssign(CMemoryView* memoryView, size_t address, const char* type, int64_t value); CMemoryBlocks* memoryViewBlocks(CMemoryView* memoryView); +void memoryViewBlocksDelete(CMemoryBlocks* memoryBlocks); CSearch* searchCreate(const char** types, size_t numTypes); CSearch* searchCreateUnmanaged(void* search); @@ -138,7 +139,9 @@ void searchDelete(CSearch* search); int searchNumResults(CSearch* search); bool searchHasUniqueResult(CSearch* search); CSearchResult* searchUniqueResult(CSearch* search); +void searchResultDelete(CSearchResult* searchResult); CSearchTypedResults* searchTypedResults(CSearch* search); +void searchTypedResultsDelete(CSearchTypedResults* searchTypedResults); CGameData* gameDataCreate(); void gameDataDelete(CGameData* gameData); diff --git a/src/utils.cpp b/src/utils.cpp index a4b08952b..66e1b2dcc 100644 --- a/src/utils.cpp +++ b/src/utils.cpp @@ -2,7 +2,6 @@ #include #include -#include #include using namespace std; @@ -81,5 +80,4 @@ string drillUp(const vector& targets, const string& fail, const string& } return {}; } - } From 845a0ac1b63971b9b96fe0375db312eaa7da6767 Mon Sep 17 00:00:00 2001 From: Anthony Platanios Date: Sat, 13 Apr 2019 12:21:15 -0400 Subject: [PATCH 30/33] Addressed the remaining of @endrift's comments. --- src/retro-c.cpp | 34 ++++++++++++++++++++++++++++++++++ src/retro-c.h | 5 +++++ 2 files changed, 39 insertions(+) diff --git a/src/retro-c.cpp b/src/retro-c.cpp index 699e8a109..8ed11cdc3 100644 --- a/src/retro-c.cpp +++ b/src/retro-c.cpp @@ -300,6 +300,14 @@ CValidActions* gameDataValidActions(CGameData* gameData) { return new CValidActions {actions, numActionsInner, numActionsOuter}; } +void gameDataValidActionsDelete(CValidActions* validActions) { + for (int i = 0; i < validActions->numActionsOuter; i++) { + delete validActions->actions[i]; + } + delete validActions->numActionsInner; + delete validActions; +} + void gameDataUpdateRam(CGameData* gameData) { static_cast(gameData->data)->updateRam(); static_cast(gameData->scenario)->update(); @@ -393,6 +401,10 @@ CCropInfo* gameDataCropInfo(CGameData* gameData, unsigned int player) { return new CCropInfo {x, y, width, height}; } +void gameDataCropInfoDelete(CCropInfo* cropInfo) { + delete cropInfo; +} + CMemoryView* gameDataMemory(CGameData* gameData) { return memoryViewCreate(&static_cast(gameData->data)->addressSpace()); } @@ -422,6 +434,28 @@ CNames* gameDataListSearchNames(CGameData* gameData) { return new CNames {namesArray, names.size()}; } +void gameDataNamesDelete(CNames* names) { + for (int i = 0; i < names->numNames; i++) { + delete names->names[i]; + } + delete names->names; + delete names; +} + +void gameDataVariableDelete(CVariable* variable) { + delete variable->name; + delete variable->type; + delete variable; +} + +void gameDataVariablesDelete(CVariables* variables) { + for (int i = 0; i < variables->numVariables; i++) { + gameDataVariableDelete(&variables->variables[i]); + } + delete variables->variables; + delete variables; +} + CMovie* movieCreate(const char* name, bool record, unsigned int players) { Movie* movie; if (record) { diff --git a/src/retro-c.h b/src/retro-c.h index a4d76d78f..2cab4ab18 100644 --- a/src/retro-c.h +++ b/src/retro-c.h @@ -150,6 +150,7 @@ bool gameDataSave(CGameData* gameData, const char* dataFilename, const char* sce void gameDataReset(CGameData* gameData); uint16_t gameDataFilterAction(CGameData* gameData, uint16_t action); CValidActions* gameDataValidActions(CGameData* gameData); +void gameDataValidActionsDelete(CValidActions* validActions); void gameDataUpdateRam(CGameData* gameData); bool gameDataLookupBoolValue(CGameData* gameData, const char* name); int64_t gameDataLookupIntValue(CGameData* gameData, const char* name); @@ -166,12 +167,16 @@ float gameDataCurrentReward(CGameData* gameData, unsigned int player); float gameDataTotalReward(CGameData* gameData, unsigned int player); bool gameDataIsDone(CGameData* gameData); CCropInfo* gameDataCropInfo(CGameData* gameData, unsigned int player); +void gameDataCropInfoDelete(CCropInfo* cropInfo); CMemoryView* gameDataMemory(CGameData* gameData); void gameDataSearch(CGameData* gameData, const char* name, int64_t value); void gameDataDeltaSearch(CGameData* gameData, const char* name, const char* op, int64_t ref); CSearch* gameDataGetSearch(CGameData* gameData, const char* name); void gameDataRemoveSearch(CGameData* gameData, const char* name); CNames* gameDataListSearchNames(CGameData* gameData); +void gameDataNamesDelete(CNames* names); +void gameDataVariableDelete(CVariable* variable); +void gameDataVariablesDelete(CVariables* variables); CMovie* movieCreate(const char* name, bool record, unsigned int players); void movieDelete(CMovie* movie); From 0a96f8c4eb6212f2585d582cfd6237af520bbdde Mon Sep 17 00:00:00 2001 From: Anthony Platanios Date: Sat, 20 Jul 2019 01:45:09 -0400 Subject: [PATCH 31/33] Added support for deleting the obtained emulator screen. --- src/retro-c.cpp | 5 +++++ src/retro-c.h | 1 + 2 files changed, 6 insertions(+) diff --git a/src/retro-c.cpp b/src/retro-c.cpp index 8ed11cdc3..f0845eb5b 100644 --- a/src/retro-c.cpp +++ b/src/retro-c.cpp @@ -73,6 +73,11 @@ CEmulatorScreen* emulatorGetScreen(CEmulator* emulator) { return new CEmulatorScreen {data, (size_t) w, (size_t) h, 3}; } +void emulatorScreenDelete(CEmulatorScreen* screen) { + delete screen->values; + delete screen; +} + double emulatorGetScreenRate(CEmulator* emulator) { return static_cast(emulator->emulator)->getFrameRate(); } diff --git a/src/retro-c.h b/src/retro-c.h index 2cab4ab18..8b8ad9d8b 100644 --- a/src/retro-c.h +++ b/src/retro-c.h @@ -117,6 +117,7 @@ void emulatorStep(CEmulator* emulator); CBytes* emulatorGetState(CEmulator* emulator); bool emulatorSetState(CEmulator* emulator, CBytes* state); CEmulatorScreen* emulatorGetScreen(CEmulator* emulator); +void emulatorScreenDelete(CEmulatorScreen* screen); double emulatorGetScreenRate(CEmulator* emulator); CEmulatorAudio* emulatorGetAudio(CEmulator* emulator); double emulatorGetAudioRate(CEmulator* emulator); From 92316e07e54bc09c0c14584238a54424f47201c7 Mon Sep 17 00:00:00 2001 From: Anthony Platanios Date: Sat, 20 Jul 2019 01:56:09 -0400 Subject: [PATCH 32/33] Added some more missing 'delete' functions. --- src/retro-c.cpp | 14 ++++++++++++++ src/retro-c.h | 3 +++ 2 files changed, 17 insertions(+) diff --git a/src/retro-c.cpp b/src/retro-c.cpp index f0845eb5b..a24bdeb03 100644 --- a/src/retro-c.cpp +++ b/src/retro-c.cpp @@ -53,6 +53,11 @@ CBytes* emulatorGetState(CEmulator* emulator) { return new CBytes {reinterpret_cast(bytes), numBytes}; } +void emulatorStateDelete(CBytes* state) { + delete state->bytes; + delete state; +} + bool emulatorSetState(CEmulator* emulator, CBytes* state) { return static_cast(emulator->emulator)->unserialize(state->bytes, state->numBytes); } @@ -90,6 +95,11 @@ CEmulatorAudio* emulatorGetAudio(CEmulator* emulator) { return new CEmulatorAudio {samples, numSamples}; } +void emulatorAudioDelete(CEmulatorAudio* audio) { + delete audio->samples; + delete audio; +} + double emulatorGetAudioRate(CEmulator* emulator) { return static_cast(emulator->emulator)->getAudioRate(); } @@ -101,6 +111,10 @@ CEmulatorResolution* emulatorGetResolution(CEmulator* emulator) { return new CEmulatorResolution {w, h}; } +void emulatorResolutionDelete(CEmulatorResolution* resolution) { + delete resolution; +} + void emulatorSetButtonMask(CEmulator* emulator, const uint8_t* mask, size_t maskSize, unsigned int player) { if (maskSize > N_BUTTONS) { fprintf(stderr, "mask.size() > N_BUTTONS."); diff --git a/src/retro-c.h b/src/retro-c.h index 8b8ad9d8b..9de29b60d 100644 --- a/src/retro-c.h +++ b/src/retro-c.h @@ -115,13 +115,16 @@ CEmulator* emulatorCreate(const char* romPath); void emulatorDelete(CEmulator* emulator); void emulatorStep(CEmulator* emulator); CBytes* emulatorGetState(CEmulator* emulator); +void emulatorStateDelete(CBytes* state); bool emulatorSetState(CEmulator* emulator, CBytes* state); CEmulatorScreen* emulatorGetScreen(CEmulator* emulator); void emulatorScreenDelete(CEmulatorScreen* screen); double emulatorGetScreenRate(CEmulator* emulator); CEmulatorAudio* emulatorGetAudio(CEmulator* emulator); +void emulatorAudioDelete(CEmulatorAudio* audio); double emulatorGetAudioRate(CEmulator* emulator); CEmulatorResolution* emulatorGetResolution(CEmulator* emulator); +void emulatorResolutionDelete(CEmulatorResolution* resolution); void emulatorSetButtonMask(CEmulator* emulator, const uint8_t* mask, size_t maskSize, unsigned int player); void emulatorAddCheat(CEmulator* emulator, const char* code); void emulatorClearCheats(CEmulator* emulator); From d3f5b1463298228f10f0df308160863ab0f93fde Mon Sep 17 00:00:00 2001 From: Anthony Platanios Date: Sat, 27 Jul 2019 15:16:21 -0400 Subject: [PATCH 33/33] Added support for installing the retro C API using pkgconfig. --- CMakeLists.txt | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/CMakeLists.txt b/CMakeLists.txt index 2bd3aff4a..32e3727f2 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -33,6 +33,7 @@ endif() if(NOT CMAKE_BUILD_TYPE) set(CMAKE_BUILD_TYPE RelWithDebInfo) endif() +set(PKGCONFIG_INSTALL_DIR "${CMAKE_INSTALL_PREFIX}/lib/pkgconfig/" CACHE STRING "Base directory for pkgconfig files.") option(BUILD_TESTS "Should tests be built" ON) option(BUILD_UI "Should integration UI be built" OFF) option(BUILD_LUAJIT "Should static LuaJIT be used instead of system Lua" ON) @@ -295,6 +296,18 @@ if(BUILD_C) OUTPUT_NAME retro CXX_VISIBILITY_PRESET default) target_link_libraries(retro-c retro-base ${STATIC_LDFLAGS}) + install(TARGETS retro-c) + file(WRITE ${CMAKE_CURRENT_BINARY_DIR}/retro-c.pc +" +Name: ${PROJECT_NAME} +Description: Retro C API. +URL: https://github.com/openai/retro +Version: ${PROJECT_VERSION} +Requires: +Libs: -L${CMAKE_INSTALL_PREFIX}/lib -lretro +Cflags: -I${CMAKE_INSTALL_PREFIX}/include +") + install(FILES ${CMAKE_CURRENT_BINARY_DIR}/retro-c.pc DESTINATION ${PKGCONFIG_INSTALL_DIR}) endif() if(BUILD_TESTS)