diff --git a/desmume/src/commandline.cpp b/desmume/src/commandline.cpp index cfe87f775..cb6c23ac4 100644 --- a/desmume/src/commandline.cpp +++ b/desmume/src/commandline.cpp @@ -80,6 +80,9 @@ CommandLine::CommandLine() , disable_sound(0) , disable_limiter(0) , windowed_fullscreen(0) +, frameskip(0) +, horizontal(0) +, scale(1.0) , _rtc_day(-1) , _rtc_hour(-1) { @@ -122,12 +125,15 @@ static const char* help_string = \ " --windowed-fullscreen" ENDL " Launches in windowed fullscreen (same as alt+enter)" ENDL #else +" --scale N scale factor for window; default 1.0" ENDL +" --horizontal display touch screen to the right; default OFF" ENDL " --nojoy Disables joystick support" ENDL #endif " --disable-sound Disables the sound output" ENDL " --disable-limiter Disables the 60fps limiter" ENDL " --rtc-day D Override RTC day, 0=Sunday, 6=Saturday" ENDL " --rtc-hour H Override RTC hour, 0=midnight, 23=an hour before" ENDL +" --frameskip N Set frameskip to N; default 0" ENDL ENDL "Arguments affecting overall emulation parameters (`sync settings`): " ENDL #ifdef HAVE_JIT @@ -195,6 +201,8 @@ ENDL #define OPT_3D_RENDER 3 #define OPT_3D_TEXTURE_UPSCALE 81 #define OPT_GPU_RESOLUTION_MULTIPLIER 82 +#define OPT_FRAMESKIP 83 +#define OPT_SCALE 84 #define OPT_JIT_SIZE 100 #define OPT_CONSOLE_TYPE 200 @@ -258,7 +266,10 @@ bool CommandLine::parse(int argc,char **argv) { "windowed-fullscreen", no_argument, &windowed_fullscreen, 1 }, #else { "nojoy", no_argument, &_commandline_linux_nojoy, 1}, + { "horizontal", no_argument, &horizontal, 1}, + { "scale", required_argument, NULL, OPT_SCALE}, #endif + { "frameskip", required_argument, NULL, OPT_FRAMESKIP}, { "disable-sound", no_argument, &disable_sound, 1}, { "disable-limiter", no_argument, &disable_limiter, 1}, { "rtc-day", required_argument, NULL, OPT_RTC_DAY}, @@ -335,6 +346,8 @@ bool CommandLine::parse(int argc,char **argv) case OPT_3D_RENDER: _render3d = optarg; break; case OPT_3D_TEXTURE_UPSCALE: texture_upscale = atoi(optarg); break; case OPT_GPU_RESOLUTION_MULTIPLIER: gpu_resolution_multiplier = atoi(optarg); break; + case OPT_SCALE: scale = atof(optarg); break; + case OPT_FRAMESKIP: frameskip = atoi(optarg); break; //RTC settings case OPT_RTC_DAY: _rtc_day = atoi(optarg); break; diff --git a/desmume/src/commandline.h b/desmume/src/commandline.h index 467a69b05..47a28aca6 100644 --- a/desmume/src/commandline.h +++ b/desmume/src/commandline.h @@ -49,6 +49,7 @@ public: int texture_upscale; int gpu_resolution_multiplier; int language; + float scale; std::string nds_file; std::string play_movie_file; std::string record_movie_file; @@ -65,6 +66,8 @@ public: int disable_sound; int disable_limiter; int windowed_fullscreen; + int frameskip; + int horizontal; bool parse(int argc,char **argv); diff --git a/desmume/src/frontend/posix/cli/main.cpp b/desmume/src/frontend/posix/cli/main.cpp index c47213c3b..9e16f53ea 100644 --- a/desmume/src/frontend/posix/cli/main.cpp +++ b/desmume/src/frontend/posix/cli/main.cpp @@ -29,18 +29,6 @@ #define VERSION "Unknown version" #endif -/* - * FIXME: Not sure how to detect OpenGL in a platform portable way. - */ -#ifdef HAVE_GL_GL_H -#define INCLUDE_OPENGL_2D -#endif - -#ifdef INCLUDE_OPENGL_2D -#include -#include -#endif - #ifndef CLI_UI #define CLI_UI #endif @@ -68,9 +56,15 @@ class CliDriver : public BaseDriver private: gdbstub_handle_t __stubs[2]; public: + virtual void EMU_DebugIdleEnter() { + SPU_Pause(1); + } virtual void EMU_DebugIdleUpdate() { gdbstub_wait(__stubs, -1L); } + virtual void EMU_DebugIdleWakeUp() { + SPU_Pause(0); + } virtual void setStubs(gdbstub_handle_t stubs[2]) { this->__stubs[0] = stubs[0]; this->__stubs[1] = stubs[1]; @@ -94,6 +88,7 @@ static float nds_screen_size_ratio = 1.0f; static SDL_Window * window; static SDL_Renderer * renderer; +static SDL_Texture *screen[2]; /* Flags to pass to SDL_SetVideoMode */ static int sdl_videoFlags; @@ -148,14 +143,9 @@ class configured_features : public CommandLine { public: int auto_pause; - int frameskip; int engine_3d; int savetype; - -#ifdef INCLUDE_OPENGL_2D - int opengl_2d; -#endif int firmware_language; }; @@ -164,15 +154,10 @@ static void init_config( class configured_features *config) { config->auto_pause = 0; - config->frameskip = 0; config->engine_3d = 1; config->savetype = 0; -#ifdef INCLUDE_OPENGL_2D - config->opengl_2d = 0; -#endif - /* use the default language */ config->firmware_language = -1; } @@ -183,7 +168,6 @@ fill_config( class configured_features *config, int argc, char ** argv) { GOptionEntry options[] = { { "auto-pause", 0, 0, G_OPTION_ARG_NONE, &config->auto_pause, "Pause emulation if focus is lost", NULL}, - { "frameskip", 0, 0, G_OPTION_ARG_INT, &config->frameskip, "Set frameskip", "FRAMESKIP"}, { "3d-engine", 0, 0, G_OPTION_ARG_INT, &config->engine_3d, "Select 3d rendering engine. Available engines:\n" "\t\t\t\t\t\t 0 = 3d disabled\n" "\t\t\t\t\t\t 1 = internal rasterizer (default)\n" @@ -197,9 +181,6 @@ fill_config( class configured_features *config, "\t\t\t\t\t\t 5 = FLASH 2mbit\n" "\t\t\t\t\t\t 6 = FLASH 4mbit\n", "SAVETYPE"}, -#ifdef INCLUDE_OPENGL_2D - { "opengl-2d", 0, 0, G_OPTION_ARG_NONE, &config->opengl_2d, "Enables using OpenGL for screen rendering", NULL}, -#endif { "fwlang", 0, 0, G_OPTION_ARG_INT, &config->firmware_language, "Set the language in the firmware, LANG as follows:\n" "\t\t\t\t\t\t 0 = Japanese\n" "\t\t\t\t\t\t 1 = English\n" @@ -283,183 +264,38 @@ joinThread_gdb( void *thread_handle) { } #endif -#ifdef INCLUDE_OPENGL_2D -/* initialization openGL function */ -static int -initGL( GLuint *screen_texture) { - GLenum errCode; - u16 blank_texture[256 * 256]; - - memset(blank_texture, 0, sizeof(blank_texture)); - - /* Enable Texture Mapping */ - glEnable( GL_TEXTURE_2D ); - - /* Set the background black */ - glClearColor( 0.0f, 0.0f, 0.0f, 0.5f ); - - /* Depth buffer setup */ - glClearDepth( 1.0f ); - - /* Enables Depth Testing */ - glEnable( GL_DEPTH_TEST ); - - /* The Type Of Depth Test To Do */ - glDepthFunc( GL_LEQUAL ); - - /* Create The Texture */ - glGenTextures(2, screen_texture); - - for (int i = 0; i < 2; i++) - { - glBindTexture(GL_TEXTURE_2D, screen_texture[i]); - - /* Generate The Texture */ - glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 256, 256, - 0, GL_RGBA, - GL_UNSIGNED_SHORT_1_5_5_5_REV, - blank_texture); - - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); - - /* Linear Filtering */ - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); - } - - if ((errCode = glGetError()) != GL_NO_ERROR) { - const GLubyte *errString; - - errString = gluErrorString(errCode); - fprintf( stderr, "Failed to init GL: %s\n", errString); - - return 0; - } - - return 1; -} - -static void -resizeWindow( u16 width, u16 height, GLuint *screen_texture) { - - int comp_width = 3 * width; - int comp_height = 2 * height; - GLenum errCode; - - initGL(screen_texture); - -#ifdef HAVE_LIBAGG - Hud.reset(); -#endif - - if ( comp_width > comp_height) { - width = 2*height/3; - } - height = 3*width/2; - nds_screen_size_ratio = 256.0 / (double)width; - - /* Setup our viewport. */ - glViewport( 0, 0, ( GLint )width, ( GLint )height ); - - /* - * change to the projection matrix and set - * our viewing volume. - */ - glMatrixMode( GL_PROJECTION ); - glLoadIdentity( ); - - gluOrtho2D( 0.0, 256.0, 384.0, 0.0); - - /* Make sure we're chaning the model view and not the projection */ - glMatrixMode( GL_MODELVIEW ); - - /* Reset The View */ - glLoadIdentity( ); - - if ((errCode = glGetError()) != GL_NO_ERROR) { - const GLubyte *errString; - - errString = gluErrorString(errCode); - fprintf( stderr, "GL resize failed: %s\n", errString); - } -} - - -static void -opengl_Draw(GLuint *texture) { - const NDSDisplayInfo &displayInfo = GPU->GetDisplayInfo(); - - /* Clear The Screen And The Depth Buffer */ - glClear( GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT ); - - /* Move Into The Screen 5 Units */ - glLoadIdentity( ); - - /* Draw the main screen as a textured quad */ - glBindTexture(GL_TEXTURE_2D, texture[NDSDisplayID_Main]); - glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, GPU_FRAMEBUFFER_NATIVE_WIDTH, GPU_FRAMEBUFFER_NATIVE_HEIGHT, - GL_RGBA, - GL_UNSIGNED_SHORT_1_5_5_5_REV, - displayInfo.renderedBuffer[NDSDisplayID_Main]); - - GLfloat backlightIntensity = displayInfo.backlightIntensity[NDSDisplayID_Main]; - - glBegin(GL_QUADS); - glTexCoord2f(0.00f, 0.00f); glVertex2f( 0.0f, 0.0f); glColor4f(backlightIntensity, backlightIntensity, backlightIntensity, 1.0f); - glTexCoord2f(1.00f, 0.00f); glVertex2f(256.0f, 0.0f); glColor4f(backlightIntensity, backlightIntensity, backlightIntensity, 1.0f); - glTexCoord2f(1.00f, 0.75f); glVertex2f(256.0f, 192.0f); glColor4f(backlightIntensity, backlightIntensity, backlightIntensity, 1.0f); - glTexCoord2f(0.00f, 0.75f); glVertex2f( 0.0f, 192.0f); glColor4f(backlightIntensity, backlightIntensity, backlightIntensity, 1.0f); - glEnd(); - - /* Draw the touch screen as a textured quad */ - glBindTexture(GL_TEXTURE_2D, texture[NDSDisplayID_Touch]); - glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, GPU_FRAMEBUFFER_NATIVE_WIDTH, GPU_FRAMEBUFFER_NATIVE_HEIGHT, - GL_RGBA, - GL_UNSIGNED_SHORT_1_5_5_5_REV, - displayInfo.renderedBuffer[NDSDisplayID_Touch]); - - backlightIntensity = displayInfo.backlightIntensity[NDSDisplayID_Touch]; - - glBegin(GL_QUADS); - glTexCoord2f(0.00f, 0.00f); glVertex2f( 0.0f, 192.0f); glColor4f(backlightIntensity, backlightIntensity, backlightIntensity, 1.0f); - glTexCoord2f(1.00f, 0.00f); glVertex2f(256.0f, 192.0f); glColor4f(backlightIntensity, backlightIntensity, backlightIntensity, 1.0f); - glTexCoord2f(1.00f, 0.75f); glVertex2f(256.0f, 384.0f); glColor4f(backlightIntensity, backlightIntensity, backlightIntensity, 1.0f); - glTexCoord2f(0.00f, 0.75f); glVertex2f( 0.0f, 384.0f); glColor4f(backlightIntensity, backlightIntensity, backlightIntensity, 1.0f); - glEnd(); - - /* Flush the drawing to the screen */ - SDL_GL_SwapBuffers( ); -} -#endif - -/* this is a stub for resizeWindow_stub in the case of no gl headers or no opengl 2d */ -#ifdef INCLUDE_OPENGL_2D -static void -resizeWindow_stub (u16 width, u16 height, GLuint *screen_texture) { -} -#else static void resizeWindow_stub (u16 width, u16 height, void *screen_texture) { } -#endif -static void -Draw( void) { - const NDSDisplayInfo &displayInfo = GPU->GetDisplayInfo(); - const size_t pixCount = GPU_FRAMEBUFFER_NATIVE_WIDTH * GPU_FRAMEBUFFER_NATIVE_HEIGHT; - ColorspaceApplyIntensityToBuffer16(displayInfo.nativeBuffer16[NDSDisplayID_Main], pixCount, displayInfo.backlightIntensity[NDSDisplayID_Main]); - ColorspaceApplyIntensityToBuffer16(displayInfo.nativeBuffer16[NDSDisplayID_Touch], pixCount, displayInfo.backlightIntensity[NDSDisplayID_Touch]); - - SDL_Surface *rawImage = SDL_CreateRGBSurfaceFrom(displayInfo.masterNativeBuffer16, GPU_FRAMEBUFFER_NATIVE_WIDTH, GPU_FRAMEBUFFER_NATIVE_HEIGHT * 2, 16, GPU_FRAMEBUFFER_NATIVE_WIDTH * sizeof(u16), 0x001F, 0x03E0, 0x7C00, 0); - if(rawImage == NULL) return; - - SDL_Texture *texture = SDL_CreateTextureFromSurface(renderer, rawImage); - SDL_FreeSurface(rawImage); - SDL_RenderCopy(renderer, texture, NULL, NULL); - SDL_RenderPresent(renderer); - - return; +static void Draw(class configured_features *cfg) { + const float scale = cfg->scale; + const unsigned w = GPU_FRAMEBUFFER_NATIVE_WIDTH, h = GPU_FRAMEBUFFER_NATIVE_HEIGHT; + const int ws = w * scale, hs = h * scale; + const NDSDisplayInfo &displayInfo = GPU->GetDisplayInfo(); + const size_t pixCount = w * h; + ColorspaceApplyIntensityToBuffer16(displayInfo.nativeBuffer16[NDSDisplayID_Main], pixCount, displayInfo.backlightIntensity[NDSDisplayID_Main]); + ColorspaceApplyIntensityToBuffer16(displayInfo.nativeBuffer16[NDSDisplayID_Touch], pixCount, displayInfo.backlightIntensity[NDSDisplayID_Touch]); + const SDL_Rect destrect_v[2] = { + { 0, 0 , ws, hs}, + { 0, hs, ws, hs}, + }; + const SDL_Rect destrect_h[2] = { + { 0, 0 , ws, hs}, + { ws, 0, ws, hs}, + }; + unsigned i, off = 0, n = pixCount*2; + for(i = 0; i < 2; ++i) { + void *p = 0; + int pitch; + SDL_LockTexture(screen[i], NULL, &p, &pitch); + memcpy(p, ((char*)displayInfo.masterNativeBuffer16)+off, n); + SDL_UnlockTexture(screen[i]); + SDL_RenderCopy(renderer, screen[i], NULL, cfg->horizontal ? &destrect_h[i] : &destrect_v[i]); + off += n; + } + SDL_RenderPresent(renderer); + return; } static void desmume_cycle(struct ctrls_event_config * cfg) @@ -481,11 +317,14 @@ static void desmume_cycle(struct ctrls_event_config * cfg) } /* Update mouse position and click */ - if(mouse.down) NDS_setTouchPos(mouse.x, mouse.y); + if(mouse.down) { + NDS_setTouchPos(mouse.x, mouse.y); + mouse.down = 2; + } if(mouse.click) { NDS_releaseTouch(); - mouse.click = FALSE; + mouse.click = 0; } update_keypad(cfg->keypad); /* Update keypad */ @@ -513,6 +352,7 @@ int main(int argc, char ** argv) { int limiter_frame_counter = 0; int limiter_tick0 = 0; int error; + unsigned i; GKeyFile *keyfile; @@ -524,10 +364,6 @@ int main(int argc, char ** argv) { u32 fps_previous_time = 0; #endif -#ifdef INCLUDE_OPENGL_2D - GLuint screen_texture[2]; -#endif - NDS_Init(); init_config( &my_config); @@ -621,6 +457,16 @@ int main(int argc, char ** argv) { ((CliDriver*)driver)->setStubs(stubs); gdbstub_wait_set_enabled(stubs[0], 1); gdbstub_wait_set_enabled(stubs[1], 1); + + if(stubs[0] || stubs[1]) { +#ifdef HAVE_JIT + if(CommonSettings.use_jit) { + fprintf(stderr, "GDB stub enabled, turning off jit (they're incompatible)\n"); + arm_jit_sync(); + arm_jit_reset(CommonSettings.use_jit=0); + } +#endif + } #endif if ( !my_config.disable_sound) { @@ -655,53 +501,28 @@ int main(int argc, char ** argv) { return 1; } -#ifdef INCLUDE_OPENGL_2D - if ( my_config.opengl_2d) { - /* the flags to pass to SDL_SetVideoMode */ - sdl_videoFlags = SDL_OPENGL; /* Enable OpenGL in SDL */ - sdl_videoFlags |= SDL_RESIZABLE; /* Enable window resizing */ - - - /* Sets up OpenGL double buffering */ - SDL_GL_SetAttribute( SDL_GL_DOUBLEBUFFER, 1 ); - - window = SDL_CreateWindow( "Desmume SDL", SDL_WINDOWPOS_UNDEFINED, SDL_WINDOWPOS_UNDEFINED, 256, 192 * 2, - sdl_videoFlags ); - - /* Verify there is a window */ - if ( !window ) { - fprintf( stderr, "Window creation failed: %s\n", SDL_GetError( ) ); - exit( -1); - } - - - /* initialize OpenGL */ - if ( !initGL( screen_texture)) { - fprintf( stderr, "Failed to init GL, fall back to software render\n"); - - my_config.opengl_2d = 0; - } - } - - if ( !my_config.opengl_2d) { -#endif - sdl_videoFlags |= SDL_SWSURFACE; - window = SDL_CreateWindow( "Desmume SDL", SDL_WINDOWPOS_UNDEFINED, SDL_WINDOWPOS_UNDEFINED, 256, 384, sdl_videoFlags ); + nds_screen_size_ratio = my_config.scale; + ctrls_cfg.horizontal = my_config.horizontal; + unsigned width = 256 + my_config.horizontal*256; + unsigned height = 192 + 192 * !my_config.horizontal; + sdl_videoFlags |= SDL_WINDOW_OPENGL; + window = SDL_CreateWindow( "Desmume SDL", SDL_WINDOWPOS_UNDEFINED, SDL_WINDOWPOS_UNDEFINED, + width*my_config.scale, height*my_config.scale, sdl_videoFlags ); if ( !window ) { fprintf( stderr, "Window creation failed: %s\n", SDL_GetError( ) ); exit( -1); } + ctrls_cfg.window = window; - renderer = SDL_CreateRenderer(window, -1, SDL_RENDERER_ACCELERATED); -#ifdef INCLUDE_OPENGL_2D - } + renderer = SDL_CreateRenderer(window, -1, SDL_RENDERER_ACCELERATED); + + uint32_t desmume_pixelformat = SDL_MasksToPixelFormatEnum(16, 0x001F, 0x03E0, 0x7C00, 0); + + for(i = 0; i < 2; ++i) + screen[i] = SDL_CreateTexture(renderer, desmume_pixelformat, SDL_TEXTUREACCESS_STREAMING, + GPU_FRAMEBUFFER_NATIVE_WIDTH, GPU_FRAMEBUFFER_NATIVE_HEIGHT); - /* set the initial window size */ - if ( my_config.opengl_2d) { - resizeWindow( 256, 192*2, screen_texture); - } -#endif /* Initialize joysticks */ if(!init_joy()) return 1; @@ -734,11 +555,7 @@ int main(int argc, char ** argv) { ctrls_cfg.focused = 1; ctrls_cfg.fake_mic = 0; ctrls_cfg.keypad = 0; -#ifdef INCLUDE_OPENGL_2D - ctrls_cfg.screen_texture = screen_texture; -#else ctrls_cfg.screen_texture = NULL; -#endif ctrls_cfg.resize_cb = &resizeWindow_stub; while(!ctrls_cfg.sdl_quit) { @@ -749,14 +566,7 @@ int main(int argc, char ** argv) { DrawHUD(); #endif -#ifdef INCLUDE_OPENGL_2D - if ( my_config.opengl_2d) { - opengl_Draw(screen_texture); - ctrls_cfg.resize_cb = &resizeWindow; - } - else -#endif - Draw(); + Draw(&my_config); #ifdef HAVE_LIBAGG osd->clear(); @@ -797,7 +607,7 @@ int main(int argc, char ** argv) { fps_frame_counter = 0; fps_timing = 0; - snprintf( win_title, sizeof(win_title), "Desmume %f", fps); + snprintf( win_title, sizeof(win_title), "Desmume %.02f", fps); SDL_SetWindowTitle( window, win_title ); } diff --git a/desmume/src/frontend/posix/shared/ctrlssdl.cpp b/desmume/src/frontend/posix/shared/ctrlssdl.cpp index 09e8fdf26..e8d0b7154 100644 --- a/desmume/src/frontend/posix/shared/ctrlssdl.cpp +++ b/desmume/src/frontend/posix/shared/ctrlssdl.cpp @@ -34,6 +34,7 @@ u16 keyboard_cfg[NB_KEYS]; u16 joypad_cfg[NB_KEYS]; u16 nbr_joy; mouse_status mouse; +static int fullscreen; static SDL_Joystick **open_joysticks = NULL; @@ -259,7 +260,7 @@ u16 get_set_joy_key(int index) { static signed long screen_to_touch_range( signed long scr, float size_ratio) { - return (signed long)((float)scr * size_ratio); + return (signed long)((float)scr / size_ratio); } /* Set mouse coordinates */ @@ -500,6 +501,12 @@ process_ctrls_event( SDL_Event& event, break; case SDL_KEYDOWN: + if ((event.key.keysym.sym == SDLK_RETURN) && (event.key.keysym.mod & KMOD_ALT)) { + SDL_SetWindowFullscreen(cfg->window, fullscreen ? 0 : SDL_WINDOW_FULLSCREEN); + fullscreen = !fullscreen; + break; + } + switch(event.key.keysym.sym){ case SDLK_LSHIFT: shift_pressed |= 1; @@ -558,6 +565,7 @@ process_ctrls_event( SDL_Event& event, case SDLK_F10: int prevexec; prevexec = execute; + emu_halt(EMUHALT_REASON_USER_REQUESTED_HALT, NDSErrorTag_None); execute = FALSE; SPU_Pause(1); if(!shift_pressed){ @@ -576,14 +584,12 @@ process_ctrls_event( SDL_Event& event, break; case SDL_MOUSEBUTTONDOWN: - if(event.button.button==1) - mouse.down = TRUE; + if(event.button.button==1 && !mouse.down) + mouse.down = 1; break; - + case SDL_MOUSEMOTION: - if(!mouse.down) - break; - else { + { signed long scaled_x = screen_to_touch_range( event.button.x, cfg->nds_screen_size_ratio); @@ -591,14 +597,18 @@ process_ctrls_event( SDL_Event& event, screen_to_touch_range( event.button.y, cfg->nds_screen_size_ratio); - if( scaled_y >= 192) + if(!cfg->horizontal && scaled_y >= 192) set_mouse_coord( scaled_x, scaled_y - 192); + else if(cfg->horizontal && scaled_x >= 256) + set_mouse_coord( scaled_x - 256, scaled_y); } break; case SDL_MOUSEBUTTONUP: - if(mouse.down) mouse.click = TRUE; - mouse.down = FALSE; + if(mouse.down) { + mouse.click = 1; + if(mouse.down > 1) mouse.down = 0; + } break; case SDL_QUIT: diff --git a/desmume/src/frontend/posix/shared/ctrlssdl.h b/desmume/src/frontend/posix/shared/ctrlssdl.h index 466bc6c9d..916c4d45e 100644 --- a/desmume/src/frontend/posix/shared/ctrlssdl.h +++ b/desmume/src/frontend/posix/shared/ctrlssdl.h @@ -75,8 +75,8 @@ struct mouse_status { signed long x; signed long y; - BOOL click; - BOOL down; + int click; + int down; }; extern mouse_status mouse; @@ -85,18 +85,15 @@ extern mouse_status mouse; struct ctrls_event_config { unsigned short keypad; float nds_screen_size_ratio; + int horizontal; int auto_pause; int focused; int sdl_quit; int boost; int fake_mic; -#ifdef HAVE_GL_GL_H - GLuint *screen_texture; - void (*resize_cb)(u16 width, u16 height, GLuint *screen_texture); -#else void *screen_texture; void (*resize_cb)(u16 width, u16 height, void *screen_texture); -#endif + SDL_Window *window; }; void load_default_config(const u32 kbCfg[]); diff --git a/desmume/src/frontend/posix/shared/sndsdl.cpp b/desmume/src/frontend/posix/shared/sndsdl.cpp index 892c65819..31f3ca222 100644 --- a/desmume/src/frontend/posix/shared/sndsdl.cpp +++ b/desmume/src/frontend/posix/shared/sndsdl.cpp @@ -51,10 +51,9 @@ SNDSDLUnMuteAudio, SNDSDLSetVolume }; -static u16 *stereodata16; -static u32 soundoffset; -static volatile u32 soundpos; -static u32 soundlen; +static u8 *stereodata; +static u8 *mixerdata; +static u32 soundoff; static u32 soundbufsize; static SDL_AudioSpec audiofmt; int audio_volume; @@ -81,20 +80,26 @@ DWORD WINAPI SNDXBOXThread( LPVOID ) static void MixAudio(void *userdata, Uint8 *stream, int len) { int i; - Uint8 *soundbuf=(Uint8 *)stereodata16; - - Uint8 *stream_tmp=(Uint8 *)malloc(len); - for (i = 0; i < len; i++) - { - if (soundpos >= soundbufsize) - soundpos = 0; - - stream_tmp[i] = soundbuf[soundpos]; - soundpos++; + /* if the volume is max, we don't need to call the mixer and do additional + memory copying/cleaning, but can copy directly into the SDL buffer. */ + u8 *dest = audio_volume == SDL_MIX_MAXVOLUME ? stream : mixerdata; + SDL_LockAudio(); + if (len > soundoff) { + //dprintf(2, "bu: want %u, got %u\n", (unsigned)len, (unsigned)soundoff); + /* buffer underrun - rather than zeroing out SDL's audio buffer, we just + hand back the existing data, which reduces cracking */ + len = soundoff; + } + memcpy(dest, stereodata, len); + soundoff -= len; + /* move rest of prebuffered data to the beginning of the buffer */ + if (soundoff) + memmove(stereodata, stereodata+len, soundoff); + SDL_UnlockAudio(); + if(audio_volume != SDL_MIX_MAXVOLUME) { + memset(stream, 0, len); + SDL_MixAudio(stream, mixerdata, len, audio_volume); } - memset(stream, 0, len); - SDL_MixAudio(stream, stream_tmp, len, audio_volume); - free(stream_tmp); } ////////////////////////////////////////////////////////////////////////////// @@ -114,34 +119,37 @@ int SNDSDLInit(int buffersize) //samples should be a power of 2 according to SDL-doc //so normalize it to the nearest power of 2 here u32 normSamples = 512; - while (normSamples < audiofmt.samples) - normSamples <<= 1; + while (normSamples < audiofmt.samples) normSamples <<= 1; audiofmt.samples = normSamples; - - soundlen = audiofmt.freq / 60; // 60 for NTSC - soundbufsize = buffersize * sizeof(s16) * 2; - if (SDL_OpenAudio(&audiofmt, NULL) != 0) + SDL_AudioSpec obtained; + if (SDL_OpenAudio(&audiofmt, &obtained) != 0) { return -1; } - if ((stereodata16 = (u16 *)malloc(soundbufsize)) == NULL) + audiofmt = obtained; + + /* allocate multiple of the size needed by SDL to be able to efficiently pre-buffer. + we effectively need the engine to pre-buffer a couple milliseconds because the + frontend might call SDL_Delay() to achieve the desired framerate, during which + the buffer isn't updated by the SPU. */ + soundbufsize = audiofmt.size * 4; + soundoff = 0; + + if ((stereodata = (u8*)calloc(soundbufsize, 1)) == NULL || + (mixerdata = (u8*)calloc(soundbufsize, 1)) == NULL) return -1; - memset(stereodata16, 0, soundbufsize); - - soundpos = 0; - - SDL_PauseAudio(0); - #ifdef _XBOX - doterminate = false; + doterminate = false; terminated = false; CreateThread(0,0,SNDXBOXThread,0,0,0); #endif + SDL_PauseAudio(0); + return 0; } @@ -157,38 +165,22 @@ void SNDSDLDeInit() #endif SDL_CloseAudio(); - if (stereodata16) - free(stereodata16); + free(stereodata); + free(mixerdata); + stereodata = NULL; + mixerdata = NULL; } ////////////////////////////////////////////////////////////////////////////// void SNDSDLUpdateAudio(s16 *buffer, u32 num_samples) { - u32 copy1size=0, copy2size=0; + // dprintf(2, "up: %u\n", num_samples); + u8 *incoming = (u8*) buffer; + u32 n = num_samples * 4; SDL_LockAudio(); - - if ((soundbufsize - soundoffset) < (num_samples * sizeof(s16) * 2)) - { - copy1size = (soundbufsize - soundoffset); - copy2size = (num_samples * sizeof(s16) * 2) - copy1size; - } - else - { - copy1size = (num_samples * sizeof(s16) * 2); - copy2size = 0; - } - - memcpy((((u8 *)stereodata16)+soundoffset), buffer, copy1size); -// ScspConvert32uto16s((s32 *)leftchanbuffer, (s32 *)rightchanbuffer, (s16 *)(((u8 *)stereodata16)+soundoffset), copy1size / sizeof(s16) / 2); - - if (copy2size) - memcpy(stereodata16, ((u8 *)buffer)+copy1size, copy2size); -// ScspConvert32uto16s((s32 *)leftchanbuffer, (s32 *)rightchanbuffer, (s16 *)stereodata16, copy2size / sizeof(s16) / 2); - - soundoffset += copy1size + copy2size; - soundoffset %= soundbufsize; - + memcpy(stereodata+soundoff, incoming, n); + soundoff += n; SDL_UnlockAudio(); } @@ -196,14 +188,11 @@ void SNDSDLUpdateAudio(s16 *buffer, u32 num_samples) u32 SNDSDLGetAudioSpace() { - u32 freespace=0; - - if (soundoffset > soundpos) - freespace = soundbufsize - soundoffset + soundpos; - else - freespace = soundpos - soundoffset; - - return (freespace / sizeof(s16) / 2); + u32 tmp; + SDL_LockAudio(); + tmp = (soundbufsize - soundoff)/4; + SDL_UnlockAudio(); + return tmp; } ////////////////////////////////////////////////////////////////////////////// @@ -222,16 +211,29 @@ void SNDSDLUnMuteAudio() ////////////////////////////////////////////////////////////////////////////// +/* the engine's min/max is 0/100, SDLs 0/128 */ void SNDSDLSetVolume(int volume) { + u32 tmp = volume * SDL_MIX_MAXVOLUME; + SDL_LockAudio(); + audio_volume = tmp / 100; + SDL_UnlockAudio(); } ////////////////////////////////////////////////////////////////////////////// +/* these 2 are special functions that the GTK frontend calls directly. + and it has a slider where its max is 128. doh. */ + int SNDSDLGetAudioVolume() { - return audio_volume; + SDL_LockAudio(); + int tmp = audio_volume; + SDL_UnlockAudio(); + return tmp; } -void SNDSDLSetAudioVolume(int value) -{ - audio_volume = value; + +void SNDSDLSetAudioVolume(int volume) { + SDL_LockAudio(); + audio_volume = volume; + SDL_UnlockAudio(); }