• Run SDL2 application on RetroPie for Raspberry Pi

    3
    0 Votes
    3 Posts
    1k Views
    Z

    Thanks, the incorrect library was the main issue with this program! Another few things I noticed while experimenting with this code snippet:

    apparently Vertex Arrays don't work with GLESv2 (stackoverflow), so you have to use Vertex Buffers errors in vertex/fragment shader are only detected when linking the program, not on compilation when using opengl extensions (e.g. GL_OES_mapbuffer, see Raspberry Pi Video Core API for available extensions) you have to put#define GL_GLEXT_PROTOTYPES before including SDL2/SDL_opengles2.h and additionally link with -lbrcmEGL in order to get the functions if you don't call SDL_Quit() before exiting your program, the raspberry pi's console will be blocked (it seems like the input focus is still on the SDL window otherwise)

    I updated the code with a few more comments and fixed some stuff:
    main.c:

    #include <SDL2/SDL.h> #include <SDL2/SDL_opengles2.h> #define FULLSCREEN 1 #define TRIANGLE_SIZE 0.9f #define INFO_LOG_BUFFER_SIZE 1024 // Shader sources const GLchar* vertexSource = "attribute vec2 position;\n" "attribute vec4 color;\n" "varying vec4 out_color;\n" "uniform mat4 proj_mat;\n" "uniform mat4 model_mat;\n" "void main()\n" "{\n" " gl_Position = proj_mat*model_mat*vec4(position, 0, 1.0);\n" " out_color = color;\n" "}\n"; const GLchar* fragmentSource = "varying vec4 out_color;\n" "void main()\n" "{\n" " gl_FragColor = out_color;\n" "}\n"; // struct representing a colored 2D vertex typedef struct{ float x; float y; float r; float g; float b; float a; }Vertex; // adjusting viewport and projection matrix to fit current window dimensions void resize(int w, int h, GLint proj_mat_location); // create rotation matrix (z axis) and upload to shader at given uniform location void setRotationMatrix(float rad, GLint model_mat_location); // create orthogonal matrix and upload to shader at given uniform location void setOrthoMatrix(float left, float right, float bottom, float top, float n, float f, GLint proj_mat_location); int main() { // initialize SDL printf("Initializing SDL...\n"); if (SDL_Init(SDL_INIT_VIDEO) < 0) { printf("ERROR: Failed to initialize SDL: %s\n", SDL_GetError()); return 1; } // setting SDL flags unsigned int sdl_flags = SDL_WINDOW_OPENGL; SDL_DisplayMode current; current.w = 800; current.h = 600; if(FULLSCREEN){ sdl_flags |= SDL_WINDOW_FULLSCREEN; // getting current display-resolution if (SDL_GetDesktopDisplayMode(0, &current) != 0){ printf("Could not retrieve current display resolution: %s\n", SDL_GetError()); } }else{ sdl_flags |= SDL_WINDOW_RESIZABLE; } const char * fullscreen_string = FULLSCREEN ? "(fullscreen)" : ""; printf("Creating window %dx%d%s...\n", current.w, current.h, fullscreen_string); SDL_GL_SetAttribute(SDL_GL_RED_SIZE, 8); SDL_GL_SetAttribute(SDL_GL_GREEN_SIZE, 8); SDL_GL_SetAttribute(SDL_GL_BLUE_SIZE, 8); SDL_GL_SetAttribute(SDL_GL_DEPTH_SIZE, 16); // use GLESv2 SDL_GL_SetAttribute(SDL_GL_CONTEXT_MAJOR_VERSION, 2); SDL_GL_SetAttribute(SDL_GL_DOUBLEBUFFER, 1); // activate V-Sync SDL_GL_SetSwapInterval(1); SDL_Window * window = SDL_CreateWindow("Hello GLES!", SDL_WINDOWPOS_UNDEFINED, SDL_WINDOWPOS_UNDEFINED, current.w, current.h, sdl_flags); if(window == NULL) { printf("Error while creating window: %s\n", SDL_GetError()); SDL_Quit(); return 1; } // create gl context printf("Creating OpenGL context...\n"); SDL_GLContext context = SDL_GL_CreateContext(window); if(context == NULL) { printf("Error while creating OpenGL Context: %s\n", SDL_GetError()); SDL_DestroyWindow(window); SDL_Quit(); return 1; } // hide mouse cursor SDL_ShowCursor(0); // set gl parameters glClearColor(1.f, 1.f, 1.f, 1.f); glEnable(GL_BLEND); glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); glDisable(GL_DEPTH_TEST); glDisable(GL_CULL_FACE); // create RGB-triangle data and copy to vertex buffer GLuint vbo; glGenBuffers(1, &vbo); glBindBuffer(GL_ARRAY_BUFFER, vbo); Vertex vertices[3]; for(int i = 0; i < 3; i++){ vertices[i].x = cos(i*(2*M_PI/3.0f))*TRIANGLE_SIZE; vertices[i].y = sin(i*(2*M_PI/3.0f))*TRIANGLE_SIZE; vertices[i].r = 0.0f; vertices[i].g = 0.0f; vertices[i].b = 0.0f; vertices[i].a = 1.0f; } vertices[0].r = 1.0f; vertices[1].g = 1.0f; vertices[2].b = 1.0f; glBufferData(GL_ARRAY_BUFFER, sizeof(vertices), vertices, GL_STATIC_DRAW); printf("Compiling Shader...\n"); // compile the vertex shader GLuint vertexShader = glCreateShader(GL_VERTEX_SHADER); glShaderSource(vertexShader, 1, &vertexSource, NULL); glCompileShader(vertexShader); // compile the fragment shader GLuint fragmentShader = glCreateShader(GL_FRAGMENT_SHADER); glShaderSource(fragmentShader, 1, &fragmentSource, NULL); glCompileShader(fragmentShader); // link vertex and fragment shader into shader program GLuint shader_program = glCreateProgram(); glAttachShader(shader_program, vertexShader); glAttachShader(shader_program, fragmentShader); glLinkProgram(shader_program); // program info log char info_log_buffer[INFO_LOG_BUFFER_SIZE]; info_log_buffer[0] = '\0'; glGetProgramInfoLog(shader_program, INFO_LOG_BUFFER_SIZE, 0, info_log_buffer); if(info_log_buffer[0] != '\0') printf("Shader-Program-Info:\n%s\n", info_log_buffer); // linking successfull? int status; glGetProgramiv(shader_program, GL_LINK_STATUS, &status); if(status == GL_FALSE){ SDL_GL_DeleteContext(context); SDL_DestroyWindow(window); SDL_Quit(); return 1; } // use custom shader glUseProgram(shader_program); // feed vertex attributes with triangle-data // position GLint posAttrib = glGetAttribLocation(shader_program, "position"); glEnableVertexAttribArray(posAttrib); glVertexAttribPointer(posAttrib, 2, GL_FLOAT, GL_FALSE, sizeof(Vertex), 0); // color GLint colorAttrib = glGetAttribLocation(shader_program, "color"); glEnableVertexAttribArray(colorAttrib); glVertexAttribPointer(colorAttrib, 4, GL_FLOAT, GL_FALSE, sizeof(Vertex), (const GLvoid*)(2*sizeof(float))); // retrieve uniform locations GLint proj_mat_location = glGetUniformLocation(shader_program, "proj_mat"); GLint model_mat_location = glGetUniformLocation(shader_program, "model_mat"); // inital resize to set viewport and projection mastrix resize(current.w, current.h, proj_mat_location); // run main loop printf("Rendering triangle...\n"); while(1){ int quit = 0; SDL_Event e; while(SDL_PollEvent(&e)){ if(e.type == SDL_QUIT || e.type == SDL_KEYDOWN) quit = 1; else if(e.type == SDL_WINDOWEVENT && e.window.event == SDL_WINDOWEVENT_RESIZED) resize(e.window.data1, e.window.data2, proj_mat_location); } if(quit){ printf("Program was quit by user!\n"); break; } glClearColor(1,1,1,1); glClear(GL_COLOR_BUFFER_BIT); setRotationMatrix(SDL_GetTicks()/1000.f * M_PI/2.f, model_mat_location); glDrawArrays(GL_TRIANGLES, 0, 3); SDL_GL_SwapWindow(window); } // clean up SDL_GL_DeleteContext(context); SDL_DestroyWindow(window); SDL_Quit(); return 0; } void setRotationMatrix(float rad, GLint model_mat_location) { // rotation around z axis float sin_angle = sin(rad); float cos_angle = cos(rad); float mat[16]; mat[0] = cos_angle; mat[1] = sin_angle; mat[2] = 0; mat[3] = 0; mat[4] = -sin_angle; mat[5] = cos_angle; mat[6] = 0; mat[7] = 0; mat[8] = 0; mat[9] = 0; mat[10] = 1; mat[11] = 0; mat[12] = 0; mat[13] = 0; mat[14] = 0; mat[15] = 1; glUniformMatrix4fv(model_mat_location, 1, GL_FALSE, mat); } void resize(int w, int h, GLint proj_mat_location) { glViewport(0, 0, w, h); // set orthogonal view so that coordinates [-1, 1] area always visible and proportional on x and y axis if(w > h){ float f = w/(float)h; setOrthoMatrix(-f, f, -1, 1, -1, 1, proj_mat_location); }else{ float f = h/(float)w; setOrthoMatrix(-1, 1, -f, f, -1, 1, proj_mat_location); } } void setOrthoMatrix(float left, float right, float bottom, float top, float n, float f, GLint proj_mat_location) { // set orthogonal matrix float mat[16]; mat[0] = 2.0f/(right-left); mat[1] = 0.f; mat[2] = 0.f; mat[3] = 0.f; mat[4] = 0.f; mat[5] = 2.0f/(top-bottom); mat[6] = 0.f; mat[7] = 0.f; mat[8] = 0.f; mat[9] = 0.f; mat[10] =-2.f/(f-n); mat[11] = 0.f; mat[12] =-(right+left)/(right-left); mat[13] =-(top+bottom)/(top-bottom); mat[14] =-(f+n)/(f-n); mat[15] = 1.f; glUniformMatrix4fv(proj_mat_location, 1, GL_FALSE, mat); }

    Compiles and runs on Raspberry Pi 3:

    gcc main.c -o gles_test -lSDL2 -lSDL2main -L/opt/vc/lib -lbrcmGLESv2 -lm ./gles_test

    triangle.png

    I hope this might be usefull to someone :)

    @mitu Thanks again for your quick reply!

  • Suggestion: swapping X and Y

    1
    0 Votes
    1 Posts
    346 Views
    No one has replied
  • 0 Votes
    3 Posts
    12k Views
    thedishkingT

    Thank you for posting this!

  • 2 Votes
    1 Posts
    392 Views
    No one has replied
  • 0 Votes
    1 Posts
    316 Views
    No one has replied
  • Still no Retropie for Rpi4?

    Locked
    12
    -11 Votes
    12 Posts
    2k Views
    mituM

    @Bryan00569 Enough trolling.

  • Request adding these emulators

    4
    0 Votes
    4 Posts
    1k Views
    mituM

    @Darksavior Yes, it's annoying. I know about the FPS bug, I tested the patch and it's ok. There are a few more bugs besides the FPS counter that were fixed after 1.7.8.4, we'll see if the PR will bump to the next release or include the patches.

  • 1 Votes
    5 Posts
    987 Views
    E

    I've been considering compressing roms lately as I keep them uncompressed for all systems to prevent SD write cycles from extractions. These wouldn't extract or cache whatsoever, right? Also does RetroArch cache from my current .bin's and .cue's to "/tmp/Retroarch/"? I've been considering changing RetroArch's tmp to "/tmp/" (a RAM drive) but that would choke a pi3 if it tried to cache a PSX game, thus I'm trying to trim them without the need of extraction.

  • 0 Votes
    7 Posts
    2k Views
    mituM

    @bishop If you think so, then you shouldn't have posted the link. I removed the site link, since it's obviously still not free to redistribute.

  • 2 Votes
    10 Posts
    2k Views
    ClydeC

    @Darksavior One other potential problem with /tmp/retroarch came to my mind. If it doesn't exist on boot time because RA deleted it, the auto-mount via fstab will fail. After one successful mount however, it will be protected from deletion by the mount.

    Thus, the safe sequence would be:

    Create the directory via mkdir -p /tmp/retroarch Edit the fstab like described above. Reboot.

    Then, the directory will be there on boot time, the mount to ram will happen, and prevent deletion until shutdown. Rinse and repeat. :)

    This isn't necessary if the whole /tmp is mounted to ram, of course.

  • 0 Votes
    6 Posts
    1k Views
    N

    After an evening of pondering this, I have figured out what I did to screw it up. I have created multiple images of RetroPie setups that were reasonably customized and saved piles of things I referred to as "Clean" associated with those. (For example, known good ROMS, BIOS, and Meta Data like Scraper results.)

    What happened was that I missed a step trying to recreate my steps. So here's the abbreviated version of what I did that messed it up.

    Wrote the correct, unaltered, unupdated 4.5.1 image to the SD card (I really couldn't believe I would have written the wrong image). Copied vast amounts of "Clean" altered configs (for a setup that was designed for SNES controller compatibility, and thus didn't use PSX). Boomie. (At this point, I believe my copying of configs was all it took to scramble it up.)

    It should have been obvious when the pixel art launch screens came up (part of the config I just copied), but I honestly recall thinking "Oh cool, 4.5.1 uses the same pixel art things I liked for launching games."

    Thus, to your point, I had 4.5.1, with a bunch of 4.4 config wedged in manually after the fact. Worse, because my previously configured system never used PSX (not enough RasPi power when I created it, and not enough buttons when using SNES controllers), I had no idea that there might have been a bug with it that had been hiding in what I was copying.

    Thanks for the feedback.

  • solarus-1.6: request for comments and testing

    36
    1 Votes
    36 Posts
    5k Views
    cyperghostC

    @ExarKunIv try to use dos2unix scriptfile.sh
    I think you've wrong line endings.... Because for me the script runs flawless and if it spit out errors then there is likely something wrong with the interpretion of the script caused by wrong LE.

    Edit:
    Okay nevermind!

  • RPi4 Build Status / Devs

    9
    0 Votes
    9 Posts
    3k Views
    DarksaviorD

    @retropi19 git clone --branch fkms_rpi4 --depth=1 https://github.com/RetroPie/RetroPie-Setup.git

  • Add Coin Credit Requirement for non coin operated games

    2
    0 Votes
    2 Posts
    722 Views
    mituM

    No, this is not implemented - why would you need such a feature ?

  • 0 Votes
    2 Posts
    430 Views
    mituM

    @Sparkathor There's a joystick selection tool that can be used to configure which controller is Player 1 for different systems - https://github.com/meleu/RetroPie-joystick-selection.

  • 0 Votes
    27 Posts
    8k Views
    OneSwitchO

    @IanDaemon Thanks, Ian. This doesn't work on a CRT monitor (at least not with Pi2Scart). More here:

  • 0 Votes
    1 Posts
    454 Views
    No one has replied
  • Updated Solarus Engine

    11
    1 Votes
    11 Posts
    2k Views
    P

    @hhromic thank you, I will tell him. He is currently trying to make an "earthbound" theme resource pack for solarus, then wants to do 2 player co-op. Hopefully someone on Discord can help him out!

  • Plex Port

    8
    0 Votes
    8 Posts
    6k Views
    B

    RasPlex is a JeOS build around Plex, pretty much like LibreELEC is built around Kodi.

    Sorry, didn't make it clear but I was thinking like a Dual Boot:
    https://www.google.com/search?q=RasPlex+RetroPie

    If you don't want to Dual Boot, maybe the Kodi addon would be best:
    https://retropie.org.uk/forum/topic/9673/new-user-wanting-to-use-retropie-and-plex-media-server

    https://kodi.tv/plex-add-on-for-kodi

  • Mame plus Controls configs not setup like on mame 2003

    2
    0 Votes
    2 Posts
    491 Views
    G

    Well m assuming you are referring to street fighter games. Pick 6 button(snes layout) or modern for these games. 8 button is specifically for an certain arcade panel layout. Classic layout is for 99% of other games that are wrong with this setup.

Contributions to the project are always appreciated, so if you would like to support us with a donation you can do so here.

Hosting provided by Mythic-Beasts. See the Hosting Information page for more information.