Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- // g++ sdl_nes_rom.cpp /usr/lib/libretro/nestopia_libretro.so -I../src -lSDL2 -o sdl_nes_rom
- // There is a lot of hardcoded path, you will need:
- // /tmp/kikoo/ <- an empty dir (working directory for nestopia-core)
- // /tmp/lol.nes <- a ROM file of no more than 196624 bytes (my largest test ROM file :) )
- // Sorry.
- #include "libretro.h"
- #include <SDL2/SDL.h>
- #include <iostream>
- #include <fstream>
- // SDL working variables kept in a global
- struct sdl_stuff_t {
- SDL_Surface* current_frame;
- SDL_Texture* current_texture;
- SDL_Renderer* renderer;
- SDL_Window* window;
- };
- static sdl_stuff_t sdl_stuff;
- // *_cb libretro callbacks: it is called by nestopia-core when it need some information
- // see https://buildbot.libretro.com/docs/specs/api/ and libretro.h for more information
- bool environment_cb(unsigned cmd, void *data) {
- std::cout << "environment_cb: cmd=" << cmd << std::endl;
- switch (cmd) {
- case RETRO_ENVIRONMENT_GET_SYSTEM_DIRECTORY:
- {
- std::cout << " `-> RETRO_ENVIRONMENT_GET_SYSTEM_DIRECTORY: /tmp/kikoo" << std::endl;
- char const ** path = (char const **)data;
- *path = "/tmp/kikoo";
- return true;
- }
- case RETRO_ENVIRONMENT_SET_PIXEL_FORMAT:
- std::cout << " `-> RETRO_ENVIRONMENT_SET_PIXEL_FORMAT: " << *((int*)data) << std::endl;
- return true;
- default:
- return false;
- };
- }
- void video_cb(const void *data, unsigned width, unsigned height, size_t pitch) {
- std::cout << "got a frame of " << width << 'x' << height << " (pitch: " << pitch << ')' << std::endl;
- if (pitch != 0) {
- SDL_LockSurface(sdl_stuff.current_frame);
- ::memcpy(sdl_stuff.current_frame->pixels, data, 4 * width * height);
- SDL_UnlockSurface(sdl_stuff.current_frame);
- //uint8_t const * const begin = (uint8_t const *)data;
- //uint8_t const * b = begin;
- //std::ofstream ofs("/tmp/lol.pic");
- //while (b - begin < 4 * width * height) {
- // ofs << *b;
- // ++b;
- //}
- //ofs.close();
- }
- }
- void audio_sample_cb(int16_t left, int16_t right) {
- }
- size_t audio_batch_cb(const int16_t *data, size_t frames) {
- return frames;
- }
- void input_poll_cb() {
- }
- int16_t input_state_cb(unsigned port, unsigned device, unsigned index, unsigned id) {
- return 0;
- }
- // Create a window an initialize sdl_stuff global variable
- bool init_sdl() {
- if (SDL_Init(SDL_INIT_VIDEO) != 0) {
- std::cerr << "SDL_Init Error: " << SDL_GetError() << std::endl;
- return false;
- }
- sdl_stuff.window = SDL_CreateWindow("Hello World!", 100, 100, 640, 480, SDL_WINDOW_SHOWN);
- if (sdl_stuff.window == nullptr) {
- std::cerr << "SDL_CreateWindow Error: " << SDL_GetError() << std::endl;
- SDL_Quit();
- return false;
- }
- sdl_stuff.renderer = SDL_CreateRenderer(sdl_stuff.window, -1, SDL_RENDERER_ACCELERATED | SDL_RENDERER_PRESENTVSYNC);
- if (sdl_stuff.renderer == nullptr) {
- SDL_DestroyWindow(sdl_stuff.window);
- std::cerr << "SDL_CreateRenderer Error: " << SDL_GetError() << std::endl;
- SDL_Quit();
- return false;
- }
- sdl_stuff.current_frame = SDL_CreateRGBSurface(0, 256, 240, 32, 0xff000000, 0x00ff0000, 0x0000ff00, 0x000000ff);
- if (sdl_stuff.current_frame == nullptr) {
- SDL_DestroyRenderer(sdl_stuff.renderer);
- SDL_DestroyWindow(sdl_stuff.window);
- std::cerr << "SDL_CreateRGBSurface Error: " << SDL_GetError() << std::endl;
- SDL_Quit();
- return false;
- }
- sdl_stuff.current_texture = nullptr;
- return true;
- }
- // Emulate a frame of the game and show it
- void process_one_frame() {
- // Get a frame from nestopia-core
- retro_run();
- // Convert it to a SDL texture
- if (sdl_stuff.current_texture != nullptr) {
- SDL_DestroyTexture(sdl_stuff.current_texture);
- }
- sdl_stuff.current_texture = SDL_CreateTextureFromSurface(sdl_stuff.renderer, sdl_stuff.current_frame);
- if (sdl_stuff.current_texture == nullptr) {
- std::cerr << "Failed to allocate texture" << std::endl;
- return;
- }
- // Render
- SDL_RenderClear(sdl_stuff.renderer);
- SDL_RenderCopy(sdl_stuff.renderer, sdl_stuff.current_texture, NULL, NULL);
- SDL_RenderPresent(sdl_stuff.renderer);
- }
- int main() {
- // Check API version of the core (should be tested against RETRO_API_VERSION in real life)
- std::cout << "API version: " << retro_api_version() << std::endl;
- // Initialize the core
- retro_set_environment(environment_cb);
- retro_set_video_refresh(video_cb);
- retro_set_audio_sample(audio_sample_cb);
- retro_set_audio_sample_batch(audio_batch_cb);
- retro_set_input_poll(input_poll_cb);
- retro_set_input_state(input_state_cb);
- retro_init();
- // Get some information about the core
- retro_system_info system_info;
- retro_get_system_info(&system_info);
- std::cout << "library name: '" << system_info.library_name << "'" << std::endl;
- std::cout << "library version: '" << system_info.library_version << "'" << std::endl;
- std::cout << "need fullpath: " << (system_info.need_fullpath ? "true" : "false") << std::endl;
- std::cout << "block extract: " << (system_info.block_extract ? "true" : "false") << std::endl;
- // Load a game
- char* game_data = (char*)::malloc(196624);
- std::ifstream ifs("/tmp/lol.nes");
- ifs.read(game_data, 196624);
- retro_game_info game_info {
- .path = "/tmp/lol.nes",
- .data = game_data,
- .size = (size_t)ifs.gcount(),
- .meta = nullptr
- };
- ifs.close();
- bool res = retro_load_game(&game_info);
- std::cout << "retro_load_game: " << (res ? "true" : "false") << std::endl;
- // Create an window
- if (! init_sdl()) {
- retro_deinit();
- return 1;
- }
- // Run for three frames
- for (int i = 0; i < 10 * 60; ++i) {
- process_one_frame();
- }
- // Good bye
- SDL_DestroyTexture(sdl_stuff.current_texture);
- SDL_FreeSurface(sdl_stuff.current_frame);
- SDL_DestroyRenderer(sdl_stuff.renderer);
- SDL_DestroyWindow(sdl_stuff.window);
- SDL_Quit();
- retro_deinit();
- return 0;
- }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement