Advertisement
Guest User

libretro + sdl prototype

a guest
Aug 22nd, 2017
81
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C++ 5.72 KB | None | 0 0
  1. // g++ sdl_nes_rom.cpp /usr/lib/libretro/nestopia_libretro.so -I../src -lSDL2 -o sdl_nes_rom
  2.  
  3. // There is a lot of hardcoded path, you will need:
  4. //  /tmp/kikoo/ <- an empty dir (working directory for nestopia-core)
  5. //  /tmp/lol.nes <- a ROM file of no more than 196624 bytes (my largest test ROM file :) )
  6. // Sorry.
  7.  
  8. #include "libretro.h"
  9. #include <SDL2/SDL.h>
  10. #include <iostream>
  11. #include <fstream>
  12.  
  13. // SDL working variables kept in a global
  14. struct sdl_stuff_t {
  15.     SDL_Surface* current_frame;
  16.     SDL_Texture* current_texture;
  17.     SDL_Renderer* renderer;
  18.     SDL_Window* window;
  19. };
  20. static sdl_stuff_t sdl_stuff;
  21.  
  22. // *_cb libretro callbacks: it is called by nestopia-core when it need some information
  23. //      see https://buildbot.libretro.com/docs/specs/api/ and libretro.h for more information
  24.  
  25. bool environment_cb(unsigned cmd, void *data) {
  26.     std::cout << "environment_cb: cmd=" << cmd << std::endl;
  27.     switch (cmd) {
  28.         case RETRO_ENVIRONMENT_GET_SYSTEM_DIRECTORY:
  29.         {
  30.             std::cout << " `-> RETRO_ENVIRONMENT_GET_SYSTEM_DIRECTORY: /tmp/kikoo" << std::endl;
  31.             char const ** path = (char const **)data;
  32.             *path = "/tmp/kikoo";
  33.             return true;
  34.         }
  35.         case RETRO_ENVIRONMENT_SET_PIXEL_FORMAT:
  36.             std::cout << " `-> RETRO_ENVIRONMENT_SET_PIXEL_FORMAT: " << *((int*)data) << std::endl;
  37.             return true;
  38.         default:
  39.             return false;
  40.     };
  41. }
  42.  
  43. void video_cb(const void *data, unsigned width, unsigned height, size_t pitch) {
  44.     std::cout << "got a frame of " << width << 'x' << height << " (pitch: " << pitch << ')' << std::endl;
  45.  
  46.     if (pitch != 0) {
  47.         SDL_LockSurface(sdl_stuff.current_frame);
  48.         ::memcpy(sdl_stuff.current_frame->pixels, data, 4 * width * height);
  49.         SDL_UnlockSurface(sdl_stuff.current_frame);
  50.  
  51.         //uint8_t const * const begin = (uint8_t const *)data;
  52.         //uint8_t const * b = begin;
  53.         //std::ofstream ofs("/tmp/lol.pic");
  54.         //while (b - begin < 4 * width * height) {
  55.         //  ofs << *b;
  56.         //  ++b;
  57.         //}
  58.         //ofs.close();
  59.     }
  60. }
  61.  
  62. void audio_sample_cb(int16_t left, int16_t right) {
  63. }
  64.  
  65. size_t audio_batch_cb(const int16_t *data, size_t frames) {
  66.     return frames;
  67. }
  68.  
  69. void input_poll_cb() {
  70. }
  71.  
  72. int16_t input_state_cb(unsigned port, unsigned device, unsigned index, unsigned id) {
  73.     return 0;
  74. }
  75.  
  76. // Create a window an initialize sdl_stuff global variable
  77. bool init_sdl() {
  78.     if (SDL_Init(SDL_INIT_VIDEO) != 0) {
  79.         std::cerr << "SDL_Init Error: " << SDL_GetError() << std::endl;
  80.         return false;
  81.     }
  82.  
  83.     sdl_stuff.window = SDL_CreateWindow("Hello World!", 100, 100, 640, 480, SDL_WINDOW_SHOWN);
  84.     if (sdl_stuff.window == nullptr) {
  85.         std::cerr << "SDL_CreateWindow Error: " << SDL_GetError() << std::endl;
  86.         SDL_Quit();
  87.         return false;
  88.     }
  89.  
  90.     sdl_stuff.renderer = SDL_CreateRenderer(sdl_stuff.window, -1, SDL_RENDERER_ACCELERATED | SDL_RENDERER_PRESENTVSYNC);
  91.     if (sdl_stuff.renderer == nullptr) {
  92.         SDL_DestroyWindow(sdl_stuff.window);
  93.         std::cerr << "SDL_CreateRenderer Error: " << SDL_GetError() << std::endl;
  94.         SDL_Quit();
  95.         return false;
  96.     }
  97.  
  98.     sdl_stuff.current_frame = SDL_CreateRGBSurface(0, 256, 240, 32, 0xff000000, 0x00ff0000, 0x0000ff00, 0x000000ff);
  99.     if (sdl_stuff.current_frame == nullptr) {
  100.         SDL_DestroyRenderer(sdl_stuff.renderer);
  101.         SDL_DestroyWindow(sdl_stuff.window);
  102.         std::cerr << "SDL_CreateRGBSurface Error: " << SDL_GetError() << std::endl;
  103.         SDL_Quit();
  104.         return false;
  105.     }
  106.  
  107.     sdl_stuff.current_texture = nullptr;
  108.  
  109.     return true;
  110. }
  111.  
  112. // Emulate a frame of the game and show it
  113. void process_one_frame() {
  114.     // Get a frame from nestopia-core
  115.     retro_run();
  116.  
  117.     // Convert it to a SDL texture
  118.     if (sdl_stuff.current_texture != nullptr) {
  119.         SDL_DestroyTexture(sdl_stuff.current_texture);
  120.     }
  121.     sdl_stuff.current_texture = SDL_CreateTextureFromSurface(sdl_stuff.renderer, sdl_stuff.current_frame);
  122.     if (sdl_stuff.current_texture == nullptr) {
  123.         std::cerr << "Failed to allocate texture" << std::endl;
  124.         return;
  125.     }
  126.  
  127.     // Render
  128.     SDL_RenderClear(sdl_stuff.renderer);
  129.     SDL_RenderCopy(sdl_stuff.renderer, sdl_stuff.current_texture, NULL, NULL);
  130.     SDL_RenderPresent(sdl_stuff.renderer);
  131. }
  132.  
  133. int main() {
  134.     // Check API version of the core (should be tested against RETRO_API_VERSION in real life)
  135.     std::cout << "API version: " << retro_api_version() << std::endl;
  136.  
  137.     // Initialize the core
  138.     retro_set_environment(environment_cb);
  139.     retro_set_video_refresh(video_cb);
  140.     retro_set_audio_sample(audio_sample_cb);
  141.     retro_set_audio_sample_batch(audio_batch_cb);
  142.     retro_set_input_poll(input_poll_cb);
  143.     retro_set_input_state(input_state_cb);
  144.     retro_init();
  145.  
  146.     // Get some information about the core
  147.     retro_system_info system_info;
  148.     retro_get_system_info(&system_info);
  149.     std::cout << "library name: '" << system_info.library_name << "'" << std::endl;
  150.     std::cout << "library version: '" << system_info.library_version << "'" << std::endl;
  151.     std::cout << "need fullpath: " << (system_info.need_fullpath ? "true" : "false") << std::endl;
  152.     std::cout << "block extract: " << (system_info.block_extract ? "true" : "false") << std::endl;
  153.  
  154.     // Load a game
  155.     char* game_data = (char*)::malloc(196624);
  156.     std::ifstream ifs("/tmp/lol.nes");
  157.     ifs.read(game_data, 196624);
  158.     retro_game_info game_info {
  159.         .path = "/tmp/lol.nes",
  160.         .data = game_data,
  161.         .size = (size_t)ifs.gcount(),
  162.         .meta = nullptr
  163.     };
  164.     ifs.close();
  165.     bool res = retro_load_game(&game_info);
  166.     std::cout << "retro_load_game: " << (res ? "true" : "false") << std::endl;
  167.  
  168.     // Create an window
  169.     if (! init_sdl()) {
  170.         retro_deinit();
  171.         return 1;
  172.     }
  173.  
  174.     // Run for three frames
  175.     for (int i = 0; i < 10 * 60; ++i) {
  176.         process_one_frame();
  177.     }
  178.  
  179.     // Good bye
  180.     SDL_DestroyTexture(sdl_stuff.current_texture);
  181.     SDL_FreeSurface(sdl_stuff.current_frame);
  182.     SDL_DestroyRenderer(sdl_stuff.renderer);
  183.     SDL_DestroyWindow(sdl_stuff.window);
  184.     SDL_Quit();
  185.     retro_deinit();
  186.     return 0;
  187. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement