Skip to content

Commit

Permalink
Convert game_ai from CPP to C. STEP 2: add C function calls
Browse files Browse the repository at this point in the history
  • Loading branch information
MatPoliquin committed Jan 21, 2025
1 parent d8126dc commit 5d59960
Show file tree
Hide file tree
Showing 4 changed files with 108 additions and 51 deletions.
87 changes: 56 additions & 31 deletions ai/game_ai.cpp
Original file line number Diff line number Diff line change
@@ -1,35 +1,36 @@
#include "game_ai.h"
#include <stdio.h>
#include <retro_assert.h>
#include <bitset>
#include <iostream>
#include <string>
#include <stdarg.h>
#include <string.h>

#ifdef _WIN32
#include <windows.h>
#else
#include <dlfcn.h>
#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;
Expand All @@ -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)
Expand All @@ -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;
Expand All @@ -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);
Expand All @@ -95,8 +106,20 @@ extern "C" void game_ai_init()
{
dlinfo(myso, RTLD_DI_ORIGIN, (void *) &game_ai_lib_path);

CreateGameAI = reinterpret_cast<creategameai_t>(dlsym(myso, "CreateGameAI"));
retro_assert(CreateGameAI);
create_game_ai = reinterpret_cast<create_game_ai_t>(dlsym(myso, "create_game_ai"));
retro_assert(create_game_ai);

game_ai_lib_init = reinterpret_cast<game_ai_lib_init_t>(dlsym(myso, "game_ai_lib_init"));
retro_assert(game_ai_lib_init);

game_ai_lib_think = reinterpret_cast<game_ai_lib_think_t>(dlsym(myso, "game_ai_lib_think"));
retro_assert(game_ai_lib_think);

game_ai_lib_set_show_debug = reinterpret_cast<game_ai_lib_set_show_debug_t>(dlsym(myso, "game_ai_lib_set_show_debug"));
retro_assert(game_ai_lib_set_show_debug);

game_ai_lib_set_debug_log = reinterpret_cast<game_ai_lib_set_debug_log_t>(dlsym(myso, "game_ai_lib_set_debug_log"));
retro_assert(game_ai_lib_set_debug_log);
}
#endif
}
Expand All @@ -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;
Expand All @@ -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);
}
}
Expand Down
10 changes: 9 additions & 1 deletion deps/game_ai_lib/GameAI.h
Original file line number Diff line number Diff line change
Expand Up @@ -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:
Expand All @@ -22,5 +25,10 @@ class GameAI {
debug_log_t debugLogFunc;
};

#endif

typedef GameAI * (*creategameai_t)(const char *);
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);
36 changes: 30 additions & 6 deletions deps/game_ai_lib/GameAILocal.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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<GameAI*>(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<GameAI*>(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<GameAI*>(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<GameAI*>(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")
Expand All @@ -43,7 +67,7 @@ extern "C" DllExport GameAI * CreateGameAI(const char * name)
ptr->DebugPrint(game_name.c_str());
}

return (GameAI *) ptr;
return (void *) ptr;
}

//=======================================================
Expand All @@ -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();
Expand Down Expand Up @@ -90,7 +114,7 @@ void GameAILocal::LoadConfig_Player(const nlohmann::detail::iter_impl<const nloh
if (models.count(model.key()) == 0)
{
models.insert(std::pair<std::string, RetroModel*>(model.key(), load_model));
}
}
}
}
}
Expand Down
26 changes: 13 additions & 13 deletions deps/game_ai_lib/test.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@
#include "RetroModel.h"

#ifdef _WIN32
#include <windows.h>
#include <windows.h>
#else
#include <dlfcn.h>
#endif
Expand All @@ -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;
Expand Down Expand Up @@ -80,7 +80,7 @@ void test_opencv(std::map<std::string, bool> & 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");
Expand All @@ -100,19 +100,19 @@ void test_opencv(std::map<std::string, bool> & tests)
void test_loadlibrary(std::map<std::string, bool> & 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);

Expand All @@ -122,20 +122,20 @@ void test_loadlibrary(std::map<std::string, bool> & tests)
{
tests["LOAD LIBRARY"] = true;

func = reinterpret_cast<creategameai_t>(dlsym(myso, "CreateGameAI"));
func = reinterpret_cast<create_game_ai_t>(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
}

Expand Down Expand Up @@ -197,6 +197,6 @@ int main()
const char * result = i.second ? "PASS" : "FAIL";
std::cout << i.first << "..." << result << std::endl;
}

return 0;
}

0 comments on commit 5d59960

Please sign in to comment.