#include "rc_os_defines.h"

#ifdef RC_ANDROID
#define RC_MOBILE
#endif

#ifdef RC_IOS
#define RC_MOBILE
#endif


#ifdef RC_ANDROID

#include <android/log.h>
//Using SDL and standard IO
#include "SDL.h"
#include "SDL_image.h"
#include "SDL2_gfxPrimitives.h"
#include "SDL_ttf.h"
#include <string>
#include <stdio.h>
#include <iostream>
#include "SDL_mixer.h"
#include "SDL_net.h"
//#include "../SDL/src/core/android/SDL_android.h"

//#include "../SDL/src/dynapi/SDL_dynapi_overrides.h"

//#include "../soft_render/SDL_rotate.c"

#include <assert.h>

#include "theoraplay.h"

#else

#ifdef RC_IOS

//Using SDL and standard IO
#include "SDL2/SDL.h"
#include "SDL2/SDL_image.h"
#include "SDL2/SDL2_gfxPrimitives.h"
#include "SDL2/SDL_ttf.h"
#include <string>
#include <stdio.h>
#include <iostream>
#include "SDL2/SDL_mixer.h"
#include "SDL2/SDL_net.h"

#include <assert.h>

#include "theoraplay.h"

#else
//Using SDL and standard IO
#include <SDL2/SDL.h>
#include <SDL2/SDL_image.h>
#include <SDL2/SDL2_gfxPrimitives.h>
#include <SDL2/SDL_ttf.h>
#include <string>
#include <sstream>
#include <stdio.h>
#include <iostream>
#include <SDL2/SDL_mixer.h>
#include <SDL2/SDL_net.h>
#include <string.h>
#include <unistd.h>
#include <assert.h>

#include <irrlicht.h>

#include "theoraplay.h"

#endif //RC_IOS

#endif // RC_ANDROID

//#include "soft_render/SDL_rotate.c"

#include <set>

using namespace std;

#ifdef RC_MOBILE
//Screen dimension constants
const int SCREEN_WIDTH = 640;
const int SCREEN_HEIGHT = 480;

const int MAX_WINDOWS = 1;  //8
const int MAX_SCREENS = 8; //32
const int MAX_IMAGES = 4096; //65536;
const int MAX_SPRITES = 32; //1024;
const int MAX_SOUNDS = 1024;
const int MAX_MUSIC = 1;
const int MAX_FONTS = 32;
const int MAX_FINGERS = 10;
const int MAX_SOCKETS = 256;
const int MAX_ACCELS = 20;
const int MAX_GYROS = 20;
const int MAX_JOYSTICKS = 8;
#else

//Screen dimension constants
const int SCREEN_WIDTH = 640;
const int SCREEN_HEIGHT = 480;

const int MAX_WINDOWS = 8;  //8
const int MAX_SCREENS = 8; //32
const int MAX_IMAGES = 4096; //65536;
const int MAX_SOUNDS = 1024;
const int MAX_MUSIC = 1;
const int MAX_FONTS = 32;
const int MAX_FINGERS = 10;
const int MAX_SOCKETS = 256;
const int MAX_ACCELS = 20;
const int MAX_GYROS = 20;
const int MAX_JOYSTICKS = 8;
#endif // RC_MOBILE

SDL_Window * rc_win[MAX_WINDOWS];
int rc_win_event[MAX_WINDOWS];
SDL_Texture * rc_backBuffer[MAX_WINDOWS];
SDL_Rect rc_bb_rect[MAX_WINDOWS];
SDL_Surface * rc_win_surface[MAX_WINDOWS];
SDL_Renderer * rc_win_renderer[MAX_WINDOWS];
Uint32 rc_win_id[MAX_WINDOWS];
bool rc_win_exitOnClose[MAX_WINDOWS];

Uint32 rc_screen_format[MAX_WINDOWS];

SDL_Texture * rc_himage[MAX_IMAGES][MAX_WINDOWS];
SDL_Rect rc_himage_rect[MAX_IMAGES];
bool rc_image_isLoaded[MAX_IMAGES];

SDL_Texture * rc_hscreen[MAX_WINDOWS][MAX_SCREENS];
SDL_Surface * rc_sscreen[MAX_WINDOWS][MAX_SCREENS];
SDL_Rect rc_screen_rect[MAX_WINDOWS][MAX_SCREENS];
int rc_screen_z[MAX_WINDOWS][MAX_SCREENS];
SDL_Rect rc_screenview[MAX_WINDOWS][MAX_SCREENS];
int rc_screen_width[MAX_WINDOWS][MAX_SCREENS];
int rc_screen_height[MAX_WINDOWS][MAX_SCREENS];
Uint8 rc_screen_transparent[MAX_WINDOWS][MAX_SCREENS];
int rc_screen_zOrder[MAX_WINDOWS][MAX_SCREENS];
bool rc_screen_visible[MAX_WINDOWS][MAX_SCREENS];

SDL_Surface * rc_simage[MAX_IMAGES];
SDL_Rect rc_image_rect[MAX_IMAGES];
Uint32 rc_image_width[MAX_IMAGES];
Uint32 rc_image_height[MAX_IMAGES];
Uint32 rc_image_colorKey[MAX_IMAGES];
Uint8 rc_image_colorKey_r[MAX_IMAGES];
Uint8 rc_image_colorKey_g[MAX_IMAGES];
Uint8 rc_image_colorKey_b[MAX_IMAGES];
Uint8 rc_image_colorKey_a[MAX_IMAGES];

int rc_active_window = -1;
int rc_active_screen = -1;

Uint32 rc_ink = 0x00000000;
SDL_Color rc_ink_color;
Uint32 rc_paper = 0x00000000;
Uint32 rc_clearColor = 0x00000000;
Uint32 rc_colorKey = 0x00000000;
SDL_Color rc_colorKey_color;
int rc_colorKey_switch = 0;

int rc_console_width[MAX_WINDOWS]; //number of characters wide
int rc_console_height[MAX_WINDOWS]; //number of rows
int rc_sConsole_x[MAX_WINDOWS];
int rc_sConsole_y[MAX_WINDOWS];
Uint8 rc_cursor_visible = 1;
SDL_Color rc_console_pen;
int rc_pen_color = 0x00FFFFFF;
SDL_Surface * rc_console = NULL;
SDL_Texture * rc_hconsole[MAX_WINDOWS];
TTF_Font * rc_console_font = NULL;
string rc_input_buffer = "";

TTF_Font * rc_draw_font[MAX_FONTS];
string rc_draw_font_path = "";
int rc_active_font = -1;

int rc_inkey = 0;
SDL_Keycode rc_keycode;
SDL_Scancode rc_scancode;
SDL_Keymod rc_keymod;
int rc_mouseX = 0;
int rc_mouseY = 0;
int rc_mbutton1 = 0;
int rc_mbutton2 = 0;
int rc_mbutton3 = 0;
int rc_mwheelx = 0;
int rc_mwheely = 0;

int rc_global_mouseX = 0;
int rc_global_mouseY = 0;

//SDL_Event event;

Uint32 prev_color = 0;

bool rc_engine_isRunning = false;
bool rc_engine_isInitialized = false;
bool rc_media_isActive = false;

const Uint8 * keyState = NULL;

SDL_Joystick * rc_joystick[MAX_JOYSTICKS];
int rc_joy_axis[MAX_JOYSTICKS][100];
int rc_numJoysticks = 0;
int rc_joybutton[MAX_JOYSTICKS][100];
SDL_JoystickID rc_joyID[MAX_JOYSTICKS];

SDL_Joystick * tmp_joy;
SDL_JoystickID tmp_joy_id;
int tmp_joy_flag = 0;

SDL_Haptic * rc_haptic[MAX_JOYSTICKS]; //1 for each joystick

double rc_pressure = 0;
int rc_touchX = 0;
int rc_touchY = 0;
int rc_motionX = 0;
int rc_motionY = 0;
int rc_touch = 0;
int rc_mt_status = 0;
int rc_mt_x = 0;
int rc_mt_y = 0;
int rc_mt_numFingers = 0;
double rc_mt_theta = 0;
double rc_mt_dist = 0;
SDL_TouchID rc_touchDevice;
SDL_Finger rc_finger[MAX_FINGERS];
set<int> rc_fingers_pressed;

SDL_Sensor * rc_accel[MAX_ACCELS];
int num_accels = 0;

SDL_Sensor * rc_gyro[MAX_GYROS];
int num_gyros = 0;

int rc_win_width[MAX_WINDOWS];
int rc_win_height[MAX_WINDOWS];

Uint32 rc_update_timer = 0;
Uint32 rc_auto_time = 0;
int rc_update_flag = 0;

Mix_Chunk * rc_sound[MAX_SOUNDS];
Mix_Music * rc_music;

TCPsocket rc_socket[MAX_SOCKETS];

UDPsocket rc_udp_socket[MAX_SOCKETS];
UDPpacket * rc_udp_packet;
int rc_udp_channel;
string rc_udp_data;
int rc_udp_len;
int rc_udp_maxlen;
string rc_udp_host;
Uint16 rc_udp_port;
int rc_packet_size = 0;
SDLNet_SocketSet rc_socket_set;


SDL_PixelFormat * rc_pformat;
SDL_DisplayMode rc_displayMode[MAX_WINDOWS];

string rc_textinput_string = "";
//string * rc_textinput_oldString;
string rc_textinput_char = "";
int rc_textinput_timer = 0;
int rc_textinput_delay = 100;
bool rc_textinput_flag = true;
bool rc_textinput_isActive = false;
int rc_textinput_waitHold = 800;
bool rc_textinput_hold = false;
bool rc_toggleBackspace = true;


static Uint32 baseticks = 0;

uint32_t rc_fps[MAX_WINDOWS];
uint32_t rc_fps_frames[MAX_WINDOWS];
uint32_t rc_fps_timer[MAX_WINDOWS];

#ifdef RC_MOBILE
double rc_mouse_scale_x = 0;
double rc_mouse_scale_y = 0;
#else
double rc_fullscreen_mouse_scale_x[MAX_WINDOWS];
double rc_fullscreen_mouse_scale_y[MAX_WINDOWS];
#endif // RC_MOBILE

typedef struct AudioQueue
{
    const THEORAPLAY_AudioPacket *audio;
    int offset;
    struct AudioQueue *next;
} AudioQueue;

static volatile AudioQueue *audio_queue = NULL;
static volatile AudioQueue *audio_queue_tail = NULL;

THEORAPLAY_Decoder *decoder = NULL;
const THEORAPLAY_VideoFrame *video = NULL;
const THEORAPLAY_AudioPacket *audio = NULL;
SDL_Texture * overlay = NULL;
void * overlay_pixels;
int pitch;
SDL_Event event;
Uint32 framems = 0;
int initfailed = 0;
int quit = 0;
bool rc_video_isPlaying = false;
Uint32 rc_video_position = 0;
bool rc_video_reset = false;
int rc_video_loops = 0;
const THEORAPLAY_AudioPacket * first_audio = NULL;
const THEORAPLAY_VideoFrame * first_video = NULL;
bool rc_audio_isOpen = false;
bool rc_video_isLoaded = false;
string rc_video_file = "";
bool rc_video_isPaused = false;
Uint32 rc_video_pauseTicks = 0;
bool rc_video_end = false;
SDL_Rect rc_video_dstrect;
int rc_video_width = 0;
int rc_video_height = 0;
int rc_video_length = 0;
int rc_video_fps = 0;
int rc_video_currentLoop = 0;

bool mobile_active_window_flag = true;

void rc_setTouchFingerEvent(SDL_FingerID fingerID, double x, double y, double pressure)
{
    for(int i = 0; i < MAX_FINGERS; i++)
    {
        if(rc_finger[i].id == -1 || rc_finger[i].id == fingerID)
        {
            rc_finger[i].id = fingerID;
            rc_finger[i].x = x;
            rc_finger[i].y = y;
            rc_finger[i].pressure = pressure;
            if(rc_finger[i].pressure > 0)
            {
                rc_fingers_pressed.insert(i);
            }
            return;
        }
    }
}

int mobile_event_filter(void* userdata, SDL_Event* evt)
{
    SDL_Event event = evt[0];
    switch(evt->type)
    {
        case SDL_APP_WILLENTERBACKGROUND:
            mobile_active_window_flag = false;
            break;
        case SDL_APP_DIDENTERFOREGROUND:
            if(!mobile_active_window_flag)
            {
                //rc_win_renderer[0] = SDL_GetRenderer(rc_win[0]);
            }
            mobile_active_window_flag = true;
            break;

        case SDL_FINGERDOWN:
            rc_touch = 1;
            rc_touchX = event.tfinger.x * rc_win_width[rc_active_window];
            rc_touchY = event.tfinger.y * rc_win_height[rc_active_window];
#ifdef RC_IOS
            rc_pressure = 1; //FIXME: On IOS pressure is always getting reported as 0 on finger down so I am just setting it to 1 until I figure this out
#else
            rc_pressure = event.tfinger.pressure;
#endif
            rc_setTouchFingerEvent(event.tfinger.fingerId, rc_touchX, rc_touchY, rc_pressure);
            break;
        case SDL_FINGERUP:
            rc_touch = 0;
            rc_mt_status = 0;
            rc_touchX = event.tfinger.x * rc_win_width[rc_active_window];
            rc_touchY = event.tfinger.y * rc_win_height[rc_active_window];
            rc_pressure = event.tfinger.pressure;
            rc_setTouchFingerEvent(event.tfinger.fingerId, -1, -1, 0);
            break;
        case SDL_FINGERMOTION:
            rc_touch = 1;
            rc_touchX = event.tfinger.x * rc_win_width[rc_active_window];
            rc_touchY = event.tfinger.y * rc_win_height[rc_active_window];
            rc_motionX = event.tfinger.dx * rc_win_width[rc_active_window];
            rc_motionY = event.tfinger.dy * rc_win_height[rc_active_window];
#ifdef RC_IOS
            rc_pressure = 1;
#else
            rc_pressure = event.tfinger.pressure;
#endif
            rc_setTouchFingerEvent(event.tfinger.fingerId, rc_touchX, rc_touchY, rc_pressure);
            break;
        case SDL_MULTIGESTURE:
            rc_touch = 2;
            rc_mt_status = 1;
            rc_mt_x = event.mgesture.x;
            rc_mt_y = event.mgesture.y;
            rc_mt_numFingers = event.mgesture.numFingers;
            rc_mt_dist = event.mgesture.dDist;
            rc_mt_theta = event.mgesture.dTheta;
#ifdef RC_IOS
            rc_pressure = 1;
#else
            rc_pressure = event.tfinger.pressure;
#endif
            break;

    }
    return 0;
}

bool rc_media_init()
{
    rc_socket_set = SDLNet_AllocSocketSet(MAX_SOCKETS*2); //*2 for udp and tcp

    if(rc_socket_set == NULL)
    {
        cout << "Init Error: " << SDL_GetError() << endl;
    }

    for(int i = 0; i < MAX_SOCKETS; i++)
    {
        rc_socket[i] = NULL;
        rc_udp_socket[i] = NULL;
    }

    for(int i = 0; i < MAX_FONTS; i++)
        rc_draw_font[i] = NULL;

    for(int i = 0; i < MAX_SOUNDS; i++)
        rc_sound[i] = NULL;

    rc_music = NULL;

    for(int i = 0; i < MAX_WINDOWS; i++)
    {
        rc_win[i] = NULL;
        rc_win_surface[i] = NULL;
        rc_win_renderer[i] = NULL;
        rc_win_id[i] = 0;
        rc_hconsole[i] = NULL;
        rc_backBuffer[i] = NULL;
        rc_bb_rect[i].x = 0;
        rc_bb_rect[i].y = 0;
        rc_bb_rect[i].w = 0;
        rc_bb_rect[i].h = 0;

        rc_fps[i] = 0;
        rc_fps_frames[i] = 0;
        rc_fps_timer[i] = 0;

        for(int j = 0; j < MAX_SCREENS; j++)
        {
            rc_hscreen[i][j] = NULL;
            rc_sscreen[i][j] = NULL;
            rc_screen_rect[i][j].x = 0;
            rc_screen_rect[i][j].y = 0;
            rc_screen_rect[i][j].w = 0;
            rc_screen_rect[i][j].h = 0;
            rc_screen_z[i][j] = j;
            rc_screen_zOrder[i][j] = j;
            rc_screen_visible[i][j] = false;
        }
    }
    for(int i = 0; i < MAX_IMAGES; i++)
    {
        for(int w = 0; w < MAX_WINDOWS; w++)
            rc_himage[i][w] = NULL;

        rc_simage[i] = NULL;
        rc_image_rect[i].x = 0;
        rc_image_rect[i].y = 0;
        rc_image_rect[i].w = 0;
        rc_image_rect[i].h = 0;
        rc_image_isLoaded[i] = false;
    }
    rc_ink_color.r = 0;
    rc_ink_color.g = 0;
    rc_ink_color.b = 0;
    rc_ink_color.a = 0;
    #ifdef RC_WEB
    if(SDL_Init(SDL_INIT_AUDIO | SDL_INIT_EVENTS | SDL_INIT_TIMER | SDL_INIT_VIDEO | SDL_INIT_JOYSTICK) < 0)
    #else
    if(SDL_Init(SDL_INIT_AUDIO | SDL_INIT_EVENTS | SDL_INIT_TIMER | SDL_INIT_VIDEO | SDL_INIT_JOYSTICK | SDL_INIT_HAPTIC | SDL_INIT_SENSOR) < 0)
    #endif
    {
        cout << "Init Error: " << SDL_GetError() << endl;
        //return false;
    }

    #ifdef RC_MOBILE
        SDL_SetEventFilter(mobile_event_filter, NULL);
    #endif // RC_MOBILE

    if(IMG_Init(IMG_INIT_JPG | IMG_INIT_PNG | IMG_INIT_TIF) < 0)
    {
        cout << "IMG Init Error: " << IMG_GetError() << endl;
        //return false;
    }

    if(TTF_Init() < 0)
    {
        cout << "TTF Init Error: " << TTF_GetError() << endl;
        //return false;
    }

    if(Mix_OpenAudio(MIX_DEFAULT_FREQUENCY, MIX_DEFAULT_FORMAT, 2, 2048) < 0)
    {
        cout << "OpenAudio Error: " << Mix_GetError() << endl;
    }

    if (SDLNet_Init() < 0)
	{
		fprintf(stderr, "SDLNet_Init: %s\n", SDLNet_GetError());
		exit(EXIT_FAILURE);
	}

    for(int i = 0; i < MAX_FINGERS; i++)
    {
        rc_finger[i].id = -1;
        rc_finger[i].x = -1;
        rc_finger[i].y = -1;
        rc_finger[i].pressure = 0;
    }

    for(int i = 0; i < SDL_NumSensors(); i++)
    {
        rc_accel[num_accels] =  NULL;
        rc_gyro[num_gyros] =    NULL;
        switch(SDL_SensorGetDeviceType(i))
        {
            case SDL_SENSOR_ACCEL:
                rc_accel[num_accels] = SDL_SensorOpen(i);
                num_accels++;
                break;
            case SDL_SENSOR_GYRO:
                rc_gyro[num_gyros] = SDL_SensorOpen(i);
                num_gyros++;
                break;
        }
    }

	rc_pformat = SDL_AllocFormat(SDL_PIXELFORMAT_ARGB8888);

	//rc_active_font = -1;

	rc_udp_packet = SDLNet_AllocPacket(512);
	rc_packet_size = 512;

    rc_console_pen.r = 255;
    rc_console_pen.g = 255;
    rc_console_pen.b = 255;
    rc_console_pen.a = 0;
    rc_media_isActive = true;

    for(int i = 0; i < MAX_JOYSTICKS; i++)
    {
        if(i < SDL_NumJoysticks())
        {
            rc_joystick[i] = SDL_JoystickOpen(i);
            if(rc_joystick[i]==NULL)
            {
                cout << "Joystick " << i << " could not be opened: " << SDL_GetError() << endl;
            }
            rc_joyID[i] = SDL_JoystickInstanceID(rc_joystick[i]);
            #ifdef RC_WEB
            rc_haptic[i] = NULL;
            #else
            rc_haptic[i] = SDL_HapticOpenFromJoystick(rc_joystick[i]);
            SDL_HapticRumbleInit(rc_haptic[i]);
            #endif
            //if(rc_haptic[i] == NULL){ cout << "HAP NULL: " << SDL_GetError() << endl; }
            rc_numJoysticks++;
        }
        else
        {
            rc_joystick[i] = NULL;
            rc_haptic[i] =  NULL;
            rc_joyID[i] = -1;
        }
    }
    SDL_SetHint("SDL_JOYSTICK_ALLOW_BACKGROUND_EVENTS", "1");

    return true;
}

void rc_media_quit()
{
    for(int i = 0; i < MAX_FONTS; i++)
    {
        if(rc_draw_font[i] != NULL)
            TTF_CloseFont(rc_draw_font[i]);
    }

    //cout << "Font closed" << endl;

    for(int i = 0; i < MAX_SOUNDS; i++)
    {
        if(rc_sound[i] != NULL)
            Mix_FreeChunk(rc_sound[i]);
        rc_sound[i] = NULL;
    }
    if(rc_music != NULL)
        Mix_FreeMusic(rc_music);
    rc_music = NULL;

    for(int i = 0; i < MAX_JOYSTICKS; i++)
    {
        SDL_JoystickClose(rc_joystick[i]);
        SDL_HapticClose(rc_haptic[i]);
    }

    //cout << "Music Closed" << endl;

    for(int i = 0; i < MAX_WINDOWS; i++)
    {

        //cout << "Destroy Canvases" << endl;

        for(int j = 0; j < MAX_SCREENS; j++)
        {
            if(rc_sscreen[i][j] != NULL)
            {
                //cout << "Free Surface rc_sscreen[" << i << "][" << j << "]  -----  ";
                SDL_FreeSurface(rc_sscreen[i][j]);
                //cout << "SUCCESS\n";
                //SDL_DestroyTexture(rc_hscreen[i][j]);
            }
            if(rc_hscreen[i][j] != NULL)
            {
                SDL_DestroyTexture(rc_hscreen[i][j]);
            }
        }

        //cout << "Destroy Images" << endl;

        for(int j = 0; j < MAX_IMAGES; j++)
        {
            if(rc_himage[j][i] != NULL)
                SDL_DestroyTexture(rc_himage[j][i]);
            rc_himage[j][i] = NULL;
        }

        //cout << "Destroy Window #" << i << endl;

        if(rc_win[i] != NULL)
        {
            SDL_DestroyRenderer(rc_win_renderer[i]);
            rc_win_renderer[i] = NULL;
            SDL_DestroyWindow(rc_win[i]);
            rc_win[i] = NULL;
        }
    }

    //cout << "NORMAL BOOTS" << endl;

    if(audio)
    {
        THEORAPLAY_freeAudio(audio);
        audio = NULL;
    }
    if(video)
    {
        THEORAPLAY_freeVideo(video);
        video = NULL;
    }
    if(decoder)
    {
        THEORAPLAY_stopDecode(decoder);
        decoder = NULL;
    }
    IMG_Quit();
    TTF_Quit();
    Mix_Quit();
    if(rc_socket_set)
    {
        SDLNet_FreeSocketSet(rc_socket_set);
        rc_socket_set = NULL;
    }
    //SDLNet_FreePacket(rc_udp_packet);
	SDLNet_Quit();
    SDL_Quit();
}

int rc_debug_msg(string msg)
{
    const SDL_MessageBoxButtonData buttons[] = {
        { /* .flags, .buttonid, .text */        0, 0, "no" },
        { SDL_MESSAGEBOX_BUTTON_RETURNKEY_DEFAULT, 1, "yes" },
        { SDL_MESSAGEBOX_BUTTON_ESCAPEKEY_DEFAULT, 2, "cancel" },
    };
    const SDL_MessageBoxColorScheme colorScheme = {
        { /* .colors (.r, .g, .b) */
            /* [SDL_MESSAGEBOX_COLOR_BACKGROUND] */
            { 255,   0,   0 },
            /* [SDL_MESSAGEBOX_COLOR_TEXT] */
            {   0, 255,   0 },
            /* [SDL_MESSAGEBOX_COLOR_BUTTON_BORDER] */
            { 255, 255,   0 },
            /* [SDL_MESSAGEBOX_COLOR_BUTTON_BACKGROUND] */
            {   0,   0, 255 },
            /* [SDL_MESSAGEBOX_COLOR_BUTTON_SELECTED] */
            { 255,   0, 255 }
        }
    };
    const SDL_MessageBoxData messageboxdata = {
        SDL_MESSAGEBOX_INFORMATION, /* .flags */
        NULL, /* .window */
        msg.c_str(), /* .title */
        "select a button", /* .message */
        SDL_arraysize(buttons), /* .numbuttons */
        buttons, /* .buttons */
        &colorScheme /* .colorScheme */
    };
    int buttonid;
    if (SDL_ShowMessageBox(&messageboxdata, &buttonid) < 0) {
        SDL_Log("error displaying message box");
        return 1;
    }
    if (buttonid == -1) {
        SDL_Log("no selection");
    } else {
        SDL_Log("selection was %s", buttons[buttonid].text);
    }
    return 0;
}

inline Uint32 rc_media_windowMode(int visible_flag, int fullscreen_flag, int resizable_flag, int borderless_flag, int highDPI_flag)
{
    Uint32 window_mode = ( visible_flag == 0 ? SDL_WINDOW_HIDDEN : SDL_WINDOW_SHOWN ) |
                         ( fullscreen_flag == 0 ? 0 : SDL_WINDOW_FULLSCREEN_DESKTOP ) |
                         ( resizable_flag == 0 ? 0 : SDL_WINDOW_RESIZABLE ) |
                         ( borderless_flag == 0 ? 0 : SDL_WINDOW_BORDERLESS ) |
                         ( highDPI_flag == 0 ? 0 : SDL_WINDOW_ALLOW_HIGHDPI );
    return window_mode;
}

inline Uint32 rc_media_windowFlags(int win_num)
{
    if(win_num < 0 || win_num >= MAX_WINDOWS)
    {
        cout << "Window #" << win_num << " is not an available Window Slot" << endl;
        return 0;
    }
    if(rc_win[win_num] == NULL)
    {
        cout << "Window #" << win_num << " is not currently open" << endl;
        return 0;
    }
    return SDL_GetWindowFlags(rc_win[win_num]);
}

inline bool rc_media_openWindow_hw(int win_num, string caption, int x, int y, int w, int h, Uint32 flags, int vsync_flag)
{
    //cout << "start windowOpen" << endl;
    if(win_num < 0 || win_num >= MAX_WINDOWS)
    {
        cout << "Window #" << win_num << " is not an available Window Slot" << endl;
        return false;
    }
    if(rc_win[win_num] != NULL)
    {
        cout << "Window #" << win_num << " is currently open" << endl;
        return false;
    }

    bool vsync = vsync_flag == 0 ? false : true;
    rc_win_exitOnClose[win_num] = true;

    #ifdef RC_MOBILE
		flags = flags | SDL_WINDOW_FULLSCREEN_DESKTOP;
	#endif // RC_MOBILE

    rc_win[win_num] = SDL_CreateWindow(caption.c_str(), x, y, w, h, flags);
    if(rc_win[win_num] == NULL)
    {
        cout << "Error: " << SDL_GetError() << endl;
        return false;
    }

    if(rc_active_window == -1)
        rc_active_window = win_num;

    //rc_win_surface[win_num] = SDL_GetWindowSurface(rc_win[win_num]);
    rc_win_id[win_num] = SDL_GetWindowID(rc_win[win_num]);

    rc_win_width[win_num] = w;
    rc_win_height[win_num] = h;
    //SDL_SetSurfaceRLE(rc_win_surface[win_num],1);
    //rc_console = SDL_CreateRGBSurface(0, w, h, 32, 0, 0, 0, 0);
    //SDL_SetColorKey(rc_console, SDL_TRUE, rc_clearColor);
    //cout << "boob physics" << endl;

#ifdef RC_MOBILE
    rc_win_renderer[win_num] = SDL_GetRenderer(rc_win[win_num]);
    if(rc_win_renderer[win_num] != NULL)
    {
        SDL_DestroyRenderer(rc_win_renderer[win_num]);
    }
#endif // RC_MOBILE

    if(vsync)
        rc_win_renderer[win_num] = SDL_CreateRenderer(rc_win[win_num], -1, SDL_RENDERER_ACCELERATED | SDL_RENDERER_TARGETTEXTURE | SDL_RENDERER_PRESENTVSYNC);
    else
        rc_win_renderer[win_num] = SDL_CreateRenderer(rc_win[win_num], -1, SDL_RENDERER_ACCELERATED | SDL_RENDERER_TARGETTEXTURE);


    if(rc_win_renderer[win_num] == NULL)
    {
#ifdef RC_ANDROID
        //rc_debug_msg("No Renderer");
        __android_log_write(ANDROID_LOG_ERROR, "This is crazy: ", SDL_GetError());
        rc_win_renderer[win_num] = SDL_GetRenderer(rc_win[win_num]);
        if(rc_win_renderer[win_num] == NULL)
        {
            __android_log_write(ANDROID_LOG_ERROR, "Renderer Error: ", SDL_GetError());
            exit(0);
        }
        SDL_DestroyRenderer(rc_win_renderer[win_num]);
        rc_win_renderer[win_num] = NULL;
        if(vsync)
            rc_win_renderer[win_num] = SDL_CreateRenderer(rc_win[win_num], -1, SDL_RENDERER_ACCELERATED | SDL_RENDERER_PRESENTVSYNC | SDL_RENDERER_TARGETTEXTURE);
        else
            rc_win_renderer[win_num] = SDL_CreateRenderer(rc_win[win_num], -1, SDL_RENDERER_ACCELERATED | SDL_RENDERER_TARGETTEXTURE);

        if(rc_win_renderer[win_num] == NULL)
        {
            __android_log_write(ANDROID_LOG_ERROR, "Renderer Error2: ", SDL_GetError());
            exit(0);
        }
#else
        cout << "WindowOpen Error: " << SDL_GetError() << endl;
        exit(0);
#endif
    }

    SDL_SetRenderDrawBlendMode(rc_win_renderer[win_num], SDL_BLENDMODE_BLEND);

    //cout << "booty" << endl;

#ifndef RC_MOBILE

    for(int i = 0; i < MAX_IMAGES; i++)
    {
        if(rc_image_isLoaded[i])
        {
            for(int w = 0; w < MAX_WINDOWS; w++)
            {
                if(rc_win[w] != NULL && rc_himage[i][w]==NULL)
                {
                    SDL_Surface * tmp_surf = SDL_CreateRGBSurface(0, rc_image_width[i], rc_image_height[i], 32, 0, 0, 0, 0);
                    //cout << "ColorKey = " << (Uint32)rc_image_colorKey_r[i] << ", ";
                    //cout << (Uint32)rc_image_colorKey_g[i] << ", ";
                    //cout << (Uint32)rc_image_colorKey_b[i] << ", ";
                    //cout << (Uint32)rc_image_colorKey_a[i] << endl;
                    SDL_FillRect(tmp_surf, NULL, rc_image_colorKey[i]);
                    SDL_SetRenderTarget(rc_win_renderer[w], NULL);
                    SDL_Rect t_rect;
                    t_rect.x = 0;
                    t_rect.y = 0;
                    t_rect.w = tmp_surf->w;
                    t_rect.h = tmp_surf->h;
                    Uint8 r, g, b, a;
                    SDL_GetRenderDrawColor(rc_win_renderer[w], &r, &g, &b, &a);
                    SDL_SetRenderDrawColor(rc_win_renderer[w], rc_image_colorKey_r[i], rc_image_colorKey_g[i], rc_image_colorKey_b[i], 255);
                    SDL_RenderFillRect(rc_win_renderer[w], NULL);
                    SDL_SetRenderDrawColor(rc_win_renderer[w], r, g, b, a);
                    SDL_RenderCopy(rc_win_renderer[w], rc_himage[i][w], NULL, &t_rect);
                    SDL_RenderReadPixels(rc_win_renderer[w],&t_rect,tmp_surf->format->format,tmp_surf->pixels,tmp_surf->pitch);
                    SDL_SetColorKey(tmp_surf, SDL_TRUE, rc_image_colorKey[i]);
                    rc_himage[i][w] = SDL_CreateTextureFromSurface(rc_win_renderer[w], tmp_surf);
                    SDL_FreeSurface(tmp_surf);
                    break;
                }
            }
        }
    }

#endif // RC_MOBILE

    //SDL_SetHint(SDL_HINT_RENDER_SCALE_QUALITY, "linear");
    //SDL_RenderSetLogicalSize(rc_win_renderer[win_num], w, h);

    //cout << "boobs" << endl;

    rc_backBuffer[win_num] = SDL_CreateTexture(rc_win_renderer[win_num], rc_pformat->format, SDL_TEXTUREACCESS_TARGET, w, h);
    //cout << "dbg 1" << endl;

#ifdef RC_MOBILE

    if(SDL_GetDesktopDisplayMode(0, &rc_displayMode[win_num])<0)
    {
        cout << "Something happend: " << SDL_GetError() << endl;
    }

#else

    if(SDL_GetWindowDisplayMode(rc_win[win_num], &rc_displayMode[win_num])<0)
    {
        cout << "Something happend: " << SDL_GetError() << endl;
    }

#endif // RC_ANDROID
    //cout << "dbg 2" << endl;
    rc_bb_rect[win_num].x = 0;
    rc_bb_rect[win_num].y = 0;
    //cout << "dbg 3" << endl;
    rc_bb_rect[win_num].w = rc_displayMode[win_num].w;
    //cout << "dbg 4" << endl;
    rc_bb_rect[win_num].h = rc_displayMode[win_num].h;

    //cout << "cunt" << endl;

#ifdef RC_MOBILE
    rc_mouse_scale_x = (double)((double)w / (double)rc_displayMode[win_num].w);
    rc_mouse_scale_y = (double)((double)h / (double)rc_displayMode[win_num].h);
#else
    if((flags&SDL_WINDOW_FULLSCREEN_DESKTOP)!=0)
    {
        //cout << "fullscreen" << endl;
        //cout << "W = " << w << endl;
        //cout << "D.W = " << rc_displayMode[win_num].w << endl;
        rc_fullscreen_mouse_scale_x[win_num] = (double)((double)w / (double)rc_displayMode[win_num].w);
        //cout << "fs = " << rc_fullscreen_mouse_scale_x[win_num] << endl;
        rc_fullscreen_mouse_scale_y[win_num] = (double)((double)h / (double)rc_displayMode[win_num].h);
        //cout << "display mode = " << rc_fullscreen_mouse_scale_x[win_num] << ", " << rc_fullscreen_mouse_scale_y[win_num] << endl;
    }
    else
    {
        rc_fullscreen_mouse_scale_x[win_num] = 1;
        rc_fullscreen_mouse_scale_y[win_num] = 1;
    }
#endif // RC_ANDROID

    //#ifndef RC_ANDROID
    rc_hconsole[win_num] = SDL_CreateTexture(rc_win_renderer[win_num],rc_pformat->format,SDL_TEXTUREACCESS_TARGET,w,h);
    SDL_SetTextureBlendMode(rc_hconsole[win_num], SDL_BLENDMODE_BLEND);
    SDL_SetRenderTarget(rc_win_renderer[win_num], rc_hconsole[win_num]);
    SDL_SetRenderDrawColor(rc_win_renderer[win_num], 0, 0, 0, 0);
    SDL_RenderClear(rc_win_renderer[win_num]);
    SDL_SetRenderTarget(rc_win_renderer[win_num], NULL);
    //#endif // RC_ANDROID

    //cout << "wtf" << endl;

    rc_console_width[win_num] = w/8;
    rc_console_height[win_num] = h/8;
    rc_sConsole_x[win_num] = 0;
    rc_sConsole_y[win_num] = 0;

    //cout << "cdi" << endl;

#ifdef RC_MOBILE
    SDL_SetRenderTarget(rc_win_renderer[rc_active_window], rc_backBuffer[rc_active_window]);
    SDL_SetRenderDrawColor(rc_win_renderer[rc_active_window], 0, 0, 0, 255);
    SDL_RenderClear(rc_win_renderer[rc_active_window]);
    SDL_SetRenderTarget(rc_win_renderer[rc_active_window], NULL);
    SDL_RenderClear(rc_win_renderer[rc_active_window]);
    rc_win_width[win_num] = w;
    rc_win_height[win_num] = h;
#else
    SDL_SetRenderDrawColor(rc_win_renderer[win_num], 0, 0, 0, 255);
    SDL_RenderClear(rc_win_renderer[win_num]);
#endif // RC_ANDROID

    SDL_RenderPresent(rc_win_renderer[win_num]);

    //cout << "open complete" << endl;

    //rc_debug_msg("Window Creation Successful");

    return true;
}

inline void rc_media_closeWindow_hw(int win_num)
{
    if(win_num < 0 && win_num >= MAX_WINDOWS)
    {
        cout << "Window Index is out of Range" << endl;
        return;
    }
    SDL_DestroyTexture(rc_hconsole[win_num]);
    SDL_DestroyTexture(rc_backBuffer[win_num]);
    SDL_DestroyRenderer(rc_win_renderer[win_num]);
    if(rc_win[win_num]!=NULL)
        SDL_DestroyWindow(rc_win[win_num]);
    rc_win_renderer[win_num] = NULL;
    rc_win[win_num] = NULL;
}

inline int rc_media_setRenderScaleQuality(int n)
{
    stringstream s;
    s << n;

    if(SDL_SetHint(SDL_HINT_RENDER_SCALE_QUALITY, s.str().c_str()))
       return 1;
    return 0;
}

inline int rc_media_getRenderScaleQuality()
{
    string hint = SDL_GetHint(SDL_HINT_RENDER_SCALE_QUALITY) == NULL ? "" : SDL_GetHint(SDL_HINT_RENDER_SCALE_QUALITY);
    int hint_val = 0;
    if(hint.compare("")!=0)
    {
        #ifdef RC_WINDOWS
        hint_val = atoi(hint.c_str());
        #else
            #ifdef RC_ANDROID
            hint_val = atoi(hint.c_str());
            #else
            hint_val = stoi(hint);
            #endif
        #endif
    }
    return hint_val;
}

inline void rc_media_getDesktopDisplayMode(int index, double * w, double * h, double * freq)
{
    SDL_DisplayMode dm;
    SDL_GetDesktopDisplayMode(index, &dm);
    *w = (double)dm.w;
    *h = (double)dm.h;
    *freq = (double)dm.refresh_rate;
}

inline void rc_media_setActiveWindow(int win_num)
{
    if(win_num < 0 || win_num >= MAX_WINDOWS)
    {
        cout << "Window Index Out of Range" << endl;
        return;
    }
    rc_active_window = win_num;
}

void rc_media_raiseWindow(int win_num)
{
    if(win_num < 0 || win_num >= MAX_WINDOWS)
    {
        cout << "Window Index Out of Range" << endl;
        return;
    }
    if(rc_win[win_num]==NULL)
    {
        //cout << "Window does not Exist" << endl;
        return;
    }
    rc_active_window = win_num;
    SDL_RaiseWindow(rc_win[win_num]);
}

void rc_media_showWindow(int win_num)
{
    if(win_num < 0 || win_num >= MAX_WINDOWS)
    {
        cout << "Window Index Out of Range" << endl;
        return;
    }
    if(rc_win[win_num]==NULL)
    {
        //cout << "Window does not Exist" << endl;
        return;
    }
    SDL_ShowWindow(rc_win[win_num]);
}

void rc_media_hideWindow(int win_num)
{
    if(win_num < 0 || win_num >= MAX_WINDOWS)
    {
        cout << "Window Index Out of Range" << endl;
        return;
    }
    if(rc_win[win_num]==NULL)
    {
        //cout << "Window does not Exist" << endl;
        return;
    }
    SDL_HideWindow(rc_win[win_num]);
}

bool rc_winCheck(int win_num)
{
    if(win_num < 0 || win_num >= MAX_WINDOWS)
    {
        cout << "Window Index Out of Range" << endl;
        return false;
    }
    if(rc_win[win_num]==NULL)
    {
        //cout << "Window does not Exist" << endl;
        return false;
    }
    return true;
}

void rc_media_setWindowTitle(int win_num, string title)
{
    if(rc_winCheck(win_num))
    {
        SDL_SetWindowTitle(rc_win[win_num], title.c_str());
    }
    else
    {
        cout << "SetWindowTitle Error: Window #" << win_num << " is not an active window" << endl;
    }
}

string rc_media_getWindowTitle(int win_num)
{
    if(rc_winCheck(win_num))
    {
        return SDL_GetWindowTitle(rc_win[win_num]);
    }
    else
    {
        cout << "WindowTitle Error: Window #" << win_num << " is not an active window" << endl;
        return "";
    }
}

void rc_media_setWindowPosition(int win_num, int x, int y)
{
    if(rc_winCheck(win_num))
        SDL_SetWindowPosition(rc_win[win_num], x, y);
    else
        cout << "SetWindowPosition Error: Window #" << win_num << " is not an active window" << endl;
}

void rc_media_getWindowPosition(int win_num, double * x, double * y)
{
    int x_data=0, y_data=0;
    if(rc_winCheck(win_num))
        SDL_GetWindowPosition(rc_win[win_num],&x_data,&y_data);
    else
        cout << "GetWindowPosition Error: Window #" << win_num << " is not an active window" << endl;
    *x = x_data;
    *y = y_data;
}


void rc_onResize(int win_num)
{
    SDL_Texture * current_tgt = SDL_GetRenderTarget(rc_win_renderer[win_num]);
    int w = 0;
    int h = 0;
    SDL_DestroyTexture(rc_backBuffer[win_num]);
    rc_backBuffer[win_num] = NULL;
    Uint32 win_flags = SDL_GetWindowFlags(rc_win[win_num]);
    if( (win_flags & SDL_WINDOW_RESIZABLE) && !(win_flags & SDL_WINDOW_FULLSCREEN_DESKTOP) )
        SDL_GetWindowSize(rc_win[win_num], &w, &h);
    else
    {
        w = rc_win_width[win_num];
        h = rc_win_height[win_num];
    }
    rc_win_width[win_num] = w;
    rc_win_height[win_num] = h;
    //cout << "debug1: " << w << ", " << h << endl;
    rc_backBuffer[win_num] = SDL_CreateTexture(rc_win_renderer[win_num], rc_pformat->format, SDL_TEXTUREACCESS_TARGET, w, h);

#ifdef RC_MOBILE

    if(SDL_GetDesktopDisplayMode(0, &rc_displayMode[win_num])<0)
    {
        cout << "Something happend: " << SDL_GetError() << endl;
    }

#else

    if(SDL_GetWindowDisplayMode(rc_win[win_num], &rc_displayMode[win_num])<0)
    {
        cout << "Something happend: " << SDL_GetError() << endl;
    }

#endif // RC_ANDROID

    rc_bb_rect[win_num].x = 0;
    rc_bb_rect[win_num].y = 0;
    rc_bb_rect[win_num].w = rc_displayMode[win_num].w;
    rc_bb_rect[win_num].h = rc_displayMode[win_num].h;

    //cout << "bb_rect = " << rc_bb_rect[win_num].w << ", " << rc_bb_rect[win_num].h << endl;

    Uint32 flags = SDL_GetWindowFlags(rc_win[win_num]);

#ifdef RC_MOBILE
    rc_mouse_scale_x = (double)((double)w / (double)rc_displayMode[win_num].w);
    rc_mouse_scale_y = (double)((double)h / (double)rc_displayMode[win_num].h);
#else
    if((flags & SDL_WINDOW_FULLSCREEN_DESKTOP)!=0)
    {
        rc_fullscreen_mouse_scale_x[win_num] = (double)((double)rc_win_width[win_num] / (double)rc_displayMode[win_num].w);
        rc_fullscreen_mouse_scale_y[win_num] = (double)((double)rc_win_height[win_num] / (double)rc_displayMode[win_num].h);
        //cout << "resize_fullscreen: " << w << " / " << rc_displayMode[win_num].w << endl;
    }
    else
    {
        //cout << "resize window mode" << endl;
        rc_fullscreen_mouse_scale_x[win_num] = 1;
        rc_fullscreen_mouse_scale_y[win_num] = 1;
    }
#endif // RC_ANDROID

    SDL_DestroyTexture(rc_hconsole[win_num]);
    rc_hconsole[win_num] = SDL_CreateTexture(rc_win_renderer[win_num],rc_pformat->format,SDL_TEXTUREACCESS_TARGET,w,h);
    SDL_SetTextureBlendMode(rc_hconsole[win_num], SDL_BLENDMODE_BLEND);
    SDL_SetRenderTarget(rc_win_renderer[win_num], rc_hconsole[win_num]);
    SDL_SetRenderDrawColor(rc_win_renderer[win_num], 0, 0, 0, 0);
    SDL_RenderClear(rc_win_renderer[win_num]);
    SDL_SetRenderTarget(rc_win_renderer[win_num], current_tgt);

    rc_console_width[win_num] = w/8;
    rc_console_height[win_num] = h/8;
    rc_sConsole_x[win_num] = 0;
    rc_sConsole_y[win_num] = 0;

}


void rc_media_setWindowSize(int win_num, int w, int h)
{
    if(rc_winCheck(win_num))
    {
        SDL_SetWindowSize(rc_win[win_num], w, h);

        rc_win_width[win_num] = w;
        rc_win_height[win_num] = h;

        rc_onResize(win_num);
    }
    else
        cout << "SetWindowSize Error: Window #" << win_num << " is not an active window" << endl;
}

void rc_media_getWindowSize(int win_num, double * w, double * h)
{
    int w_data = -1, h_data = -1;
    if(rc_winCheck(win_num))
        SDL_GetWindowSize(rc_win[win_num], &w_data, &h_data);
    else
        cout << "GetWindowSize Error: Window#" << win_num << " is not an active window" << endl;
    *w = w_data;
    *h = h_data;
}

void rc_media_setWindowMinSize(int win_num, int w, int h)
{
    if(rc_winCheck(win_num))
        SDL_SetWindowMinimumSize(rc_win[win_num], w, h);
    else
        cout << "SetWindowMinSize Error: Window#" << win_num << " is not an active window" << endl;
}

void rc_media_getWindowMinSize(int win_num, double * w, double * h)
{
    int w_data=0, h_data=0;
    if(rc_winCheck(win_num))
        SDL_GetWindowMinimumSize(rc_win[win_num], &w_data, &h_data);
    else
        cout << "GetWindowMinSize Error: Window #" << win_num << " is not an active window" << endl;
    *w = w_data;
    *h = h_data;
}

void rc_media_setWindowMaxSize(int win_num, int w, int h)
{
    if(rc_winCheck(win_num))
        SDL_SetWindowMaximumSize(rc_win[win_num], w, h);
    else
        cout << "SetWindowMaxSize Error: Window #" << win_num << " is not an active window" << endl;
}

void rc_media_getWindowMaxSize(int win_num, double * w, double * h)
{
    int w_data=0, h_data=0;
    if(rc_winCheck(win_num))
        SDL_GetWindowMaximumSize(rc_win[win_num], &w_data, &h_data);
    else
        cout << "GetWindowMaxSize Error: Window #" << win_num << " is not an active window" << endl;
    *w = w_data;
    *h = h_data;
}

bool rc_media_windowIsFullscreen(int win_num)
{
    if(rc_winCheck(win_num))
    {
        Uint32 wflags = SDL_GetWindowFlags(rc_win[win_num]);
        Uint32 wflags_cmp1 = wflags & SDL_WINDOW_FULLSCREEN;
        Uint32 wflags_cmp2 = wflags & SDL_WINDOW_FULLSCREEN_DESKTOP;
        if(wflags_cmp1 || wflags_cmp2)
        {
            //cout << "wflags = " << (int)wflags << endl;
            //cout << "SDL_WIN_FSCREEN = " << (int)SDL_WINDOW_FULLSCREEN << endl;
            //cout << "SDL_WIN_FSCREEN_D = " << (int)SDL_WINDOW_FULLSCREEN_DESKTOP << endl;
            return true;
        }
        else
        {
            //cout << "wflags = " << (int)wflags << endl;
            //cout << "SDL_WIN_FSCREEN = " << (int)SDL_WINDOW_FULLSCREEN << endl;
            //cout << "SDL_WIN_FSCREEN_D = " << (int)SDL_WINDOW_FULLSCREEN_DESKTOP << endl;
            return false;
        }
    }
    else
    {
        cout << "WindowIsFullscreen Error: Window #" << win_num << " is not an active window" << endl;
        return false;
    }
}

bool rc_media_windowIsVisible(int win_num)
{
    if(rc_winCheck(win_num))
    {
        Uint32 wflags = SDL_GetWindowFlags(rc_win[win_num]);
        if(wflags & SDL_WINDOW_SHOWN)
            return true;
        else
            return false;
    }
    else
    {
        cout << "WindowIsVisible Error: Window #" << win_num << " is not an active window" << endl;
        return false;
    }
}

bool rc_media_windowHasMouseFocus(int win_num)
{
    if(rc_winCheck(win_num))
    {
        Uint32 wflags = SDL_GetWindowFlags(rc_win[win_num]);
        if(wflags & SDL_WINDOW_MOUSE_FOCUS)
            return true;
        else
            return false;
    }
    else
    {
        cout << "WindowHasMouseFocus Error: Window #" << win_num << " is not an active window" << endl;
        return false;
    }
}

bool rc_media_windowHasInputFocus(int win_num)
{
    if(rc_winCheck(win_num))
    {
        Uint32 wflags = SDL_GetWindowFlags(rc_win[win_num]);
        if(wflags & SDL_WINDOW_INPUT_FOCUS)
            return true;
        else
            return false;
    }
    else
    {
        cout << "WindowHasInputFocus Error: Window #" << win_num << " is not an active window" << endl;
        return false;
    }
}

bool rc_media_windowIsBordered(int win_num)
{
    if(rc_winCheck(win_num))
    {
        Uint32 wflags = SDL_GetWindowFlags(rc_win[win_num]);
        if(wflags & SDL_WINDOW_BORDERLESS)
            return false;
        else
            return true;
    }
    else
    {
        cout << "WindowIsBordered Error: Window #" << win_num << " is not an active window" << endl;
        return false;
    }
}

bool rc_media_windowIsResizable(int win_num)
{
    if(rc_winCheck(win_num))
    {
        Uint32 wflags = SDL_GetWindowFlags(rc_win[win_num]);
        if(wflags & SDL_WINDOW_RESIZABLE)
            return true;
        else
            return false;
    }
    else
    {
        cout << "WindowIsResizable Error: Window #" << win_num << " is not an active window" << endl;
        return false;
    }
}

bool rc_media_windowIsMinimized(int win_num)
{
    if(rc_winCheck(win_num))
    {
        Uint32 wflags = SDL_GetWindowFlags(rc_win[win_num]);
        if(wflags & SDL_WINDOW_MINIMIZED)
            return true;
        else
            return false;
    }
    else
    {
        cout << "WindowIsMinimized Error: Window #" << win_num << " is not an active window" << endl;
        return false;
    }
}

bool rc_media_windowIsMaximized(int win_num)
{
    if(rc_winCheck(win_num))
    {
        Uint32 wflags = SDL_GetWindowFlags(rc_win[win_num]);
        if(wflags & SDL_WINDOW_MAXIMIZED)
            return true;
        else
            return false;
    }
    else
    {
        cout << "WindowIsMaximized Error: Window #" << win_num << " is not an active window" << endl;
        return false;
    }
}

void rc_media_setWindowFullscreen(int win_num, int flag)
{
    if(rc_winCheck(win_num))
    {
        switch(flag)
        {
            case 0:
                flag = 0;
                break;
            default:
                flag = SDL_WINDOW_FULLSCREEN_DESKTOP;
                break;
        }

        Uint32 wflags_preOp = SDL_GetWindowFlags(rc_win[win_num]);
        if( flag != 0 && ( (wflags_preOp & SDL_WINDOW_FULLSCREEN_DESKTOP) || (wflags_preOp & SDL_WINDOW_FULLSCREEN) ) )
            return;
        else if( flag == 0 && !((wflags_preOp & SDL_WINDOW_FULLSCREEN_DESKTOP) || (wflags_preOp & SDL_WINDOW_FULLSCREEN)))
            return;

        if(SDL_SetWindowFullscreen(rc_win[win_num], flag) < 0)
        {
            cout << "SetWindowFullscreen Error: " << SDL_GetError() << endl;
            return;
        }

        rc_win_renderer[win_num] = SDL_GetRenderer(rc_win[win_num]);
        //cout << "debug = " << (rc_win_renderer[win_num] == NULL) << endl;

        Uint32 wflags = SDL_GetWindowFlags(rc_win[win_num]);
        Uint32 wflags_cmp1 = wflags & SDL_WINDOW_FULLSCREEN;
        Uint32 wflags_cmp2 = wflags & SDL_WINDOW_FULLSCREEN_DESKTOP;
        if(!(wflags_cmp1 || wflags_cmp2))
        {
            #ifndef RC_MOBILE
            rc_fullscreen_mouse_scale_x[win_num] = 1;
            rc_fullscreen_mouse_scale_y[win_num] = 1;
            #endif // RC_MOBILE
        }
        else if(SDL_GetWindowDisplayMode(rc_win[win_num], &rc_displayMode[win_num])<0)
        {
            cout << "Something happend: " << SDL_GetError() << endl;
            #ifndef RC_MOBILE
            rc_fullscreen_mouse_scale_x[win_num] = 1;
            rc_fullscreen_mouse_scale_y[win_num] = 1;
            #endif // RC_MOBILE
        }
        else
        {
            #ifndef RC_MOBILE
            rc_fullscreen_mouse_scale_x[win_num] = (double)((double)rc_win_width[win_num] / (double)rc_displayMode[win_num].w);
            rc_fullscreen_mouse_scale_y[win_num] = (double)((double)rc_win_height[win_num] / (double)rc_displayMode[win_num].h);
            #endif // RC_MOBILE
        }

        SDL_PumpEvents();
        SDL_FlushEvents(SDL_FIRSTEVENT, SDL_LASTEVENT);
        // SDL_GetWindowDisplayMode(rc_win[win_num],&rc_displayMode[win_num]);
        //rc_bb_rect[win_num].w = rc_displayMode[win_num].w;
        //rc_bb_rect[win_num].h = rc_displayMode[win_num].h;
        //rc_win_surface[win_num] = SDL_GetWindowSurface(rc_win[win_num]);
    }
    else
        cout << "SetWindowFullscreen Error: Window #" << win_num << " is not an active window" << endl;
}

void rc_media_maximizeWindow(int win_num)
{
    if(rc_winCheck(win_num))
    {
        SDL_MaximizeWindow(rc_win[win_num]);
        if( (SDL_GetWindowFlags(rc_win[win_num]) & SDL_WINDOW_RESIZABLE) )
            return;
        SDL_GetWindowDisplayMode(rc_win[win_num],&rc_displayMode[win_num]);
        rc_bb_rect[win_num].w = rc_displayMode[win_num].w;
        rc_bb_rect[win_num].h = rc_displayMode[win_num].h;
        rc_win_surface[win_num] = SDL_GetWindowSurface(rc_win[win_num]);
        #ifndef RC_MOBILE
        rc_fullscreen_mouse_scale_x[win_num] = (double)((double)rc_win_width[win_num] / (double)rc_displayMode[win_num].w);
        rc_fullscreen_mouse_scale_y[win_num] = (double)((double)rc_win_height[win_num] / (double)rc_displayMode[win_num].h);
        #endif // RC_MOBILE
    }
    else
        cout << "MaximizeWindow Error: Window #" << win_num << " is not an active window" << endl;
}

void rc_media_minimizeWindow(int win_num)
{
    if(rc_winCheck(win_num))
    {
        SDL_MinimizeWindow(rc_win[win_num]);
        SDL_GetWindowDisplayMode(rc_win[win_num],&rc_displayMode[win_num]);
        rc_bb_rect[win_num].w = rc_displayMode[win_num].w;
        rc_bb_rect[win_num].h = rc_displayMode[win_num].h;
        rc_win_surface[win_num] = SDL_GetWindowSurface(rc_win[win_num]);
        #ifndef RC_MOBILE
        rc_fullscreen_mouse_scale_x[win_num] = (double)((double)rc_win_width[win_num] / (double)rc_displayMode[win_num].w);
        rc_fullscreen_mouse_scale_y[win_num] = (double)((double)rc_win_height[win_num] / (double)rc_displayMode[win_num].h);
        #endif // RC_MOBILE
    }
    else
        cout << "MinimizeWindow Error: Window #" << win_num << " is not an active window" << endl;
}

void rc_media_setWindowBordered(int win_num, bool b)
{
    SDL_bool bswitch = SDL_FALSE;
    if(b)
        bswitch = SDL_TRUE;
    if(rc_winCheck(win_num))
        SDL_SetWindowBordered(rc_win[win_num], bswitch);
    else
        cout << "SetWindowBorder Error: Window #" << win_num << " is not an active window" << endl;
}

void rc_media_setWindowResizable(int win_num, bool b)
{
    SDL_bool bswitch = SDL_FALSE;
    if(b)
        bswitch = SDL_TRUE;
    if(rc_winCheck(win_num))
        SDL_SetWindowResizable(rc_win[win_num], bswitch);
    else
        cout << "SetWindowResizable Error: Window #" << win_num << " is not an active window" << endl;
}

int rc_media_numWindows()
{
    int num = 0;
    for(int i = 0; i < MAX_WINDOWS; i++)
        if(rc_win[i])
            num++;
    return num;
}

bool rc_media_windowExists(int win_num)
{
    if(rc_winCheck(win_num))
    {
        if(rc_win[win_num])
            return true;
        return false;
    }
    return false;
}

void rc_media_restoreWindow(int win_num)
{
    if(rc_winCheck(win_num))
    {
        SDL_RestoreWindow(rc_win[win_num]);
        SDL_GetWindowDisplayMode(rc_win[win_num], &rc_displayMode[win_num]);
        rc_bb_rect[win_num].w = rc_displayMode[win_num].w;
        rc_bb_rect[win_num].h = rc_displayMode[win_num].h;
        rc_win_surface[win_num] = SDL_GetWindowSurface(rc_win[win_num]);
        #ifndef RC_MOBILE
        rc_fullscreen_mouse_scale_x[win_num] = (double)((double)rc_win_width[win_num] / (double)rc_displayMode[win_num].w);
        rc_fullscreen_mouse_scale_y[win_num] = (double)((double)rc_win_height[win_num] / (double)rc_displayMode[win_num].h);
        #endif // RC_MOBILE
    }
    else
        cout << "RestoreWindow Error: Window #" << win_num << " is not an active window" << endl;
}

void rc_media_setWindowIcon(int win_num, int slot)
{
    SDL_Rect img_rect;
    img_rect.x = 0;
    img_rect.y = 0;
    img_rect.w = rc_image_width[slot];
    img_rect.h = rc_image_height[slot];
    if(rc_himage[slot][win_num] != NULL)
    {
        //SDL_RendererFlip rf = (SDL_RendererFlip)(SDL_FLIP_VERTICAL);

        SDL_Surface * tmp_surf = SDL_CreateRGBSurface(0, rc_image_width[slot], rc_image_height[slot], 32, 0, 0, 0, 0);
        SDL_Texture * tmp_tex = SDL_CreateTexture(rc_win_renderer[rc_active_window], rc_pformat->format, SDL_TEXTUREACCESS_TARGET, rc_image_width[slot], rc_image_height[slot]);
        SDL_SetRenderTarget(rc_win_renderer[rc_active_window],NULL);
        SDL_RenderCopy(rc_win_renderer[rc_active_window],rc_himage[slot][rc_active_window],NULL,&img_rect);
        //SDL_RenderCopyEx(rc_win_renderer[rc_active_window],rc_himage[slot][rc_active_window],NULL,NULL,0,NULL,rf);

        SDL_RenderReadPixels(rc_win_renderer[rc_active_window], &img_rect, rc_pformat->format,tmp_surf->pixels,tmp_surf->pitch);

        SDL_SetColorKey(tmp_surf,SDL_TRUE,rc_image_colorKey[slot]);

        SDL_SetWindowIcon(rc_win[rc_active_window], tmp_surf);


        if(rc_active_screen >= 0)
            SDL_SetRenderTarget(rc_win_renderer[rc_active_window], rc_hscreen[rc_active_window][rc_active_screen]);

        SDL_DestroyTexture(tmp_tex);
        SDL_FreeSurface(tmp_surf);
    }
}

string rc_media_getClipboardText()
{
    return (string) SDL_GetClipboardText();
}

void rc_media_setClipboardText(string txt)
{
    SDL_SetClipboardText(txt.c_str());
}

int rc_media_hasClipboardText()
{
    return (int)SDL_HasClipboardText();
}

bool rc_screenCheck(int s_num = -1)
{
    if(s_num == -1)
        s_num = rc_active_screen;
    if(s_num > MAX_SCREENS || s_num < 0)
        return false;
    if(rc_sscreen[rc_active_window][s_num] == NULL && rc_hscreen[rc_active_window][s_num] == NULL)
        return false;
    return true;
}

void rc_media_openScreen_hw(int s_num, int w, int h, int vpx, int vpy, int vpw, int vph, int flag)
{
    //cout << "start CanvasOpen in " << rc_active_window << ", " << s_num << endl;
    if(s_num < 0 || s_num > MAX_SCREENS)
    {
        cout << "Canvas #" << s_num << " is not available" << endl;
        return;
    }
    if(rc_hscreen[rc_active_window][s_num]!=NULL)
    {
        cout << "Canvas #" << s_num << " is already open" << endl;
        return;
    }
    //cout << "got to this point" << endl;
    rc_hscreen[rc_active_window][s_num] = SDL_CreateTexture(rc_win_renderer[rc_active_window], rc_pformat->format, SDL_TEXTUREACCESS_TARGET, w, h);
    //cout << "hscreen texture created" << endl;
    rc_screen_transparent[rc_active_window][s_num] = 0;

    //cout << "Canvas is created" << endl;

    switch(flag)
    {
        case 0:
            //solid screen
            break;
        case 1:
            rc_screen_transparent[rc_active_window][s_num] = 1;
            SDL_SetTextureBlendMode(rc_hscreen[rc_active_window][s_num], SDL_BLENDMODE_BLEND);
            SDL_SetRenderTarget(rc_win_renderer[rc_active_window], rc_hscreen[rc_active_window][s_num]);
            SDL_SetRenderDrawColor(rc_win_renderer[rc_active_window], 0, 0, 0, 0);
            SDL_RenderClear(rc_win_renderer[rc_active_window]);
            //cout << "screen opened\n";
            break;
    }

    //cout << "Flags are set" << endl;

    rc_screen_rect[rc_active_window][s_num].x = vpx;
    rc_screen_rect[rc_active_window][s_num].y = vpy;
    rc_screen_rect[rc_active_window][s_num].w = vpw;
    rc_screen_rect[rc_active_window][s_num].h = vph;
    rc_screen_width[rc_active_window][s_num] = w;
    rc_screen_height[rc_active_window][s_num] = h;
    rc_screenview[rc_active_window][s_num].x = 0;
    rc_screenview[rc_active_window][s_num].y = 0;
    rc_screenview[rc_active_window][s_num].w = vpw;
    rc_screenview[rc_active_window][s_num].h = vph;
    rc_screen_visible[rc_active_window][s_num] = true;
    if(rc_active_screen == -1)
        rc_active_screen = s_num;

    SDL_SetRenderTarget(rc_win_renderer[rc_active_window], rc_hscreen[rc_active_window][rc_active_screen]);

    //cout << "Canvas is open" << endl;
}

void rc_media_closeScreen_hw(int s_num)
{
    if(rc_screenCheck(s_num))
    {
        SDL_DestroyTexture(rc_hscreen[rc_active_window][s_num]);
        rc_hscreen[rc_active_window][s_num] = NULL;
        rc_screen_visible[rc_active_window][s_num] = false;
    }
}

void rc_media_screen_hw(int s_num)
{
    if(rc_screenCheck(s_num))
    {
        rc_active_screen = s_num;
        SDL_SetRenderTarget(rc_win_renderer[rc_active_window], rc_hscreen[rc_active_window][s_num]);
        //cout << "active screen = hscreen[" << rc_active_window << "][" << s_num << "]\n";
    }
}

void rc_media_setScreenVisible(int s_num, int flag)
{
    if(rc_screenCheck(s_num) && flag == 0)
    {
        rc_screen_visible[rc_active_window][s_num] = false;
        return;
    }
    rc_screen_visible[rc_active_window][s_num] = true;
}

bool rc_media_screenIsVisible(int s_num)
{
    return rc_screen_visible[rc_active_window][s_num];
}

void rc_media_setScreenViewport(int s_num, int x, int y, int w, int h)
{
    if(rc_screenCheck(s_num))
    {
        rc_screen_rect[rc_active_window][s_num].x = x;
        rc_screen_rect[rc_active_window][s_num].y = y;
        rc_screen_rect[rc_active_window][s_num].w = w;
        rc_screen_rect[rc_active_window][s_num].h = h;
    }
}

void rc_media_getScreenViewport(int s_num, double * x, double * y, double * w, double * h)
{
    if(rc_screenCheck(s_num))
    {
        *x = rc_screen_rect[rc_active_window][s_num].x;
        *y = rc_screen_rect[rc_active_window][s_num].y;
        *w = rc_screen_rect[rc_active_window][s_num].w;
        *h = rc_screen_rect[rc_active_window][s_num].h;
    }
    else
        cout << "GetScreenViewport Error: Screen #" << s_num << " is not accessible" << endl;
}

void rc_media_screenOffset(int s_num, int x, int y)
{
    if(rc_screenCheck(s_num))
    {
        //removed error checks because you only live once
        rc_screenview[rc_active_window][s_num].x = x;
        rc_screenview[rc_active_window][s_num].y = y;
        rc_screenview[rc_active_window][s_num].w = rc_screen_rect[rc_active_window][s_num].w;
        rc_screenview[rc_active_window][s_num].h = rc_screen_rect[rc_active_window][s_num].h;
        //SDL_SetClipRect(rc_sscreen[rc_active_window][rc_active_screen], &rc_screenview[rc_active_window][rc_active_screen]);
    }
}

void rc_media_getScreenOffset(int s_num, double * x, double * y)
{
    if(rc_screenCheck(s_num))
    {
        *x = rc_screenview[rc_active_window][s_num].x;
        *y = rc_screenview[rc_active_window][s_num].y;
    }
}

void rc_media_getScreenSize(int s_num, double * w, double * h)
{
    if(rc_screenCheck(s_num))
    {
        *w = rc_screen_width[rc_active_window][s_num];
        *h = rc_screen_height[rc_active_window][s_num];
    }
}

void rc_media_clearScreen_hw()
{
    if(rc_screenCheck())
    {
        //cout << "Clear screen\n";
        //SDL_LockSurface(rc_sscreen[rc_active_window][rc_active_screen]);
        //SDL_SetRenderTarget(rc_win_renderer[rc_active_window], rc_hscreen[rc_active_window][rc_active_screen]);
        SDL_SetRenderDrawColor(rc_win_renderer[rc_active_window], rc_clearColor>>16, rc_clearColor>>8, rc_clearColor, rc_clearColor>>24);
        SDL_RenderClear(rc_win_renderer[rc_active_window]);
        SDL_SetRenderDrawColor(rc_win_renderer[rc_active_window], rc_ink_color.r, rc_ink_color.g, rc_ink_color.b, rc_ink_color.a);
        //SDL_RenderFillRect(rc_win_renderer[rc_active_window], &rc_screen_rect[rc_active_window][rc_active_screen]);
        //SDL_SetRenderTarget(rc_win_renderer[rc_active_window], rc_hscreen[rc_active_window][rc_active_screen]);
    }
}

void rc_media_setScreenAlpha_hw(int s_num, Uint8 alpha)
{
    if(rc_screenCheck(s_num))
    {
        SDL_SetTextureAlphaMod(rc_hscreen[rc_active_window][s_num], alpha);
    }
}

Uint32 rc_media_ScreenAlpha_hw(int s_num)
{
    Uint8 alpha = 0;
    if(rc_screenCheck(s_num))
    {
        SDL_GetTextureAlphaMod(rc_hscreen[rc_active_window][s_num], &alpha);
    }
    return (Uint32)alpha;
}

int rc_media_setScreenBlendMode_hw(int s_num, int blend_mode)
{
    if(!rc_screenCheck(s_num))
    {
        return -1;
    }
    int rslt = -1;
    SDL_BlendMode b = SDL_BLENDMODE_NONE;
    switch(blend_mode)
    {
    case 0: //SDL_BLENDMODE_NONE
        b = SDL_BLENDMODE_NONE;
        break;
    case 1: //SDL_BLENDMODE_BLEND
        b = SDL_BLENDMODE_BLEND;
        break;
    case 2: //SDL_BLENDMODE_ADD
        b = SDL_BLENDMODE_ADD;
        break;
    case 4: //SDL_BLENDMODE_MOD
        b = SDL_BLENDMODE_MOD;
        break;
    default:
        return rslt;
    }
    rslt = SDL_SetTextureBlendMode(rc_hscreen[rc_active_window][s_num], b);

    return rslt;
}

int rc_media_screenBlendMode_hw(int s_num)
{
    if(!rc_screenCheck(s_num))
    {
        return -1;
    }
    SDL_BlendMode blend_mode = SDL_BLENDMODE_NONE;
    int rslt = SDL_GetTextureBlendMode(rc_hscreen[rc_active_window][s_num], &blend_mode);
    if(rslt < 0)
    {
        cout << "CanvasBlendMode Error: " << SDL_GetError() << endl;
        return rslt;
    }
    return blend_mode;
}

int rc_media_setScreenColorMod_hw(int s_num, Uint32 c)
{
    if(!rc_screenCheck(s_num))
    {
        return -1;
    }
    int rslt = -1;

    Uint8 r = c>>16;
    Uint8 g = c>>8;
    Uint8 b = c;

    //cout << "C = " << c << endl;
    //cout << "RGB = " << (Uint32)r << ", " << (Uint32)g << ", " << (Uint32)b << endl;

    rslt = SDL_SetTextureColorMod(rc_hscreen[rc_active_window][s_num], r, g, b);
    return rslt;
}

int rc_media_screenColorMod_hw(int s_num)
{
    if(!rc_screenCheck(s_num))
    {
        return -1;
    }

    Uint8 r = 0;
    Uint8 g = 0;
    Uint8 b = 0;
    int rslt = SDL_GetTextureColorMod(rc_hscreen[rc_active_window][s_num], &r, &g, &b);

    if(rslt < 0)
    {
        cout << "CanvasColorMode Error: " << SDL_GetError() << endl;
        return rslt;
    }

    Uint32 c_mod = (Uint32)SDL_MapRGBA(rc_pformat,r,g,b,255);

    //cout << "-RGB = " << (int)r << ", " << (int)g << ", " << (int)b << endl;

    return c_mod;
}
//----------------


void rc_media_copyScreen_hw(int src_screen, int sx, int sy, int sw, int sh, int dst_screen, int dx, int dy)
{
    if(rc_screenCheck(src_screen) && rc_screenCheck(dst_screen))
    {
        SDL_Rect src_rect, dst_rect;
        src_rect.x = sx;
        src_rect.y = sy;
        src_rect.w = sw;
        src_rect.h = sh;
        dst_rect.x = dx;
        dst_rect.y = dy;
        dst_rect.w = sw;
        dst_rect.h = sh;
        //SDL_BlitSurface(rc_sscreen[rc_active_window][src_screen], &src_rect, rc_sscreen[rc_active_window][dst_screen], &dst_rect);
        SDL_SetRenderTarget(rc_win_renderer[rc_active_window], rc_hscreen[rc_active_window][dst_screen]);
        SDL_RenderCopy(rc_win_renderer[rc_active_window], rc_hscreen[rc_active_window][src_screen], &src_rect, &dst_rect);
        SDL_SetRenderTarget(rc_win_renderer[rc_active_window], rc_hscreen[rc_active_window][rc_active_screen]);
    }
}

void rc_media_getScreenClip_hw(int slot, int sx, int sy, int sw, int sh)
{
    if(rc_screenCheck(rc_active_screen))
    {
        SDL_RendererFlip rf = (SDL_RendererFlip)SDL_FLIP_NONE;
        int w = 0;
        int h = 0;
        SDL_QueryTexture(rc_hscreen[rc_active_window][rc_active_screen], NULL, NULL, &w, &h);
        SDL_Texture * tmp_tex = SDL_CreateTexture(rc_win_renderer[rc_active_window], rc_pformat->format, SDL_TEXTUREACCESS_TARGET, w, h);
        SDL_SetRenderTarget(rc_win_renderer[rc_active_window], tmp_tex);
        SDL_SetRenderDrawColor(rc_win_renderer[rc_active_window], rc_clearColor>>16, rc_clearColor>>8, rc_clearColor, rc_clearColor>>24);
        SDL_RenderClear(rc_win_renderer[rc_active_window]);
        SDL_SetRenderDrawColor(rc_win_renderer[rc_active_window], rc_ink_color.r, rc_ink_color.g, rc_ink_color.b, rc_ink_color.a);
        SDL_Point center;
        center.x = w/2;
        center.y = h/2;
        SDL_RenderCopyEx(rc_win_renderer[rc_active_window], rc_hscreen[rc_active_window][rc_active_screen], NULL, NULL, 0, &center,rf);
        SDL_Surface * img_surf = SDL_CreateRGBSurface(0, sw, sh, 32, 0, 0, 0, 0);
        SDL_Rect src_rect;
        src_rect.x = sx;
        src_rect.y = sy;
        src_rect.w = sw;
        src_rect.h = sh;
        //SDL_BlitSurface(rc_sscreen[rc_active_window][src_screen], &src_rect, rc_sscreen[rc_active_window][dst_screen], &dst_rect);
        SDL_RenderReadPixels(rc_win_renderer[rc_active_window], &src_rect, rc_pformat->format, img_surf->pixels, img_surf->pitch);
        SDL_SetRenderTarget(rc_win_renderer[rc_active_window], rc_hscreen[rc_active_window][rc_active_screen]);
        SDL_DestroyTexture(tmp_tex);

        for(int i = 0; i < MAX_WINDOWS; i++)
        {
            if(rc_win_renderer[i]!=NULL)
            {
                if(rc_himage[slot][i]!=NULL)
                {
                    SDL_DestroyTexture(rc_himage[slot][i]);
                    rc_himage[slot][i] = NULL;
                }
                rc_himage[slot][i] = SDL_CreateTextureFromSurface(rc_win_renderer[i], img_surf);
                rc_himage_rect[slot].x = 0;
                rc_himage_rect[slot].y = 0;
                rc_himage_rect[slot].w = img_surf->w;
                rc_himage_rect[slot].h = img_surf->h;
                rc_image_width[slot] = img_surf->w;
                rc_image_height[slot] = img_surf->h;
                rc_image_isLoaded[slot] = true;
            }
        }

        SDL_FreeSurface(img_surf);
    }
}

void rc_media_getScreenClip2_hw(int slot, int sx, int sy, int sw, int sh, bool flag)
{
    if(!flag)
    {
        rc_media_getScreenClip_hw(slot, sx, sy, sw, sh);
    }
    else if(rc_screenCheck(rc_active_screen))
    {
        if(rc_himage[slot][rc_active_window] != NULL)
        {
            cout << "CanvasClip_Ex Error: Image slot is already occupied" << endl;
            return;
        }
        SDL_Rect src, dst;
        rc_himage[slot][rc_active_window] = SDL_CreateTexture(rc_win_renderer[rc_active_window], rc_pformat->format, SDL_TEXTUREACCESS_TARGET, sw, sh);
        src.x = sx;
        src.y = sy;
        src.w = sw;
        src.h = sh;
        dst.x = 0;
        dst.y = 0;
        dst.w = sw;
        dst.h = sh;
        rc_himage_rect[slot] = dst;
        rc_image_width[slot] = sw;
        rc_image_height[slot] = sh;
        rc_image_isLoaded[slot] = true;
        SDL_SetRenderTarget(rc_win_renderer[rc_active_window], rc_himage[slot][rc_active_window]);
        SDL_SetRenderDrawColor(rc_win_renderer[rc_active_window], 0, 0, 0, 0);
        SDL_RenderClear(rc_win_renderer[rc_active_window]);
        SDL_RenderCopy(rc_win_renderer[rc_active_window], rc_hscreen[rc_active_window][rc_active_screen], &src, &dst);
        SDL_SetRenderTarget(rc_win_renderer[rc_active_window], rc_hscreen[rc_active_window][rc_active_screen]);
        SDL_SetRenderDrawColor(rc_win_renderer[rc_active_window], rc_ink_color.r, rc_ink_color.g, rc_ink_color.b, rc_ink_color.a);
    }
}



void rc_media_getWindowClip_hw(int slot, int sx, int sy, int sw, int sh)
{
    SDL_Surface * img_surf = SDL_CreateRGBSurface(0, sw, sh, 32, 0, 0, 0, 0);
    SDL_Rect src_rect;
    src_rect.x = sx;
    src_rect.y = sy;
    src_rect.w = sw;
    src_rect.h = sh;
    //SDL_BlitSurface(rc_sscreen[rc_active_window][src_screen], &src_rect, rc_sscreen[rc_active_window][dst_screen], &dst_rect);
    SDL_SetRenderTarget(rc_win_renderer[rc_active_window], NULL);
    SDL_RenderReadPixels(rc_win_renderer[rc_active_window], &src_rect, rc_pformat->format, img_surf->pixels, img_surf->pitch);

    for(int i = 0; i < MAX_WINDOWS; i++)
    {
        if(rc_win_renderer[i]!=NULL)
        {
            if(rc_himage[slot][i]!=NULL)
            {
                SDL_DestroyTexture(rc_himage[slot][i]);
                rc_himage[slot][i] = NULL;
            }
            rc_himage[slot][i] = SDL_CreateTextureFromSurface(rc_win_renderer[i], img_surf);
            rc_himage_rect[slot].x = 0;
            rc_himage_rect[slot].y = 0;
            rc_himage_rect[slot].w = img_surf->w;
            rc_himage_rect[slot].h = img_surf->h;
            rc_image_width[slot] = img_surf->w;
            rc_image_height[slot] = img_surf->h;
            rc_image_isLoaded[slot] = true;
        }
    }

    SDL_FreeSurface(img_surf);
    SDL_SetRenderTarget(rc_win_renderer[rc_active_window], rc_hscreen[rc_active_window][rc_active_screen]);
}

void rc_media_cloneScreen_hw(int src_screen, int dst_screen)
{
    if(rc_screenCheck(src_screen) && (dst_screen >= 0 && dst_screen < MAX_SCREENS))
    {
        if(rc_hscreen[rc_active_window][dst_screen] == NULL)
        {
            rc_hscreen[rc_active_window][dst_screen] = rc_hscreen[rc_active_window][src_screen];
            rc_screen_width[rc_active_window][dst_screen] = rc_screen_width[rc_active_window][src_screen];
            rc_screen_height[rc_active_window][dst_screen] = rc_screen_height[rc_active_window][src_screen];
            rc_screen_rect[rc_active_window][dst_screen] = rc_screen_rect[rc_active_window][src_screen];
            rc_screenview[rc_active_window][dst_screen] = rc_screenview[rc_active_window][src_screen];
            rc_screen_visible[rc_active_window][dst_screen] = rc_screen_visible[rc_active_window][src_screen];
        }
    }
}

void rc_sortZ(int priority_screen)
{
    int aw  = rc_active_window;
    int draw_order = 0;
    for(int z = 0; z < MAX_SCREENS; z++)
    {
        if(rc_screen_z[aw][priority_screen] == z)
        {
            rc_screen_zOrder[aw][draw_order] = priority_screen;
            draw_order++;
        }
        for(int n = 0; n < MAX_SCREENS; n++)
        {
			if(rc_screen_z[aw][n] == z && n != priority_screen)
			{
				rc_screen_zOrder[aw][draw_order] = n;
				draw_order++;
			}
		}
    }
}

void rc_media_setScreenZ(int s_num, int z)
{
    if(rc_screenCheck(s_num))
    {
        if(z < 0 || z >= MAX_SCREENS)
        {
            cout << "SetScreenZ Error: Z Order must be a value from 0 to " << MAX_SCREENS-1 << endl;
            return;
        }
        //int tmp_z = 0;
        //int tmp_order[MAX_SCREENS];
        //cout << "z_start: " << rc_screen_zOrder[rc_active_window][rc_active_screen] << endl;

        rc_screen_z[rc_active_window][s_num] = z;

        rc_sortZ(s_num);

        //for(int i = 0; i < MAX_SCREENS; i++)
            //cout << "z: " << rc_screen_zOrder[rc_active_window][i] << endl;
    }
}

int rc_media_screenZ(int s_num)
{
    if(rc_screenCheck(s_num))
    {
        return rc_screen_z[rc_active_window][s_num];
    }
    return -1;
}

void rc_media_box_hw(int x1, int y1, int x2, int y2)
{
	Sint16 vx[4], vy[4];

    vx[0] = (Sint16)x1;
    vy[0] = (Sint16)y1;

    vx[1] = (Sint16)x2;
    vy[1] = (Sint16)y1;

    vx[2] = (Sint16)x2;
    vy[2] = (Sint16)y2;

    vx[3] = (Sint16)x1;
    vy[3] = (Sint16)y2;

    polygonRGBA(rc_win_renderer[rc_active_window], vx, vy, 4, rc_ink_color.r, rc_ink_color.g, rc_ink_color.b, rc_ink_color.a);
}

void rc_media_boxFill_hw(int x1, int y1, int x2, int y2)
{
	Sint16 vx[4], vy[4];

    vx[0] = (Sint16)x1;
    vy[0] = (Sint16)y1;

    vx[1] = (Sint16)x2;
    vy[1] = (Sint16)y1;

    vx[2] = (Sint16)x2;
    vy[2] = (Sint16)y2;

    vx[3] = (Sint16)x1;
    vy[3] = (Sint16)y2;

    filledPolygonRGBA(rc_win_renderer[rc_active_window], vx, vy, 4, rc_ink_color.r, rc_ink_color.g, rc_ink_color.b, rc_ink_color.a);
}

void rc_media_rectangle(int x, int y, int w, int h)
{
	SDL_Rect rect_dim;
    rect_dim.x = x;
    rect_dim.y = y;
    rect_dim.w = w;
    rect_dim.h = h;

    SDL_RenderDrawRect(rc_win_renderer[rc_active_window], &rect_dim);
}

void rc_media_rectangleFill(int x, int y, int w, int h)
{
    SDL_Rect rect_dim;
    rect_dim.x = x;
    rect_dim.y = y;
    rect_dim.w = w;
    rect_dim.h = h;

    SDL_RenderFillRect(rc_win_renderer[rc_active_window], &rect_dim);
}

void rc_media_roundRect(int x, int y, int w, int h, int r)
{
    roundedRectangleRGBA(rc_win_renderer[rc_active_window], x, y, x+(w-1), y+(h-1), r, rc_ink_color.r, rc_ink_color.g, rc_ink_color.b, rc_ink_color.a);
}

void rc_media_roundRectFill(int x, int y, int w, int h, int r)
{
    roundedBoxRGBA(rc_win_renderer[rc_active_window], x, y, x+(w-1), y+(h-1), r, rc_ink_color.r, rc_ink_color.g, rc_ink_color.b, rc_ink_color.a);
}

void rc_media_circle_hw(int xc, int yc, int r)
{
    circleRGBA(rc_win_renderer[rc_active_window], xc, yc, r, rc_ink >> 16, rc_ink >> 8, rc_ink, rc_ink >> 24);
}

void rc_media_circleFill_hw(int xc, int yc, int r)
{
    filledCircleRGBA(rc_win_renderer[rc_active_window], xc, yc, r, rc_ink_color.r, rc_ink_color.g, rc_ink_color.b, rc_ink_color.a);
}

void rc_media_ellipse_hw(int xc, int yc, int width, int height)
{
    ellipseRGBA(rc_win_renderer[rc_active_window], xc, yc, width, height, rc_ink >> 16, rc_ink >> 8, rc_ink, rc_ink>>24);
}

void rc_media_ellipseFill_hw(int xc, int yc, int width, int height)
{
    filledEllipseRGBA(rc_win_renderer[rc_active_window], xc, yc, width, height, rc_ink >> 16, rc_ink >> 8, rc_ink, rc_ink>>24);
}

Uint32 rc_media_getPixel_hw(int x, int y)
{
    //Uint32 * s_pixels = (Uint32*) rc_win_surface[rc_active_window]->pixels;
    #ifdef RC_MOBILE
    SDL_Texture * tmp_buf = SDL_CreateTexture(rc_win_renderer[rc_active_window], rc_pformat->format, SDL_TEXTUREACCESS_TARGET, rc_win_width[rc_active_window], rc_win_height[rc_active_window]);
    if(tmp_buf==NULL)
        return 0;
    SDL_SetRenderTarget(rc_win_renderer[rc_active_window], tmp_buf);
    SDL_RendererFlip rf = SDL_FLIP_NONE;
    SDL_RenderCopyEx(rc_win_renderer[rc_active_window], rc_backBuffer[rc_active_window], NULL, NULL, 0, NULL, rf);
    #else
    SDL_SetRenderTarget(rc_win_renderer[rc_active_window], NULL);
    #endif // RC_MOBILE

    //cout << "surface = ( " << rc_win_surface[rc_active_window]->w << ", " << rc_win_surface[rc_active_window]->h << " ) " << endl;
    //int w = 0;
    //int h = 0;
    //SDL_GetWindowSize(rc_win[rc_active_window], &w, &h);
    //w = rc_displayMode[rc_active_window].w;
    //h = rc_displayMode[rc_active_window].h;
    Uint32 * s_pixels = (Uint32*)SDL_malloc(sizeof(Uint32));
    SDL_Rect p_rect;
    #ifdef RC_MOBILE
    p_rect.x = x;
    p_rect.y = y;
    #else
    p_rect.x = x / rc_fullscreen_mouse_scale_x[rc_active_window];
    p_rect.y = y / rc_fullscreen_mouse_scale_y[rc_active_window];
    #endif // RC_MOBILE
    p_rect.w = 1;
    p_rect.h = 1;
    SDL_RenderReadPixels(rc_win_renderer[rc_active_window], &p_rect, rc_pformat->format, (void*)s_pixels, 4);

    Uint32 p_color =  s_pixels[0];

    #ifdef RC_MOBILE
    SDL_DestroyTexture(tmp_buf);
    int r = p_color & 255;
    int g = (p_color >> 8) & 255;
    int b = (p_color >> 16) & 255;
    int a = (p_color >> 24) & 255;
    //p_color = SDL_MapRGBA(rc_pformat, r, g, b, a);
    #endif // RC_MOBILE

    //cout << "color = " << p_color << endl;
    SDL_free(s_pixels);
    SDL_SetRenderTarget(rc_win_renderer[rc_active_window], rc_hscreen[rc_active_window][rc_active_screen]);
    return p_color;
}

void rc_media_ink(Uint32 ink_color)
{
    //cout << "ink = " << ink_color << endl;
    rc_ink = ink_color;
    rc_ink_color.a = ink_color>>24;//ink_color >> 24;
    //cout << "alpha = " << (int)rc_ink_color.a << endl;
    rc_ink_color.r = ink_color >> 16;
    rc_ink_color.g = ink_color >> 8;
    rc_ink_color.b = ink_color;
    SDL_SetRenderDrawColor(rc_win_renderer[rc_active_window], rc_ink_color.r, rc_ink_color.g, rc_ink_color.b, rc_ink_color.a);
}

void rc_media_setClearColor(Uint32 c_color)
{
    rc_clearColor = c_color;
}

Uint32 rc_media_rgb(Uint8 r, Uint8 g, Uint8 b)
{
    //cout << "r = " << (int)  r << "   g = " << (int) g << "   b = " << (int)b << endl;
    Uint32 rgba_map = (Uint32)SDL_MapRGBA(rc_pformat,r,g,b,255);
    //Uint32 rgba_map = (r << 16) + (g << 8) + b + (255 << 24);// + (255<<24);
    //cout << "rgb_out = " << rgba_map << endl;
    return rgba_map;
}

Uint32 rc_media_rgba(Uint8 r, Uint8 g, Uint8 b, Uint8 a)
{
    Uint32 rgba_map = (Uint32)SDL_MapRGBA(rc_pformat,r,g,b,a);
    //rgba_map = rgba_map + (a<<24);
    return rgba_map;
}

void rc_media_line_hw(int x1, int y1, int x2, int y2)
{
    lineRGBA(rc_win_renderer[rc_active_window], x1, y1, x2, y2, rc_ink >> 16, rc_ink >> 8, rc_ink, rc_ink >> 24);
}

void rc_getPrevColor(int x, int y)
{
    //cout << "PCOLOR #1" << endl;
    Uint32 * s_pixels = (Uint32*)rc_sscreen[rc_active_window][rc_active_screen]->pixels;
    //cout << "PCOLOR #2: " << y << " , " << rc_active_window << " , " << rc_active_screen << " , " << x << endl;
    prev_color = s_pixels[y*rc_sscreen[rc_active_window][rc_active_screen]->w+x];
    //cout << "PCOLOR #3" << endl;
}

void rc_media_floodFill_sw(int x, int y, Uint32* s_pixels, int pitch, int w)
{
    int s_lock = 0;
    //cout << "u1" << endl;
    if(SDL_MUSTLOCK(rc_sscreen[rc_active_window][rc_active_screen]))
    {
        //cout << "u2" << endl;
        s_lock = 1;
        SDL_LockSurface(rc_sscreen[rc_active_window][rc_active_screen]);
    }
    //cout << "u3" << endl;
    //Uint32 * s_pixels = (Uint32*) rc_sscreen[rc_active_window][rc_active_screen]->pixels;
    //cout << "u4" << endl;
    //int pitch = rc_sscreen[rc_active_window][rc_active_screen]->pitch;
    //cout << "u5" << endl;
    //int w = rc_sscreen[rc_active_window][rc_active_screen]->pitch/4;
    //cout << "u6" << endl;

    // Base cases
    if (x < 0 || x >= rc_screen_width[rc_active_window][rc_active_screen] || y < 0 || y >= rc_screen_height[rc_active_window][rc_active_screen])
        return;
    //cout << "u7" << endl;
    if (s_pixels[y*w+x] != prev_color)
        return;
    //cout << "u8" << endl;

    // Replace the color at (x, y)
    s_pixels[y*w+x] = rc_ink;

    //cout << "u8-1" << endl; cout << "x = " << x << "; y = " << y << endl;

    // Recur for north, east, south and west
    rc_media_floodFill_sw(x+1, y, s_pixels, pitch, w);
    rc_media_floodFill_sw(x-1, y, s_pixels, pitch, w);
    rc_media_floodFill_sw(x, y+1, s_pixels, pitch, w);
    rc_media_floodFill_sw(x, y-1, s_pixels, pitch, w);

    //cout << "u8-2" << endl;

    if(s_lock == 1)
    {
        //cout << "u9" << endl;
        SDL_UnlockSurface(rc_sscreen[rc_active_window][rc_active_screen]);
        //cout << "u10" << endl;
    }
}

void rc_media_floodFill_hw(int x, int y)
{
    rc_sscreen[rc_active_window][rc_active_screen] = SDL_CreateRGBSurface(0, rc_screen_width[rc_active_window][rc_active_screen], rc_screen_height[rc_active_window][rc_active_screen], 32, 0, 0, 0, 0);
    SDL_Rect c_screen;
    c_screen.x = 0;
    c_screen.y = 0;
    c_screen.w = rc_screen_width[rc_active_window][rc_active_screen];
    c_screen.h = rc_screen_height[rc_active_window][rc_active_screen];
    SDL_SetRenderTarget(rc_win_renderer[rc_active_window],NULL);
    SDL_RenderCopy(rc_win_renderer[rc_active_window],rc_hscreen[rc_active_window][rc_active_screen],NULL,&c_screen);
    //SDL_RendererFlip rf = (SDL_RendererFlip)SDL_FLIP_VERTICAL;
    //SDL_RenderCopyEx(rc_win_renderer[rc_active_window],rc_hscreen[rc_active_window][rc_active_screen],NULL,NULL,0,NULL,rf);

    //cout << "DEBUG_FLOOD CP 1" << endl;

    if(SDL_RenderReadPixels(rc_win_renderer[rc_active_window], &c_screen, rc_pformat->format,rc_sscreen[rc_active_window][rc_active_screen]->pixels,rc_sscreen[rc_active_window][rc_active_screen]->pitch) < 0)
    {
        cout << "ReadPixel Error: " << SDL_GetError() << endl;
        SDL_SetRenderTarget(rc_win_renderer[rc_active_window], rc_hscreen[rc_active_window][rc_active_screen]);

    }
    else
    {
        //cout << "DEBUG_FLOOD CP 2" << endl;
        rc_getPrevColor(x, y);
        //cout << "DEBUG_FLOOD CP 3" << endl;
        Uint32 * s_pixels = (Uint32*) rc_sscreen[rc_active_window][rc_active_screen]->pixels;
        int pitch = rc_sscreen[rc_active_window][rc_active_screen]->pitch;
        int w = rc_sscreen[rc_active_window][rc_active_screen]->pitch/4;
        //cout << "pitch = " << pitch << endl;
        //cout << "w = " << w << endl;
        //string bs=""; cin>>bs;
        if(s_pixels[y*w+x] != rc_ink)
            rc_media_floodFill_sw(x,y,s_pixels, pitch, w);
        //cout << "DEBUG_FLOOD CP 4" << endl;
        SDL_Texture * tmp_tex = SDL_CreateTextureFromSurface(rc_win_renderer[rc_active_window], rc_sscreen[rc_active_window][rc_active_screen]);
        //cout << "DEBUG_FLOOD CP 5" << endl;

        if(tmp_tex==NULL)
        {
            cout << "FloodFill Error: Canvas Buffer could not be created" << endl;
            SDL_SetRenderTarget(rc_win_renderer[rc_active_window], rc_hscreen[rc_active_window][rc_active_screen]);

        }
        else
        {
            SDL_SetRenderTarget(rc_win_renderer[rc_active_window], rc_hscreen[rc_active_window][rc_active_screen]);
            SDL_RenderCopy(rc_win_renderer[rc_active_window],tmp_tex,NULL,NULL);
        }
        SDL_DestroyTexture(tmp_tex);
    }

    SDL_FreeSurface(rc_sscreen[rc_active_window][rc_active_screen]);
    rc_sscreen[rc_active_window][rc_active_screen] = NULL;

}

void rc_media_drawPixel_hw(int x, int y)
{
    pixelRGBA(rc_win_renderer[rc_active_window], x, y, rc_ink_color.r, rc_ink_color.g, rc_ink_color.b, rc_ink_color.a);
}

void rc_media_poly(unsigned int n, double* vx_d, double* vy_d)
{
    Sint16 vx[n], vy[n];
    for(int i = 0; i < n; i++)
    {
        vx[i] = (Sint16)vx_d[i];
        vy[i] = (Sint16)vy_d[i];
    }
    polygonRGBA(rc_win_renderer[rc_active_window], vx, vy, n, rc_ink_color.r, rc_ink_color.g, rc_ink_color.b, rc_ink_color.a);
}

void rc_media_polyfill(unsigned int n, double* vx_d, double* vy_d)
{
    Sint16 vx[n], vy[n];
    for(int i = 0; i < n; i++)
    {
        vx[i] = (Sint16)vx_d[i];
        vy[i] = (Sint16)vy_d[i];
    }
    filledPolygonRGBA(rc_win_renderer[rc_active_window], vx, vy, n, rc_ink_color.r, rc_ink_color.g, rc_ink_color.b, rc_ink_color.a);
}

void rc_media_loadImage_hw(int slot, string img_file)
{
    if(slot < 0 || slot >= MAX_IMAGES)
    {
        cout << "LoadImage Error: Image Slot must be in the range of 0 to " << MAX_IMAGES << endl;
        return;
    }
    if(rc_himage[slot][rc_active_window]!=NULL)
    {
        cout << "LoadImage Error: Image " << slot << " is already in use" << endl;
        return;
    }
    //mariocircuit-1.png
    SDL_Surface * image = IMG_Load(img_file.c_str());
    if(image == NULL)
    {
        cout << "~Image: " << img_file.c_str() << endl;
        cout << "LoadImage Error: " << IMG_GetError() << endl;
        return;
    }
    #ifdef RC_MOBILE
        SDL_Surface * image_cv = SDL_ConvertSurfaceFormat(image, rc_pformat->format, 0);
    #else
        SDL_Surface * image_cv = SDL_ConvertSurface(image, rc_pformat,0);
    #endif // RC_MOBILE
    rc_image_width[slot] = image_cv->w;
    rc_image_height[slot] = image_cv->h;
    rc_image_isLoaded[slot] = true;
    if(image_cv == NULL)
    {
        cout << "LoadImage Error: " << SDL_GetError() << endl;
        SDL_FreeSurface(image);
        return;
    }

    #ifdef RC_MOBILE
    if(rc_himage[slot][rc_active_window] != NULL)
        SDL_DestroyTexture(rc_himage[slot][rc_active_window]);
    rc_himage[slot][rc_active_window] = SDL_CreateTextureFromSurface(rc_win_renderer[rc_active_window], image_cv);
    SDL_SetTextureBlendMode(rc_himage[slot][rc_active_window], SDL_BLENDMODE_BLEND);
    #else

    for(int i = 0; i < MAX_WINDOWS; i++)
    {
        if(rc_himage[slot][i] != NULL)
            SDL_DestroyTexture(rc_himage[slot][i]);
        rc_himage[slot][i] = SDL_CreateTextureFromSurface(rc_win_renderer[i], image_cv);
        SDL_SetTextureBlendMode(rc_himage[slot][i], SDL_BLENDMODE_BLEND);
        if(i == rc_active_window && rc_himage[slot][rc_active_window] == NULL)
        {
            cout << "#LoadImage Error: " << SDL_GetError() << endl;
            SDL_FreeSurface(image);
            SDL_FreeSurface(image_cv);
            for(int j = 0; j < i; j++)
                SDL_DestroyTexture(rc_himage[slot][j]);
            return;
        }
    }

    #endif // RC_MOBILE
    SDL_FreeSurface(image);
    SDL_FreeSurface(image_cv);
}

void rc_media_loadImage_ex_hw(int slot, string img_file, double color)
{
    if(slot < 0 || slot >= MAX_IMAGES)
    {
        cout << "LoadImage_Ex Error: Image Slot must be in the range of 0 to " << MAX_IMAGES << endl;
        return;
    }
    if(rc_himage[slot][rc_active_window]!=NULL)
    {
        cout << "LoadImage_Ex Error: Image Slot is already in use" << endl;
        return;
    }
    SDL_Surface * image = IMG_Load(img_file.c_str());
    if(image == NULL)
    {
        cout << "LoadImage_Ex Error: " << SDL_GetError() << endl;
        return;
    }

    if(color < 0)
    {
        Uint32 * c = (Uint32*)image->pixels;
        SDL_SetColorKey(image, SDL_TRUE, c[0]);
    }
    else
        SDL_SetColorKey(image, SDL_TRUE, (Uint32)color);

    #ifdef RC_MOBILE
    SDL_Surface * image_cv = SDL_ConvertSurfaceFormat(image, rc_pformat->format, 0);
    #else
    SDL_Surface * image_cv = SDL_ConvertSurface(image, rc_pformat,0);
    #endif // RC_MOBILE
    rc_image_width[slot] = image_cv->w;
    rc_image_height[slot] = image_cv->h;
    rc_image_isLoaded[slot] = true;
    if(image_cv == NULL)
    {
        cout << "LoadImage_Ex Error: " << SDL_GetError() << endl;
        SDL_FreeSurface(image);
        return;
    }

    #ifdef RC_MOBILE
    if(rc_himage[slot][rc_active_window] != NULL)
        SDL_DestroyTexture(rc_himage[slot][rc_active_window]);
    rc_himage[slot][rc_active_window] = SDL_CreateTextureFromSurface(rc_win_renderer[rc_active_window], image_cv);
    SDL_SetTextureBlendMode(rc_himage[slot][rc_active_window], SDL_BLENDMODE_BLEND);
    #else

    for(int i = 0; i < MAX_WINDOWS; i++)
    {
        if(rc_himage[slot][i] != NULL)
            SDL_DestroyTexture(rc_himage[slot][i]);
        rc_himage[slot][i] = SDL_CreateTextureFromSurface(rc_win_renderer[i], image_cv);
        SDL_SetTextureBlendMode(rc_himage[slot][i], SDL_BLENDMODE_BLEND);
        if(i == rc_active_window && rc_himage[slot][rc_active_window] == NULL)
        {
            cout << "#LoadImage_Ex Error: " << SDL_GetError() << endl;
            SDL_FreeSurface(image);
            SDL_FreeSurface(image_cv);
            for(int j = 0; j < i; j++)
                SDL_DestroyTexture(rc_himage[slot][j]);
            return;
        }
    }

    #endif // RC_MOBILE

    SDL_FreeSurface(image);
    SDL_FreeSurface(image_cv);
}

void rc_media_createImage_hw(int slot, int w, int h, double * pdata)
{
    if(rc_himage[slot][rc_active_window] != NULL)
    {
        cout << "CreateImage Error: Image already exist" << endl;
        return;
    }

    SDL_Surface * img_surf = SDL_CreateRGBSurface(0, w, h, 32, 0, 0, 0, 0);
    Uint32 * img_pixels = (Uint32*)img_surf->pixels;
    for(int i = 0; i < (w*h); i++)
    {
        img_pixels[i] = (Uint32)pdata[i];
    }
    #ifdef RC_MOBILE
    SDL_DestroyTexture(rc_himage[slot][rc_active_window]);
    rc_himage[slot][rc_active_window] = SDL_CreateTextureFromSurface(rc_win_renderer[rc_active_window], img_surf);
    SDL_SetTextureBlendMode(rc_himage[slot][rc_active_window], SDL_BLENDMODE_BLEND);

    if(rc_himage[slot][rc_active_window] == NULL)
    {
        cout << "#CreateImage Error: " << SDL_GetError() << endl;
        SDL_FreeSurface(img_surf);
        SDL_DestroyTexture(rc_himage[slot][rc_active_window]);
        return;
    }
    #else
    for(int i = 0; i < MAX_WINDOWS; i++)
    {
        SDL_DestroyTexture(rc_himage[slot][i]);
        rc_himage[slot][i] = SDL_CreateTextureFromSurface(rc_win_renderer[i], img_surf);
        SDL_SetTextureBlendMode(rc_himage[slot][i], SDL_BLENDMODE_BLEND);
    }
    if(rc_himage[slot][rc_active_window] == NULL)
    {
        cout << "#CreateImage Error: " << SDL_GetError() << endl;
        SDL_FreeSurface(img_surf);
        for(int j = 0; j < MAX_WINDOWS; j++)
        {
            SDL_DestroyTexture(rc_himage[slot][j]);
            rc_himage[slot][j] = NULL;
        }
        return;
    }
    #endif // RC_MOBILE
    rc_image_width[slot] = img_surf->w;
    rc_image_height[slot] = img_surf->h;
    rc_image_isLoaded[slot] = true;
    SDL_FreeSurface(img_surf);
}

void rc_media_createImage_Ex_hw(int slot, int w, int h, double * pdata, double color)
{
    if(rc_himage[slot][rc_active_window] != NULL)
    {
        cout << "CreateImage_Ex Error: Image already exist" << endl;
        return;
    }

    SDL_Surface * img_surf = SDL_CreateRGBSurface(0, w, h, 32, 0, 0, 0, 0);
    Uint32 * img_pixels = (Uint32*)img_surf->pixels;
    for(int i = 0; i < (w*h); i++)
    {
        img_pixels[i] = (Uint32)pdata[i];
    }
    #ifdef RC_MOBILE
    SDL_Surface * image_cv = SDL_ConvertSurfaceFormat(img_surf, rc_pformat->format,0);
    #else
    SDL_Surface * image_cv = SDL_ConvertSurface(img_surf, rc_pformat,0);
    #endif // RC_MOBILE
    if(image_cv == NULL)
    {
        cout << "CreateImage_Ex Error: " << SDL_GetError() << endl;
        SDL_FreeSurface(img_surf);
        return;
    }
    if((Uint32)color<0)
        SDL_SetColorKey(image_cv, SDL_TRUE, img_pixels[0]);
    else
        SDL_SetColorKey(image_cv, SDL_TRUE, (Uint32)color);

    #ifdef RC_MOBILE
    SDL_DestroyTexture(rc_himage[slot][rc_active_window]);
    rc_himage[slot][rc_active_window] = SDL_CreateTextureFromSurface(rc_win_renderer[rc_active_window], image_cv);
    SDL_SetTextureBlendMode(rc_himage[slot][rc_active_window], SDL_BLENDMODE_BLEND);

    if(rc_himage[slot][rc_active_window] == NULL)
    {
        cout << "#CreateImage_Ex Error: " << SDL_GetError() << endl;
        SDL_FreeSurface(img_surf);
        SDL_FreeSurface(image_cv);
        SDL_DestroyTexture(rc_himage[slot][rc_active_window]);
        rc_himage[slot][rc_active_window] = NULL;
        return;
    }
    #else
    for(int i = 0; i < MAX_WINDOWS; i++)
    {
        SDL_DestroyTexture(rc_himage[slot][i]);
        rc_himage[slot][i] = SDL_CreateTextureFromSurface(rc_win_renderer[i], image_cv);
        SDL_SetTextureBlendMode(rc_himage[slot][i], SDL_BLENDMODE_BLEND);
    }
    if(rc_himage[slot][rc_active_window] == NULL)
    {
        cout << "#CreateImage_Ex Error: " << SDL_GetError() << endl;
        SDL_FreeSurface(img_surf);
        SDL_FreeSurface(image_cv);
        for(int j = 0; j < MAX_WINDOWS; j++)
        {
            SDL_DestroyTexture(rc_himage[slot][j]);
            rc_himage[slot][j] = NULL;
        }
        return;
    }
    #endif // RC_MOBILE
    rc_image_width[slot] = image_cv->w;
    rc_image_height[slot] = image_cv->h;
    rc_image_isLoaded[slot] = true;
    SDL_FreeSurface(img_surf);
    SDL_FreeSurface(image_cv);
}

void rc_media_bufferFromImage(int slot, double * pdata)
{
    SDL_Rect img_rect;
    img_rect.x = 0;
    img_rect.y = 0;
    img_rect.w = rc_image_width[slot];
    img_rect.h = rc_image_height[slot];

    //cout << "Debug data: " << img_rect.w << ", " << img_rect.h << endl;


    //SDL_RendererFlip rf = (SDL_RendererFlip)(SDL_FLIP_VERTICAL);

    SDL_Surface * tmp_surf = SDL_CreateRGBSurface(0, rc_image_width[slot], rc_image_height[slot], 32, 0, 0, 0, 0);
    SDL_Texture * tmp_tex = SDL_CreateTexture(rc_win_renderer[rc_active_window], rc_pformat->format, SDL_TEXTUREACCESS_TARGET, rc_image_width[slot], rc_image_height[slot]);
    SDL_SetRenderTarget(rc_win_renderer[rc_active_window],NULL);
    SDL_RenderCopy(rc_win_renderer[rc_active_window],rc_himage[slot][rc_active_window],NULL,&img_rect);
    //SDL_RenderCopyEx(rc_win_renderer[rc_active_window],rc_himage[slot][rc_active_window],NULL,NULL,0,NULL,rf);

    SDL_RenderReadPixels(rc_win_renderer[rc_active_window], &img_rect, rc_pformat->format,tmp_surf->pixels,tmp_surf->pitch);
    //cout << "Colorkey = " << (Uint32)r << ", " << (Uint32)g << ", " << (Uint32)b << ", " << (Uint32)a << endl;
    Uint32 * pxl = (Uint32*)tmp_surf->pixels;

    for(int y = 0; y < img_rect.h; y ++)
    {
        for(int x = 0; x < img_rect.w; x++)
        {
            pdata[y*img_rect.w+x] = pxl[y*img_rect.w+x];
        }
    }

    SDL_SetRenderTarget(rc_win_renderer[rc_active_window], rc_hscreen[rc_active_window][rc_active_screen]);
    SDL_DestroyTexture(tmp_tex);
    SDL_FreeSurface(tmp_surf);

}

#ifdef RC_IOS
void rc_media_colorKey_hw(int slot, double color)
{
    Uint32 c = (Uint32) color;
    //Uint8 r = c >> 16;
    //Uint8 g = c >> 8;
    //Uint8 b = c;
    //Uint8 a = c >> 24;
    //c = SDL_MapRGBA(rc_win_surface[0]->format,r,g,b,255);
    if(color > 0)
    {
        //return;
        SDL_RendererFlip rf = (SDL_RendererFlip)(SDL_FLIP_NONE);

        SDL_Surface * tmp_surf = SDL_CreateRGBSurface(0, rc_image_width[slot], rc_image_height[slot], 32, 0, 0, 0, 0);
        SDL_Texture * tmp_tex = SDL_CreateTexture(rc_win_renderer[rc_active_window], rc_pformat->format, SDL_TEXTUREACCESS_TARGET, rc_image_width[slot], rc_image_height[slot]);
        SDL_SetRenderTarget(rc_win_renderer[rc_active_window],tmp_tex);
        //SDL_RenderCopy(rc_win_renderer[rc_active_window],rc_himage[slot][rc_active_window],NULL,NULL);
        SDL_RenderCopyEx(rc_win_renderer[rc_active_window],rc_himage[slot][rc_active_window],NULL,NULL,0,NULL,rf);

        SDL_RenderReadPixels(rc_win_renderer[rc_active_window], NULL, rc_pformat->format,tmp_surf->pixels,tmp_surf->pitch);
        //cout << "Colorkey = " << (Uint32)r << ", " << (Uint32)g << ", " << (Uint32)b << ", " << (Uint32)a << endl;
        SDL_SetColorKey(tmp_surf,SDL_TRUE,c);

        for(int i = 0; i < MAX_WINDOWS; i++)
        {
            SDL_DestroyTexture(rc_himage[slot][i]);
            rc_himage[slot][i] = SDL_CreateTextureFromSurface(rc_win_renderer[i], tmp_surf);
        }
        SDL_SetRenderTarget(rc_win_renderer[rc_active_window], rc_hscreen[rc_active_window][rc_active_screen]);
        SDL_DestroyTexture(tmp_tex);
        SDL_FreeSurface(tmp_surf);
    }
    else
    {
        SDL_RendererFlip rf = (SDL_RendererFlip)(SDL_FLIP_NONE);

        SDL_Surface * tmp_surf = SDL_CreateRGBSurface(0, rc_image_width[slot], rc_image_height[slot], 32, 0, 0, 0, 0);
        //SDL_Surface * tmp_surf = SDL_ConvertSurfaceFormat(tmp_psurf, rc_pformat->format, 0);
        //SDL_FreeSurface(tmp_psurf);
        SDL_Texture * tmp_tex = SDL_CreateTexture(rc_win_renderer[rc_active_window], rc_pformat->format, SDL_TEXTUREACCESS_TARGET, rc_image_width[slot], rc_image_height[slot]);
        SDL_SetRenderTarget(rc_win_renderer[rc_active_window],tmp_tex);
        //SDL_RenderCopy(rc_win_renderer[rc_active_window],rc_himage[slot][rc_active_window],NULL,NULL);
        SDL_RenderCopyEx(rc_win_renderer[rc_active_window],rc_himage[slot][rc_active_window],NULL,NULL,0,NULL,rf);

        SDL_RenderReadPixels(rc_win_renderer[rc_active_window], NULL, rc_pformat->format,tmp_surf->pixels,tmp_surf->pitch);
        //cout << "Colorkey = " << (Uint32)r << ", " << (Uint32)g << ", " << (Uint32)b << ", " << (Uint32)a << endl;
        Uint32 * gcolor = (Uint32*)tmp_surf->pixels;
        c = gcolor[0];
        SDL_SetColorKey(tmp_surf,SDL_TRUE,c);

        for(int i = 0; i < MAX_WINDOWS; i++)
        {
            SDL_DestroyTexture(rc_himage[slot][i]);
            rc_himage[slot][i] = SDL_CreateTextureFromSurface(rc_win_renderer[i], tmp_surf);
        }
        SDL_SetRenderTarget(rc_win_renderer[rc_active_window], rc_hscreen[rc_active_window][rc_active_screen]);
        SDL_DestroyTexture(tmp_tex);
        SDL_FreeSurface(tmp_surf);
    }
}
#else
void rc_media_colorKey_hw(int slot, double color)
{
    Uint32 c = (Uint32) color;
    //Uint8 r = c >> 16;
    //Uint8 g = c >> 8;
    //Uint8 b = c;
    //Uint8 a = c >> 24;
    //c = SDL_MapRGBA(rc_win_surface[0]->format,r,g,b,255);
    SDL_Rect img_rect;
    img_rect.x = 0;
    img_rect.y = 0;
    img_rect.w = rc_image_width[slot];
    img_rect.h = rc_image_height[slot];
    if(color >= 0)
    {
        //return;
        //SDL_RendererFlip rf = (SDL_RendererFlip)(SDL_FLIP_VERTICAL);

        SDL_Surface * tmp_surf = SDL_CreateRGBSurface(0, rc_image_width[slot], rc_image_height[slot], 32, 0, 0, 0, 0);
        SDL_Texture * tmp_tex = SDL_CreateTexture(rc_win_renderer[rc_active_window], rc_pformat->format, SDL_TEXTUREACCESS_TARGET, rc_image_width[slot], rc_image_height[slot]);
        SDL_SetRenderTarget(rc_win_renderer[rc_active_window],NULL);
        SDL_RenderCopy(rc_win_renderer[rc_active_window],rc_himage[slot][rc_active_window],NULL,&img_rect);
        //SDL_RenderCopyEx(rc_win_renderer[rc_active_window],rc_himage[slot][rc_active_window],NULL,NULL,0,NULL,rf);

        SDL_RenderReadPixels(rc_win_renderer[rc_active_window], &img_rect, rc_pformat->format,tmp_surf->pixels,tmp_surf->pitch);
        //cout << "Colorkey = " << (Uint32)r << ", " << (Uint32)g << ", " << (Uint32)b << ", " << (Uint32)a << endl;
        rc_image_colorKey[slot] = c;
        rc_image_colorKey_r[slot] = c >> 16;
        rc_image_colorKey_g[slot] = c >> 8;
        rc_image_colorKey_b[slot] = c;
        rc_image_colorKey_a[slot] = c >> 24;

        SDL_SetColorKey(tmp_surf,SDL_TRUE,c);

        for(int i = 0; i < MAX_WINDOWS; i++)
        {
            SDL_DestroyTexture(rc_himage[slot][i]);
            rc_himage[slot][i] = SDL_CreateTextureFromSurface(rc_win_renderer[i], tmp_surf);
        }
        SDL_SetRenderTarget(rc_win_renderer[rc_active_window], rc_hscreen[rc_active_window][rc_active_screen]);
        SDL_DestroyTexture(tmp_tex);
        SDL_FreeSurface(tmp_surf);
    }
    else
    {
        //SDL_RendererFlip rf = (SDL_RendererFlip)(SDL_FLIP_VERTICAL);

        SDL_Surface * tmp_surf = SDL_CreateRGBSurface(0, rc_image_width[slot], rc_image_height[slot], 32, 0, 0, 0, 0);
        SDL_Texture * tmp_tex = SDL_CreateTexture(rc_win_renderer[rc_active_window], rc_pformat->format, SDL_TEXTUREACCESS_TARGET, rc_image_width[slot], rc_image_height[slot]);
        SDL_SetRenderTarget(rc_win_renderer[rc_active_window],NULL);
        SDL_RenderCopy(rc_win_renderer[rc_active_window],rc_himage[slot][rc_active_window],NULL,&img_rect);
        //SDL_RenderCopyEx(rc_win_renderer[rc_active_window],rc_himage[slot][rc_active_window],NULL,NULL,0,NULL,rf);

        SDL_RenderReadPixels(rc_win_renderer[rc_active_window], &img_rect, rc_pformat->format,tmp_surf->pixels,tmp_surf->pitch);
        //cout << "Colorkey = " << (Uint32)r << ", " << (Uint32)g << ", " << (Uint32)b << ", " << (Uint32)a << endl;
        Uint32 * pxl = (Uint32*)tmp_surf->pixels;
        c = pxl[0];
        rc_image_colorKey[slot] = c;
        rc_image_colorKey_r[slot] = c >> 16;
        rc_image_colorKey_g[slot] = c >> 8;
        rc_image_colorKey_b[slot] = c;
        rc_image_colorKey_a[slot] = c >> 24;
        SDL_SetColorKey(tmp_surf,SDL_TRUE,c);

        for(int i = 0; i < MAX_WINDOWS; i++)
        {
            SDL_DestroyTexture(rc_himage[slot][i]);
            rc_himage[slot][i] = SDL_CreateTextureFromSurface(rc_win_renderer[i], tmp_surf);
        }
        SDL_SetRenderTarget(rc_win_renderer[rc_active_window], rc_hscreen[rc_active_window][rc_active_screen]);
        SDL_DestroyTexture(tmp_tex);
        SDL_FreeSurface(tmp_surf);
    }
}
#endif //RC_IOS

void rc_media_deleteImage_hw(int slot)
{
    if(slot < 0 || slot >= MAX_IMAGES)
    {
        cout << "DeleteImage Error: Image Slot must be in the range of 0 to " << MAX_IMAGES-1 << endl;
        return;
    }
    for(int i = 0; i < MAX_WINDOWS; i++)
    {
        if(rc_himage[slot][i] == NULL)
            continue;
        SDL_DestroyTexture(rc_himage[slot][i]);
        rc_himage[slot][i] = NULL;
    }
    rc_image_isLoaded[slot] = false;
    rc_image_width[slot] = 0;
    rc_image_height[slot] = 0;
}

void rc_media_setImageAlpha_hw(int slot, Uint8 alpha)
{
    if(slot < 0 || slot >= MAX_IMAGES)
    {
        cout << "SetImageAlpha Error: Image Slot must be in the range of 0 to " << MAX_IMAGES-1 << endl;
        return;
    }
    if(rc_himage[slot][rc_active_window]==NULL)
    {
        cout << "SetImageAlpha Error: Image Slot is empty" << endl;
        return;
    }
    for(int i = 0; i < MAX_WINDOWS; i++)
    {
        if(rc_himage[slot][i] != NULL)
        {
            SDL_SetTextureAlphaMod(rc_himage[slot][i],alpha);
        }
    }
}

int rc_media_getImageAlpha_hw(int slot)
{
    if(slot < 0 || slot >= MAX_IMAGES)
    {
        cout << "GetImageAlpha Error: Image Slot must be in the range of 0 to " << MAX_IMAGES-1 << endl;
        return -1;
    }
    if(rc_himage[slot][rc_active_window]==NULL)
    {
        cout << "GetImageAlpha Error: Image Slot is empty" << endl;
        return -1;
    }
    Uint8 a = 0;
    SDL_GetTextureAlphaMod(rc_himage[slot][rc_active_window], &a);
    return a;
}

void rc_media_getImageSize_hw(int slot, double * w, double * h)
{
    if(slot < 0 || slot >= MAX_IMAGES)
    {
        cout << "GetImageSize Error: Image Slot must be in the range of 0 to " << MAX_IMAGES-1 << endl;
        return;
    }
    if(rc_himage[slot][rc_active_window]==NULL)
    {
        cout << "GetImageSize Error: Image Slot is empty" << endl;
        *w = 0;
        *h = 0;
        return;
    }
    Uint32 format = 0;
    int access = 0, width = 0, height = 0;
    SDL_QueryTexture(rc_himage[slot][rc_active_window], &format, &access, &width, &height);
    *w = width;
    *h = height;
}

int rc_media_setImageBlendMode_hw(int slot, int blend_mode)
{
    if(slot < 0 || slot >= MAX_IMAGES)
    {
        cout << "SetImageBlendMode Error: Image Slot must be in the range of 0 to " << MAX_IMAGES-1 << endl;
        return -1;
    }
    if(rc_himage[slot][rc_active_window]==NULL)
    {
        cout << "SetImageBlendMode Error: Image Slot is empty" << endl;
        return -1;
    }
    int rslt = -1;
    SDL_BlendMode b = SDL_BLENDMODE_NONE;
    switch(blend_mode)
    {
    case 0: //SDL_BLENDMODE_NONE
        b = SDL_BLENDMODE_NONE;
        break;
    case 1: //SDL_BLENDMODE_BLEND
        b = SDL_BLENDMODE_BLEND;
        break;
    case 2: //SDL_BLENDMODE_ADD
        b = SDL_BLENDMODE_ADD;
        break;
    case 4: //SDL_BLENDMODE_MOD
        b = SDL_BLENDMODE_MOD;
        break;
    default:
        return rslt;
    }
    for(int i = 0; i < MAX_WINDOWS; i++)
    {
        if(rc_himage[slot][i] != NULL)
        {

            rslt = SDL_SetTextureBlendMode(rc_himage[slot][i], b);
        }
    }
    return rslt;
}

int rc_media_imageBlendMode_hw(int slot)
{
    if(slot < 0 || slot >= MAX_IMAGES)
    {
        cout << "ImageBlendMode Error: Image Slot must be in the range of 0 to " << MAX_IMAGES-1 << endl;
        return -1;
    }
    if(rc_himage[slot][rc_active_window]==NULL)
    {
        cout << "ImageBlendMode Error: Image Slot is empty" << endl;
        return -1;
    }
    SDL_BlendMode blend_mode = SDL_BLENDMODE_NONE;
    int rslt = SDL_GetTextureBlendMode(rc_himage[slot][rc_active_window], &blend_mode);
    if(rslt < 0)
    {
        cout << "ImageBlendMode Error: " << SDL_GetError() << endl;
        return rslt;
    }
    return blend_mode;
}

int rc_media_setImageColorMod_hw(int slot, Uint32 c)
{
    if(slot < 0 || slot >= MAX_IMAGES)
    {
        cout << "SetImageColorMod Error: Image Slot must be in the range of 0 to " << MAX_IMAGES-1 << endl;
        return -1;
    }
    if(rc_himage[slot][rc_active_window]==NULL)
    {
        cout << "SetImageColorMod Error: Image Slot is empty" << endl;
        return -1;
    }
    int rslt = -1;

    Uint8 r = c>>16;
    Uint8 g = c>>8;
    Uint8 b = c;

    //cout << "C = " << c << endl;
    //cout << "RGB = " << (Uint32)r << ", " << (Uint32)g << ", " << (Uint32)b << endl;

    for(int i = 0; i < MAX_WINDOWS; i++)
    {
        if(rc_himage[slot][i] != NULL)
        {

            rslt = SDL_SetTextureColorMod(rc_himage[slot][i], r, g, b);
        }
    }
    return rslt;
}

int rc_media_imageColorMod_hw(int slot)
{
    if(slot < 0 || slot >= MAX_IMAGES)
    {
        cout << "ImageColorMod Error: Image Slot must be in the range of 0 to " << MAX_IMAGES-1 << endl;
        return -1;
    }
    if(rc_himage[slot][rc_active_window]==NULL)
    {
        cout << "ImageColorMod Error: Image Slot is empty" << endl;
        return -1;
    }

    Uint8 r = 0;
    Uint8 g = 0;
    Uint8 b = 0;
    int rslt = SDL_GetTextureColorMod(rc_himage[slot][rc_active_window], &r, &g, &b);

    if(rslt < 0)
    {
        cout << "ImageColorMode Error: " << SDL_GetError() << endl;
        return rslt;
    }

    Uint32 c_mod = (Uint32)SDL_MapRGBA(rc_pformat,r,g,b,255);

    //cout << "-RGB = " << (int)r << ", " << (int)g << ", " << (int)b << endl;

    return c_mod;
}

void rc_media_copyImage_hw(int src_slot, int dst_slot)
{
    //return;
    if(src_slot < 0 || src_slot >= MAX_IMAGES || dst_slot < 0 || dst_slot >= MAX_IMAGES)
    {
        cout << "CopyImage Error: Image Slot should be in the range of 0 to " << MAX_IMAGES-1 << endl;
        return;
    }
    if(rc_himage[src_slot][rc_active_window]!=NULL && rc_himage[dst_slot][rc_active_window]==NULL)
    {
        //rc_simage[dst_slot] = SDL_ConvertSurface(rc_simage[src_slot], rc_simage[src_slot]->format, 0);
        SDL_Surface * tmp_surf = SDL_CreateRGBSurface(0, rc_image_width[src_slot], rc_image_height[src_slot], 32, 0, 0, 0, 0);
        SDL_Texture * tmp_tex = SDL_CreateTexture(rc_win_renderer[rc_active_window], tmp_surf->format->format, SDL_TEXTUREACCESS_TARGET, tmp_surf->w, tmp_surf->h);
        SDL_SetRenderTarget(rc_win_renderer[rc_active_window], tmp_tex);
        SDL_RendererFlip rf = SDL_FLIP_NONE;
        SDL_RenderCopyEx(rc_win_renderer[rc_active_window],rc_himage[src_slot][rc_active_window],NULL,NULL,0,NULL,rf);
        SDL_RenderReadPixels(rc_win_renderer[rc_active_window],NULL,tmp_surf->format->format,tmp_surf->pixels,tmp_surf->pitch);
        for(int i = 0; i < MAX_WINDOWS; i++)
        {
            if(rc_himage[dst_slot][i] != NULL)
            {
                //cout << "slot " << dst_slot << "   win " << i << endl;
                SDL_DestroyTexture(rc_himage[dst_slot][i]);
                rc_himage[dst_slot][i] = NULL;
            }
            rc_himage[dst_slot][i] = SDL_CreateTextureFromSurface(rc_win_renderer[rc_active_window],tmp_surf);
        }
        rc_image_width[dst_slot] = tmp_surf->w;
        rc_image_height[dst_slot] = tmp_surf->h;
        SDL_FreeSurface(tmp_surf);
        SDL_DestroyTexture(tmp_tex);
        SDL_SetRenderTarget(rc_win_renderer[rc_active_window],rc_hscreen[rc_active_window][rc_active_screen]);
        rc_image_isLoaded[dst_slot] = true;
    }
    else
    {
        cout << "CopyImage Error: Image slot could not be used" << endl;
        return;
    }
}

void rc_media_rotateImage_hw(int slot, int x, int y, double degrees)
{
    //double PI = 3.14159265359;
    //double angle = degrees * PI/180;
    //double theta = SDL_acos(rc_simage[0]->w/2+angle);
    SDL_Rect dst;
    dst.x = x;
    dst.y = y;
    dst.w = rc_image_width[slot];
    dst.h = rc_image_height[slot];
    SDL_RendererFlip rf = SDL_FLIP_NONE;
    SDL_RenderCopyEx(rc_win_renderer[rc_active_window], rc_himage[slot][rc_active_window], NULL, &dst, degrees, NULL, rf);
}

void rc_media_rotateImageEX_hw(int slot, int x, int y, int src_x, int src_y, int src_w, int src_h, double degrees)
{
    //double PI = 3.14159265359;
    //double angle = degrees * PI/180;
    //double theta = SDL_acos(rc_simage[0]->w/2+angle);
    SDL_RendererFlip rf = SDL_FLIP_NONE;
    SDL_Rect c_rect;
    c_rect.x = src_x;
    c_rect.y = src_y;
    c_rect.w = src_w;
    c_rect.h = src_h;
    SDL_Rect dst;
    dst.x = x;
    dst.y = y;
    dst.w = src_w;
    dst.h = src_h;
    SDL_RenderCopyEx(rc_win_renderer[rc_active_window],rc_himage[slot][rc_active_window],&c_rect, &dst,degrees,NULL,rf);
}


void rc_media_zoomImage_hw(int slot, int x, int y, double zoom_x, double zoom_y)
{
    SDL_Rect dst;
    dst.x = x;
    dst.y = y;
    dst.w = rc_image_width[slot] * zoom_x;
    dst.h = rc_image_height[slot] * zoom_y;
    SDL_RenderCopy(rc_win_renderer[rc_active_window], rc_himage[slot][rc_active_window], NULL, &dst);
}

void rc_media_zoomImageEX_hw(int slot, int x, int y, int src_x, int src_y, int src_w, int src_h, double zoom_x, double zoom_y)
{
    int zw = src_w * zoom_x;
    int zh = src_h * zoom_y;
    int ax = src_w/2 - zw/2, ay = src_h/2 - zh/2;
    SDL_Rect r;
    r.x = x+ax; r.y = y+ay;
    r.w = zw; r.h = zh;
    SDL_Rect s_rect;
    s_rect.x = src_x;
    s_rect.y = src_y;
    s_rect.w = src_w;
    s_rect.h = src_h;
    SDL_RendererFlip rf = SDL_FLIP_NONE;
    SDL_RenderCopyEx(rc_win_renderer[rc_active_window],rc_himage[slot][rc_active_window],&s_rect,&r,0,NULL,rf);
}

void rc_media_rotozoomImage_hw(int slot, int x, int y, float degrees, float zoom_x, float zoom_y)
{
    SDL_Rect dst;
    dst.x = x;
    dst.y = y;
    dst.w = rc_image_width[slot] * zoom_x;
    dst.h = rc_image_height[slot] * zoom_y;
    SDL_RendererFlip rf = SDL_FLIP_NONE;
    SDL_RenderCopyEx(rc_win_renderer[rc_active_window],rc_himage[slot][rc_active_window],NULL,&dst,degrees,NULL,rf);
}

void rc_media_rotozoomImageEX_hw(int slot, int x, int y, int src_x, int src_y, int src_w, int src_h, float degrees, float zoom_x, float zoom_y)
{
    //cout << "src w,h = " << src_w << ", " << src_h << endl;
    SDL_Rect src, dst;
    src.x = src_x;
    src.y = src_y;
    src.w = src_w;
    src.h = src_h;
    dst.x = x;
    dst.y = y;
    dst.w = src_w * zoom_x;
    dst.h = src_h * zoom_y;
    SDL_RendererFlip rf = SDL_FLIP_NONE;
    SDL_RenderCopyEx(rc_win_renderer[rc_active_window],rc_himage[slot][rc_active_window],&src,&dst,degrees,NULL,rf);
}

void rc_media_MirrorImage_hw(int slot, Uint8 flipH, Uint8 flipV)
{
    SDL_RendererFlip rf = SDL_FLIP_NONE;
    if(flipH!=0)
        rf = (SDL_RendererFlip)(rf | SDL_FLIP_HORIZONTAL);
    if(flipV!=0)
        rf = (SDL_RendererFlip)(rf | SDL_FLIP_VERTICAL);
    SDL_Surface * m_surf = SDL_CreateRGBSurface(0, rc_image_width[slot], rc_image_height[slot], 32, 0, 0, 0, 0);
    SDL_Texture * m_tex = SDL_CreateTexture(rc_win_renderer[rc_active_window], m_surf->format->format,SDL_TEXTUREACCESS_TARGET,rc_image_width[slot],rc_image_height[slot]);
    SDL_SetRenderTarget(rc_win_renderer[rc_active_window],m_tex);
    SDL_RenderCopyEx(rc_win_renderer[rc_active_window],rc_himage[slot][rc_active_window],NULL,NULL,0,NULL,rf);
    SDL_RenderReadPixels(rc_win_renderer[rc_active_window],NULL,m_surf->format->format,m_surf->pixels,m_surf->pitch);
    for(int i = 0; i < MAX_WINDOWS; i++)
    {
        if(rc_win[i]!=NULL)
        {
            SDL_DestroyTexture(rc_himage[slot][i]);
            rc_himage[slot][i] = SDL_CreateTextureFromSurface(rc_win_renderer[i],m_surf);
        }
    }
    SDL_DestroyTexture(m_tex);
    SDL_FreeSurface(m_surf);
    SDL_SetRenderTarget(rc_win_renderer[rc_active_window],rc_hscreen[rc_active_window][rc_active_screen]);
}

void rc_media_drawImage_hw(int slot, int x, int y)
{
    if(slot >= 0 && slot < MAX_IMAGES)
    {
        if(rc_hscreen[rc_active_window][rc_active_screen] ==  NULL)
        {
            cout << "DrawImage Error: Canvas #" << slot << " does not exist" << endl;
            return;
        }
        SDL_Rect img_pos;
        img_pos.x = x;
        img_pos.y = y;
        img_pos.w = rc_image_width[slot];
        img_pos.h = rc_image_height[slot];

        if(SDL_RenderCopy(rc_win_renderer[rc_active_window],rc_himage[slot][rc_active_window],NULL,&img_pos) < 0)
            cout << "DrawImage error: " << SDL_GetError() << endl;

    }
}

void rc_media_drawImage_Flip(int slot, int x, int y, int flipH, int flipV)
{
    SDL_RendererFlip rf = SDL_FLIP_NONE;
    if(flipH!=0)
        rf = (SDL_RendererFlip)(rf | SDL_FLIP_HORIZONTAL);
    if(flipV!=0)
        rf = (SDL_RendererFlip)(rf | SDL_FLIP_VERTICAL);

    SDL_Rect dst;
    dst.x = x;
    dst.y = y;
    dst.w = rc_image_width[slot];
    dst.h = rc_image_height[slot];

    SDL_RenderCopyEx(rc_win_renderer[rc_active_window],rc_himage[slot][rc_active_window], NULL, &dst, 0, NULL, rf);
}

void rc_media_drawImage_Flip_Ex(int slot, int x, int y, int src_x, int src_y, int src_w, int src_h, int flipH, int flipV)
{
    SDL_RendererFlip rf = SDL_FLIP_NONE;
    if(flipH!=0)
        rf = (SDL_RendererFlip)(rf | SDL_FLIP_HORIZONTAL);
    if(flipV!=0)
        rf = (SDL_RendererFlip)(rf | SDL_FLIP_VERTICAL);

    SDL_Rect dst;
    dst.x = x;
    dst.y = y;
    dst.w = rc_image_width[slot];
    dst.h = rc_image_height[slot];

    SDL_Rect src;
    src.x = src_x;
    src.y = src_y;
    src.w = src_w;
    src.h = src_h;

    SDL_RenderCopyEx(rc_win_renderer[rc_active_window],rc_himage[slot][rc_active_window], &src, &dst, 0, NULL, rf);
}

void rc_media_drawImage_Clip_hw(int slot, int x, int y, int src_x, int src_y, int src_w, int src_h)
{
    SDL_Rect src, dst;
    src.x = src_x;
    src.y = src_y;
    src.w = src_w;
    src.h = src_h;
    dst.x = x;
    dst.y = y;
    dst.w = src_w;
    dst.h = src_h;
    SDL_RenderCopy(rc_win_renderer[rc_active_window], rc_himage[slot][rc_active_window], &src, &dst);
}

void rc_media_drawImage_Blit_hw(int slot, int screen_x, int screen_y, int scale_w, int scale_h, int src_x, int src_y, int src_w, int src_h)
{
    SDL_Rect src, dst;
    src.x = src_x;
    src.y = src_y;
    src.w = src_w;
    src.h = src_h;
    dst.x = screen_x;
    dst.y = screen_y;
    dst.w = scale_w;
    dst.h = scale_h;
    SDL_RenderCopy(rc_win_renderer[rc_active_window], rc_himage[slot][rc_active_window], &src, &dst);
}

void rc_media_drawImage_Transform(int slot, int x, int y, int w, int h, int src_x, int src_y, int src_w, int src_h, double angle, int center_x, int center_y, int flipH, int flipV)
{
    SDL_RendererFlip rf = SDL_FLIP_NONE;
    if(flipH!=0)
        rf = (SDL_RendererFlip)(rf | SDL_FLIP_HORIZONTAL);
    if(flipV!=0)
        rf = (SDL_RendererFlip)(rf | SDL_FLIP_VERTICAL);

    SDL_Rect dst;
    dst.x = x;
    dst.y = y;
    dst.w = w;
    dst.h = h;

    SDL_Rect src;
    src.x = src_x;
    src.y = src_y;
    src.w = src_w;
    src.h = src_h;

    SDL_Point center;
    center.x = center_x;
    center.y = center_y;

    SDL_RenderCopyEx(rc_win_renderer[rc_active_window],rc_himage[slot][rc_active_window], &src, &dst, angle, &center, rf);
}

int SaveBMP(int slot, string file)
{
    SDL_Rect img_rect;
    img_rect.x = 0;
    img_rect.y = 0;
    img_rect.w = rc_image_width[slot];
    img_rect.h = rc_image_height[slot];

    //cout << "Debug data: " << img_rect.w << ", " << img_rect.h << endl;


    //SDL_RendererFlip rf = (SDL_RendererFlip)(SDL_FLIP_VERTICAL);

    SDL_Surface * tmp_surf = SDL_CreateRGBSurface(0, rc_image_width[slot], rc_image_height[slot], 32, 0, 0, 0, 0);
    SDL_Texture * tmp_tex = SDL_CreateTexture(rc_win_renderer[rc_active_window], rc_pformat->format, SDL_TEXTUREACCESS_TARGET, rc_image_width[slot], rc_image_height[slot]);
    SDL_SetRenderTarget(rc_win_renderer[rc_active_window],NULL);
    SDL_RenderCopy(rc_win_renderer[rc_active_window],rc_himage[slot][rc_active_window],NULL,&img_rect);
    //SDL_RenderCopyEx(rc_win_renderer[rc_active_window],rc_himage[slot][rc_active_window],NULL,NULL,0,NULL,rf);

    SDL_RenderReadPixels(rc_win_renderer[rc_active_window], &img_rect, rc_pformat->format,tmp_surf->pixels,tmp_surf->pitch);

    if(rc_active_screen >= 0 && rc_active_screen < MAX_SCREENS)
        SDL_SetRenderTarget(rc_win_renderer[rc_active_window], rc_hscreen[rc_active_window][rc_active_screen]);

    SDL_DestroyTexture(tmp_tex);

    int ret_val = SDL_SaveBMP(tmp_surf, file.c_str());
    SDL_FreeSurface(tmp_surf);

    return ret_val;
}

int SavePNG(int slot, string file)
{
    SDL_Rect img_rect;
    img_rect.x = 0;
    img_rect.y = 0;
    img_rect.w = rc_image_width[slot];
    img_rect.h = rc_image_height[slot];

    //cout << "Debug data: " << img_rect.w << ", " << img_rect.h << endl;


    //SDL_RendererFlip rf = (SDL_RendererFlip)(SDL_FLIP_VERTICAL);

    SDL_Surface * tmp_surf = SDL_CreateRGBSurface(0, rc_image_width[slot], rc_image_height[slot], 32, 0, 0, 0, 0);
    SDL_Texture * tmp_tex = SDL_CreateTexture(rc_win_renderer[rc_active_window], rc_pformat->format, SDL_TEXTUREACCESS_TARGET, rc_image_width[slot], rc_image_height[slot]);
    SDL_SetRenderTarget(rc_win_renderer[rc_active_window],NULL);
    SDL_RenderCopy(rc_win_renderer[rc_active_window],rc_himage[slot][rc_active_window],NULL,&img_rect);
    //SDL_RenderCopyEx(rc_win_renderer[rc_active_window],rc_himage[slot][rc_active_window],NULL,NULL,0,NULL,rf);

    SDL_RenderReadPixels(rc_win_renderer[rc_active_window], &img_rect, rc_pformat->format,tmp_surf->pixels,tmp_surf->pitch);

    if(rc_active_screen >= 0 && rc_active_screen < MAX_SCREENS)
        SDL_SetRenderTarget(rc_win_renderer[rc_active_window], rc_hscreen[rc_active_window][rc_active_screen]);

    SDL_DestroyTexture(tmp_tex);

    int ret_val = IMG_SavePNG(tmp_surf, file.c_str());
    SDL_FreeSurface(tmp_surf);

    return ret_val;
}

int SaveJPG(int slot, string file)
{
    SDL_Rect img_rect;
    img_rect.x = 0;
    img_rect.y = 0;
    img_rect.w = rc_image_width[slot];
    img_rect.h = rc_image_height[slot];

    //cout << "Debug data: " << img_rect.w << ", " << img_rect.h << endl;


    //SDL_RendererFlip rf = (SDL_RendererFlip)(SDL_FLIP_VERTICAL);

    SDL_Surface * tmp_surf = SDL_CreateRGBSurface(0, rc_image_width[slot], rc_image_height[slot], 32, 0, 0, 0, 0);
    SDL_Texture * tmp_tex = SDL_CreateTexture(rc_win_renderer[rc_active_window], rc_pformat->format, SDL_TEXTUREACCESS_TARGET, rc_image_width[slot], rc_image_height[slot]);
    SDL_SetRenderTarget(rc_win_renderer[rc_active_window],NULL);
    SDL_RenderCopy(rc_win_renderer[rc_active_window],rc_himage[slot][rc_active_window],NULL,&img_rect);
    //SDL_RenderCopyEx(rc_win_renderer[rc_active_window],rc_himage[slot][rc_active_window],NULL,NULL,0,NULL,rf);

    SDL_RenderReadPixels(rc_win_renderer[rc_active_window], &img_rect, rc_pformat->format,tmp_surf->pixels,tmp_surf->pitch);

    if(rc_active_screen >= 0 && rc_active_screen < MAX_SCREENS)
        SDL_SetRenderTarget(rc_win_renderer[rc_active_window], rc_hscreen[rc_active_window][rc_active_screen]);

    SDL_DestroyTexture(tmp_tex);

    int ret_val = IMG_SaveJPG(tmp_surf, file.c_str(), 100);
    SDL_FreeSurface(tmp_surf);

    return ret_val;
}


#ifdef RC_WEB
int rc_media_drawGeometry(int slot, int num_vertices, double* vertices, int num_indices, double* indices)
{
    return 0;
}
#else
int rc_media_drawGeometry(int slot, int num_vertices, double* vertices, int num_indices, double* indices)
{
    SDL_Vertex geo_vert[( num_vertices >= 1 ? num_vertices : 1)];

    int vert_size = 8;

    for(int i = 0; i < num_vertices; i++)
    {
        geo_vert[i].position.x = vertices[i*vert_size+0];
        geo_vert[i].position.y = vertices[i*vert_size+1];
        geo_vert[i].color.r = (Uint8)vertices[i*vert_size+2];
        geo_vert[i].color.g = (Uint8)vertices[i*vert_size+3];
        geo_vert[i].color.b = (Uint8)vertices[i*vert_size+4];
        geo_vert[i].color.a = (Uint8)vertices[i*vert_size+5];
        geo_vert[i].tex_coord.x = vertices[i*vert_size+6];
        geo_vert[i].tex_coord.y = vertices[i*vert_size+7];
    }

    int geo_index[(num_indices <= 0 ? 1 : num_indices)];

    for(int i = 0; i < num_indices; i++)
    {
        geo_index[i] = (int) indices[i];
    }

    return SDL_RenderGeometry(rc_win_renderer[rc_active_window],
                              (slot >= 0 ? rc_himage[slot][rc_active_window] : NULL),
                              geo_vert, num_vertices,
                              (num_indices <= 0 ? NULL : geo_index), num_indices);
}
#endif //RC_WEB

void rc_media_getCursor(double * x, double * y)
{
    *x = rc_sConsole_x[rc_active_window];
    *y = rc_sConsole_y[rc_active_window];
}

void rc_media_showCursor()
{
    rc_cursor_visible = 1;
}

void rc_media_hideCursor()
{
    rc_cursor_visible = 0;
}

void rc_media_locate(int x, int y)
{
    rc_sConsole_x[rc_active_window] = x;
    rc_sConsole_y[rc_active_window] = y;
}

string rc_fillSpace(int n)
{
    string s = "";
    for(int i = 0; i < n; i++)
        s.append(" ");
    return s;
}

void rc_append_sConsole(string txt)
{
    string tc = txt;
    string t_out[rc_console_height[rc_active_window]];

    int i = 0;

    if(rc_sConsole_x[rc_active_window] >= rc_console_width[rc_active_window])
        rc_sConsole_x[rc_active_window] = 0;

    while(tc.compare("")!=0)
    {
        if(tc.substr(i).length() > ( rc_console_width[rc_active_window] - rc_sConsole_x[rc_active_window]) )
        {
            t_out[i] = rc_fillSpace(rc_sConsole_x[rc_active_window]) + tc.substr(i, rc_console_width[rc_active_window] - rc_sConsole_x[rc_active_window]);
            rc_sConsole_x[rc_active_window] = 0;
            tc = tc.substr( (rc_console_width[rc_active_window] - rc_sConsole_x[rc_active_window]) );
            i++;
        }
        else
        {
            t_out[i] = rc_fillSpace(rc_sConsole_x[rc_active_window]) + tc;
            rc_sConsole_x[rc_active_window] = 0;
            i++;
            break;
        }
    }

    rc_sConsole_y[rc_active_window] += i;
}

#ifdef RC_MOBILE
void rc_media_cls()
{
    if(rc_winCheck(rc_active_window))
    {
        SDL_SetRenderTarget(rc_win_renderer[rc_active_window], rc_backBuffer[rc_active_window]);
        SDL_SetRenderDrawColor(rc_win_renderer[rc_active_window], rc_clearColor>>16, rc_clearColor>>8, rc_clearColor, rc_clearColor>>24);
        SDL_RenderClear(rc_win_renderer[rc_active_window]);

        SDL_SetRenderTarget(rc_win_renderer[rc_active_window], rc_hconsole[rc_active_window]);
        SDL_SetRenderDrawColor(rc_win_renderer[rc_active_window], 0, 0, 0, 0);
        SDL_RenderClear(rc_win_renderer[rc_active_window]);

        SDL_SetRenderTarget(rc_win_renderer[rc_active_window], NULL);
        SDL_SetRenderDrawColor(rc_win_renderer[rc_active_window], rc_clearColor>>16, rc_clearColor>>8, rc_clearColor, rc_clearColor>>24);
        SDL_RenderClear(rc_win_renderer[rc_active_window]);

        if(rc_active_screen >= 0)
            SDL_SetRenderTarget(rc_win_renderer[rc_active_window], rc_hscreen[rc_active_window][rc_active_screen]);
        rc_media_ink(rc_ink);
    }
}

void rc_media_printS_hw(string txt)
{
    SDL_SetRenderTarget(rc_win_renderer[rc_active_window], rc_hconsole[rc_active_window]);

    string tc = txt;
    string t_out[rc_console_height[rc_active_window]];

    int i = 0;

    if(rc_sConsole_x[rc_active_window] >= rc_console_width[rc_active_window])
        rc_sConsole_x[rc_active_window] = 0;

    while(tc.compare("")!=0)
    {
        if(tc.substr(i).length() > ( rc_console_width[rc_active_window] - rc_sConsole_x[rc_active_window]) )
        {
            t_out[i] = rc_fillSpace(rc_sConsole_x[rc_active_window]) + tc.substr(i, rc_console_width[rc_active_window] - rc_sConsole_x[rc_active_window]);
            rc_sConsole_x[rc_active_window] = 0;
            tc = tc.substr( (rc_console_width[rc_active_window] - rc_sConsole_x[rc_active_window]) );
            i++;
        }
        else
        {
            t_out[i] = rc_fillSpace(rc_sConsole_x[rc_active_window]) + tc;
            rc_sConsole_x[rc_active_window] = 0;
            i++;
            break;
        }
    }

    for(int n = 0; n < i; n++)
        stringRGBA(rc_win_renderer[rc_active_window], 0, (rc_sConsole_y[rc_active_window] + n) * 8, t_out[n].c_str(), rc_ink_color.r, rc_ink_color.g, rc_ink_color.b, rc_ink_color.a);

    rc_sConsole_y[rc_active_window] += i;

    SDL_SetRenderTarget(rc_win_renderer[rc_active_window], NULL);
    SDL_RenderCopy(rc_win_renderer[rc_active_window],rc_hconsole[rc_active_window],NULL,NULL);

    SDL_RenderPresent(rc_win_renderer[rc_active_window]);

    if(rc_active_screen >= 0)
    	SDL_SetRenderTarget(rc_win_renderer[rc_active_window], rc_hscreen[rc_active_window][rc_active_screen]);
    return;
}

string rc_media_inputS_hw(string prompt)
{
    SDL_Surface * input_surface = NULL;
    SDL_Texture * input_texture = NULL;
    bool loop = true;
    SDL_Event in_evt;
    string in_buf = prompt;
    string rtn_string = "";
    string tc = in_buf;
    string t_out[rc_console_height[rc_active_window]];
    int i = 0;
    SDL_Rect first_line, sub_line;
    first_line.x = (rc_sConsole_x[rc_active_window] * 8) + (prompt.length()*8);
    first_line.y = rc_sConsole_y[rc_active_window] * 8;
    first_line.w = 0;
    first_line.h = 8;
    sub_line.x = 0;
    sub_line.y = (rc_sConsole_y[rc_active_window]+1) * 8;
    sub_line.w = 0;
    sub_line.h = 8;
    SDL_SetRenderTarget(rc_win_renderer[rc_active_window], rc_hconsole[rc_active_window]);
    SDL_Rect txt_rect;
    txt_rect = first_line;
    txt_rect.w = 128;
    txt_rect.h = 128;
    //SDL_SetTextInputRect(&txt_rect);

    SDL_StartTextInput();

    while(loop)
    {
        while(SDL_PollEvent(&in_evt))
        {
            switch(in_evt.type)
            {
                case SDL_TEXTINPUT:
                    in_buf += in_evt.text.text;
                    break;
                case SDL_KEYDOWN:
                    switch(in_evt.key.keysym.sym)
                    {
                        case SDLK_RETURN:
                            loop = false;
                            break;
                        case SDLK_BACKSPACE:
                            if(in_buf.length()-1 >= prompt.length() && in_buf.length()-1 >= 0)
                                in_buf = in_buf.substr(0, in_buf.length()-1);
                            break;
                    }
            }
        }
        if(in_buf.length()>0)
        {
        	SDL_SetRenderTarget(rc_win_renderer[rc_active_window],rc_hconsole[rc_active_window]);
            tc = in_buf;
            i = 0;
            int x = rc_sConsole_x[rc_active_window];
            if(x >= rc_console_width[rc_active_window])
                x = 0;

            while(tc.compare("")!=0)
            {
                if(tc.length() > ( rc_console_width[rc_active_window] - x) )
                {
                    t_out[i] = rc_fillSpace(x) + tc.substr(0, rc_console_width[rc_active_window] - x);
                    if(i == 0 && ((t_out[i].length() - prompt.length() - x)*8) > first_line.w)
                    {
                        first_line.w = (t_out[i].length() - prompt.length() - x) * 8;
                    }
                    else if(i != 0 && (t_out[i].length() * 8) > sub_line.w)
                    {
                        sub_line.w = t_out[i].length() * 8;
                    }
                    tc = tc.substr( (rc_console_width[rc_active_window] - x) );
                    x = 0;
                    i++;
                }
                else
                {
                    t_out[i] = rc_fillSpace(x) + tc;
                    if(i == 0 && ((t_out[i].length() - prompt.length() - x)*8) > first_line.w)
                    {
                        first_line.w = (t_out[i].length() - prompt.length() - x) * 8;
                    }
                    else if(i != 0 && (t_out[i].length() * 8) > sub_line.w)
                    {
                        sub_line.w = t_out[i].length() * 8;
                    }
                    x = 0;
                    i++;
                    break;
                }
                if(i >= rc_console_height[rc_active_window])
                    break;
            }

            SDL_SetRenderDrawColor(rc_win_renderer[rc_active_window], rc_clearColor>>16, rc_clearColor>>8, rc_clearColor, 255);
            SDL_RenderFillRect(rc_win_renderer[rc_active_window], &first_line);

            if(((i-1)*8) > sub_line.h)
                sub_line.h = i*8;

            if(sub_line.h > 0)
                SDL_RenderFillRect(rc_win_renderer[rc_active_window], &sub_line);

            SDL_SetRenderDrawColor(rc_win_renderer[rc_active_window], rc_ink_color.r, rc_ink_color.g, rc_ink_color.b, rc_ink_color.a);

            for(int n = 0; n < i; n++)
            {
                stringRGBA(rc_win_renderer[rc_active_window], 0, (rc_sConsole_y[rc_active_window] + n) * 8, t_out[n].c_str(), rc_ink_color.r, rc_ink_color.g, rc_ink_color.b, 255);//rc_ink_color.a);
            }
            SDL_SetRenderTarget(rc_win_renderer[rc_active_window],NULL);
            SDL_RenderCopy(rc_win_renderer[rc_active_window],rc_hconsole[rc_active_window],NULL,NULL);
            SDL_RenderPresent(rc_win_renderer[rc_active_window]);
        }
    }
    SDL_StopTextInput();
    rc_sConsole_y[rc_active_window] += i;
    rc_sConsole_x[rc_active_window] = 0;
    if(rc_active_screen >= 0)
    	SDL_SetRenderTarget(rc_win_renderer[rc_active_window],rc_hscreen[rc_active_window][rc_active_screen]);
    return in_buf.substr(prompt.length());
}

string rc_media_ZoneInputS_hw(int x, int y, int w, int h)
{
    SDL_Surface * input_surface = NULL;
    SDL_Texture * input_texture = NULL;
    bool loop = true;
    SDL_Event in_evt;
    string in_buf = "";
    string rtn_string = "";
    string tc = "";
    string t_out[rc_console_height[rc_active_window]];
    int i = 0;
    SDL_Rect zone;
    zone.x = x;
    zone.y = y;
    zone.w = w;
    zone.h = h;
    SDL_SetRenderTarget(rc_win_renderer[rc_active_window], rc_hconsole[rc_active_window]);
    SDL_StartTextInput();
    while(loop)
    {
        if(SDL_PollEvent(&in_evt))
        {
            switch(in_evt.type)
            {
                case SDL_TEXTINPUT:
                    in_buf += in_evt.text.text;
                    break;
                case SDL_KEYDOWN:
                    switch(in_evt.key.keysym.sym)
                    {
                        case SDLK_RETURN:
                            loop = false;
                            break;
                        case SDLK_BACKSPACE:
                            if(in_buf.length()-1 >= 0)
                                in_buf = in_buf.substr(0, in_buf.length()-1);
                            break;
                    }
            }
        }
        if(in_buf.length()>=0)
        {
            tc = in_buf;
            i = 0;

            while(tc.compare("")!=0)
            {
                if(tc.length() > (w/8) )
                {
                    t_out[i] = tc.substr(0, (w/8) );
                    tc = tc.substr( w/8 );
                    i++;
                }
                else
                {
                    t_out[i] = tc;
                    i++;
                    break;
                }

                if(i >= rc_console_height[rc_active_window])
                    break;
            }

            SDL_SetRenderTarget(rc_win_renderer[rc_active_window], rc_hconsole[rc_active_window]);
            SDL_SetRenderDrawColor(rc_win_renderer[rc_active_window], rc_clearColor>>16, rc_clearColor>>8, rc_clearColor, rc_clearColor>>24);
            SDL_RenderFillRect(rc_win_renderer[rc_active_window], &zone);

            //cout << "zone txt color = " << (int)rc_ink_color.r << ", " << (int)rc_ink_color.g << ", " << (int)rc_ink_color.b << ", " << (int)rc_ink_color.a << endl;

            SDL_SetRenderDrawColor(rc_win_renderer[rc_active_window], rc_ink_color.r, rc_ink_color.g, rc_ink_color.b, rc_ink_color.a);

            //cout << "n < " << (int) (h/8) << endl;

            for(int n = 0; n < (h/8) && n < i; n++)
            {
                stringRGBA(rc_win_renderer[rc_active_window], x, y + (n * 8), t_out[n].c_str(), rc_ink_color.r, rc_ink_color.g, rc_ink_color.b, rc_ink_color.a);
            }

            SDL_SetRenderTarget(rc_win_renderer[rc_active_window], NULL);
            SDL_RenderCopy(rc_win_renderer[rc_active_window], rc_hconsole[rc_active_window], NULL, NULL);
            SDL_RenderPresent(rc_win_renderer[rc_active_window]);
        }
    }
    SDL_StopTextInput();
    if(rc_active_screen >= 0)
        SDL_SetRenderTarget(rc_win_renderer[rc_active_window],rc_hscreen[rc_active_window][rc_active_screen]);
    return in_buf;
}
#else

void rc_media_cls()
{
    if(rc_winCheck(rc_active_window))
    {
        SDL_SetRenderTarget(rc_win_renderer[rc_active_window], rc_hconsole[rc_active_window]);
        SDL_SetRenderDrawColor(rc_win_renderer[rc_active_window], 0, 0, 0, 0);
        SDL_RenderClear(rc_win_renderer[rc_active_window]);

        SDL_SetRenderTarget(rc_win_renderer[rc_active_window], NULL);
        SDL_SetRenderDrawColor(rc_win_renderer[rc_active_window], rc_clearColor>>16, rc_clearColor>>8, rc_clearColor, rc_clearColor>>24);
        SDL_RenderClear(rc_win_renderer[rc_active_window]);

        if(rc_active_screen >= 0)
            SDL_SetRenderTarget(rc_win_renderer[rc_active_window], rc_hscreen[rc_active_window][rc_active_screen]);
        rc_media_ink(rc_ink);
    }
}

void rc_media_printS_hw(string txt)
{
    if(rc_active_window < 0)
        return;

    SDL_SetRenderTarget(rc_win_renderer[rc_active_window], rc_hconsole[rc_active_window]);

    string tc = txt;
    string t_out[rc_console_height[rc_active_window]];

    int i = 0;

    if(rc_sConsole_x[rc_active_window] >= rc_console_width[rc_active_window])
        rc_sConsole_x[rc_active_window] = 0;

    while(tc.compare("")!=0)
    {
        if(tc.substr(i).length() > ( rc_console_width[rc_active_window] - rc_sConsole_x[rc_active_window]) )
        {
            t_out[i] = rc_fillSpace(rc_sConsole_x[rc_active_window]) + tc.substr(i, rc_console_width[rc_active_window] - rc_sConsole_x[rc_active_window]);
            rc_sConsole_x[rc_active_window] = 0;
            tc = tc.substr( (rc_console_width[rc_active_window] - rc_sConsole_x[rc_active_window]) );
            i++;
        }
        else
        {
            t_out[i] = rc_fillSpace(rc_sConsole_x[rc_active_window]) + tc;
            rc_sConsole_x[rc_active_window] = 0;
            i++;
            break;
        }
    }

    for(int n = 0; n < i; n++)
        stringRGBA(rc_win_renderer[rc_active_window], 0, (rc_sConsole_y[rc_active_window] + n) * 8, t_out[n].c_str(), rc_ink_color.r, rc_ink_color.g, rc_ink_color.b, rc_ink_color.a);

    rc_sConsole_y[rc_active_window] += i;

    SDL_SetRenderTarget(rc_win_renderer[rc_active_window], NULL);
    SDL_RenderCopy(rc_win_renderer[rc_active_window], rc_hconsole[rc_active_window], NULL, NULL);

    SDL_RenderPresent(rc_win_renderer[rc_active_window]);
    if(rc_active_screen>=0)
        SDL_SetRenderTarget(rc_win_renderer[rc_active_window], rc_hscreen[rc_active_window][rc_active_screen]);
    return;
}

string rc_media_inputS_hw(string prompt)
{
    //SDL_Surface * input_surface = NULL;
    //SDL_Texture * input_texture = NULL;
    bool loop = true;
    SDL_Event in_evt;
    string in_buf = prompt;
    string rtn_string = "";
    string tc = in_buf;
    string t_out[rc_console_height[rc_active_window]];
    int i = 0;
    SDL_Rect first_line, sub_line;
    first_line.x = (rc_sConsole_x[rc_active_window] * 8) + (prompt.length()*8);
    first_line.y = rc_sConsole_y[rc_active_window] * 8;
    first_line.w = 0;
    first_line.h = 8;
    sub_line.x = 0;
    sub_line.y = (rc_sConsole_y[rc_active_window]+1) * 8;
    sub_line.w = 0;
    sub_line.h = 8;
    SDL_SetRenderTarget(rc_win_renderer[rc_active_window], rc_hconsole[rc_active_window]);

    if(in_buf.length()>0)
    {
        tc = in_buf;
        i = 0;
        int x = rc_sConsole_x[rc_active_window];
        if(x >= rc_console_width[rc_active_window])
            x = 0;

        while(tc.compare("")!=0)
        {
            if(tc.length() > ( rc_console_width[rc_active_window] - x) )
            {
                t_out[i] = rc_fillSpace(x) + tc.substr(0, rc_console_width[rc_active_window] - x);
                if(i == 0 && ((t_out[i].length() - prompt.length() - x)*8) > first_line.w)
                {
                    first_line.w = (t_out[i].length() - prompt.length() - x) * 8;
                }
                else if(i != 0 && (t_out[i].length() * 8) > sub_line.w)
                {
                    sub_line.w = t_out[i].length() * 8;
                }
                tc = tc.substr( (rc_console_width[rc_active_window] - x) );
                x = 0;
                i++;
            }
            else
            {
                t_out[i] = rc_fillSpace(x) + tc;
                if(i == 0 && ((t_out[i].length() - prompt.length() - x)*8) > first_line.w)
                {
                    first_line.w = (t_out[i].length() - prompt.length() - x) * 8;
                }
                else if(i != 0 && (t_out[i].length() * 8) > sub_line.w)
                {
                    sub_line.w = t_out[i].length() * 8;
                }
                x = 0;
                i++;
                break;
            }
            if(i >= rc_console_height[rc_active_window])
                break;
        }

        SDL_SetRenderDrawColor(rc_win_renderer[rc_active_window], rc_clearColor>>16, rc_clearColor>>8, rc_clearColor, rc_clearColor>>24);
        SDL_RenderFillRect(rc_win_renderer[rc_active_window], &first_line);

        if(((i-1)*8) > sub_line.h)
            sub_line.h = i*8;

        if(sub_line.h > 0)
            SDL_RenderFillRect(rc_win_renderer[rc_active_window], &sub_line);

        SDL_SetRenderDrawColor(rc_win_renderer[rc_active_window], rc_ink_color.r, rc_ink_color.g, rc_ink_color.b, rc_ink_color.a);

        for(int n = 0; n < i; n++)
        {
            stringRGBA(rc_win_renderer[rc_active_window], 0, (rc_sConsole_y[rc_active_window] + n) * 8, t_out[n].c_str(), rc_ink_color.r, rc_ink_color.g, rc_ink_color.b, rc_ink_color.a);
        }
        SDL_RenderPresent(rc_win_renderer[rc_active_window]);
    }

    while(loop)
    {
        if(SDL_WaitEvent(&in_evt))
        {
            switch(in_evt.type)
            {
                case SDL_TEXTINPUT:
                    in_buf += in_evt.text.text;
                    break;
                case SDL_KEYDOWN:
                    switch(in_evt.key.keysym.sym)
                    {
                        case SDLK_RETURN:
                            loop = false;
                            break;
                        case SDLK_BACKSPACE:
                            if(in_buf.length()-1 >= prompt.length() && in_buf.length()-1 >= 0)
                                in_buf = in_buf.substr(0, in_buf.length()-1);
                            break;
                    }
            }
        }
        if(in_buf.length()>0)
        {
            tc = in_buf;
            i = 0;
            int x = rc_sConsole_x[rc_active_window];
            if(x >= rc_console_width[rc_active_window])
                x = 0;

            while(tc.compare("")!=0)
            {
                if(tc.length() > ( rc_console_width[rc_active_window] - x) )
                {
                    t_out[i] = rc_fillSpace(x) + tc.substr(0, rc_console_width[rc_active_window] - x);
                    if(i == 0 && ((t_out[i].length() - prompt.length() - x)*8) > first_line.w)
                    {
                        first_line.w = (t_out[i].length() - prompt.length() - x) * 8;
                    }
                    else if(i != 0 && (t_out[i].length() * 8) > sub_line.w)
                    {
                        sub_line.w = t_out[i].length() * 8;
                    }
                    tc = tc.substr( (rc_console_width[rc_active_window] - x) );
                    x = 0;
                    i++;
                }
                else
                {
                    t_out[i] = rc_fillSpace(x) + tc;
                    if(i == 0 && ((t_out[i].length() - prompt.length() - x)*8) > first_line.w)
                    {
                        first_line.w = (t_out[i].length() - prompt.length() - x) * 8;
                    }
                    else if(i != 0 && (t_out[i].length() * 8) > sub_line.w)
                    {
                        sub_line.w = t_out[i].length() * 8;
                    }
                    x = 0;
                    i++;
                    break;
                }
                if(i >= rc_console_height[rc_active_window])
                    break;
            }

            SDL_SetRenderDrawColor(rc_win_renderer[rc_active_window], rc_clearColor>>16, rc_clearColor>>8, rc_clearColor, rc_clearColor>>24);
            SDL_RenderFillRect(rc_win_renderer[rc_active_window], &first_line);

            if(((i-1)*8) > sub_line.h)
                sub_line.h = i*8;

            if(sub_line.h > 0)
                SDL_RenderFillRect(rc_win_renderer[rc_active_window], &sub_line);

            SDL_SetRenderDrawColor(rc_win_renderer[rc_active_window], rc_ink_color.r, rc_ink_color.g, rc_ink_color.b, rc_ink_color.a);

            for(int n = 0; n < i; n++)
            {
                stringRGBA(rc_win_renderer[rc_active_window], 0, (rc_sConsole_y[rc_active_window] + n) * 8, t_out[n].c_str(), rc_ink_color.r, rc_ink_color.g, rc_ink_color.b, rc_ink_color.a);
            }

            SDL_SetRenderTarget(rc_win_renderer[rc_active_window], NULL);
            SDL_RenderCopy(rc_win_renderer[rc_active_window], rc_hconsole[rc_active_window], NULL, NULL);

            SDL_RenderPresent(rc_win_renderer[rc_active_window]);

            SDL_SetRenderTarget(rc_win_renderer[rc_active_window], rc_hconsole[rc_active_window]);
        }
    }
    rc_sConsole_y[rc_active_window] += i;
    rc_sConsole_x[rc_active_window] = 0;
    if(rc_active_screen >= 0)
        SDL_SetRenderTarget(rc_win_renderer[rc_active_window],rc_hscreen[rc_active_window][rc_active_screen]);
    return in_buf.substr(prompt.length());
}

string rc_media_ZoneInputS_hw(int x, int y, int w, int h)
{
    //SDL_Surface * input_surface = NULL;
    //SDL_Texture * input_texture = NULL;
    bool loop = true;
    SDL_Event in_evt;
    string in_buf = "";
    string rtn_string = "";
    string tc = "";
    string t_out[rc_console_height[rc_active_window]];
    int i = 0;
    SDL_Rect zone;
    zone.x = x;
    zone.y = y;
    zone.w = w;
    zone.h = h;
    SDL_SetRenderTarget(rc_win_renderer[rc_active_window], rc_hconsole[rc_active_window]);
    while(loop)
    {
        if(SDL_WaitEvent(&in_evt))
        {
            switch(in_evt.type)
            {
                case SDL_TEXTINPUT:
                    in_buf += in_evt.text.text;
                    break;
                case SDL_KEYDOWN:
                    switch(in_evt.key.keysym.sym)
                    {
                        case SDLK_RETURN:
                            loop = false;
                            break;
                        case SDLK_BACKSPACE:
                            if(in_buf.length()-1 >= 0)
                                in_buf = in_buf.substr(0, in_buf.length()-1);
                            break;
                    }
            }
        }
        if(in_buf.length()>=0)
        {
            tc = in_buf;
            i = 0;

            while(tc.compare("")!=0)
            {
                if(tc.length() > (w/8) )
                {
                    t_out[i] = tc.substr(0, (w/8) );
                    tc = tc.substr( w/8 );
                    i++;
                }
                else
                {
                    t_out[i] = tc;
                    i++;
                    break;
                }

                if(i >= rc_console_height[rc_active_window])
                    break;
            }

            SDL_SetRenderDrawColor(rc_win_renderer[rc_active_window], rc_clearColor>>16, rc_clearColor>>8, rc_clearColor, rc_clearColor>>24);
            SDL_RenderFillRect(rc_win_renderer[rc_active_window], &zone);

            //cout << "zone txt color = " << (int)rc_ink_color.r << ", " << (int)rc_ink_color.g << ", " << (int)rc_ink_color.b << ", " << (int)rc_ink_color.a << endl;

            SDL_SetRenderDrawColor(rc_win_renderer[rc_active_window], rc_ink_color.r, rc_ink_color.g, rc_ink_color.b, rc_ink_color.a);

            //cout << "n < " << (int) (h/8) << endl;

            for(int n = 0; n < (h/8) && n < i; n++)
            {
                stringRGBA(rc_win_renderer[rc_active_window], x, y + (n * 8), t_out[n].c_str(), rc_ink_color.r, rc_ink_color.g, rc_ink_color.b, rc_ink_color.a);
            }

            SDL_SetRenderTarget(rc_win_renderer[rc_active_window], NULL);
            SDL_RenderCopy(rc_win_renderer[rc_active_window], rc_hconsole[rc_active_window], NULL, NULL);

            SDL_RenderPresent(rc_win_renderer[rc_active_window]);

            SDL_SetRenderTarget(rc_win_renderer[rc_active_window], rc_hconsole[rc_active_window]);
        }
    }
    if(rc_active_screen >= 0)
        SDL_SetRenderTarget(rc_win_renderer[rc_active_window],rc_hscreen[rc_active_window][rc_active_screen]);
    return in_buf;
}

#endif // RC_MOBILE

bool rc_media_fontIsLoaded(int slot)
{
    if(rc_draw_font[slot]!=NULL)
        return true;
    return false;
}

void rc_media_font(int slot)
{
    if(rc_draw_font[slot]!= NULL)
        rc_active_font = slot;
}

void rc_media_setFontStyle(int f_slot, int style)
{
    TTF_SetFontStyle(rc_draw_font[f_slot], style);
}

void rc_media_LoadFont(int slot, string font_path, int font_size)
{
    if(rc_draw_font[slot] != NULL)
        TTF_CloseFont(rc_draw_font[slot]);
    rc_draw_font[slot] = TTF_OpenFont(font_path.c_str(), font_size);
    if(rc_active_font == -1)
        rc_active_font = slot;
}

void rc_media_DeleteFont(int slot)
{
    if(rc_draw_font[slot] != NULL)
        TTF_CloseFont(rc_draw_font[slot]);
    rc_draw_font[slot] = NULL;
}

void rc_media_drawText_hw(string text, int x, int y)
{
    if(rc_draw_font[rc_active_font] == NULL)
    {
        cout << "DrawTextError: Could not load font at " << rc_active_font << endl;
        return;
    }
    SDL_Surface * rendered_text = TTF_RenderUTF8_Solid(rc_draw_font[rc_active_font], text.c_str(), rc_ink_color);
    //cout << "debug 1\n";
    SDL_Rect pos;
    pos.x = x;
    pos.y = y;
    pos.w = rendered_text->w;
    pos.h = rendered_text->h;
    SDL_Texture * txt_image = SDL_CreateTextureFromSurface(rc_win_renderer[rc_active_window],rendered_text);
    //SDL_BlitSurface(rendered_text, NULL, rc_sscreen[rc_active_window][rc_active_screen], &pos);
    SDL_FreeSurface(rendered_text);
    SDL_RenderCopy(rc_win_renderer[rc_active_window],txt_image,NULL,&pos);
    SDL_DestroyTexture(txt_image);
}

void rc_media_drawText_shaded_hw(string text, int x, int y, Uint32 fg_color, Uint32 bg_color)
{
    if(rc_draw_font[rc_active_font] == NULL)
    {
        cout << "DrawTextError: Could not load font at " << rc_active_font << endl;
        return;
    }
    SDL_Color fg, bg;
    fg.a = fg_color >> 24;
    fg.r = fg_color >> 16;
    fg.g = fg_color >> 8;
    fg.b = fg_color;
    bg.a = bg_color >> 24;
    bg.r = bg_color >> 16;
    bg.g = bg_color >> 8;
    bg.b = bg_color;
    SDL_Surface * rendered_text = TTF_RenderUTF8_Shaded(rc_draw_font[rc_active_font], text.c_str(), fg, bg);
    //cout << "debug 1\n";
    SDL_Rect pos;
    pos.x = x;
    pos.y = y;
    pos.w = rendered_text->w;
    pos.h = rendered_text->h;
    SDL_Texture * txt_image = SDL_CreateTextureFromSurface(rc_win_renderer[rc_active_window],rendered_text);
    //SDL_BlitSurface(rendered_text, NULL, rc_sscreen[rc_active_window][rc_active_screen], &pos);
    SDL_FreeSurface(rendered_text);
    SDL_RenderCopy(rc_win_renderer[rc_active_window],txt_image,NULL,&pos);
    SDL_DestroyTexture(txt_image);
}

void rc_media_drawText_blended_hw(string text, int x, int y)
{
    if(rc_draw_font[rc_active_font] == NULL)
    {
        cout << "DrawTextError: Could not load font at " << rc_active_font << endl;
        return;
    }
    SDL_Surface * rendered_text = TTF_RenderUTF8_Blended(rc_draw_font[rc_active_font], text.c_str(), rc_ink_color);
    //cout << "debug 1\n";
    SDL_Rect pos;
    pos.x = x;
    pos.y = y;
    pos.w = rendered_text->w;
    pos.h = rendered_text->h;
    SDL_Texture * txt_image = SDL_CreateTextureFromSurface(rc_win_renderer[rc_active_window],rendered_text);
    //SDL_BlitSurface(rendered_text, NULL, rc_sscreen[rc_active_window][rc_active_screen], &pos);
    SDL_FreeSurface(rendered_text);
    SDL_RenderCopy(rc_win_renderer[rc_active_window],txt_image,NULL,&pos);
    SDL_DestroyTexture(txt_image);
}

void rc_media_getTextSize(int f_slot, string txt, double * w, double * h)
{
    if(rc_draw_font[f_slot] == NULL)
    {
        cout << "GetTextSize Error: No font at " << f_slot << endl;
        return;
    }
    int txt_w = 0, txt_h = 0;
    TTF_SizeUTF8(rc_draw_font[f_slot], txt.c_str(), &txt_w, &txt_h);
    *w = txt_w;
    *h = txt_h;
}

void rc_media_GetRenderedText_hw(int slot, string text)
{
    if(slot < 0 || slot >= MAX_IMAGES)
    {
        cout << "GetRenderedText Error: Image must be in the range of 0 to " << MAX_IMAGES-1 << endl;
        return;
    }
    if(rc_draw_font[rc_active_font] == NULL)
    {
        cout << "GetRenderedText Error: Could not load font at " << rc_active_font << endl;
        return;
    }
    SDL_Surface * rendered_text = TTF_RenderUTF8_Solid(rc_draw_font[rc_active_font], text.c_str(), rc_ink_color);

    for(int i = 0; i < MAX_WINDOWS; i++)
    {
        if(rc_himage[slot][i] != NULL)
        {
            SDL_DestroyTexture(rc_himage[slot][i]);
            rc_himage[slot][i] = NULL;
        }
        if(rc_win[i] != NULL)
        {
            rc_himage[slot][i] = SDL_CreateTextureFromSurface(rc_win_renderer[i], rendered_text);
            rc_himage_rect[slot].x = 0;
            rc_himage_rect[slot].y = 0;
            rc_himage_rect[slot].w = rendered_text->w;
            rc_himage_rect[slot].h = rendered_text->h;
            rc_image_width[slot] = rendered_text->w;
            rc_image_height[slot] = rendered_text->h;
            rc_image_isLoaded[slot] = true;
        }
    }

    SDL_FreeSurface(rendered_text);
}

std::string rc_utf8_substr(const std::string& str, unsigned int start, unsigned int leng)
{
    if (leng==0) { return ""; }
    unsigned int c, i, ix, q, min=std::string::npos, max=std::string::npos;
    for (q=0, i=0, ix=str.length(); i < ix; i++, q++)
    {
        if (q==start){ min=i; }
        if (q<=start+leng || leng==std::string::npos){ max=i; }

        c = (unsigned char) str[i];
        if      (
                 //c>=0   &&
                 c<=127) i+=0;
        else if ((c & 0xE0) == 0xC0) i+=1;
        else if ((c & 0xF0) == 0xE0) i+=2;
        else if ((c & 0xF8) == 0xF0) i+=3;
        //else if (($c & 0xFC) == 0xF8) i+=4; // 111110bb //byte 5, unnecessary in 4 byte UTF-8
        //else if (($c & 0xFE) == 0xFC) i+=5; // 1111110b //byte 6, unnecessary in 4 byte UTF-8
        else return "";//invalid utf8
    }
    if (q<=start+leng || leng==std::string::npos){ max=i; }
    if (min==std::string::npos || max==std::string::npos) { return ""; }
    return str.substr(min,max-min);
}

std::size_t rc_utf8_length(std::string const &s)
{
  return std::count_if(s.begin(), s.end(),
    [](char c) { return (static_cast<unsigned char>(c) & 0xC0) != 0x80; } );
}

int rc_getEvents()
{
    SDL_Event event;
    int g_events = SDL_PollEvent(&event);
    //int g_events = SDL_WaitEvent(&event);
    //cout << "G_EVENT = " << g_events << endl;
    //cout << "TYPE = " << event.type << endl;
    if(!g_events)
        return 0;
    switch(event.type)
    {
        case SDL_QUIT:
            SDL_PumpEvents();
            //rc_media_quit();
            exit(0);
            break;
        case SDL_WINDOWEVENT:
            if(event.window.event == SDL_WINDOWEVENT_RESIZED)
            {
                for(int i = 0; i < MAX_WINDOWS; i++)
                {
                    if(rc_win_id[i] == event.window.windowID)
                    {
                        rc_active_window = i;
                        rc_win_event[i] = 4;
                        rc_onResize(rc_active_window);
                        break;
                    }
                }
            }
            else if(event.window.event == SDL_WINDOWEVENT_CLOSE)
            {
                Uint32 win_id = -1;
                for(int i = 0; i < MAX_WINDOWS; i++)
                {
                    if(rc_win[i])
                    {
                        win_id = SDL_GetWindowID(rc_win[i]);
                        if(win_id == event.window.windowID)
                        {
                            rc_win_event[i] = 1;
                            if(SDL_QuitRequested() != 0)
                            {
                                //SDL_PumpEvents();
                                SDL_FlushEvent(SDL_QUIT);
                            }
                            if(rc_win_exitOnClose[i])
                            {
                                rc_media_closeWindow_hw(i);
                                return 0;
                                //rc_win_event[i] = 0;
                            }
                            break;
                        }
                        win_id = -1;
                    }
                }
            }
            else if(event.window.event == SDL_WINDOWEVENT_MINIMIZED)
            {
                Uint32 win_id = -1;
                for(int i = 0; i < MAX_WINDOWS; i++)
                {
                    if(rc_win[i])
                    {
                        win_id = SDL_GetWindowID(rc_win[i]);
                        if(win_id == event.window.windowID)
                        {
                            rc_win_event[i] = 2;
                            //rc_media_closeWindow_hw(i);
                            break;
                        }
                        win_id = -1;
                    }
                }
            }
            else if(event.window.event == SDL_WINDOWEVENT_MAXIMIZED)
            {
                Uint32 win_id = -1;
                for(int i = 0; i < MAX_WINDOWS; i++)
                {
                    if(rc_win[i])
                    {
                        win_id = SDL_GetWindowID(rc_win[i]);
                        if(win_id == event.window.windowID)
                        {
                            rc_win_event[i] = 3;
                            //rc_media_closeWindow_hw(i);
                            break;
                        }
                        win_id = -1;
                    }
                }
            }
            break;
        case SDL_TEXTINPUT:
            if(rc_textinput_flag == true)
            {
                rc_textinput_string += event.text.text;
            }
            break;
        case SDL_KEYUP:
            break;
        case SDL_KEYDOWN:
            if(rc_textinput_isActive && event.key.keysym.sym == SDLK_BACKSPACE && rc_textinput_string.length() > 0
               && rc_toggleBackspace)
            {
                rc_textinput_string = rc_utf8_substr(rc_textinput_string, 0, rc_utf8_length(rc_textinput_string)-1);
            }

            rc_inkey = event.key.keysym.sym;
            break;
        //case SDL_MOUSEMOTION:
            //SDL_GetMouseState(&rc_mouseX, &rc_mouseY);
            //break;
        case SDL_MOUSEBUTTONUP:
            //SDL_GetMouseState(&rc_mouseX, &rc_mouseY);
            rc_mbutton1 = 0;
            rc_mbutton2 = 0;
            rc_mbutton3 = 0;
            //break;
            switch(event.button.button)
            {
                case SDL_BUTTON_LEFT:
                    rc_mbutton1 = 0;
                    break;
                case SDL_BUTTON_MIDDLE:
                    rc_mbutton2 = 0;
                    break;
                case SDL_BUTTON_RIGHT:
                    rc_mbutton3 = 0;
                    break;
            }
            break;
        case SDL_MOUSEBUTTONDOWN:
            //SDL_GetMouseState(&rc_mouseX, &rc_mouseY);
            //rc_mbutton1 = 0;
            //rc_mbutton2 = 0;
            //rc_mbutton3 = 0;
            switch(event.button.button)
            {
                case SDL_BUTTON_LEFT:
                    rc_mbutton1 = 1;
                    break;
                case SDL_BUTTON_MIDDLE:
                    rc_mbutton2 = 1;
                    break;
                case SDL_BUTTON_RIGHT:
                    rc_mbutton3 = 1;
                    break;
            }
            break;
        case SDL_MOUSEWHEEL:
            rc_mwheelx = event.wheel.x;
            rc_mwheely = event.wheel.y;
            break;
//        case SDL_JOYBUTTONDOWN:
//            rc_joybutton[event.jbutton.which][event.jbutton.button] = 1;
//            break;
//        case SDL_JOYBUTTONUP:
//            rc_joybutton[event.jbutton.which][event.jbutton.button] = 0;
//            break;
//        case SDL_JOYAXISMOTION:
//            rc_joy_axis[event.jaxis.which][event.jaxis.axis] = event.jaxis.value;
//            break;
        case SDL_JOYDEVICEREMOVED:
            //cout << "Joystick Removed: Instance " << event.jdevice.which << endl;
            for(int i = 0; i < 8; i++)
            {
                if(event.jdevice.which == rc_joyID[i] && rc_joystick[i])
                {
                    //cout << "Joystick [" << i << "] was removed" << endl;
                    SDL_HapticClose(rc_haptic[i]);
                    SDL_JoystickClose(rc_joystick[i]);
                    rc_joystick[i] = NULL;
                    rc_haptic[i] = NULL;
                    rc_joyID[i] = -1;
                    rc_numJoysticks--;
                    break;
                }
            }
            break;
        case SDL_JOYDEVICEADDED:
            //cout << "Joystick Added: " << event.jdevice.which << endl;
            tmp_joy = SDL_JoystickOpen(event.jdevice.which);
            tmp_joy_id = SDL_JoystickInstanceID(tmp_joy);
            tmp_joy_flag = 0;

            for(int i = 0; i < 8; i++)
            {
                if(tmp_joy_id == rc_joyID[i])
                {
                    tmp_joy_flag = 1;
                    break;
                }
            }

            if(event.jdevice.which >= 0 && tmp_joy_flag == 0)
            {
                for(int i = 0; i < 8; i++)
                {
                    if(rc_joystick[i] == NULL)
                    {
                        //cout << "Assigned " << i << endl;
                        rc_joystick[i] = tmp_joy;
                        rc_haptic[i] = SDL_HapticOpenFromJoystick(rc_joystick[i]);
                        SDL_HapticRumbleInit(rc_haptic[i]);
                        rc_joyID[i] = tmp_joy_id;
                        rc_numJoysticks++;
                        break;
                    }
                }
            }
            break;
#ifndef RC_MOBILE //This block handles touch events for non-mobile devices, Just in case it has a touch screen that SDL2 can get events for
        case SDL_FINGERDOWN:
            rc_touch = 1;
            rc_touchX = event.tfinger.x * rc_win_width[rc_active_window];
            rc_touchY = event.tfinger.y * rc_win_height[rc_active_window];
#ifdef RC_IOS
            rc_pressure = 1; //FIXME: On IOS pressure is always getting reported as 0 on finger down so I am just setting it to 1 until I figure this out
#else
            rc_pressure = event.tfinger.pressure;
#endif
            rc_setTouchFingerEvent(event.tfinger.fingerId, rc_touchX, rc_touchY, rc_pressure);
            break;
        case SDL_FINGERUP:
            rc_touch = 0;
            rc_mt_status = 0;
            rc_touchX = event.tfinger.x * rc_win_width[rc_active_window];
            rc_touchY = event.tfinger.y * rc_win_height[rc_active_window];
            rc_pressure = event.tfinger.pressure;
            rc_setTouchFingerEvent(event.tfinger.fingerId, -1, -1, 0);
            break;
        case SDL_FINGERMOTION:
            rc_touch = 1;
            rc_touchX = event.tfinger.x * rc_win_width[rc_active_window];
            rc_touchY = event.tfinger.y * rc_win_height[rc_active_window];
            rc_motionX = event.tfinger.dx * rc_win_width[rc_active_window];
            rc_motionY = event.tfinger.dy * rc_win_height[rc_active_window];
#ifdef RC_IOS
            rc_pressure = 1;
#else
            rc_pressure = event.tfinger.pressure;
#endif
            rc_setTouchFingerEvent(event.tfinger.fingerId, rc_touchX, rc_touchY, rc_pressure);
            break;
        case SDL_MULTIGESTURE:
            rc_touch = 2;
            rc_mt_status = 1;
            rc_mt_x = event.mgesture.x;
            rc_mt_y = event.mgesture.y;
            rc_mt_numFingers = event.mgesture.numFingers;
            rc_mt_dist = event.mgesture.dDist;
            rc_mt_theta = event.mgesture.dTheta;
#ifdef RC_IOS
            rc_pressure = 1;
#else
            rc_pressure = event.tfinger.pressure;
#endif
            break;
#endif
    }
    //cout << "end_event" << endl;
    return g_events;
}

bool rc_media_windowEvent_Close(int win_num)
{
    if(rc_winCheck(win_num))
    {
        if(rc_win_event[win_num]==1)
        {
            //cout << "Window #" << win_num << " Close_Event" << endl;
            return true;
        }
        else
            return false;
    }
    return false;
}

bool rc_media_windowEvent_Minimize(int win_num)
{
    if(rc_winCheck(win_num))
    {
        if(rc_win_event[win_num]==2)
            return true;
        else
            return false;
    }
    return false;
}

bool rc_media_windowEvent_Maximize(int win_num)
{
    if(rc_winCheck(win_num))
    {
        if(rc_win_event[win_num]==3)
            return true;
        else
            return false;
    }
    return false;
}

bool rc_media_windowEvent_Resize(int win_num)
{
    if(rc_winCheck(win_num))
    {
        if(rc_win_event[win_num]==4)
            return true;
        else
            return false;
    }
    return false;
}

void rc_media_windowEvent_setExitOnClose(int win_num, int exitOnClose)
{
    rc_win_exitOnClose[win_num] = (exitOnClose != 0) ? true : false;
}

void rc_media_getTouchFinger(int finger, double * x, double * y, double * pressure)
{
    if(finger < MAX_FINGERS)
    {
        *x = rc_finger[finger].x;
        *y = rc_finger[finger].y;
        *pressure = rc_finger[finger].pressure;
    }
}

int rc_media_numFingers()
{
    return rc_fingers_pressed.size();
    //if(rc_touchDevice)
    //    return SDL_GetNumTouchFingers(rc_touchDevice);
    //return 0;
}

double rc_media_touchPressure()
{
    return rc_pressure;
}

void rc_media_getTouch(double * status, double * x, double * y, double * distX, double * distY)
{
    *status = (double)rc_touch;
    *x = (double)rc_touchX;
    *y = (double)rc_touchY;
    *distX = (double)rc_motionX;
    *distY = (double)rc_motionY;
    return;
}

void rc_media_getMultiTouch(double * status, double * x, double * y, double * numFingers, double * dist, double * theta)
{
    *status = (double)rc_mt_status;
    *x = (double)rc_mt_x;
    *y = (double)rc_mt_y;
    *numFingers = (double)rc_mt_numFingers;
    *dist = rc_mt_dist;
    *theta = rc_mt_theta;
    return;
}

void rc_media_getAccel(uint32_t accel_num, double * x, double * y, double * z)
{
    float sensor_data[4];
    if(accel_num < num_accels)
        SDL_SensorGetData(rc_accel[accel_num], &sensor_data[0], 3);
    *x = sensor_data[0];
    *y = sensor_data[1];
    *z = sensor_data[2];
}

string rc_media_accelName(uint32_t accel_num)
{
    if(accel_num < num_accels)
        return (string)SDL_SensorGetName(rc_accel[accel_num]);
    return "";
}

int rc_media_numAccels()
{
    return num_accels;
}

void rc_media_getGyro(uint32_t gyro_num, double * x, double * y, double * z)
{
    float sensor_data[4];
    if(gyro_num < num_gyros)
        SDL_SensorGetData(rc_gyro[gyro_num], &sensor_data[0], 3);
    *x = sensor_data[0];
    *y = sensor_data[1];
    *z = sensor_data[2];
}

string rc_media_gyroName(uint32_t gyro_num)
{
    if(gyro_num < num_gyros)
        return (string)SDL_SensorGetName(rc_gyro[gyro_num]);
    return "";
}

int rc_media_numGyros()
{
    return num_gyros;
}

void rc_media_ReadInput_Start()
{
    SDL_StartTextInput();
    rc_textinput_isActive = true;
    rc_textinput_string = "";
    rc_textinput_timer = clock() / (double)(CLOCKS_PER_SEC / 1000);
}

void rc_media_ReadInput_Stop()
{
    rc_textinput_isActive = false;
    rc_textinput_timer = 0;
    rc_textinput_string = "";
    SDL_StopTextInput();
}

string rc_media_ReadInput_Text()
{
    return rc_textinput_string;
}

void rc_media_ReadInput_SetText(string txt)
{
    rc_textinput_string = txt;
}

void rc_media_ReadInput_ToggleBackspace(bool flag)
{
    rc_toggleBackspace = flag;
}

int rc_media_inkey()
{
    int k = rc_inkey;
    return k;
}

int rc_media_key(int check_Key)
{
    if(keyState == NULL)
        keyState = SDL_GetKeyboardState(NULL);
    return keyState[SDL_GetScancodeFromKey(check_Key)];
}

int rc_media_waitKey()
{
    bool wk_loop = true;
    SDL_Event e;
    while(wk_loop)
    {
        while(SDL_WaitEvent(&e))
        {
            if(e.type == SDL_KEYDOWN)
                return (int)e.key.keysym.sym;
        }
    }
    return 0;
}

void rc_media_wait(Uint32 ms)
{
    SDL_Delay(ms);
}

void rc_media_hideMouse()
{
    SDL_ShowCursor(0);
    rc_cursor_visible = 0;
}

void rc_media_showMouse()
{
    SDL_ShowCursor(1);
    rc_cursor_visible = 1;
}

bool rc_media_mouseIsVisible()
{
    return rc_cursor_visible;
}

int rc_media_mouseX()
{
    //SDL_GetMouseState(&rc_mouseX,&rc_mouseY);
    //cout << "debug: " << rc_fullscreen_mouse_scale_x[rc_active_window] << endl;
    #ifdef RC_MOBILE
    return rc_mouseX;
    #else
    return rc_mouseX * rc_fullscreen_mouse_scale_x[rc_active_window];
    #endif // RC_MOBILE
}

int rc_media_mouseY()
{
    //SDL_GetMouseState(&rc_mouseX,&rc_mouseY);
    #ifdef RC_MOBILE
    return rc_mouseY;
    #else
    return rc_mouseY * rc_fullscreen_mouse_scale_y[rc_active_window];
    #endif // RC_MOBILE
}

int rc_media_mouseButton(int m)
{
    switch(m)
    {
        case 0:
            return rc_mbutton1;
        case 1:
            return rc_mbutton2;
        case 2:
            return rc_mbutton3;
    }
    return -1;
}

void rc_media_getMouse(double * x, double * y, double * mb1, double * mb2, double * mb3)
{
    //SDL_GetMouseState(&rc_mouseX,&rc_mouseY);
    //SDL_PumpEvents();
    *mb1 = rc_mbutton1;
    *mb2 = rc_mbutton2;
    *mb3 = rc_mbutton3;
    #ifdef RC_MOBILE
    *x = rc_mouseX;
    *y = rc_mouseY;
    #else
    *x = (int)(rc_mouseX * rc_fullscreen_mouse_scale_x[rc_active_window]);
    *y = (int)(rc_mouseY * rc_fullscreen_mouse_scale_y[rc_active_window]);
    //cout << "debug getMouse = " << rc_mouseX << " * " << rc_fullscreen_mouse_scale_x[rc_active_window] << endl;
    #endif // RC_MOBILE
    return;
}

int rc_media_globalMouseX()
{
    //SDL_GetGlobalMouseState(&rc_mouseX,&rc_mouseY);
    return rc_global_mouseX;
}

int rc_media_globalMouseY()
{
    //SDL_GetGlobalMouseState(&rc_mouseX,&rc_mouseY);
    return rc_global_mouseY;
}

void rc_media_getGlobalMouse(double * x, double * y, double * mb1, double * mb2, double * mb3)
{
    //SDL_GetGlobalMouseState(&rc_mouseX,&rc_mouseY);
    //SDL_PumpEvents();
    *mb1 = rc_mbutton1;
    *mb2 = rc_mbutton2;
    *mb3 = rc_mbutton3;
    *x = rc_global_mouseX;
    *y = rc_global_mouseY;
    return;
}

int rc_media_mouseWheelX()
{
    return rc_mwheelx;
}

int rc_media_mouseWheelY()
{
    return rc_mwheely;
}

void rc_media_getMouseWheel(double * x_axis, double * y_axis)
{
    *x_axis = rc_mwheelx;
    *y_axis = rc_mwheely;
    return;
}

void rc_media_grabInput(bool flag)
{
    SDL_SetWindowGrab(rc_win[rc_active_window], flag ? SDL_TRUE : SDL_FALSE);
}

int rc_media_grabbedWindow()
{
    for(int i = 0; i < MAX_WINDOWS; i++)
    {
        if(SDL_GetWindowGrab(rc_win[i]))
            return i;
    }
    return -1;
}

void rc_media_warpMouse(int x, int y)
{
    SDL_WarpMouseInWindow(rc_win[rc_active_window], x, y);
}

void rc_media_warpMouseGlobal(int x, int y)
{
    SDL_WarpMouseGlobal(x, y);
}

void rc_media_setMouseZone(int x, int y, int w, int h)
{
    SDL_Rect r;
    r.x = x;
    r.y = y;
    r.w = w;
    r.h = h;
    SDL_SetWindowMouseRect(rc_win[rc_active_window], &r);
}

void rc_media_clearMouseZone()
{
    SDL_SetWindowMouseRect(rc_win[rc_active_window], NULL);
}

void rc_media_setWindowAlwaysOnTop(int win, bool flag)
{
    if(win < 0 || win >= MAX_WINDOWS)
        return;
    SDL_SetWindowAlwaysOnTop(rc_win[win], flag ? SDL_TRUE : SDL_FALSE);
}

void rc_media_setMouseRelative(bool flag)
{
    SDL_SetRelativeMouseMode(flag ? SDL_TRUE : SDL_FALSE);
}

void rc_media_setWindowVSync(int win, bool flag)
{
    SDL_RenderSetVSync(rc_win_renderer[win], flag ? SDL_TRUE : SDL_FALSE);
}

int rc_media_openURL(string url)
{
    return SDL_OpenURL(url.c_str());
}

string rc_media_APIVersion()
{
    SDL_version version;
    SDL_GetVersion(&version);

    stringstream ss;
    ss << (uint32_t)version.major << "." << (uint32_t)version.minor << "." << (uint32_t)version.patch;
    return ss.str();

}

int rc_media_flashWindow(int win)
{
    //SDL_FlashOperation op;
    return SDL_FlashWindow(rc_win[win], SDL_FLASH_UNTIL_FOCUSED);
}

int rc_media_messageBox(string title, string msg)
{
    return SDL_ShowSimpleMessageBox(SDL_MESSAGEBOX_INFORMATION, title.c_str(), msg.c_str(), NULL);
}

void rc_media_updateWindow_hw()
{
    if(!rc_win[rc_active_window])
        return;
    int s_num = 0;
    SDL_SetRenderTarget(rc_win_renderer[rc_active_window], rc_backBuffer[rc_active_window]);
    SDL_SetRenderDrawColor(rc_win_renderer[rc_active_window], rc_clearColor >> 16, rc_clearColor >> 8, rc_clearColor, 255);
    //SDL_RenderFillRect(rc_win_renderer[rc_active_window], NULL);
    SDL_RenderClear(rc_win_renderer[rc_active_window]);
    for(int i = MAX_SCREENS-1; i >= 0; i--)
    {
        s_num = rc_screen_zOrder[rc_active_window][i];
        //cout << "DRAW SCREEN: " << s_num << endl;
        if(rc_hscreen[rc_active_window][s_num] != NULL && rc_screen_visible[rc_active_window][s_num])
        {
            //cout << "draw canvas " << s_num << endl;
            #ifdef RC_WEB
            SDL_RenderCopy(rc_win_renderer[rc_active_window], rc_hscreen[rc_active_window][s_num], &rc_screenview[rc_active_window][s_num], &rc_screen_rect[rc_active_window][s_num]);
            #else
            SDL_RenderCopy(rc_win_renderer[rc_active_window], rc_hscreen[rc_active_window][s_num], &rc_screenview[rc_active_window][s_num], &rc_screen_rect[rc_active_window][s_num]);
            #endif
        }
    }
    //#ifndef RC_ANDROID
        SDL_RenderCopy(rc_win_renderer[rc_active_window], rc_hconsole[rc_active_window], NULL, NULL);
    //#endif // RC_ANDROID
    //cout << endl;
    SDL_SetRenderTarget(rc_win_renderer[rc_active_window], NULL);
    #if defined(RC_MOBILE) || defined(RC_WEB)
    SDL_RenderCopy(rc_win_renderer[rc_active_window], rc_backBuffer[rc_active_window], NULL, NULL);
    #else
    SDL_RenderCopy(rc_win_renderer[rc_active_window], rc_backBuffer[rc_active_window], &rc_bb_rect[rc_active_window], NULL);
    #endif // RC_ANDROID
    SDL_RenderPresent(rc_win_renderer[rc_active_window]);
    SDL_SetRenderTarget(rc_win_renderer[rc_active_window], rc_hscreen[rc_active_window][rc_active_screen]);
    SDL_SetRenderDrawColor(rc_win_renderer[rc_active_window], rc_ink_color.r, rc_ink_color.g, rc_ink_color.b, rc_ink_color.a);

    rc_fps_frames[rc_active_window]++;

    uint32_t t = SDL_GetTicks();

    if( (t - rc_fps_timer[rc_active_window]) >= 1000 )
    {
        rc_fps_timer[rc_active_window] = t;
        rc_fps[rc_active_window] = rc_fps_frames[rc_active_window];
        rc_fps_frames[rc_active_window] = 0;
    }
}

void rc_media_updateAllWindow_hw()
{
    for(int win_num = 0; win_num < MAX_WINDOWS; win_num++)
    {
        if(!rc_win[win_num])
            continue;
        int s_num = 0;
        SDL_SetRenderTarget(rc_win_renderer[win_num], rc_backBuffer[win_num]);
        SDL_SetRenderDrawColor(rc_win_renderer[win_num], rc_clearColor >> 16, rc_clearColor >> 8, rc_clearColor, 255);
        //SDL_RenderFillRect(rc_win_renderer[win_num], NULL);
        SDL_RenderClear(rc_win_renderer[win_num]);
        for(int i = MAX_SCREENS-1; i >= 0; i--)
        {
            s_num = rc_screen_zOrder[win_num][i];
            //cout << "DRAW SCREEN: " << s_num << endl;
            if(rc_hscreen[win_num][s_num] != NULL && rc_screen_visible[win_num][s_num])
            {
                //cout << "draw canvas " << s_num << endl;
                #ifdef RC_WEB
                SDL_RenderCopy(rc_win_renderer[win_num], rc_hscreen[win_num][s_num], &rc_screenview[win_num][s_num], &rc_screen_rect[win_num][s_num]);
                #else
                SDL_RenderCopy(rc_win_renderer[win_num], rc_hscreen[win_num][s_num], &rc_screenview[win_num][s_num], &rc_screen_rect[win_num][s_num]);
                #endif
            }
        }
        //#ifndef RC_ANDROID
            SDL_RenderCopy(rc_win_renderer[win_num], rc_hconsole[win_num], NULL, NULL);
        //#endif // RC_ANDROID
        //cout << endl;
        SDL_SetRenderTarget(rc_win_renderer[win_num], NULL);
        #if defined(RC_MOBILE) || defined(RC_WEB)
        SDL_RenderCopy(rc_win_renderer[win_num], rc_backBuffer[win_num], NULL, NULL);
        #else
        SDL_RenderCopy(rc_win_renderer[win_num], rc_backBuffer[win_num], &rc_bb_rect[win_num], NULL);
        #endif // RC_ANDROID
        SDL_RenderPresent(rc_win_renderer[win_num]);
        SDL_SetRenderTarget(rc_win_renderer[win_num], rc_hscreen[win_num][rc_active_screen]);
        SDL_SetRenderDrawColor(rc_win_renderer[win_num], rc_ink_color.r, rc_ink_color.g, rc_ink_color.b, rc_ink_color.a);

        rc_fps_frames[win_num]++;

        uint32_t t = SDL_GetTicks();

        if( (t - rc_fps_timer[win_num]) >= 1000 )
        {
            rc_fps_timer[win_num] = t;
            rc_fps[win_num] = rc_fps_frames[win_num];
            rc_fps_frames[win_num] = 0;
        }
    }
}

bool rc_media_imageExist_hw(int slot)
{
    return rc_image_isLoaded[slot];
}

int rc_media_numJoysticks()
{
    return SDL_NumJoysticks();
}

int rc_media_joyAxis(int joy_num, int axis)
{
    if(joy_num >= 0 && joy_num < MAX_JOYSTICKS)
        return SDL_JoystickGetAxis(rc_joystick[joy_num], axis);
    return 0;
}

int rc_media_joyButton(int joy_num, int jbutton)
{
    if(joy_num >= 0 && joy_num < MAX_JOYSTICKS)
        return SDL_JoystickGetButton(rc_joystick[joy_num], jbutton);
    return 0;
}

string rc_media_joystickName(int joy_num)
{
    if(joy_num >= 0 && joy_num < MAX_JOYSTICKS)
        return (string)SDL_JoystickName(rc_joystick[joy_num]);
    return "";
}

int rc_media_numJoyButtons(int joy_num)
{
    if(joy_num >= 0 && joy_num < MAX_JOYSTICKS)
        return SDL_JoystickNumButtons(rc_joystick[joy_num]);
    return 0;
}

int rc_media_numJoyAxes(int joy_num)
{
    if(joy_num >= 0 && joy_num < MAX_JOYSTICKS)
        return SDL_JoystickNumAxes(rc_joystick[joy_num]);
    return 0;
}

int rc_media_numJoyHats(int joy_num)
{
    if(joy_num >= 0 && joy_num < MAX_JOYSTICKS)
        return SDL_JoystickNumHats(rc_joystick[joy_num]);
    return 0;
}

int rc_media_joyHat(int joy_num, int hat)
{
    if(joy_num >= 0 && joy_num < MAX_JOYSTICKS)
        return SDL_JoystickGetHat(rc_joystick[joy_num], hat);
    return 0;
}

int rc_media_numJoyTrackBalls(int joy_num)
{
    if(joy_num >= 0 && joy_num < MAX_JOYSTICKS)
        return SDL_JoystickNumBalls(rc_joystick[joy_num]);
    return 0;
}

void rc_media_getJoyTrackBall(int joy_num, int ball, double * dx, double * dy)
{
    int x = 0;
    int y = 0;
    if(joy_num >= 0 && joy_num < MAX_JOYSTICKS)
        SDL_JoystickGetBall(rc_joystick[joy_num], ball, &x, &y);
    *dx = x;
    *dy = y;
}

bool rc_media_joystickIsConnected( int joy_num )
{
    if(joy_num >= 0 && joy_num < MAX_JOYSTICKS)
    {
        if(rc_joystick[joy_num])
            return true;
        return false;
    }
    return false;
}

void rc_media_joyRumblePlay(int joy_num, double strength, double duration)
{
    if(joy_num >= 0 && joy_num < MAX_JOYSTICKS)
    {
        SDL_HapticRumblePlay(rc_haptic[joy_num], strength, (Uint32)duration);
    }
}

void rc_media_joyRumbleStop(int joy_num)
{
    if(joy_num >= 0 && joy_num < MAX_JOYSTICKS)
        SDL_HapticRumbleStop(rc_haptic[joy_num]);
}

int rc_media_joystickIsHaptic( int joy_num )
{
    if(joy_num >= 0 && joy_num < MAX_JOYSTICKS)
    {
        if(rc_haptic[joy_num])
            return 1;
    }
    return 0;
}

int rc_media_queryAudioSpec(double * freq, double * format, double * channels)
{
    //need to do something here
    int qa_freq = 0;
    Uint16 qa_format = 0;
    int qa_channels = 0;
    int result = Mix_QuerySpec(&qa_freq, &qa_format, &qa_channels);
    *freq = (double)qa_freq;
    *format = (double)qa_format;
    *channels = (double)qa_channels;
    return result;
}

void rc_media_loadSound(int slot, string fname)
{
    if(rc_sound[slot] != NULL)
    {
        Mix_FreeChunk(rc_sound[slot]);
    }
    rc_sound[slot] = Mix_LoadWAV(fname.c_str());
    if(rc_sound[slot] == NULL)
    {
        cout << "Could not load sound: " << Mix_GetError() << endl;
        return;
    }
}

void rc_media_createSound(int slot, double * abuf, Uint32 alen, Uint8 volume)
{
    if(!rc_sound[slot])
    {
        rc_sound[slot] = (Mix_Chunk*)SDL_malloc(sizeof(Mix_Chunk));
        //cout << "sound dbg 0" << endl;
        rc_sound[slot]->allocated = 1;
        //cout << "GOOD START" << endl;
        rc_sound[slot]->abuf = (Uint8*)SDL_malloc(sizeof(Uint8)*alen);
        //cout << "sound dbg 1" << endl;
        for(int i = 0; i < alen; i++)
            rc_sound[slot]->abuf[i] = (Uint8)abuf[i];
        //cout << "sound dbg 2" << endl;
        rc_sound[slot]->alen = alen;
        rc_sound[slot]->volume = volume;
    }
}

void rc_media_loadMusic(string fname)
{
    if(rc_music != NULL)
    {
        Mix_FreeMusic(rc_music);
    }
    rc_music = Mix_LoadMUS(fname.c_str());
    if(rc_music == NULL)
    {
        cout << "Could not load music: " << Mix_GetError() << endl;
        return;
    }
}

void rc_media_deleteMusic()
{
    if(rc_music)
    {
        Mix_FreeMusic(rc_music);
        rc_music = NULL;
    }
}

void rc_media_playSound(int slot, int channel, int loops)
{
    if(rc_sound[slot] != NULL)
    {
        Mix_PlayChannel(channel, rc_sound[slot], loops);
    }
}

void rc_media_playSoundTimed(int slot, int channel, int loops, int ms)
{
    if(rc_sound[slot] != NULL)
    {
        Mix_PlayChannelTimed(channel, rc_sound[slot], loops, ms);
    }
}

void rc_media_playMusic(int loops)
{
    if(rc_music != NULL)
    {
        Mix_PlayMusic(rc_music, loops);
    }
}

int rc_media_musicIsPlaying()
{
    if(rc_music != NULL)
    {
        return Mix_PlayingMusic();
    }
    return 0;
}

void rc_media_pauseSound(int channel)
{
    if(Mix_Playing(channel))
    {
        Mix_Pause(channel);
    }
}

void rc_media_resumeSound(int channel)
{
    if(!Mix_Playing(channel))
    {
        Mix_Resume(channel);
    }
}

void rc_media_pauseMusic()
{
    if(Mix_PlayingMusic())
    {
        Mix_PauseMusic();
    }
}

void rc_media_resumeMusic()
{
    if(!Mix_PlayingMusic())
    {
        Mix_ResumeMusic();
    }
}

void rc_media_deleteSound(int slot)
{
    if(rc_sound[slot] != NULL)
    {
        Mix_FreeChunk(rc_sound[slot]);
        rc_sound[slot] = NULL;
    }
}

void rc_media_fadeMusicIn(int time, int loops)
{
    Mix_FadeInMusic(rc_music, loops, time);
}

void rc_media_fadeMusicOut(int time)
{
    Mix_FadeOutMusic(time);
}

bool rc_media_musicExists()
{
    if(rc_music != NULL)
        return true;
    return false;
}

void rc_media_setMusicVolume(int volume)
{
    Mix_VolumeMusic(volume);
}

int rc_media_getMusicVolume()
{
    return Mix_VolumeMusic(-1);
}

void rc_media_setMusicPosition(double position)
{
    Mix_SetMusicPosition(position);
}

double rc_media_getMusicPosition()
{
    return Mix_SetMusicPosition(-1);
}

void rc_media_rewindMusic()
{
    Mix_RewindMusic();
}

void rc_media_setSoundChannels(int max_channels)
{
    Mix_AllocateChannels(max_channels);
}

int rc_media_getSoundChannels()
{
    return Mix_AllocateChannels(-1);
}

bool rc_media_soundIsEnabled()
{
    return (bool) Mix_Init(0);
}

bool rc_media_soundExists(int slot)
{
    if(rc_sound[slot] != NULL)
        return true;
    return false;
}

void rc_media_setChannelVolume(int channel, int volume)
{
    Mix_Volume(channel, volume);
}

int rc_media_getChannelVolume(int channel)
{
    return Mix_Volume(channel, -1);
}

void rc_media_setSoundVolume(int slot, int volume)
{
    Mix_VolumeChunk(rc_sound[slot], volume);
}

int rc_media_getSoundVolume(int slot)
{
    return Mix_VolumeChunk(rc_sound[slot], -1);
}

void rc_media_stopMusic()
{
    Mix_HaltMusic();
}

void rc_media_stopSound(int channel)
{
    Mix_HaltChannel(channel);
}

int rc_media_channelIsPlaying(int channel)
{
    return Mix_Playing(channel);
}

int rc_media_channelIsPaused(int channel)
{
    return Mix_Paused(channel);
}

int rc_media_setChannelDistance(int channel, Uint8 dist)
{
    return Mix_SetDistance(channel, dist);
}

int rc_media_setChannelPanning(int channel, Uint8 l, Uint8 r)
{
    return Mix_SetPanning(channel, l, r);
}


int rc_media_setChannelSpacePosition(int channel, double angle, double distance)
{
    return Mix_SetPosition(channel, (Sint16)angle, (Uint8) distance);
}


//NETWORKING

//TCPsocket rc_socket[5];
//UDPsocket rc_udp_socket[5];
//UDPpacket * rc_udp_packet;
//int rc_udp_channel;
//string rc_udp_data;
//int rc_udp_len;
//int rc_udp_maxlen;
//string rc_udp_host;
//Uint16 rc_udp_port;

int rc_net_tcp_openSocket(int _socket, string host, Uint16 port)
{
    if(_socket >= MAX_SOCKETS)
    {
        cout << "TCP_SocketOpen Error: Maximum number of sockets available is " << MAX_SOCKETS << endl;
        return 0;
    }
    IPaddress ip;
    if(host.compare("") == 0)
    {
        //exit(0);
        SDLNet_ResolveHost(&ip, NULL, port);
    }
    else
    {
        //exit(0);
        SDLNet_ResolveHost(&ip, host.c_str(), port);
    }
    rc_socket[_socket] = SDLNet_TCP_Open(&ip);
    if(rc_socket[_socket])
    {
        //cout << "Add socket to socket_set" << endl;
        SDLNet_TCP_AddSocket(rc_socket_set, rc_socket[_socket]);
        return 1;
    }
    return 0;
}

void rc_net_tcp_closeSocket(int _socket)
{
    if( _socket >= MAX_SOCKETS)
    {
        cout << "TCP_SocketClose Error: Maximum number of sockets available is " << MAX_SOCKETS << endl;
        return;
    }
    SDLNet_TCP_DelSocket(rc_socket_set, rc_socket[_socket]);
    SDLNet_TCP_Close(rc_socket[_socket]);
    rc_socket[_socket] = NULL;
}

Uint32 rc_net_tcp_remoteHost(int _socket)
{
    IPaddress * ip =  SDLNet_TCP_GetPeerAddress(rc_socket[_socket]);
    return ip->host;
}

Uint32 rc_net_tcp_remotePort(int _socket)
{
    IPaddress * ip = SDLNet_TCP_GetPeerAddress(rc_socket[_socket]);
    return ip->port;
}

int rc_net_checkSockets(Uint32 m)
{
    return SDLNet_CheckSockets(rc_socket_set, m);
}

int rc_net_tcp_socketReady(int _socket)
{
    return SDLNet_SocketReady(rc_socket[_socket]);
}

int rc_net_tcp_getData(int socket, void * dst, int numBytes)
{
    int rtn = SDLNet_TCP_Recv(rc_socket[socket], dst, numBytes);
    return rtn;
}

int rc_net_tcp_getData_str(int socket, string * dst, int numBytes)
{
    char c[numBytes+1];
    int rtn = rc_net_tcp_getData(socket, c, numBytes);
    c[numBytes] = '\0';
    //cout << "Read bytes: " << (string)c << endl;
    dst[0] = c;
    return rtn;
}

int rc_net_tcp_getData_dbl(int socket, double * dst, int numBytes)
{
    int i[numBytes];
    int rtn = rc_net_tcp_getData(socket, i, numBytes);
    for(int n = 0; n < numBytes; n++)
    {
        dst[n] = i[n];
    }
    return rtn;
}

void rc_net_tcp_sendData(int socket, const char * data, int numBytes)
{
    SDLNet_TCP_Send(rc_socket[socket], data, numBytes);
}

bool rc_net_tcp_acceptSocket(int socket_server, int socket_client)
{
    //cout << "\n\nthis is a test\n\n";
    if(rc_socket[socket_server] == NULL)
    {
        //cout << "no server" << endl;
        return false;
    }
    bool val = (rc_socket[socket_client] = SDLNet_TCP_Accept(rc_socket[socket_server]));
    if(val)
        SDLNet_TCP_AddSocket(rc_socket_set, rc_socket[socket_client]);
    //cout << "cp1\n";
    return val;
}

bool rc_net_udp_openSocket(int socket, Uint16 port)
{
    bool rtn = (bool)(rc_udp_socket[socket] = SDLNet_UDP_Open(port));
    if(rtn)
        SDLNet_UDP_AddSocket(rc_socket_set, rc_udp_socket[socket]);
	return rtn;
}

int rc_net_udp_socketReady(int socket)
{
    return SDLNet_SocketReady(rc_udp_socket[socket]);
}

int rc_net_udp_readStream(int socket, string * dst, string * host, double * port)
{
    //cout << "DEBUG READSTREAM\n";
    //UDPsocket sd;       /* Socket descriptor */
	//UDPpacket *p;       /* Pointer to packet memory */
	//int quit = 0;

    /* Make space for the packet */
	//if (!(rc_udp_packet = SDLNet_AllocPacket(512)))
	//{
	//	fprintf(stderr, "SDLNet_AllocPacket: %s\n", SDLNet_GetError());
	//	exit(EXIT_FAILURE);
	//}

	/* Main loop */

    /* Wait a packet. UDP_Recv returns != 0 if a packet is coming */
    //while(!quit)
    //{
        if (SDLNet_UDP_Recv(rc_udp_socket[socket], rc_udp_packet))
        {
            //printf("UDP Packet incoming\n");
            //printf("\tChan:    %d\n", rc_udp_packet->channel);
            rc_udp_channel = rc_udp_packet->channel;
            //printf("\tData:    %s\n", (char *)rc_udp_packet->data);
            const char * c = (const char *)rc_udp_packet->data;
            //rc_udp_data = (string)c;
            *dst = (string)c;
            //printf("\tLen:     %d\n", rc_udp_packet->len);
            rc_udp_len = rc_udp_packet->len;
            //printf("\tMaxlen:  %d\n", rc_udp_packet->maxlen);
            rc_udp_maxlen = rc_udp_packet->maxlen;
            //printf("\tStatus:  %d\n", rc_udp_packet->status);
            //printf("\tAddress: %x %x\n", rc_udp_packet->address.host, rc_udp_packet->address.port);
            //rc_udp_host = SDLNet_ResolveIP(&rc_udp_packet->address);
            *host = SDLNet_ResolveIP(&rc_udp_packet->address);
            //rc_udp_port = rc_udp_packet->address.port;
            *port = rc_udp_packet->address.port;
            return 1;
            //quit = 1;
        }
        else
        {
            rc_udp_channel = 0;
            //rc_udp_data = "";
            *dst = "";
            rc_udp_len = 0;
            rc_udp_maxlen = rc_udp_packet->maxlen;
            //rc_udp_host = SDLNet_ResolveIP(&rc_udp_packet->address);
            *host = SDLNet_ResolveIP(&rc_udp_packet->address);
            //rc_udp_port = rc_udp_packet->address.port;
            *port = rc_udp_packet->address.port;
            return 0;
        }

    //}

    //SDLNet_FreePacket(rc_udp_packet);
}

Uint32 rc_net_udp_len()
{
    return rc_udp_len;
}

Uint32 rc_net_udp_maxlen()
{
    return rc_udp_maxlen;
}

string rc_net_udp_getRemoteHost(int socket)
{
    IPaddress * ip = SDLNet_UDP_GetPeerAddress(rc_udp_socket[socket],0);
    //
    return SDLNet_ResolveIP(ip);
}

Uint32 rc_net_udp_getRemotePort(int socket)
{
    IPaddress * ip = SDLNet_UDP_GetPeerAddress(rc_udp_socket[socket],0);
    return ip->port;
}

int rc_net_udp_closeSocket(int socket)
{
    SDLNet_UDP_DelSocket(rc_socket_set, rc_udp_socket[socket]);
    SDLNet_UDP_Close(rc_udp_socket[socket]);
    rc_udp_socket[socket] = NULL;
    return 0;
}

int rc_net_udp_sendData(int slot, string host, Uint16 port, string s_data)
{
    IPaddress srvadd;

    if(s_data.length()+1 > rc_packet_size)
    {
        rc_packet_size = SDLNet_ResizePacket(rc_udp_packet, s_data.length()+1);
        if(rc_packet_size < s_data.length())
        {
            cout << "UDP_SendData Error: " << SDLNet_GetError() << endl;
            return 0;
        }
    }


    if(rc_udp_packet == NULL)
        return 0;


    if (SDLNet_ResolveHost(&srvadd, host.c_str(), port) == -1)
	{
		std::cout << "UDP_SendData Error: " << SDLNet_GetError() << "\n";
		//exit(EXIT_FAILURE);
		return 0;
	}

	rc_udp_packet->address.host = srvadd.host;
    rc_udp_packet->address.port = srvadd.port;
	rc_udp_packet->data = (Uint8*)s_data.c_str();


	rc_udp_packet->len = s_data.length()+1;
	//cout << "#Data = " << (char*)rc_udp_packet->data << endl;
	//cout << "#Length = " << rc_udp_packet->len << endl;
	SDLNet_UDP_Send(rc_udp_socket[slot], -1, rc_udp_packet);

    return 1;
}

string rc_byteToString(Uint8 n)
{
    stringstream s;
    s << (Uint32)n;
    return s.str();
}

string rc_net_myLocalIP()
{
    //cout << "MYLOCALIP" << endl;
    IPaddress myIP;
    myIP.host = 0;
    myIP.port = 0;
    string net_name = SDLNet_ResolveIP(&myIP);
    SDLNet_ResolveHost(&myIP,net_name.c_str(),0);
    string ip = "";
    ip += rc_byteToString((Uint8)myIP.host) + ".";
    ip += rc_byteToString((Uint8)(myIP.host >> 8)) + ".";
    ip += rc_byteToString((Uint8)(myIP.host >> 16)) + ".";
    ip += rc_byteToString((Uint8)(myIP.host >> 24));
    //cout << "vagina: " << myIP.host << endl;
    return ip;
}

//#################VIDEO PLAYBACK#####################################################################

#ifdef RC_USE_TREMOR
void videoPlayer_audio_callback(void *userdata, Uint8 *stream, int len)
{
    // !!! FIXME: this should refuse to play if item->playms is in the future.
    //const Uint32 now = SDL_GetTicks() - baseticks;
    Sint16 *dst = (Sint16 *) stream;

    while (audio_queue && (len > 0))
    {
        volatile AudioQueue *item = audio_queue;
        AudioQueue *next = item->next;
        const int channels = item->audio->channels;

        const Sint32 *src = (Sint32 *) (item->audio->samples + (item->offset * channels));

        int cpy = (item->audio->frames - item->offset) * channels;
        int i;

        if (cpy > (len / sizeof (Sint16)))
            cpy = len / sizeof (Sint16);

        for (i = 0; i < cpy; i++)
        {
            const Sint32 val = *(src++);

            if (val < -32768)
                *(dst++) = -32768;
            else if (val > 32767)
                *(dst++) = 32767;
            else
            {
                *(dst++) = (Sint16) (val);
            }
        } // for

        item->offset += (cpy / channels);
        len -= cpy * sizeof (Sint16);

        if (item->offset >= item->audio->frames)
        {
            THEORAPLAY_freeAudio(item->audio);
            free((void *) item);
            audio_queue = next;
        } // if
    } // while

    if (!audio_queue)
        audio_queue_tail = NULL;

    if (len > 0)
        memset(dst, '\0', len);
} // audio_callback
#else
void videoPlayer_audio_callback(void *userdata, Uint8 *stream, int len)
{
    // !!! FIXME: this should refuse to play if item->playms is in the future.
    //const Uint32 now = SDL_GetTicks() - baseticks;
    Sint16 *dst = (Sint16 *) stream;

    while (audio_queue && (len > 0))
    {
        volatile AudioQueue *item = audio_queue;
        AudioQueue *next = item->next;
        const int channels = item->audio->channels;

        const float *src = item->audio->samples + (item->offset * channels);
        int cpy = (item->audio->frames - item->offset) * channels;
        int i;

        if (cpy > (len / sizeof (Sint16)))
            cpy = len / sizeof (Sint16);

        for (i = 0; i < cpy; i++)
        {
            const float val = *(src++);
            if (val < -1.0f)
                *(dst++) = -32768;
            else if (val > 1.0f)
                *(dst++) = 32767;
            else
                *(dst++) = (Sint16) (val * 32767.0f);
        } // for

        item->offset += (cpy / channels);
        len -= cpy * sizeof (Sint16);

        if (item->offset >= item->audio->frames)
        {
            THEORAPLAY_freeAudio(item->audio);
            free((void *) item);
            audio_queue = next;
        } // if
    } // while

    if (!audio_queue)
        audio_queue_tail = NULL;

    if (len > 0)
        memset(dst, '\0', len);
} // audio_callback
#endif

static void videoPlayer_queue_audio(const THEORAPLAY_AudioPacket *audio)
{
    AudioQueue *item = (AudioQueue *) malloc(sizeof (AudioQueue));
    if (!item)
    {
        THEORAPLAY_freeAudio(audio);
        return;  // oh well.
    } // if

    item->audio = audio;
    item->offset = 0;
    item->next = NULL;

    //SDL_LockAudio();
    if (audio_queue_tail)
        audio_queue_tail->next = item;
    else
        audio_queue = item;
    audio_queue_tail = item;
    //SDL_UnlockAudio();
} // queue_audio

void rc_media_loadVideo(string fname)
{
    //cout << "CRAP" << endl;
    decoder = THEORAPLAY_startDecodeFile(fname.c_str(), 30, THEORAPLAY_VIDFMT_RGBA);
    if(!decoder)
    {
        decoder = NULL;
        cout << "Failed to load video: " << fname << endl;
        return;
    }

    rc_video_file = fname;
    while (!audio || !video)
    {
        if (!audio) audio = THEORAPLAY_getAudio(decoder);
        if (!video) video = THEORAPLAY_getVideo(decoder);
        SDL_Delay(10);
    } // if
    overlay = SDL_CreateTexture(rc_win_renderer[rc_active_window], SDL_PIXELFORMAT_ABGR8888, SDL_TEXTUREACCESS_STREAMING, video->width, video->height);
    SDL_SetTextureBlendMode(overlay, SDL_BLENDMODE_BLEND);
    SDL_SetTextureAlphaMod(overlay, 255);
    framems = (video->fps == 0.0) ? 0 : ((Uint32) (1000.0 / video->fps));
    rc_video_dstrect.x = 0;
    rc_video_dstrect.y = 0;
    rc_video_dstrect.w = video->width;
    rc_video_dstrect.h = video->height;
    rc_video_width = video->width;
    rc_video_height = video->height;

    if (!overlay)
    {
        fprintf(stderr, "Video failed: %s\n", SDL_GetError());
        return;
    }
    //} // else

    initfailed = quit = (!overlay);
    rc_video_end = false;


    //fprintf(stderr, "b_debug 3.5\n");
}

int rc_media_getVideoStats(string fname, double * v_len, double * v_fps, double * v_width, double * v_height)
{
    //cout << "CRAP" << endl;
    if(decoder)
        return 0;
    decoder = THEORAPLAY_startDecodeFile(fname.c_str(), 30, THEORAPLAY_VIDFMT_RGBA);
    if(!decoder)
    {
        decoder = NULL;
        cout << "Failed to load video: " << fname << endl;
        return 0;
    }

    while(THEORAPLAY_isDecoding(decoder))
    {
        if(!video)
            video = THEORAPLAY_getVideo(decoder);
        if(video)
        {
            rc_video_length = video->playms;
            rc_video_fps = video->fps;
            rc_video_width = video->width;
            rc_video_height = video->height;
            THEORAPLAY_freeVideo(video);
            video = NULL;
        }

        if(!audio)
            audio = THEORAPLAY_getAudio(decoder);
        if(audio)
        {
            THEORAPLAY_freeAudio(audio);
            audio = NULL;
        }

        //SDL_Delay(1);
    }

    THEORAPLAY_stopDecode(decoder);
    decoder = NULL;

    *v_len = rc_video_length;
    *v_fps = rc_video_fps;
    *v_width = rc_video_width;
    *v_height = rc_video_height;
    rc_video_length = 0;
    rc_video_fps = 0;
    rc_video_width = 0;
    rc_video_height = 0;
    return 1;
}

void rc_media_getVideoSize(double * w, double * h)
{
    *w = rc_video_width;
    *h = rc_video_height;
}

void rc_media_setVideoDrawRect(int x, int y, int w, int h)
{
    rc_video_dstrect.x = x;
    rc_video_dstrect.y = y;
    rc_video_dstrect.w = w;
    rc_video_dstrect.h = h;
}

void rc_media_getVideoDrawRect(double * x, double * y, double * w, double * h)
{
    *x = rc_video_dstrect.x;
    *y = rc_video_dstrect.y;
    *w = rc_video_dstrect.w;
    *h = rc_video_dstrect.h;
}

int rc_media_videoLength()
{
    return rc_video_length;
}

void rc_cleanResume()
{
    //cout << "tat" << endl;
    //if (overlay) SDL_DestroyTexture(overlay);
    if (video) THEORAPLAY_freeVideo(video);
    if (audio) THEORAPLAY_freeAudio(audio);
    if (decoder) THEORAPLAY_stopDecode(decoder);
    //cout  << "bubble wrap" << endl;
    //SDL_ClearQueuedAudio(0);
    //while(SDL_GetQueuedAudioSize(0)>0){}

    rc_video_isPlaying = false;
    video = NULL;
    audio = NULL;
    decoder = NULL;
    decoder = THEORAPLAY_startDecodeFile(rc_video_file.c_str(), 30, THEORAPLAY_VIDFMT_RGBA);
    while(!audio && !video && THEORAPLAY_isDecoding(decoder))
    {
        audio = THEORAPLAY_getAudio(decoder);
        video = THEORAPLAY_getVideo(decoder);
        if(audio)
        {
            if(audio->playms <= rc_video_pauseTicks)
            {
                THEORAPLAY_freeAudio(audio);
                audio = NULL;
            }
        }

        if(video)
        {
            if(video->playms <= rc_video_pauseTicks)
            {
                THEORAPLAY_freeVideo(video);
                video = NULL;
            }
        }
    }
    //cout << "bankai" << endl;
}

void rc_media_playVideo(int loops)
{
    if(rc_video_isPlaying)
        return;
    if(rc_video_reset)
    {
        //cout << "RESET" << endl;
        decoder = THEORAPLAY_startDecodeFile(rc_video_file.c_str(), 30, THEORAPLAY_VIDFMT_RGBA);
        if(!decoder)
        {
            cout << "Video Reset Error: " << SDL_GetError() << endl;
        }
        while(!audio || !video)
        {
            if(!audio) audio = THEORAPLAY_getAudio(decoder);
            if(!video) video = THEORAPLAY_getVideo(decoder);
            SDL_Delay(10);
        }
        rc_video_reset = false;
    }

    Mix_CloseAudio();
    rc_video_currentLoop = 0;
    rc_video_loops = loops;
    rc_video_isPlaying = true;

    if(Mix_OpenAudio(audio->freq, AUDIO_S16SYS, audio->channels, 2048) < 0)
    {
        rc_audio_isOpen = false;
        cout << "Open Audio Error: " << Mix_GetError() <<endl;
        if(Mix_OpenAudio(MIX_DEFAULT_FREQUENCY, MIX_DEFAULT_FORMAT, 2, 2048) < 0)
        {
            cout << "Open Audio Error: " << Mix_GetError() << endl;
        }
        quit = 1;
        return;
    }

    Mix_HookMusic(videoPlayer_audio_callback, NULL);

    rc_audio_isOpen = true;

    if(!rc_video_isLoaded)
    {
        while (audio)
        {
            videoPlayer_queue_audio(audio);
            audio = THEORAPLAY_getAudio(decoder);
        } // while
    }

    baseticks = SDL_GetTicks();
    rc_video_isLoaded = true;

    if (!quit)
        Mix_Pause(-1);
}

void rc_media_stopVideo()
{
    //if(!rc_video_isPlaying)
    //    return;

    //cout << "baking soda" << endl;
    //if (overlay) SDL_DestroyTexture(overlay);
    if (video) THEORAPLAY_freeVideo(video);
    if (audio) THEORAPLAY_freeAudio(audio);
    if (decoder) THEORAPLAY_stopDecode(decoder);
    //cout  << "bubble wrap" << endl;
    //SDL_ClearQueuedAudio(0);
    //while(SDL_GetQueuedAudioSize(0)>0){}
    SDL_Delay(1500);
    if(rc_audio_isOpen)
    {
        Mix_CloseAudio();
        if(Mix_OpenAudio(MIX_DEFAULT_FREQUENCY, MIX_DEFAULT_FORMAT, 2, 2048) < 0)
        {
            cout << "OpenAudio Error: " << Mix_GetError() << endl;
        }
        Mix_HookMusic(NULL, NULL);
        rc_audio_isOpen = false;
    }
    rc_video_isPlaying = false;
    rc_video_loops = 0;
    rc_video_currentLoop = 0;
    rc_video_position = 0;
    rc_video_reset = true;
    rc_video_end = false;
    video = NULL;
    audio = NULL;
    decoder = NULL;
    //cout << "mini" << endl;
}

static bool cycleVideo()
{
    //cout << "video_start" << endl;
    if(!rc_video_isPlaying)
        return false;
    //cout << "never print this" << endl;
    //int q = !quit;
    //int tp = THEORAPLAY_isDecoding(decoder);
    //cout << "VARS = " << q << " & " << tp << endl;
    int isDecode = THEORAPLAY_isDecoding(decoder);
    if(isDecode)
        rc_video_end = false;
    else
    {
        rc_video_currentLoop++;
        if((rc_video_currentLoop <= rc_video_loops) || (rc_video_loops < 0))
        {
            rc_media_stopVideo();
            rc_media_playVideo(rc_video_loops);
            return true;
        }
        rc_video_end = true;
        rc_video_isPlaying = false;
    }

    if (!quit && isDecode)
    {
        const Uint32 now = SDL_GetTicks() - baseticks;
        rc_video_pauseTicks = now;
        rc_video_position = now;

        if (!video)
            video = THEORAPLAY_getVideo(decoder);

        //fprintf(stderr, "b_debug A\n");

        // Play video frames when it's time.
        if (video && (video->playms <= now))
        {
            //fprintf(stderr, "b_debug B\n");
            //printf("Play video frame (%u ms)!\n", video->playms);
            if ( framems && ((now - video->playms) >= framems) )
            {
                //fprintf(stderr, "b_debug C\n");
                // Skip frames to catch up, but keep track of the last one
                //  in case we catch up to a series of dupe frames, which
                //  means we'd have to draw that final frame and then wait for
                //  more.
                const THEORAPLAY_VideoFrame *last = video;
                while ((video = THEORAPLAY_getVideo(decoder)) != NULL)
                {
                    THEORAPLAY_freeVideo(last);
                    last = video;
                    if ((now - video->playms) < framems)
                        break;
                } // while

                //fprintf(stderr, "b_debug D\n");

                if (!video)
                    video = last;
            } // if

            //fprintf(stderr, "b_debug B.1\n");
            int lock_tex = SDL_LockTexture(overlay, NULL, &overlay_pixels, &pitch);
            //fprintf(stderr, "b_debug B.1.2\n");

            if (!video)  // do nothing; we're far behind and out of options.
            {
                static int warned = 0;
                if (!warned)
                {
                    warned = 1;
                    fprintf(stderr, "WARNING: Playback can't keep up!\n");
                } // if
            } // if
            else if (lock_tex<0)
            {
                //fprintf(stderr, "b_debug E\n");
                static int warned = 0;
                if (!warned)
                {
                    warned = 1;
                    fprintf(stderr, "Couldn't lock video frame: %s\n", SDL_GetError());
                } // if
            } // else if
            else
            {
                //fprintf(stderr, "b_debug 4\n");
                //SDL_Rect dstrec = { 0, 0, video->width, video->height };
                const int w = video->width;
                const int h = video->height;
                Uint8 *dst;

                const Uint8 * vbuf = (const Uint8*)video->pixels;

                dst = (Uint8*)overlay_pixels;

                SDL_memcpy(dst, vbuf, w*h*4);

                //fprintf(stderr, "b_debug 7\n");

                SDL_UnlockTexture(overlay);

                //if (SDL_DisplayYUVOverlay(overlay, &dstrect) != 0)
                if(SDL_RenderCopy(rc_win_renderer[rc_active_window], overlay, NULL, &rc_video_dstrect) < 0)
                {
                    static int warned = 0;
                    if (!warned)
                    {
                        warned = 1;
                        fprintf(stderr, "Couldn't display video frame: %s\n", SDL_GetError());
                    } // if
                } // if
                else
                {
                    //SDL_RenderPresent(rc_win_renderer[rc_active_window]);
                    //cout << "window drawn" << endl;
                }
            } // else
            //fprintf(stderr, "b_debug B.5\n");

            THEORAPLAY_freeVideo(video);
            video = NULL;
        } // if
        else  // no new video frame? Give up some CPU.
        {
            SDL_Delay(10);
        } // else

        //fprintf(stderr, "b_debug F\n");
        while ((audio = THEORAPLAY_getAudio(decoder)) != NULL)
            videoPlayer_queue_audio(audio);

        return true;
    } // while
    return false;

} // playfile

void rc_media_deleteVideo()
{
    //cout << "cream soda" << endl;
    if (overlay) SDL_DestroyTexture(overlay);
    overlay = NULL;
    if (video) THEORAPLAY_freeVideo(video);
    video = NULL;
    if (audio) THEORAPLAY_freeAudio(audio);
    audio = NULL;
    if (decoder) THEORAPLAY_stopDecode(decoder);
    decoder = NULL;
    //cout  << "bubble wrap" << endl;
    if(rc_audio_isOpen)
    {
        Mix_CloseAudio();
        if(Mix_OpenAudio(MIX_DEFAULT_FREQUENCY, MIX_DEFAULT_FORMAT, 2, 2048) < 0)
        {
            cout << "OpenAudio Error: " << Mix_GetError() << endl;
        }
        rc_audio_isOpen = false;
        Mix_HookMusic(NULL, NULL);
    }
    rc_video_file = "";
    rc_video_isLoaded = false;
    rc_video_isPlaying = false;
    rc_video_loops = 0;
    rc_video_position = 0;
    rc_video_length = 0;
    rc_video_width = 0;
    rc_video_height = 0;
    rc_video_dstrect.x = 0;
    rc_video_dstrect.y = 0;
    rc_video_dstrect.w = 0;
    rc_video_dstrect.h = 0;
    //cout << "mini" << endl;
}

void rc_media_pauseVideo()
{
    //if(rc_video_isPaused)
    //    return;
    rc_video_isPlaying = false;
    if (video) THEORAPLAY_freeVideo(video);
    if (audio) THEORAPLAY_freeAudio(audio);
    Mix_Pause(-1);
    SDL_Delay(1500);
    if(rc_audio_isOpen)
    {
        Mix_CloseAudio();
        if(Mix_OpenAudio(MIX_DEFAULT_FREQUENCY, MIX_DEFAULT_FORMAT, 2, 2048) < 0)
        {
            cout << "OpenAudio Error: " << Mix_GetError() << endl;
        }
        rc_audio_isOpen = false;
    }
    video = NULL;
    audio = NULL;
    rc_video_isPaused = true;
}

void rc_media_resumeVideo()
{
    if(!rc_video_isPaused)
        return;

    //fprintf(stderr, "RESUME\n" );

    int dec_cycle = 0;

    while(!audio || !video)
    {
        if(!audio) audio = THEORAPLAY_getAudio(decoder);
        if(!video) video = THEORAPLAY_getVideo(decoder);
        SDL_Delay(10);
        dec_cycle++;
        if(dec_cycle == 100)
            rc_cleanResume();
        if(dec_cycle >= 200)
        {
            rc_video_isPaused = false;
            rc_media_stopVideo();
            return;
        }
        //fprintf(stderr,"working\n");
    }

    //fprintf(stderr,"debug 1\n");
    if(!rc_audio_isOpen)
        Mix_CloseAudio();
    rc_video_isPlaying = true;
    //fprintf(stderr,"debug 2\n");

    if(!rc_audio_isOpen)
    {
        if(Mix_OpenAudio(audio->freq, AUDIO_S16SYS, audio->channels, 2048) < 0)
        {
            cout << "Open Audio Error: " << Mix_GetError() <<endl;
            if(Mix_OpenAudio(MIX_DEFAULT_FREQUENCY, MIX_DEFAULT_FORMAT, 2, 2048) < 0)
            {
                cout << "OpenAudio Error: " << Mix_GetError() << endl;
            }
            quit = 1;
            return;
        }
        rc_audio_isOpen = true;
    }
    //fprintf(stderr,"debug 4\n");

    if(!rc_video_isLoaded)
    {
        //cout << "GILLITEEN" <<endl;
        while (audio)
        {
            videoPlayer_queue_audio(audio);
            audio = THEORAPLAY_getAudio(decoder);
        } // while
    }

    baseticks = SDL_GetTicks() - rc_video_pauseTicks;
    rc_video_isLoaded = true;
    rc_video_isPaused = false;

    //fprintf(stderr, "b_debug x\n");

    if (!quit)
        Mix_Pause(-1);

}

Uint32 rc_media_videoPosition()
{
    return rc_video_position;
}

void rc_media_setVideoPosition(Uint32 vpos)
{
    bool is_playing = rc_video_isPlaying;
    if(is_playing) rc_media_pauseVideo();
    rc_video_pauseTicks = vpos;
    rc_video_position = vpos;
    if(is_playing) rc_media_resumeVideo();
}

bool rc_media_videoIsPlaying()
{
    return rc_video_isPlaying;
}

bool rc_media_videoEnd()
{
    return rc_video_end;
}

bool rc_media_videoExists()
{
    if(decoder)
        return true;
    return false;
}

void rc_media_setVideoAlpha(Uint8 alpha)
{
    if(overlay)
        SDL_SetTextureAlphaMod(overlay, alpha);
}
