diff --git a/ai/game_ai.cpp b/ai/game_ai.cpp index b23664067866..43886554fb56 100644 --- a/ai/game_ai.cpp +++ b/ai/game_ai.cpp @@ -1,10 +1,8 @@ #include "game_ai.h" #include #include -#include -#include -#include #include +#include #ifdef _WIN32 #include @@ -12,24 +10,27 @@ #include #endif -#define GAME_AI_MAX_PLAYERS 2 - #include "../deps/game_ai_lib/GameAI.h" +#define GAME_AI_MAX_PLAYERS 2 -creategameai_t CreateGameAI = nullptr; -GameAI * ga = nullptr; +void * ga = nullptr; volatile void * g_ram_ptr = nullptr; volatile int g_ram_size = 0; volatile signed short int g_buttons_bits[GAME_AI_MAX_PLAYERS] = {0}; volatile int g_frameCount = 0; volatile char game_ai_lib_path[1024] = {0}; -std::string g_game_name; +volatile char g_game_name[1024] = {0}; retro_log_printf_t g_log = nullptr; -//====================================================== -// Helper functions -//====================================================== +/* GameAI Lib API*/ +create_game_ai_t create_game_ai = nullptr; +game_ai_lib_init_t game_ai_lib_init = nullptr; +game_ai_lib_think_t game_ai_lib_think = nullptr; +game_ai_lib_set_show_debug_t game_ai_lib_set_show_debug = nullptr; +game_ai_lib_set_debug_log_t game_ai_lib_set_debug_log = nullptr; + +/* Helper functions */ extern "C" void game_ai_debug_log(int level, const char *fmt, ...) { va_list vp; @@ -51,9 +52,8 @@ void array_to_bits_16(volatile signed short & result, const bool b[16]) } } -//====================================================== -// Interface to RA -//====================================================== +/* Interface to RA */ + extern "C" signed short int game_ai_input(unsigned int port, unsigned int device, unsigned int idx, unsigned int id, signed short int result) { if (ga == nullptr) @@ -69,7 +69,7 @@ extern "C" void game_ai_init() { printf("GameAIManager::Init()\n"); - if (CreateGameAI == nullptr) + if (create_game_ai == nullptr) { #ifdef _WIN32 HINSTANCE hinstLib; @@ -83,9 +83,20 @@ extern "C" void game_ai_init() if (hinstLib != NULL) { - CreateGameAI = (creategameai_t) GetProcAddress(hinstLib, "CreateGameAI"); + create_game_ai = (create_game_ai_t) GetProcAddress(hinstLib, "create_game_ai"); + retro_assert(create_game_ai); + + game_ai_lib_init = (game_ai_lib_init_t) GetProcAddress(hinstLib, "game_ai_lib_init"); + retro_assert(game_ai_lib_init); + + game_ai_lib_think = (game_ai_lib_think_t) GetProcAddress(hinstLib, "game_ai_lib_think"); + retro_assert(game_ai_lib_think); - retro_assert(CreateGameAI); + game_ai_lib_set_show_debug = (game_ai_lib_set_show_debug_t) GetProcAddress(hinstLib, "game_ai_lib_set_show_debug"); + retro_assert(game_ai_lib_set_show_debug); + + game_ai_lib_set_debug_log = (game_ai_lib_set_debug_log_t) GetProcAddress(hinstLib, "game_ai_lib_set_debug_log"); + retro_assert(game_ai_lib_set_debug_log); } #else void *myso = dlopen("libgame_ai.so", RTLD_NOW); @@ -95,8 +106,20 @@ extern "C" void game_ai_init() { dlinfo(myso, RTLD_DI_ORIGIN, (void *) &game_ai_lib_path); - CreateGameAI = reinterpret_cast(dlsym(myso, "CreateGameAI")); - retro_assert(CreateGameAI); + create_game_ai = reinterpret_cast(dlsym(myso, "create_game_ai")); + retro_assert(create_game_ai); + + game_ai_lib_init = reinterpret_cast(dlsym(myso, "game_ai_lib_init")); + retro_assert(game_ai_lib_init); + + game_ai_lib_think = reinterpret_cast(dlsym(myso, "game_ai_lib_think")); + retro_assert(game_ai_lib_think); + + game_ai_lib_set_show_debug = reinterpret_cast(dlsym(myso, "game_ai_lib_set_show_debug")); + retro_assert(game_ai_lib_set_show_debug); + + game_ai_lib_set_debug_log = reinterpret_cast(dlsym(myso, "game_ai_lib_set_debug_log")); + retro_assert(game_ai_lib_set_debug_log); } #endif } @@ -106,7 +129,7 @@ extern "C" void game_ai_load(const char * name, void * ram_ptr, int ram_size, re { printf("GameAIManager::Load\n"); - g_game_name = name; + strcpy((char *) &g_game_name[0], name); g_ram_ptr = ram_ptr; g_ram_size = ram_size; @@ -117,43 +140,45 @@ extern "C" void game_ai_load(const char * name, void * ram_ptr, int ram_size, re extern "C" void game_ai_think(bool override_p1, bool override_p2, bool show_debug, const void *frame_data, unsigned int frame_width, unsigned int frame_height, unsigned int frame_pitch, unsigned int pixel_format) { if (ga) - ga->SetShowDebug(show_debug); + game_ai_lib_set_show_debug(ga, show_debug); if (ga == nullptr && g_ram_ptr != nullptr) { - ga = CreateGameAI(g_game_name.c_str()); + ga = create_game_ai((char *) &g_game_name[0]); retro_assert(ga); if (ga) { - std::string data_path((char *)game_ai_lib_path); - data_path += "/data/"; - data_path += g_game_name; + char data_path[1024] = {0}; + strcpy(&data_path[0], (char *)game_ai_lib_path); + strcat(&data_path[0], "/data/"); + strcat(&data_path[0], (char *)g_game_name); + - ga->Init((void *) g_ram_ptr, g_ram_size); + game_ai_lib_init(ga, (void *) g_ram_ptr, g_ram_size); - ga->SetDebugLog(game_ai_debug_log); + game_ai_lib_set_debug_log(ga, game_ai_debug_log); } } - if (g_frameCount >= 3) + if (g_frameCount >= (GAMEAI_SKIPFRAMES - 1)) { if (ga) { - bool b[16] = {0}; + bool b[GAMEAI_MAX_BUTTONS] = {0}; g_buttons_bits[0]=0; g_buttons_bits[1]=0; if (override_p1) { - ga->Think(b, 0, frame_data, frame_width, frame_height, frame_pitch, pixel_format); + game_ai_lib_think(ga, b, 0, frame_data, frame_width, frame_height, frame_pitch, pixel_format); array_to_bits_16(g_buttons_bits[0], b); } if (override_p2) { - ga->Think(b, 1, frame_data, frame_width, frame_height, frame_pitch, pixel_format); + game_ai_lib_think(ga, b, 1, frame_data, frame_width, frame_height, frame_pitch, pixel_format); array_to_bits_16(g_buttons_bits[1], b); } } diff --git a/deps/game_ai_lib/GameAI.h b/deps/game_ai_lib/GameAI.h index a763605c47df..549174167fa2 100644 --- a/deps/game_ai_lib/GameAI.h +++ b/deps/game_ai_lib/GameAI.h @@ -9,6 +9,9 @@ typedef void (*debug_log_t)(int level, const char *fmt, ...); #define GAMEAI_MAX_BUTTONS 16 +#define GAMEAI_SKIPFRAMES 4 + +#ifdef __cplusplus class GameAI { public: @@ -22,5 +25,10 @@ class GameAI { debug_log_t debugLogFunc; }; +#endif -typedef GameAI * (*creategameai_t)(const char *); \ No newline at end of file +typedef void * (*create_game_ai_t)(const char *); +typedef void (*game_ai_lib_init_t)(void * obj_ptr, void * ram_ptr, int ram_size); +typedef void (*game_ai_lib_think_t)(void * obj_ptr, bool buttons[GAMEAI_MAX_BUTTONS], int player, const void *frame_data, unsigned int frame_width, unsigned int frame_height, unsigned int frame_pitch, unsigned int pixel_format); +typedef void (*game_ai_lib_set_show_debug_t)(void * obj_ptr, const bool show); +typedef void (*game_ai_lib_set_debug_log_t)(void * obj_ptr, debug_log_t func); diff --git a/deps/game_ai_lib/GameAILocal.cpp b/deps/game_ai_lib/GameAILocal.cpp index 37c2fdf6622b..a2a50b2a73ec 100644 --- a/deps/game_ai_lib/GameAILocal.cpp +++ b/deps/game_ai_lib/GameAILocal.cpp @@ -14,13 +14,37 @@ //======================================================= -// CreateGameAI +// C API //======================================================= -extern "C" DllExport GameAI * CreateGameAI(const char * name) +extern "C" DllExport void game_ai_lib_init(void * obj_ptr, void * ram_ptr, int ram_size) +{ + if (obj_ptr) + static_cast(obj_ptr)->Init(ram_ptr, ram_size); +} + +extern "C" DllExport void game_ai_lib_think(void * obj_ptr,bool buttons[GAMEAI_MAX_BUTTONS], int player, const void *frame_data, unsigned int frame_width, unsigned int frame_height, unsigned int frame_pitch, unsigned int pixel_format) +{ + if (obj_ptr) + static_cast(obj_ptr)->Think(buttons, player, frame_data, frame_width, frame_height, frame_pitch, pixel_format); +} + +extern "C" DllExport void game_ai_lib_set_show_debug(void * obj_ptr,const bool show) +{ + if (obj_ptr) + static_cast(obj_ptr)->SetShowDebug(show); +} + +extern "C" DllExport void game_ai_lib_set_debug_log(void * obj_ptr,debug_log_t func) +{ + if (obj_ptr) + static_cast(obj_ptr)->SetDebugLog(func); +} + +extern "C" DllExport void * create_game_ai(const char * name) { std::filesystem::path path = name; std::string game_name = path.parent_path().filename().string(); - + GameAILocal * ptr = nullptr; if(game_name == "NHL941on1-Genesis") @@ -43,7 +67,7 @@ extern "C" DllExport GameAI * CreateGameAI(const char * name) ptr->DebugPrint(game_name.c_str()); } - return (GameAI *) ptr; + return (void *) ptr; } //======================================================= @@ -57,7 +81,7 @@ void GameAILocal::InitRAM(void * ram_ptr, int ram_size) //retro_data.load() //std::cout << memDataPath << std::endl; retro_data.load(memDataPath.string()); - + Retro::AddressSpace* m_addressSpace = nullptr; m_addressSpace = &retro_data.addressSpace(); m_addressSpace->reset(); @@ -90,7 +114,7 @@ void GameAILocal::LoadConfig_Player(const nlohmann::detail::iter_impl(model.key(), load_model)); - } + } } } } diff --git a/deps/game_ai_lib/test.cpp b/deps/game_ai_lib/test.cpp index 539a2c2cb76a..5fa406b967bb 100644 --- a/deps/game_ai_lib/test.cpp +++ b/deps/game_ai_lib/test.cpp @@ -9,7 +9,7 @@ #include "RetroModel.h" #ifdef _WIN32 -#include +#include #else #include #endif @@ -31,7 +31,7 @@ Ort::Session session(env, model_path, Ort::SessionOptions{ nullptr }); ... // Run inference std::vector outputTensors = -session.Run(Ort::RunOptions{nullptr}, inputNames.data(), &inputTensor, +session.Run(Ort::RunOptions{nullptr}, inputNames.data(), &inputTensor, inputNames.size(), outputNames.data(), outputNames.size()); const float* outputDataPtr = outputTensors[0].GetTensorMutableData(); std::cout << outputDataPtr[0] << std::endl; @@ -80,7 +80,7 @@ void test_opencv(std::map & tests) cv::cvtColor(image, grey, cv::COLOR_RGB2GRAY); cv::resize(grey, result, cv::Size(84,84), cv::INTER_AREA); - + if ( !image.data ) { printf("No image data \n"); @@ -100,19 +100,19 @@ void test_opencv(std::map & tests) void test_loadlibrary(std::map & tests) { GameAI * ga = nullptr; - creategameai_t func = nullptr; + create_game_ai_t func = nullptr; #ifdef _WIN32 - HINSTANCE hinstLib; + HINSTANCE hinstLib; BOOL fFreeResult, fRunTimeLinkSuccess = FALSE; hinstLib = LoadLibrary(TEXT("game_ai.dll")); - if (hinstLib != NULL) - { + if (hinstLib != NULL) + { tests["LOAD LIBRARY"] = true; - func = (creategameai_t) GetProcAddress(hinstLib, "CreateGameAI"); - } + func = (create_game_ai_t) GetProcAddress(hinstLib, "create_game_ai"); + } #else void *myso = dlopen("./libgame_ai.so", RTLD_NOW); @@ -122,20 +122,20 @@ void test_loadlibrary(std::map & tests) { tests["LOAD LIBRARY"] = true; - func = reinterpret_cast(dlsym(myso, "CreateGameAI")); + func = reinterpret_cast(dlsym(myso, "create_game_ai")); } #endif if(func) { tests["GET CREATEGAME FUNC"] = true; - ga = func("./data/NHL941on1-Genesis/NHL941on1.md"); + ga = (GameAI *) func("./data/NHL941on1-Genesis/NHL941on1.md"); if(ga) tests["CREATEGAME FUNC"] = true; } #ifdef _WIN32 - fFreeResult = FreeLibrary(hinstLib); + fFreeResult = FreeLibrary(hinstLib); #endif } @@ -197,6 +197,6 @@ int main() const char * result = i.second ? "PASS" : "FAIL"; std::cout << i.first << "..." << result << std::endl; } - + return 0; } \ No newline at end of file