Ejemplo n.º 1
0
bool retro_load_game(const struct retro_game_info *info)
{
   enum retro_pixel_format fmt = RETRO_PIXEL_FORMAT_XRGB8888;
   if (!environ_cb(RETRO_ENVIRONMENT_SET_PIXEL_FORMAT, &fmt))
      return false;

   struct retro_frame_time_callback frame_cb = { frame_time_cb, 1000000 / 60 };
   frame_cb.callback(frame_cb.reference);
   environ_cb(RETRO_ENVIRONMENT_SET_FRAME_TIME_CALLBACK, &frame_cb);

   load_game();

   (void)info;
   return true;
}
void GlRenderer::bind_libretro_framebuffer()
{
    uint32_t f_w = this->frontend_resolution[0];
    uint32_t f_h = this->frontend_resolution[1];
    uint16_t _w = this->config->display_resolution[0];
    uint16_t _h = this->config->display_resolution[1];

    uint32_t upscale = this->internal_upscaling;

    // XXX scale w and h when implementing increased internal
    // resolution
    uint32_t w = (uint32_t) _w * upscale;
    uint32_t h = (uint32_t) _h * upscale;

    if (w != f_w || h != f_h) {
        // We need to change the frontend's resolution
        struct retro_game_geometry geometry;
        geometry.base_width  = w;
        geometry.base_height = h;
        // Max parameters are ignored by this call
        geometry.max_width  = 0;
        geometry.max_height = 0;
        // Is this accurate?
        geometry.aspect_ratio = 4.0/3.0;


        printf("Target framebuffer size: %dx%d\n", w, h);

        environ_cb(RETRO_ENVIRONMENT_SET_GEOMETRY, &geometry);

        this->frontend_resolution[0] = w;
        this->frontend_resolution[1] = h;
    }

    // Bind the output framebuffer provided by the frontend
    /* TODO/FIXME - I think glsm_ctl(BIND) is the way to go here. Check with the libretro devs */
    GLuint fbo = glsm_get_current_framebuffer();
    glBindFramebuffer(GL_DRAW_FRAMEBUFFER, fbo);
    glViewport(0, 0, (GLsizei) w, (GLsizei) h);
}
bool GlRenderer::refresh_variables()
{
    struct retro_variable var = {0};

    var.key = "beetle_psx_internal_resolution";
    uint8_t upscaling = 1;
    if (environ_cb(RETRO_ENVIRONMENT_GET_VARIABLE, &var) && var.value) {
        /* Same limitations as libretro.cpp */
        upscaling = var.value[0] -'0';
    }

    var.key = "beetle_psx_filter";
    uint8_t filter = 0;
    if (environ_cb(RETRO_ENVIRONMENT_GET_VARIABLE, &var) && var.value) {
       if (!strcmp(var.value, "nearest"))
          filter = 0;
       else if (!strcmp(var.value, "3point N64"))
          filter = 1;
       else if (!strcmp(var.value, "bilinear"))
          filter = 2;

       this->filter_type = filter;
    }

    var.key = "beetle_psx_internal_color_depth";
    uint8_t depth = 16;
    if (environ_cb(RETRO_ENVIRONMENT_GET_VARIABLE, &var) && var.value) {
        depth = !strcmp(var.value, "32bpp") ? 32 : 16;
    }


    var.key = "beetle_psx_scale_dither";
    bool scale_dither = false;
    if (environ_cb(RETRO_ENVIRONMENT_GET_VARIABLE, &var) && var.value) {
       if (!strcmp(var.value, "enabled"))
          scale_dither = true;
       else
          scale_dither = false;
    }

    var.key = "beetle_psx_wireframe";
    bool wireframe = false;
    if (environ_cb(RETRO_ENVIRONMENT_GET_VARIABLE, &var) && var.value) {
       if (!strcmp(var.value, "enabled"))
          wireframe = true;
       else
          wireframe = false;
    }

    bool rebuild_fb_out =   upscaling != this->internal_upscaling ||
                            depth != this->internal_color_depth;

    if (rebuild_fb_out) {
        if (depth > 16) {
            this->command_buffer->disable_attribute("dither");
        } else {
            this->command_buffer->enable_attribute("dither");
        }

        uint32_t native_width = (uint32_t) VRAM_WIDTH_PIXELS;
        uint32_t native_height = (uint32_t) VRAM_HEIGHT;

        uint32_t w = native_width * upscaling;
        uint32_t h = native_height * upscaling;

        GLenum texture_storage = GL_RGB5_A1;
        switch (depth) {
        case 16:
            texture_storage = GL_RGB5_A1;
            break;
        case 32:
            texture_storage = GL_RGBA8;
            break;
        default:
            printf("Unsupported depth %d\n", depth);
            exit(EXIT_FAILURE);
        }

        Texture* fb_out = new Texture(w, h, texture_storage);

        if (this->fb_out) {
            delete this->fb_out;
            this->fb_out = NULL;
        }

        this->fb_out = fb_out;

        // This is a bit wasteful since it'll re-upload the data
        // to `fb_texture` even though we haven't touched it but
        // this code is not very performance-critical anyway.

        uint16_t top_left[2] = {0, 0};
        uint16_t dimensions[2] = {(uint16_t) VRAM_WIDTH_PIXELS, (uint16_t) VRAM_HEIGHT};
        this->upload_textures(top_left, dimensions, this->config->vram);


        if (this->fb_out_depth) {
            delete this->fb_out_depth;
            this->fb_out_depth = NULL;
        }

        this->fb_out_depth = new Texture(w, h, GL_DEPTH_COMPONENT32F);
    }

    uint32_t dither_scaling = scale_dither ? upscaling : 1;
    this->command_buffer->program->uniform1ui("dither_scaling", (GLuint) dither_scaling);
    this->command_buffer->program->uniform1ui("texture_flt", this->filter_type);

    this->command_polygon_mode = wireframe ? GL_LINE : GL_FILL;

    glLineWidth((GLfloat) upscaling);

    // If the scaling factor has changed the frontend should be
    // reconfigured. We can't do that here because it could
    // destroy the OpenGL context which would destroy `self`
    //// r5 - replace 'self' by 'this'
    bool reconfigure_frontend = this->internal_upscaling != upscaling;

    this->internal_upscaling = upscaling;
    this->internal_color_depth = depth;

    return reconfigure_frontend;
}
GlRenderer::GlRenderer(DrawConfig* config)
{

    struct retro_variable var = {0};

    var.key = "beetle_psx_internal_resolution";
    uint8_t upscaling = 1;
    if (environ_cb(RETRO_ENVIRONMENT_GET_VARIABLE, &var) && var.value) {
        /* Same limitations as libretro.cpp */
        upscaling = var.value[0] -'0';
    }

    var.key = "beetle_psx_filter";
    uint8_t filter = 0;
    if (environ_cb(RETRO_ENVIRONMENT_GET_VARIABLE, &var) && var.value) {
       if (!strcmp(var.value, "nearest"))
          filter = 0;
       else if (!strcmp(var.value, "3point N64"))
          filter = 1;
       else if (!strcmp(var.value, "bilinear"))
          filter = 2;

       this->filter_type = filter;
    }

    var.key = "beetle_psx_internal_color_depth";
    uint8_t depth = 16;
    if (environ_cb(RETRO_ENVIRONMENT_GET_VARIABLE, &var) && var.value) {
       if (!strcmp(var.value, "32bpp"))
          depth = 32;
       else
          depth = 16;
    }


    var.key = "beetle_psx_scale_dither";
    bool scale_dither = false;
    if (environ_cb(RETRO_ENVIRONMENT_GET_VARIABLE, &var) && var.value) {
       if (!strcmp(var.value, "enabled"))
          scale_dither = true;
       else
          scale_dither = false;
    }

    var.key = "beetle_psx_wireframe";
    bool wireframe = false;
    if (environ_cb(RETRO_ENVIRONMENT_GET_VARIABLE, &var) && var.value) {
       if (!strcmp(var.value, "enabled"))
          wireframe = true;
       else
          wireframe = false;
    }

    printf("Building OpenGL state (%dx internal res., %dbpp)\n", upscaling, depth);

    DrawBuffer<CommandVertex>* opaque_command_buffer =
        GlRenderer::build_buffer<CommandVertex>(
            command_vertex,
            command_fragment,
            VERTEX_BUFFER_LEN,
            true);

    DrawBuffer<OutputVertex>* output_buffer =
        GlRenderer::build_buffer<OutputVertex>(
            output_vertex,
            output_fragment,
            4,
            false);

    DrawBuffer<ImageLoadVertex>* image_load_buffer =
        GlRenderer::build_buffer<ImageLoadVertex>(
            image_load_vertex,
            image_load_fragment,
            4,
            false);

    uint32_t native_width  = (uint32_t) VRAM_WIDTH_PIXELS;
    uint32_t native_height = (uint32_t) VRAM_HEIGHT;

    // Texture holding the raw VRAM texture contents. We can't
    // meaningfully upscale it since most games use paletted
    // textures.
    Texture* fb_texture = new Texture(native_width, native_height, GL_RGB5_A1);

    if (depth > 16) {
        // Dithering is superfluous when we increase the internal
        // color depth
        opaque_command_buffer->disable_attribute("dither");
    }

    uint32_t dither_scaling = scale_dither ? upscaling : 1;
    GLenum command_draw_mode = wireframe ? GL_LINE : GL_FILL;

    opaque_command_buffer->program->uniform1ui("dither_scaling", dither_scaling);
    opaque_command_buffer->program->uniform1ui("texture_flt", this->filter_type);

    GLenum texture_storage = GL_RGB5_A1;
    switch (depth) {
    case 16:
        texture_storage = GL_RGB5_A1;
        break;
    case 32:
        texture_storage = GL_RGBA8;
        break;
    default:
        printf("Unsupported depth %d\n", depth);
        exit(EXIT_FAILURE);
    }

    Texture* fb_out = new Texture( native_width * upscaling,
                                   native_height * upscaling,
                                   texture_storage);

    Texture* fb_out_depth = new Texture( fb_out->width,
                                         fb_out->height,
                                         GL_DEPTH_COMPONENT32F);


    // let mut state = GlRenderer {
    this->filter_type    = filter;
    this->command_buffer = opaque_command_buffer;
    this->command_draw_mode = GL_TRIANGLES;
    this->semi_transparent_vertices.reserve((size_t) VERTEX_BUFFER_LEN);
    this->semi_transparency_mode =  SemiTransparencyMode_Average;
    this->command_polygon_mode = command_draw_mode;
    this->output_buffer = output_buffer;
    this->image_load_buffer = image_load_buffer;
    this->config = config;
    this->fb_texture = fb_texture;
    this->fb_out = fb_out;
    this->fb_out_depth = fb_out_depth;
    this->frontend_resolution[0] = 0;
    this->frontend_resolution[1] = 0;
    this->internal_upscaling = upscaling;
    this->internal_color_depth = depth;
    this->primitive_ordering = 0;
    this->tex_x_mask = 0;
    this->tex_x_or = 0;
    this->tex_y_mask = 0;
    this->tex_y_or = 0;
    // }

    this->display_off = true;

    //// NOTE: r5 - I have no idea what a borrow checker is.
    // Yet an other copy of this 1MB array to make the borrow
    // checker happy...
    uint16_t top_left[2] = {0, 0};
    uint16_t dimensions[2] = {(uint16_t) VRAM_WIDTH_PIXELS, (uint16_t) VRAM_HEIGHT};
    this->upload_textures(top_left, dimensions, this->config->vram);
}
Ejemplo n.º 5
0
void MAPPER_Init()
{

    struct retro_keyboard_callback callback = { keyboard_event };
    environ_cb(RETRO_ENVIRONMENT_SET_KEYBOARD_CALLBACK, &callback);

    inputList.clear();

    inputList.push_back(new MouseButton(RDID(MOUSE_LEFT), 0));
    inputList.push_back(new MouseButton(RDID(MOUSE_RIGHT), 1));

    struct retro_input_descriptor desc[64];
    joytype=JOY_AUTO;
    if(connected[0] && connected[1])
    {
        joytype = JOY_2AXIS;
        joystick_type[0] = JOY_2AXIS;
        joystick_type[1] = JOY_2AXIS;
    }
    else
    {
        if(connected[0])
        {
            joytype = joystick_type[0];
            joystick_type[1] = JOY_NONE;
        }
        else
           joystick_type[0] = JOY_NONE;

        if(connected[1])
        {
            joytype = joystick_type[1];
            joystick_type[0] = JOY_NONE;
        }
        else
           joystick_type[1] = JOY_NONE;

    }

    struct retro_input_descriptor desc_dpad[] = {
        { 0, RETRO_DEVICE_JOYPAD, 0, RETRO_DEVICE_ID_JOYPAD_LEFT, "D-Pad Left" },
        { 0, RETRO_DEVICE_JOYPAD, 0, RETRO_DEVICE_ID_JOYPAD_UP, "D-Pad Up" },
        { 0, RETRO_DEVICE_JOYPAD, 0, RETRO_DEVICE_ID_JOYPAD_DOWN, "D-Pad Down" },
        { 0, RETRO_DEVICE_JOYPAD, 0, RETRO_DEVICE_ID_JOYPAD_RIGHT, "D-Pad Right" },
        { 1, RETRO_DEVICE_JOYPAD, 0, RETRO_DEVICE_ID_JOYPAD_LEFT, "D-Pad Left" },
        { 1, RETRO_DEVICE_JOYPAD, 0, RETRO_DEVICE_ID_JOYPAD_UP, "D-Pad Up" },
        { 1, RETRO_DEVICE_JOYPAD, 0, RETRO_DEVICE_ID_JOYPAD_DOWN, "D-Pad Down" },
        { 1, RETRO_DEVICE_JOYPAD, 0, RETRO_DEVICE_ID_JOYPAD_RIGHT, "D-Pad Right" },
        { 255, 255, 255, 255, "" },
    };

    struct retro_input_descriptor desc_2axis[] = {
        { 0, RETRO_DEVICE_ANALOG, RETRO_DEVICE_INDEX_ANALOG_LEFT, RETRO_DEVICE_ID_ANALOG_X, "Analog X" },
        { 0, RETRO_DEVICE_ANALOG, RETRO_DEVICE_INDEX_ANALOG_LEFT, RETRO_DEVICE_ID_ANALOG_Y, "Analog Y" },
        { 1, RETRO_DEVICE_ANALOG, RETRO_DEVICE_INDEX_ANALOG_LEFT, RETRO_DEVICE_ID_ANALOG_X, "Analog X" },
        { 1, RETRO_DEVICE_ANALOG, RETRO_DEVICE_INDEX_ANALOG_LEFT, RETRO_DEVICE_ID_ANALOG_Y, "Analog Y" },
        { 255, 255, 255, 255, "" },

    };

    struct retro_input_descriptor desc_4axis[] = {
        { 0, RETRO_DEVICE_ANALOG, RETRO_DEVICE_INDEX_ANALOG_LEFT, RETRO_DEVICE_ID_ANALOG_X, "Left Analog X" },
        { 0, RETRO_DEVICE_ANALOG, RETRO_DEVICE_INDEX_ANALOG_LEFT, RETRO_DEVICE_ID_ANALOG_Y, "Left Analog Y" },
        { 0, RETRO_DEVICE_ANALOG, RETRO_DEVICE_INDEX_ANALOG_RIGHT, RETRO_DEVICE_ID_ANALOG_X, "Right Analog X" },
        { 0, RETRO_DEVICE_ANALOG, RETRO_DEVICE_INDEX_ANALOG_RIGHT, RETRO_DEVICE_ID_ANALOG_Y, "Right Analog Y" },
        { 1, RETRO_DEVICE_ANALOG, RETRO_DEVICE_INDEX_ANALOG_LEFT, RETRO_DEVICE_ID_ANALOG_X, "Left Analog X" },
        { 1, RETRO_DEVICE_ANALOG, RETRO_DEVICE_INDEX_ANALOG_LEFT, RETRO_DEVICE_ID_ANALOG_Y, "Left Analog Y" },
        { 1, RETRO_DEVICE_ANALOG, RETRO_DEVICE_INDEX_ANALOG_RIGHT, RETRO_DEVICE_ID_ANALOG_X, "Right Analog X" },
        { 1, RETRO_DEVICE_ANALOG, RETRO_DEVICE_INDEX_ANALOG_RIGHT, RETRO_DEVICE_ID_ANALOG_Y, "Right Analog Y" },
        { 255, 255, 255, 255, "" },

    };

    struct retro_input_descriptor desc_kbd[] = {
        { 0, RETRO_DEVICE_JOYPAD, 0, RETRO_DEVICE_ID_JOYPAD_LEFT, "Kbd Left" },
        { 0, RETRO_DEVICE_JOYPAD, 0, RETRO_DEVICE_ID_JOYPAD_UP, "Kbd Up" },
        { 0, RETRO_DEVICE_JOYPAD, 0, RETRO_DEVICE_ID_JOYPAD_DOWN, "Kbd Down" },
        { 0, RETRO_DEVICE_JOYPAD, 0, RETRO_DEVICE_ID_JOYPAD_RIGHT, "Kbd Right" },
        { 0, RETRO_DEVICE_JOYPAD, 0, RETRO_DEVICE_ID_JOYPAD_START, "Enter" },
        { 0, RETRO_DEVICE_JOYPAD, 0, RETRO_DEVICE_ID_JOYPAD_SELECT, "Esc" },
        { 255, 255, 255, 255, "" },
    };

    struct retro_input_descriptor desc_2button[] = {
        { 0, RETRO_DEVICE_JOYPAD, 0, RETRO_DEVICE_ID_JOYPAD_B, "Button 2" },
        { 0, RETRO_DEVICE_JOYPAD, 0, RETRO_DEVICE_ID_JOYPAD_Y, "Button 1" },
        { 0, RETRO_DEVICE_JOYPAD, 0, RETRO_DEVICE_ID_JOYPAD_START, "Enter" },
        { 0, RETRO_DEVICE_JOYPAD, 0, RETRO_DEVICE_ID_JOYPAD_SELECT, "Esc" },
        { 1, RETRO_DEVICE_JOYPAD, 0, RETRO_DEVICE_ID_JOYPAD_B, "Button 2" },
        { 1, RETRO_DEVICE_JOYPAD, 0, RETRO_DEVICE_ID_JOYPAD_Y, "Button 1" },
        { 1, RETRO_DEVICE_JOYPAD, 0, RETRO_DEVICE_ID_JOYPAD_START, "Enter" },
        { 1, RETRO_DEVICE_JOYPAD, 0, RETRO_DEVICE_ID_JOYPAD_SELECT, "Esc" },
        { 255, 255, 255, 255, "" },
    };

    struct retro_input_descriptor desc_4button[] = {
        { 0, RETRO_DEVICE_JOYPAD, 0, RETRO_DEVICE_ID_JOYPAD_Y, "Button 1" },
        { 0, RETRO_DEVICE_JOYPAD, 0, RETRO_DEVICE_ID_JOYPAD_X, "Button 2" },
        { 0, RETRO_DEVICE_JOYPAD, 0, RETRO_DEVICE_ID_JOYPAD_B, "Button 3" },
        { 0, RETRO_DEVICE_JOYPAD, 0, RETRO_DEVICE_ID_JOYPAD_A, "Button 4" },
        { 0, RETRO_DEVICE_JOYPAD, 0, RETRO_DEVICE_ID_JOYPAD_START, "Esc" },
        { 0, RETRO_DEVICE_JOYPAD, 0, RETRO_DEVICE_ID_JOYPAD_SELECT, "Enter" },
        { 1, RETRO_DEVICE_JOYPAD, 0, RETRO_DEVICE_ID_JOYPAD_Y, "Button 1" },
        { 1, RETRO_DEVICE_JOYPAD, 0, RETRO_DEVICE_ID_JOYPAD_X, "Button 2" },
        { 1, RETRO_DEVICE_JOYPAD, 0, RETRO_DEVICE_ID_JOYPAD_B, "Button 3" },
        { 1, RETRO_DEVICE_JOYPAD, 0, RETRO_DEVICE_ID_JOYPAD_A, "Button 4" },
        { 1, RETRO_DEVICE_JOYPAD, 0, RETRO_DEVICE_ID_JOYPAD_START, "Enter" },
        { 1, RETRO_DEVICE_JOYPAD, 0, RETRO_DEVICE_ID_JOYPAD_SELECT, "Esc" },
        { 255, 255, 255, 255, "" },
    };

    struct retro_input_descriptor empty = { 255, 255, 255, 255, "" };

    int i = 0;
    int j = 0;
    int k = 0;

    for(i=0;i<64;i++)
        desc[i] = empty;

    i=0;

    for(int port=0;port<2;port++)
    {
        log_cb(RETRO_LOG_INFO, "Configuring port: %d\n",port);
        switch(joystick_type[port])
        {
            case JOY_2AXIS:
                //buttons
                inputList.push_back(new JoystickButton(port, RDID(JOYPAD_Y), port, 0));
                inputList.push_back(new JoystickButton(port, RDID(JOYPAD_B), port, 1));
                inputList.push_back(new EmulatedKeyPress(0, RDID(JOYPAD_START),51));
                inputList.push_back(new EmulatedKeyPress(0, RDID(JOYPAD_SELECT),48));

                for(j=0;desc_2button[j].port!=port;j++);
                for(;desc_2button[j].port == port;j++)
                {
                    desc[i] = desc_2button[j];
                    i++;
                }

                //axes
                if(dpad[port])
                {
                    inputList.push_back(new JoystickHat(port, RDID(JOYPAD_LEFT), port, 0));
                    inputList.push_back(new JoystickHat(port, RDID(JOYPAD_RIGHT), port, 0));
                    inputList.push_back(new JoystickHat(port, RDID(JOYPAD_UP), port, 1));
                    inputList.push_back(new JoystickHat(port, RDID(JOYPAD_DOWN), port, 1));

                    for(j=0;desc_dpad[j].port!=port;j++);
                    for(;desc_dpad[j].port == port;j++)
                    {
                        desc[i] = desc_dpad[j];
                        i++;
                    }
                }
                else
                {
                    inputList.push_back(new JoystickAxis(port, RDIX(ANALOG_LEFT), RDID(ANALOG_X), port, 0));
                    inputList.push_back(new JoystickAxis(port, RDIX(ANALOG_LEFT), RDID(ANALOG_Y), port, 1));

                    for(j=0;desc_2axis[j].port!=port;j++);
                    for(;desc_2axis[j].port == port;j++)
                    {
                        desc[i] = desc_2axis[j];
                        i++;
                    }
                }

                if(emulated_kbd[port] && port == 0)
                {
                    inputList.push_back(new EmulatedKeyPress(0, RDID(JOYPAD_LEFT),80));
                    inputList.push_back(new EmulatedKeyPress(0, RDID(JOYPAD_RIGHT),83));
                    inputList.push_back(new EmulatedKeyPress(0, RDID(JOYPAD_UP),81));
                    inputList.push_back(new EmulatedKeyPress(0, RDID(JOYPAD_DOWN),82));
                    inputList.push_back(new EmulatedKeyPress(0, RDID(JOYPAD_START),51));
                    inputList.push_back(new EmulatedKeyPress(0, RDID(JOYPAD_SELECT),48));

                    for(j=0;desc_kbd[j].port!=port;j++);
                    for(;desc_kbd[j].port == port;j++)
                    {
                        desc[i] = desc_kbd[j];
                        i++;
                    }
                }

                JOYSTICK_Enable(port, true);
                break;
            case JOY_4AXIS:
                //buttons
                inputList.push_back(new JoystickButton(port, RDID(JOYPAD_Y), 0, 0));
                inputList.push_back(new JoystickButton(port, RDID(JOYPAD_X), 0, 1));
                inputList.push_back(new JoystickButton(port, RDID(JOYPAD_B), 1, 0));
                inputList.push_back(new JoystickButton(port, RDID(JOYPAD_A), 1, 1));
                inputList.push_back(new EmulatedKeyPress(0, RDID(JOYPAD_START),51));
                inputList.push_back(new EmulatedKeyPress(0, RDID(JOYPAD_SELECT),48));

                for(j=0;desc_4button[j].port!=port;j++);
                for(;desc_4button[j].port == port;j++)
                {
                    desc[i] = desc_4button[j];
                    i++;
                }

                //axes
                if(dpad[port])
                {
                    inputList.push_back(new JoystickHat(port, RDID(JOYPAD_LEFT), port, 0));
                    inputList.push_back(new JoystickHat(port, RDID(JOYPAD_RIGHT), port, 0));
                    inputList.push_back(new JoystickHat(port, RDID(JOYPAD_UP), port, 1));
                    inputList.push_back(new JoystickHat(port, RDID(JOYPAD_DOWN), port, 1));

                    for(j=0;desc_dpad[j].port!=port;j++);
                    for(;desc_dpad[j].port == port;j++)
                    {
                        desc[i] = desc_dpad[j];
                        i++;
                    }
                }
                else
                {
                    inputList.push_back(new JoystickAxis(port, RDIX(ANALOG_LEFT), RDID(ANALOG_X), 0, 0));
                    inputList.push_back(new JoystickAxis(port, RDIX(ANALOG_LEFT), RDID(ANALOG_Y), 0, 1));
                    inputList.push_back(new JoystickAxis(port, RDIX(ANALOG_RIGHT), RDID(ANALOG_X), 1, 0));
                    inputList.push_back(new JoystickAxis(port, RDIX(ANALOG_RIGHT), RDID(ANALOG_Y), 1, 1));
                    for(j=0;desc_2axis[j].port!=port;j++);
                    for(;desc_2axis[j].port == port;j++)
                    {
                        desc[i] = desc_2axis[j];
                        i++;
                    }
                }

                if(emulated_kbd[port] && port == 0)
                {
                    inputList.push_back(new EmulatedKeyPress(0, RDID(JOYPAD_LEFT),80));
                    inputList.push_back(new EmulatedKeyPress(0, RDID(JOYPAD_RIGHT),83));
                    inputList.push_back(new EmulatedKeyPress(0, RDID(JOYPAD_UP),81));
                    inputList.push_back(new EmulatedKeyPress(0, RDID(JOYPAD_DOWN),82));
                    inputList.push_back(new EmulatedKeyPress(0, RDID(JOYPAD_START),51));
                    inputList.push_back(new EmulatedKeyPress(0, RDID(JOYPAD_SELECT),48));

                    for(j=0;desc_kbd[j].port!=port;j++);
                    for(;desc_kbd[j].port == port;j++)
                    {
                        desc[i] = desc_kbd[j];
                        i++;
                    }
                }

                JOYSTICK_Enable(0, true);
                JOYSTICK_Enable(1, true);
                break;

        }

    }

    /*for(i=0;i<64;i++)
        log_cb(RETRO_LOG_DEBUG,"%d\n",desc[i].port);*/

    environ_cb(RETRO_ENVIRONMENT_SET_INPUT_DESCRIPTORS, desc);


}