summaryrefslogtreecommitdiffstats
path: root/firmware/target/hosted/sdl
diff options
context:
space:
mode:
Diffstat (limited to 'firmware/target/hosted/sdl')
-rw-r--r--firmware/target/hosted/sdl/button-sdl.c2018
-rw-r--r--firmware/target/hosted/sdl/button-sdl.h32
-rw-r--r--firmware/target/hosted/sdl/kernel-sdl.c162
-rw-r--r--firmware/target/hosted/sdl/lcd-bitmap.c416
-rw-r--r--firmware/target/hosted/sdl/lcd-bitmap.h35
-rw-r--r--firmware/target/hosted/sdl/lcd-charcells.c198
-rw-r--r--firmware/target/hosted/sdl/lcd-charcells.h34
-rw-r--r--firmware/target/hosted/sdl/lcd-remote-bitmap.c111
-rw-r--r--firmware/target/hosted/sdl/lcd-remote-bitmap.h32
-rw-r--r--firmware/target/hosted/sdl/lcd-sdl.c113
-rw-r--r--firmware/target/hosted/sdl/lcd-sdl.h43
-rw-r--r--firmware/target/hosted/sdl/pcm-sdl.c373
-rw-r--r--firmware/target/hosted/sdl/sim-ui-defines.h405
-rw-r--r--firmware/target/hosted/sdl/system-sdl.c236
-rw-r--r--firmware/target/hosted/sdl/system-sdl.h52
-rw-r--r--firmware/target/hosted/sdl/thread-sdl.c610
-rw-r--r--firmware/target/hosted/sdl/thread-sdl.h32
-rw-r--r--firmware/target/hosted/sdl/timer-sdl.c61
18 files changed, 4963 insertions, 0 deletions
diff --git a/firmware/target/hosted/sdl/button-sdl.c b/firmware/target/hosted/sdl/button-sdl.c
new file mode 100644
index 0000000000..51ba8cff92
--- /dev/null
+++ b/firmware/target/hosted/sdl/button-sdl.c
@@ -0,0 +1,2018 @@
+/***************************************************************************
+ * __________ __ ___.
+ * Open \______ \ ____ ____ | | _\_ |__ _______ ___
+ * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
+ * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
+ * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
+ * \/ \/ \/ \/ \/
+ * $Id$
+ *
+ * Copyright (C) 2002 by Felix Arends
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
+ * KIND, either express or implied.
+ *
+ ****************************************************************************/
+
+#include <math.h>
+#include "sim-ui-defines.h"
+#include "lcd-charcells.h"
+#include "lcd-remote.h"
+#include "config.h"
+#include "button.h"
+#include "kernel.h"
+#include "backlight.h"
+#include "misc.h"
+#include "sim_tasks.h"
+#include "button-sdl.h"
+#include "backlight.h"
+
+#include "debug.h"
+
+#ifdef HAVE_TOUCHSCREEN
+#include "touchscreen.h"
+static int mouse_coords = 0;
+#endif
+/* how long until repeat kicks in */
+#define REPEAT_START 6
+
+/* the speed repeat starts at */
+#define REPEAT_INTERVAL_START 4
+
+/* speed repeat finishes at */
+#define REPEAT_INTERVAL_FINISH 2
+
+#ifdef HAVE_TOUCHSCREEN
+#define USB_KEY SDLK_c /* SDLK_u is taken by BUTTON_MIDLEFT */
+#else
+#define USB_KEY SDLK_u
+#endif
+
+#if defined(IRIVER_H100_SERIES) || defined (IRIVER_H300_SERIES)
+int _remote_type=REMOTETYPE_H100_LCD;
+
+int remote_type(void)
+{
+ return _remote_type;
+}
+#endif
+
+static int xy2button(int x, int y);
+
+struct event_queue button_queue;
+
+static int btn = 0; /* Hopefully keeps track of currently pressed keys... */
+
+#ifdef HAS_BUTTON_HOLD
+bool hold_button_state = false;
+bool button_hold(void) {
+ return hold_button_state;
+}
+#endif
+
+#ifdef HAS_REMOTE_BUTTON_HOLD
+bool remote_hold_button_state = false;
+bool remote_button_hold(void) {
+ return remote_hold_button_state;
+}
+#endif
+static void button_event(int key, bool pressed);
+extern bool debug_wps;
+extern bool mapping;
+static void gui_message_loop(void)
+{
+ SDL_Event event;
+ static int x,y,xybutton = 0;
+
+ if (SDL_PollEvent(&event))
+ {
+ switch(event.type)
+ {
+ case SDL_KEYDOWN:
+ button_event(event.key.keysym.sym, true);
+ break;
+ case SDL_KEYUP:
+ button_event(event.key.keysym.sym, false);
+ case SDL_MOUSEBUTTONDOWN:
+ switch ( event.button.button ) {
+#ifdef HAVE_SCROLLWHEEL
+ case SDL_BUTTON_WHEELUP:
+ button_event( SDLK_UP, true );
+ break;
+ case SDL_BUTTON_WHEELDOWN:
+ button_event( SDLK_DOWN, true );
+ break;
+#endif
+ case SDL_BUTTON_LEFT:
+ case SDL_BUTTON_MIDDLE:
+ if ( mapping && background ) {
+ x = event.button.x;
+ y = event.button.y;
+ }
+ if ( background ) {
+ xybutton = xy2button( event.button.x, event.button.y );
+ if( xybutton )
+ button_event( xybutton, true );
+ }
+ break;
+ default:
+ break;
+ }
+
+ if (debug_wps && event.button.button == 1)
+ {
+ if ( background )
+#ifdef HAVE_REMOTE
+ if ( event.button.y < UI_REMOTE_POSY ) /* Main Screen */
+ printf("Mouse at: (%d, %d)\n", event.button.x - UI_LCD_POSX -1 , event.button.y - UI_LCD_POSY - 1 );
+ else
+ printf("Mouse at: (%d, %d)\n", event.button.x - UI_REMOTE_POSX -1 , event.button.y - UI_REMOTE_POSY - 1 );
+#else
+ printf("Mouse at: (%d, %d)\n", event.button.x - UI_LCD_POSX -1 , event.button.y - UI_LCD_POSY - 1 );
+#endif
+ else
+ if ( event.button.y/display_zoom < LCD_HEIGHT ) /* Main Screen */
+ printf("Mouse at: (%d, %d)\n", event.button.x/display_zoom, event.button.y/display_zoom );
+#ifdef HAVE_REMOTE
+ else
+ printf("Mouse at: (%d, %d)\n", event.button.x/display_zoom, event.button.y/display_zoom - LCD_HEIGHT );
+#endif
+ }
+ break;
+ case SDL_MOUSEBUTTONUP:
+ switch ( event.button.button ) {
+ /* The scrollwheel button up events are ignored as they are queued immediately */
+ case SDL_BUTTON_LEFT:
+ case SDL_BUTTON_MIDDLE:
+ if ( mapping && background ) {
+ printf(" { SDLK_, %d, %d, %d, \"\" },\n", x,
+#define SQUARE(x) ((x)*(x))
+ y, (int)sqrt( SQUARE(x-(int)event.button.x)
+ + SQUARE(y-(int)event.button.y)) );
+ }
+ if ( background && xybutton ) {
+ button_event( xybutton, false );
+ xybutton = 0;
+ }
+#ifdef HAVE_TOUCHSCREEN
+ else {
+ button_event(BUTTON_TOUCHSCREEN, false);
+ }
+#endif
+ break;
+ default:
+ break;
+ }
+ break;
+
+
+ case SDL_QUIT:
+ {
+ exit(EXIT_SUCCESS);
+ break;
+ }
+ default:
+ /*printf("Unhandled event\n"); */
+ break;
+ }
+ }
+}
+
+static void button_event(int key, bool pressed)
+{
+ int new_btn = 0;
+ static bool usb_connected = false;
+ if (usb_connected && key != USB_KEY)
+ return;
+ switch (key)
+ {
+
+#ifdef HAVE_TOUCHSCREEN
+ case BUTTON_TOUCHSCREEN:
+ switch (touchscreen_get_mode())
+ {
+ case TOUCHSCREEN_POINT:
+ new_btn = BUTTON_TOUCHSCREEN;
+ break;
+ case TOUCHSCREEN_BUTTON:
+ {
+ static int touchscreen_buttons[3][3] = {
+ {BUTTON_TOPLEFT, BUTTON_TOPMIDDLE, BUTTON_TOPRIGHT},
+ {BUTTON_MIDLEFT, BUTTON_CENTER, BUTTON_MIDRIGHT},
+ {BUTTON_BOTTOMLEFT, BUTTON_BOTTOMMIDDLE, BUTTON_BOTTOMRIGHT},
+ };
+ int px_x = ((mouse_coords&0xffff0000)>>16);
+ int px_y = ((mouse_coords&0x0000ffff));
+ new_btn = touchscreen_buttons[px_y/(LCD_HEIGHT/3)][px_x/(LCD_WIDTH/3)];
+ break;
+ }
+ }
+ break;
+ case SDLK_KP7:
+ case SDLK_7:
+ new_btn = BUTTON_TOPLEFT;
+ break;
+ case SDLK_KP8:
+ case SDLK_8:
+ case SDLK_UP:
+ new_btn = BUTTON_TOPMIDDLE;
+ break;
+ case SDLK_KP9:
+ case SDLK_9:
+ new_btn = BUTTON_TOPRIGHT;
+ break;
+ case SDLK_KP4:
+ case SDLK_u:
+ case SDLK_LEFT:
+ new_btn = BUTTON_MIDLEFT;
+ break;
+ case SDLK_KP5:
+ case SDLK_i:
+ new_btn = BUTTON_CENTER;
+ break;
+ case SDLK_KP6:
+ case SDLK_o:
+ case SDLK_RIGHT:
+ new_btn = BUTTON_MIDRIGHT;
+ break;
+ case SDLK_KP1:
+ case SDLK_j:
+ new_btn = BUTTON_BOTTOMLEFT;
+ break;
+ case SDLK_KP2:
+ case SDLK_k:
+ case SDLK_DOWN:
+ new_btn = BUTTON_BOTTOMMIDDLE;
+ break;
+ case SDLK_KP3:
+ case SDLK_l:
+ new_btn = BUTTON_BOTTOMRIGHT;
+ break;
+ case SDLK_F4:
+ if(pressed)
+ {
+ touchscreen_set_mode(touchscreen_get_mode() == TOUCHSCREEN_POINT ? TOUCHSCREEN_BUTTON : TOUCHSCREEN_POINT);
+ printf("Touchscreen mode: %s\n", touchscreen_get_mode() == TOUCHSCREEN_POINT ? "TOUCHSCREEN_POINT" : "TOUCHSCREEN_BUTTON");
+ }
+ break;
+
+#endif
+ case USB_KEY:
+ if (!pressed)
+ {
+ usb_connected = !usb_connected;
+ if (usb_connected)
+ queue_post(&button_queue, SYS_USB_CONNECTED, 0);
+ else
+ queue_post(&button_queue, SYS_USB_DISCONNECTED, 0);
+ }
+ return;
+
+#ifdef HAS_BUTTON_HOLD
+ case SDLK_h:
+ if(pressed)
+ {
+ hold_button_state = !hold_button_state;
+ DEBUGF("Hold button is %s\n", hold_button_state?"ON":"OFF");
+ }
+ return;
+#endif
+
+#ifdef HAS_REMOTE_BUTTON_HOLD
+ case SDLK_j:
+ if(pressed)
+ {
+ remote_hold_button_state = !remote_hold_button_state;
+ DEBUGF("Remote hold button is %s\n",
+ remote_hold_button_state?"ON":"OFF");
+ }
+ return;
+#endif
+
+#if CONFIG_KEYPAD == GIGABEAT_PAD
+ case SDLK_KP4:
+ case SDLK_LEFT:
+ new_btn = BUTTON_LEFT;
+ break;
+ case SDLK_KP6:
+ case SDLK_RIGHT:
+ new_btn = BUTTON_RIGHT;
+ break;
+ case SDLK_KP8:
+ case SDLK_UP:
+ new_btn = BUTTON_UP;
+ break;
+ case SDLK_KP2:
+ case SDLK_DOWN:
+ new_btn = BUTTON_DOWN;
+ break;
+ case SDLK_KP_PLUS:
+ case SDLK_F8:
+ new_btn = BUTTON_POWER;
+ break;
+ case SDLK_ESCAPE:
+ new_btn = BUTTON_POWER;
+ break;
+ case SDLK_KP_ENTER:
+ case SDLK_RETURN:
+ case SDLK_a:
+ new_btn = BUTTON_A;
+ break;
+ case SDLK_KP5:
+ case SDLK_SPACE:
+ new_btn = BUTTON_SELECT;
+ break;
+ case SDLK_KP_PERIOD:
+ case SDLK_INSERT:
+ new_btn = BUTTON_MENU;
+ break;
+ case SDLK_KP9:
+ new_btn = BUTTON_VOL_UP;
+ break;
+ case SDLK_KP3:
+ new_btn = BUTTON_VOL_DOWN;
+ break;
+
+#elif CONFIG_KEYPAD == GIGABEAT_S_PAD
+ case SDLK_KP4:
+ case SDLK_LEFT:
+ new_btn = BUTTON_LEFT;
+ break;
+ case SDLK_KP6:
+ case SDLK_RIGHT:
+ new_btn = BUTTON_RIGHT;
+ break;
+ case SDLK_KP8:
+ case SDLK_UP:
+ new_btn = BUTTON_UP;
+ break;
+ case SDLK_KP2:
+ case SDLK_DOWN:
+ new_btn = BUTTON_DOWN;
+ break;
+ case SDLK_F8:
+ case SDLK_ESCAPE:
+ new_btn = BUTTON_POWER;
+ break;
+ case SDLK_KP_PLUS:
+ case SDLK_KP_ENTER:
+ case SDLK_RETURN:
+ new_btn = BUTTON_PLAY;
+ break;
+ case SDLK_KP7:
+ new_btn = BUTTON_BACK;
+ break;
+ case SDLK_KP5:
+ case SDLK_SPACE:
+ new_btn = BUTTON_SELECT;
+ break;
+ case SDLK_KP9:
+ case SDLK_KP_PERIOD:
+ case SDLK_INSERT:
+ new_btn = BUTTON_MENU;
+ break;
+
+#elif CONFIG_KEYPAD == IAUDIO_X5M5_PAD
+ case SDLK_KP4:
+ case SDLK_LEFT:
+ new_btn = BUTTON_LEFT;
+ break;
+ case SDLK_KP6:
+ case SDLK_RIGHT:
+ new_btn = BUTTON_RIGHT;
+ break;
+ case SDLK_KP8:
+ case SDLK_UP:
+ new_btn = BUTTON_UP;
+ break;
+ case SDLK_KP2:
+ case SDLK_DOWN:
+ new_btn = BUTTON_DOWN;
+ break;
+ case SDLK_KP_PLUS:
+ case SDLK_F8:
+ new_btn = BUTTON_PLAY;
+ break;
+ case SDLK_ESCAPE:
+ new_btn = BUTTON_POWER;
+ break;
+ case SDLK_KP_ENTER:
+ case SDLK_RETURN:
+ case SDLK_a:
+ new_btn = BUTTON_POWER;
+ break;
+ case SDLK_KP_DIVIDE:
+ case SDLK_F1:
+ new_btn = BUTTON_REC;
+ break;
+ case SDLK_KP5:
+ case SDLK_SPACE:
+ new_btn = BUTTON_SELECT;
+ break;
+
+#elif CONFIG_KEYPAD == IAUDIO_M3_PAD
+ case SDLK_KP4:
+ new_btn = BUTTON_LEFT;
+ break;
+ case SDLK_LEFT:
+ new_btn = BUTTON_RC_REW;
+ break;
+ case SDLK_KP6:
+ new_btn = BUTTON_RIGHT;
+ break;
+ case SDLK_RIGHT:
+ new_btn = BUTTON_RC_FF;
+ break;
+ case SDLK_KP8:
+ new_btn = BUTTON_VOL_UP;
+ break;
+ case SDLK_UP:
+ new_btn = BUTTON_RC_VOL_UP;
+ break;
+ case SDLK_KP2:
+ new_btn = BUTTON_VOL_DOWN;
+ break;
+ case SDLK_DOWN:
+ new_btn = BUTTON_RC_VOL_DOWN;
+ break;
+ case SDLK_KP_PERIOD:
+ new_btn = BUTTON_MODE;
+ break;
+ case SDLK_INSERT:
+ new_btn = BUTTON_RC_MODE;
+ break;
+ case SDLK_KP_DIVIDE:
+ new_btn = BUTTON_REC;
+ break;
+ case SDLK_F1:
+ new_btn = BUTTON_RC_REC;
+ break;
+ case SDLK_KP5:
+ new_btn = BUTTON_PLAY;
+ break;
+ case SDLK_SPACE:
+ new_btn = BUTTON_RC_PLAY;
+ break;
+ case SDLK_KP_ENTER:
+ case SDLK_RETURN:
+ new_btn = BUTTON_RC_MENU;
+ break;
+
+#elif (CONFIG_KEYPAD == IPOD_1G2G_PAD) || (CONFIG_KEYPAD == IPOD_3G_PAD) \
+ || (CONFIG_KEYPAD == IPOD_4G_PAD)
+ case SDLK_KP4:
+ case SDLK_LEFT:
+ new_btn = BUTTON_LEFT;
+ break;
+ case SDLK_KP6:
+ case SDLK_RIGHT:
+ new_btn = BUTTON_RIGHT;
+ break;
+ case SDLK_KP8:
+ case SDLK_UP:
+ new_btn = BUTTON_SCROLL_BACK;
+ break;
+ case SDLK_KP2:
+ case SDLK_DOWN:
+ new_btn = BUTTON_SCROLL_FWD;
+ break;
+ case SDLK_KP_PLUS:
+ case SDLK_F8:
+ new_btn = BUTTON_PLAY;
+ break;
+ case SDLK_KP5:
+ case SDLK_SPACE:
+ new_btn = BUTTON_SELECT;
+ break;
+ case SDLK_KP_PERIOD:
+ case SDLK_INSERT:
+ new_btn = BUTTON_MENU;
+ break;
+
+#elif CONFIG_KEYPAD == IRIVER_H10_PAD
+ case SDLK_KP4:
+ case SDLK_LEFT:
+ new_btn = BUTTON_LEFT;
+ break;
+ case SDLK_KP6:
+ case SDLK_RIGHT:
+ new_btn = BUTTON_RIGHT;
+ break;
+ case SDLK_KP8:
+ case SDLK_UP:
+ new_btn = BUTTON_SCROLL_UP;
+ break;
+ case SDLK_KP2:
+ case SDLK_DOWN:
+ new_btn = BUTTON_SCROLL_DOWN;
+ break;
+ case SDLK_KP_PLUS:
+ case SDLK_F8:
+ new_btn = BUTTON_POWER;
+ break;
+ case SDLK_ESCAPE:
+ new_btn = BUTTON_POWER;
+ break;
+ case SDLK_KP_DIVIDE:
+ case SDLK_F1:
+ new_btn = BUTTON_REW;
+ break;
+ case SDLK_KP_MULTIPLY:
+ case SDLK_F2:
+ new_btn = BUTTON_FF;
+ break;
+ case SDLK_KP5:
+ case SDLK_SPACE:
+ new_btn = BUTTON_PLAY;
+ break;
+
+#elif (CONFIG_KEYPAD == IRIVER_H100_PAD) || (CONFIG_KEYPAD == IRIVER_H300_PAD)
+ case SDLK_t:
+ if(pressed)
+ switch(_remote_type)
+ {
+ case REMOTETYPE_UNPLUGGED:
+ _remote_type=REMOTETYPE_H100_LCD;
+ DEBUGF("Changed remote type to H100\n");
+ break;
+ case REMOTETYPE_H100_LCD:
+ _remote_type=REMOTETYPE_H300_LCD;
+ DEBUGF("Changed remote type to H300\n");
+ break;
+ case REMOTETYPE_H300_LCD:
+ _remote_type=REMOTETYPE_H300_NONLCD;
+ DEBUGF("Changed remote type to H300 NON-LCD\n");
+ break;
+ case REMOTETYPE_H300_NONLCD:
+ _remote_type=REMOTETYPE_UNPLUGGED;
+ DEBUGF("Changed remote type to none\n");
+ break;
+ }
+ break;
+ case SDLK_KP4:
+ case SDLK_LEFT:
+ new_btn = BUTTON_LEFT;
+ break;
+ case SDLK_KP6:
+ case SDLK_RIGHT:
+ new_btn = BUTTON_RIGHT;
+ break;
+ case SDLK_KP8:
+ case SDLK_UP:
+ new_btn = BUTTON_UP;
+ break;
+ case SDLK_KP2:
+ case SDLK_DOWN:
+ new_btn = BUTTON_DOWN;
+ break;
+ case SDLK_KP_PLUS:
+ case SDLK_F8:
+ new_btn = BUTTON_ON;
+ break;
+ case SDLK_KP_ENTER:
+ case SDLK_RETURN:
+ case SDLK_a:
+ new_btn = BUTTON_OFF;
+ break;
+ case SDLK_KP_DIVIDE:
+ case SDLK_F1:
+ new_btn = BUTTON_REC;
+ break;
+ case SDLK_KP5:
+ case SDLK_SPACE:
+ new_btn = BUTTON_SELECT;
+ break;
+ case SDLK_KP_PERIOD:
+ case SDLK_INSERT:
+ new_btn = BUTTON_MODE;
+ break;
+
+#elif CONFIG_KEYPAD == IRIVER_IFP7XX_PAD
+ case SDLK_KP4:
+ case SDLK_LEFT:
+ new_btn = BUTTON_LEFT;
+ break;
+ case SDLK_KP6:
+ case SDLK_RIGHT:
+ new_btn = BUTTON_RIGHT;
+ break;
+ case SDLK_KP8:
+ case SDLK_UP:
+ new_btn = BUTTON_UP;
+ break;
+ case SDLK_KP2:
+ case SDLK_DOWN:
+ new_btn = BUTTON_DOWN;
+ break;
+ case SDLK_KP_PLUS:
+ case SDLK_F8:
+ new_btn = BUTTON_PLAY;
+ break;
+ case SDLK_KP_ENTER:
+ case SDLK_RETURN:
+ case SDLK_a:
+ new_btn = BUTTON_EQ;
+ break;
+ case SDLK_KP5:
+ case SDLK_SPACE:
+ new_btn = BUTTON_SELECT;
+ break;
+ case SDLK_KP_PERIOD:
+ case SDLK_INSERT:
+ new_btn = BUTTON_MODE;
+ break;
+
+#elif CONFIG_KEYPAD == ONDIO_PAD
+ case SDLK_KP4:
+ case SDLK_LEFT:
+ new_btn = BUTTON_LEFT;
+ break;
+ case SDLK_KP6:
+ case SDLK_RIGHT:
+ new_btn = BUTTON_RIGHT;
+ break;
+ case SDLK_KP8:
+ case SDLK_UP:
+ new_btn = BUTTON_UP;
+ break;
+ case SDLK_KP2:
+ case SDLK_DOWN:
+ new_btn = BUTTON_DOWN;
+ break;
+ case SDLK_KP_ENTER:
+ case SDLK_RETURN:
+ case SDLK_a:
+ new_btn = BUTTON_OFF;
+ break;
+ case SDLK_KP_PERIOD:
+ case SDLK_INSERT:
+ new_btn = BUTTON_MENU;
+ break;
+
+#elif CONFIG_KEYPAD == PLAYER_PAD
+ case SDLK_KP4:
+ case SDLK_LEFT:
+ new_btn = BUTTON_LEFT;
+ break;
+ case SDLK_KP6:
+ case SDLK_RIGHT:
+ new_btn = BUTTON_RIGHT;
+ break;
+ case SDLK_KP8:
+ case SDLK_UP:
+ new_btn = BUTTON_PLAY;
+ break;
+ case SDLK_KP2:
+ case SDLK_DOWN:
+ new_btn = BUTTON_STOP;
+ break;
+ case SDLK_KP_PLUS:
+ case SDLK_F8:
+ new_btn = BUTTON_ON;
+ break;
+ case SDLK_KP_PERIOD:
+ case SDLK_INSERT:
+ new_btn = BUTTON_MENU;
+ break;
+
+#elif CONFIG_KEYPAD == RECORDER_PAD
+ case SDLK_KP4:
+ case SDLK_LEFT:
+ new_btn = BUTTON_LEFT;
+ break;
+ case SDLK_KP6:
+ case SDLK_RIGHT:
+ new_btn = BUTTON_RIGHT;
+ break;
+ case SDLK_KP8:
+ case SDLK_UP:
+ new_btn = BUTTON_UP;
+ break;
+ case SDLK_KP2:
+ case SDLK_DOWN:
+ new_btn = BUTTON_DOWN;
+ break;
+ case SDLK_KP_PLUS:
+ case SDLK_F8:
+ new_btn = BUTTON_ON;
+ break;
+ case SDLK_KP_ENTER:
+ case SDLK_RETURN:
+ case SDLK_a:
+ new_btn = BUTTON_OFF;
+ break;
+ case SDLK_KP_DIVIDE:
+ case SDLK_F1:
+ new_btn = BUTTON_F1;
+ break;
+ case SDLK_KP_MULTIPLY:
+ case SDLK_F2:
+ new_btn = BUTTON_F2;
+ break;
+ case SDLK_KP_MINUS:
+ case SDLK_F3:
+ new_btn = BUTTON_F3;
+ break;
+ case SDLK_KP5:
+ case SDLK_SPACE:
+ new_btn = BUTTON_PLAY;
+ break;
+
+#elif CONFIG_KEYPAD == ARCHOS_AV300_PAD
+ case SDLK_KP4:
+ case SDLK_LEFT:
+ new_btn = BUTTON_LEFT;
+ break;
+ case SDLK_KP6:
+ case SDLK_RIGHT:
+ new_btn = BUTTON_RIGHT;
+ break;
+ case SDLK_KP8:
+ case SDLK_UP:
+ new_btn = BUTTON_UP;
+ break;
+ case SDLK_KP2:
+ case SDLK_DOWN:
+ new_btn = BUTTON_DOWN;
+ break;
+ case SDLK_KP_PLUS:
+ case SDLK_F8:
+ new_btn = BUTTON_ON;
+ break;
+ case SDLK_KP_ENTER:
+ case SDLK_RETURN:
+ case SDLK_a:
+ new_btn = BUTTON_OFF;
+ break;
+ case SDLK_KP_DIVIDE:
+ case SDLK_F1:
+ new_btn = BUTTON_F1;
+ break;
+ case SDLK_KP_MULTIPLY:
+ case SDLK_F2:
+ new_btn = BUTTON_F2;
+ break;
+ case SDLK_KP_MINUS:
+ case SDLK_F3:
+ new_btn = BUTTON_F3;
+ break;
+ case SDLK_KP5:
+ case SDLK_SPACE:
+ new_btn = BUTTON_SELECT;
+ break;
+
+#elif CONFIG_KEYPAD == SANSA_E200_PAD
+ case SDLK_KP4:
+ case SDLK_LEFT:
+ new_btn = BUTTON_LEFT;
+ break;
+ case SDLK_KP6:
+ case SDLK_RIGHT:
+ new_btn = BUTTON_RIGHT;
+ break;
+ case SDLK_KP8:
+ case SDLK_UP:
+ new_btn = BUTTON_SCROLL_BACK;
+ break;
+ case SDLK_KP2:
+ case SDLK_DOWN:
+ new_btn = BUTTON_SCROLL_FWD;
+ break;
+ case SDLK_KP9:
+ case SDLK_PAGEUP:
+ new_btn = BUTTON_UP;
+ break;
+ case SDLK_KP3:
+ case SDLK_PAGEDOWN:
+ new_btn = BUTTON_DOWN;
+ break;
+ case SDLK_KP1:
+ case SDLK_HOME:
+ new_btn = BUTTON_POWER;
+ break;
+ case SDLK_KP7:
+ case SDLK_END:
+ new_btn = BUTTON_REC;
+ break;
+ case SDLK_KP5:
+ case SDLK_SPACE:
+ new_btn = BUTTON_SELECT;
+ break;
+
+#elif CONFIG_KEYPAD == SANSA_C200_PAD
+ case SDLK_KP4:
+ case SDLK_LEFT:
+ new_btn = BUTTON_LEFT;
+ break;
+ case SDLK_KP6:
+ case SDLK_RIGHT:
+ new_btn = BUTTON_RIGHT;
+ break;
+ case SDLK_KP8:
+ case SDLK_UP:
+ new_btn = BUTTON_UP;
+ break;
+ case SDLK_KP2:
+ case SDLK_DOWN:
+ new_btn = BUTTON_DOWN;
+ break;
+ case SDLK_KP3:
+ new_btn = BUTTON_POWER;
+ break;
+ case SDLK_KP1:
+ new_btn = BUTTON_REC;
+ break;
+ case SDLK_KP5:
+ case SDLK_KP_ENTER:
+ case SDLK_RETURN:
+ new_btn = BUTTON_SELECT;
+ break;
+ case SDLK_KP7:
+ new_btn = BUTTON_VOL_DOWN;
+ break;
+ case SDLK_KP9:
+ new_btn = BUTTON_VOL_UP;
+ break;
+
+#elif CONFIG_KEYPAD == MROBE500_PAD
+ case SDLK_F9:
+ new_btn = BUTTON_RC_HEART;
+ break;
+ case SDLK_F10:
+ new_btn = BUTTON_RC_MODE;
+ break;
+ case SDLK_F11:
+ new_btn = BUTTON_RC_VOL_DOWN;
+ break;
+ case SDLK_F12:
+ new_btn = BUTTON_RC_VOL_UP;
+ break;
+ case SDLK_MINUS:
+ case SDLK_LESS:
+ case SDLK_LEFTBRACKET:
+ case SDLK_KP_DIVIDE:
+ new_btn = BUTTON_LEFT;
+ break;
+ case SDLK_PLUS:
+ case SDLK_GREATER:
+ case SDLK_RIGHTBRACKET:
+ case SDLK_KP_MULTIPLY:
+ new_btn = BUTTON_RIGHT;
+ break;
+ case SDLK_PAGEUP:
+ new_btn = BUTTON_RC_PLAY;
+ break;
+ case SDLK_PAGEDOWN:
+ new_btn = BUTTON_RC_DOWN;
+ break;
+ case SDLK_F8:
+ case SDLK_ESCAPE:
+ new_btn = BUTTON_POWER;
+ break;
+#elif CONFIG_KEYPAD == MROBE100_PAD
+ case SDLK_F9:
+ new_btn = BUTTON_RC_HEART;
+ break;
+ case SDLK_F10:
+ new_btn = BUTTON_RC_MODE;
+ break;
+ case SDLK_F11:
+ new_btn = BUTTON_RC_VOL_DOWN;
+ break;
+ case SDLK_F12:
+ new_btn = BUTTON_RC_VOL_UP;
+ break;
+ case SDLK_LEFT:
+ new_btn = BUTTON_RC_FF;
+ break;
+ case SDLK_RIGHT:
+ new_btn = BUTTON_RC_REW;
+ break;
+ case SDLK_UP:
+ new_btn = BUTTON_RC_PLAY;
+ break;
+ case SDLK_DOWN:
+ new_btn = BUTTON_RC_DOWN;
+ break;
+ case SDLK_KP1:
+ new_btn = BUTTON_DISPLAY;
+ break;
+ case SDLK_KP7:
+ new_btn = BUTTON_MENU;
+ break;
+ case SDLK_KP9:
+ new_btn = BUTTON_PLAY;
+ break;
+ case SDLK_KP4:
+ new_btn = BUTTON_LEFT;
+ break;
+ case SDLK_KP6:
+ new_btn = BUTTON_RIGHT;
+ break;
+ case SDLK_KP8:
+ new_btn = BUTTON_UP;
+ break;
+ case SDLK_KP2:
+ new_btn = BUTTON_DOWN;
+ break;
+ case SDLK_KP5:
+ case SDLK_SPACE:
+ new_btn = BUTTON_SELECT;
+ break;
+ case SDLK_KP_MULTIPLY:
+ case SDLK_F8:
+ case SDLK_ESCAPE:
+ new_btn = BUTTON_POWER;
+ break;
+
+#elif CONFIG_KEYPAD == COWON_D2_PAD
+ case SDLK_KP_MULTIPLY:
+ case SDLK_F8:
+ case SDLK_ESCAPE:
+ case SDLK_BACKSPACE:
+ case SDLK_DELETE:
+ new_btn = BUTTON_POWER;
+ break;
+ case SDLK_KP_PLUS:
+ case SDLK_EQUALS:
+ new_btn = BUTTON_PLUS;
+ break;
+ case SDLK_KP_MINUS:
+ case SDLK_MINUS:
+ new_btn = BUTTON_MINUS;
+ break;
+ case SDLK_KP_ENTER:
+ case SDLK_RETURN:
+ case SDLK_SPACE:
+ case SDLK_INSERT:
+ new_btn = BUTTON_MENU;
+ break;
+#elif CONFIG_KEYPAD == IAUDIO67_PAD
+ case SDLK_UP:
+ new_btn = BUTTON_RIGHT;
+ break;
+ case SDLK_DOWN:
+ new_btn = BUTTON_LEFT;
+ break;
+ case SDLK_LEFT:
+ new_btn = BUTTON_STOP;
+ break;
+ case SDLK_RETURN:
+ case SDLK_KP_ENTER:
+ case SDLK_RIGHT:
+ new_btn = BUTTON_PLAY;
+ break;
+ case SDLK_PLUS:
+ new_btn = BUTTON_VOLUP;
+ break;
+ case SDLK_MINUS:
+ new_btn = BUTTON_VOLDOWN;
+ break;
+ case SDLK_SPACE:
+ new_btn = BUTTON_MENU;
+ break;
+ case SDLK_BACKSPACE:
+ new_btn = BUTTON_POWER;
+ break;
+#elif CONFIG_KEYPAD == CREATIVEZVM_PAD
+ case SDLK_KP1:
+ new_btn = BUTTON_BACK;
+ break;
+ case SDLK_KP3:
+ new_btn = BUTTON_MENU;
+ break;
+ case SDLK_KP7:
+ new_btn = BUTTON_CUSTOM;
+ break;
+ case SDLK_KP9:
+ new_btn = BUTTON_PLAY;
+ break;
+ case SDLK_KP4:
+ case SDLK_LEFT:
+ new_btn = BUTTON_LEFT;
+ break;
+ case SDLK_KP6:
+ case SDLK_RIGHT:
+ new_btn = BUTTON_RIGHT;
+ break;
+ case SDLK_KP8:
+ case SDLK_UP:
+ new_btn = BUTTON_UP;
+ break;
+ case SDLK_KP2:
+ case SDLK_DOWN:
+ new_btn = BUTTON_DOWN;
+ break;
+ case SDLK_KP5:
+ case SDLK_SPACE:
+ new_btn = BUTTON_SELECT;
+ break;
+ case SDLK_KP_MULTIPLY:
+ case SDLK_F8:
+ case SDLK_ESCAPE:
+ new_btn = BUTTON_POWER;
+ break;
+#elif CONFIG_KEYPAD == CREATIVEZV_PAD
+ case SDLK_KP1:
+ new_btn = BUTTON_PREV;
+ break;
+ case SDLK_KP3:
+ new_btn = BUTTON_NEXT;
+ break;
+ case SDLK_KP7:
+ new_btn = BUTTON_BACK;
+ break;
+ case SDLK_p:
+ new_btn = BUTTON_PLAY;
+ break;
+ case SDLK_KP9:
+ new_btn = BUTTON_MENU;
+ break;
+ case SDLK_KP4:
+ case SDLK_LEFT:
+ new_btn = BUTTON_LEFT;
+ break;
+ case SDLK_KP6:
+ case SDLK_RIGHT:
+ new_btn = BUTTON_RIGHT;
+ break;
+ case SDLK_KP8:
+ case SDLK_UP:
+ new_btn = BUTTON_UP;
+ break;
+ case SDLK_KP2:
+ case SDLK_DOWN:
+ new_btn = BUTTON_DOWN;
+ break;
+ case SDLK_KP5:
+ case SDLK_SPACE:
+ new_btn = BUTTON_SELECT;
+ break;
+ case SDLK_KP_MULTIPLY:
+ case SDLK_F8:
+ case SDLK_ESCAPE:
+ new_btn = BUTTON_POWER;
+ break;
+ case SDLK_z:
+ new_btn = BUTTON_VOL_DOWN;
+ break;
+ case SDLK_s:
+ new_btn = BUTTON_VOL_UP;
+
+#elif CONFIG_KEYPAD == MEIZU_M6SL_PAD
+ case SDLK_KP1:
+ new_btn = BUTTON_PREV;
+ break;
+ case SDLK_KP3:
+ new_btn = BUTTON_NEXT;
+ break;
+ case SDLK_KP_ENTER:
+ case SDLK_RETURN:
+ case SDLK_a:
+ new_btn = BUTTON_PLAY;
+ break;
+ case SDLK_KP_PERIOD:
+ case SDLK_INSERT:
+ new_btn = BUTTON_MENU;
+ break;
+ case SDLK_KP8:
+ case SDLK_UP:
+ new_btn = BUTTON_UP;
+ break;
+ case SDLK_KP2:
+ case SDLK_DOWN:
+ new_btn = BUTTON_DOWN;
+ break;
+ case SDLK_KP5:
+ case SDLK_SPACE:
+ new_btn = BUTTON_SELECT;
+ break;
+#elif CONFIG_KEYPAD == SANSA_FUZE_PAD
+ case SDLK_KP4:
+ case SDLK_LEFT:
+ new_btn = BUTTON_LEFT;
+ break;
+ case SDLK_KP6:
+ case SDLK_RIGHT:
+ new_btn = BUTTON_RIGHT;
+ break;
+ case SDLK_KP8:
+ case SDLK_UP:
+ new_btn = BUTTON_SCROLL_BACK;
+ break;
+ case SDLK_KP2:
+ case SDLK_DOWN:
+ new_btn = BUTTON_SCROLL_FWD;
+ break;
+ case SDLK_PAGEUP:
+ case SDLK_KP9:
+ new_btn = BUTTON_UP;
+ break;
+ case SDLK_PAGEDOWN:
+ case SDLK_KP3:
+ new_btn = BUTTON_DOWN;
+ break;
+ case SDLK_KP_MINUS:
+ case SDLK_KP1:
+ new_btn = BUTTON_POWER;
+ break;
+ case SDLK_KP_MULTIPLY:
+ new_btn = BUTTON_HOME;
+ break;
+ case SDLK_KP5:
+ case SDLK_SPACE:
+ case SDLK_KP_ENTER:
+ case SDLK_RETURN:
+ new_btn = BUTTON_SELECT;
+ break;
+#elif CONFIG_KEYPAD == SANSA_CLIP_PAD
+ case SDLK_KP4:
+ case SDLK_LEFT:
+ new_btn = BUTTON_LEFT;
+ break;
+ case SDLK_KP6:
+ case SDLK_RIGHT:
+ new_btn = BUTTON_RIGHT;
+ break;
+ case SDLK_KP8:
+ case SDLK_UP:
+ new_btn = BUTTON_UP;
+ break;
+ case SDLK_KP2:
+ case SDLK_DOWN:
+ new_btn = BUTTON_DOWN;
+ break;
+
+ case SDLK_INSERT:
+ case SDLK_KP_MULTIPLY:
+ new_btn = BUTTON_HOME;
+ break;
+ case SDLK_SPACE:
+ case SDLK_KP5:
+ new_btn = BUTTON_SELECT;
+ break;
+ case SDLK_PAGEDOWN:
+ case SDLK_KP3:
+ new_btn = BUTTON_VOL_DOWN;
+ break;
+ case SDLK_PAGEUP:
+ case SDLK_KP9:
+ new_btn = BUTTON_VOL_UP;
+ break;
+ case SDLK_ESCAPE:
+ case SDLK_KP1:
+ new_btn = BUTTON_POWER;
+ break;
+#elif CONFIG_KEYPAD == SANSA_M200_PAD
+ case SDLK_KP4:
+ case SDLK_LEFT:
+ new_btn = BUTTON_LEFT;
+ break;
+ case SDLK_KP6:
+ case SDLK_RIGHT:
+ new_btn = BUTTON_RIGHT;
+ break;
+ case SDLK_KP8:
+ case SDLK_UP:
+ new_btn = BUTTON_UP;
+ break;
+ case SDLK_KP2:
+ case SDLK_DOWN:
+ new_btn = BUTTON_DOWN;
+ break;
+ case SDLK_PLUS:
+ new_btn = BUTTON_POWER;
+ break;
+ case SDLK_KP5:
+ new_btn = BUTTON_SELECT;
+ break;
+ case SDLK_KP7:
+ new_btn = BUTTON_VOL_DOWN;
+ break;
+ case SDLK_KP9:
+ new_btn = BUTTON_VOL_UP;
+ break;
+#elif CONFIG_KEYPAD == PHILIPS_SA9200_PAD
+ case SDLK_KP4:
+ case SDLK_LEFT:
+ new_btn = BUTTON_LEFT;
+ break;
+ case SDLK_KP6:
+ case SDLK_RIGHT:
+ new_btn = BUTTON_RIGHT;
+ break;
+ case SDLK_KP8:
+ case SDLK_UP:
+ new_btn = BUTTON_UP;
+ break;
+ case SDLK_KP2:
+ case SDLK_DOWN:
+ new_btn = BUTTON_DOWN;
+ break;
+ case SDLK_KP1:
+ new_btn = BUTTON_MENU;
+ break;
+ case SDLK_KP5:
+ case SDLK_SPACE:
+ new_btn = BUTTON_PLAY;
+ break;
+ case SDLK_KP7:
+ new_btn = BUTTON_PREV;
+ break;
+ case SDLK_KP9:
+ new_btn = BUTTON_NEXT;
+ break;
+ case SDLK_KP_ENTER:
+ case SDLK_RETURN:
+ new_btn = BUTTON_POWER;
+ break;
+ case SDLK_PAGEUP:
+ new_btn = BUTTON_VOL_UP;
+ break;
+ case SDLK_PAGEDOWN:
+ new_btn = BUTTON_VOL_DOWN;
+ break;
+#elif CONFIG_KEYPAD == PHILIPS_HDD1630_PAD
+ case SDLK_KP4:
+ case SDLK_LEFT:
+ new_btn = BUTTON_LEFT;
+ break;
+ case SDLK_KP6:
+ case SDLK_RIGHT:
+ new_btn = BUTTON_RIGHT;
+ break;
+ case SDLK_KP8:
+ case SDLK_UP:
+ new_btn = BUTTON_UP;
+ break;
+ case SDLK_KP2:
+ case SDLK_DOWN:
+ new_btn = BUTTON_DOWN;
+ break;
+ case SDLK_KP5:
+ case SDLK_SPACE:
+ new_btn = BUTTON_SELECT;
+ break;
+ case SDLK_KP7:
+ case SDLK_ESCAPE:
+ new_btn = BUTTON_POWER;
+ break;
+ case SDLK_KP1:
+ new_btn = BUTTON_PLAYLIST;
+ break;
+ case SDLK_KP9:
+ new_btn = BUTTON_VOL_UP;
+ break;
+ case SDLK_KP3:
+ new_btn = BUTTON_VOL_DOWN;
+ break;
+ case SDLK_KP_MINUS:
+ new_btn = BUTTON_MENU;
+ break;
+ case SDLK_KP_PLUS:
+ new_btn = BUTTON_VIEW;
+ break;
+#elif CONFIG_KEYPAD == ONDAVX747_PAD
+ case SDLK_ESCAPE:
+ new_btn = BUTTON_POWER;
+ break;
+ case SDLK_KP_PLUS:
+ case SDLK_PLUS:
+ case SDLK_GREATER:
+ case SDLK_RIGHTBRACKET:
+ case SDLK_KP_MULTIPLY:
+ new_btn = BUTTON_VOL_UP;
+ break;
+ case SDLK_KP_MINUS:
+ case SDLK_MINUS:
+ case SDLK_LESS:
+ case SDLK_LEFTBRACKET:
+ case SDLK_KP_DIVIDE:
+ new_btn = BUTTON_VOL_DOWN;
+ break;
+ case SDLK_KP_ENTER:
+ case SDLK_RETURN:
+ new_btn = BUTTON_MENU;
+ break;
+#elif CONFIG_KEYPAD == ONDAVX777_PAD
+ case SDLK_ESCAPE:
+ new_btn = BUTTON_POWER;
+ break;
+#elif CONFIG_KEYPAD == SAMSUNG_YH_PAD
+ case SDLK_KP4:
+ case SDLK_LEFT:
+ new_btn = BUTTON_LEFT;
+ break;
+ case SDLK_KP6:
+ case SDLK_RIGHT:
+ new_btn = BUTTON_RIGHT;
+ break;
+ case SDLK_KP8:
+ case SDLK_UP:
+ new_btn = BUTTON_UP;
+ break;
+ case SDLK_KP2:
+ case SDLK_DOWN:
+ new_btn = BUTTON_DOWN;
+ break;
+ case SDLK_KP5:
+ case SDLK_KP_ENTER:
+ new_btn = BUTTON_PLAY;
+ break;
+ case SDLK_KP9:
+ case SDLK_PAGEUP:
+ new_btn = BUTTON_FFWD;
+ break;
+#ifdef SAMSUNG_YH820
+ case SDLK_KP7:
+#else
+ case SDLK_KP3:
+#endif
+ case SDLK_PAGEDOWN:
+ new_btn = BUTTON_REW;
+ break;
+ case SDLK_KP_PLUS:
+ new_btn = BUTTON_REC;
+ break;
+#elif CONFIG_KEYPAD == MINI2440_PAD
+ case SDLK_LEFT:
+ new_btn = BUTTON_LEFT;
+ break;
+ case SDLK_RIGHT:
+ new_btn = BUTTON_RIGHT;
+ break;
+ case SDLK_UP:
+ new_btn = BUTTON_UP;
+ break;
+ case SDLK_DOWN:
+ new_btn = BUTTON_DOWN;
+ break;
+ case SDLK_F8:
+ case SDLK_ESCAPE:
+ new_btn = BUTTON_POWER;
+ break;
+ case SDLK_KP_ENTER:
+ case SDLK_RETURN:
+ case SDLK_a:
+ new_btn = BUTTON_A;
+ break;
+ case SDLK_SPACE:
+ new_btn = BUTTON_SELECT;
+ break;
+ case SDLK_KP_PERIOD:
+ case SDLK_INSERT:
+ new_btn = BUTTON_MENU;
+ break;
+ case SDLK_KP_PLUS:
+ new_btn = BUTTON_VOL_UP;
+ break;
+ case SDLK_KP_MINUS:
+ new_btn = BUTTON_VOL_DOWN;
+ break;
+#elif CONFIG_KEYPAD == PBELL_VIBE500_PAD
+ case SDLK_KP4:
+ case SDLK_LEFT:
+ new_btn = BUTTON_PREV;
+ break;
+ case SDLK_KP6:
+ case SDLK_RIGHT:
+ new_btn = BUTTON_NEXT;
+ break;
+ case SDLK_KP8:
+ case SDLK_UP:
+ new_btn = BUTTON_UP;
+ break;
+ case SDLK_KP2:
+ case SDLK_DOWN:
+ new_btn = BUTTON_DOWN;
+ break;
+ case SDLK_KP7:
+ new_btn = BUTTON_MENU;
+ break;
+ case SDLK_KP9:
+ new_btn = BUTTON_PLAY;
+ break;
+ case SDLK_KP5:
+ new_btn = BUTTON_OK;
+ break;
+ case SDLK_KP_DIVIDE:
+ new_btn = BUTTON_CANCEL;
+ break;
+ case SDLK_KP_PLUS:
+ new_btn = BUTTON_POWER;
+ break;
+ case SDLK_KP_MULTIPLY:
+ new_btn = BUTTON_REC;
+ break;
+
+#elif CONFIG_KEYPAD == MPIO_HD200_PAD
+ case SDLK_UP:
+ new_btn = BUTTON_PREV;
+ break;
+ case SDLK_DOWN:
+ new_btn = BUTTON_NEXT;
+ break;
+ case SDLK_SPACE:
+ new_btn = BUTTON_SELECT;
+ break;
+ case SDLK_RETURN:
+ new_btn = BUTTON_PLAY;
+ break;
+ case SDLK_LEFT:
+ new_btn = BUTTON_VOL_DOWN;
+ break;
+ case SDLK_RIGHT:
+ new_btn = BUTTON_VOL_UP;
+ break;
+ case SDLK_ESCAPE:
+ new_btn = BUTTON_REC;
+ break;
+
+#else
+#error No keymap defined!
+#endif /* CONFIG_KEYPAD */
+ case SDLK_KP0:
+ case SDLK_F5:
+ if(pressed)
+ {
+ sim_trigger_screendump();
+ return;
+ }
+ break;
+ }
+
+ /* Call to make up for scrollwheel target implementation. This is
+ * not handled in the main button.c driver, but on the target
+ * implementation (look at button-e200.c for example if you are trying to
+ * figure out why using button_get_data needed a hack before).
+ */
+#if defined(BUTTON_SCROLL_FWD) && defined(BUTTON_SCROLL_BACK)
+ if((new_btn == BUTTON_SCROLL_FWD || new_btn == BUTTON_SCROLL_BACK) &&
+ pressed)
+ {
+ /* Clear these buttons from the data - adding them to the queue is
+ * handled in the scrollwheel drivers for the targets. They do not
+ * store the scroll forward/back buttons in their button data for
+ * the button_read call.
+ */
+#ifdef HAVE_BACKLIGHT
+ backlight_on();
+#endif
+#ifdef HAVE_BUTTON_LIGHT
+ buttonlight_on();
+#endif
+ queue_post(&button_queue, new_btn, 1<<24);
+ new_btn &= ~(BUTTON_SCROLL_FWD | BUTTON_SCROLL_BACK);
+ }
+#endif
+
+ if (pressed)
+ btn |= new_btn;
+ else
+ btn &= ~new_btn;
+}
+#if defined(HAVE_BUTTON_DATA) && defined(HAVE_TOUCHSCREEN)
+int button_read_device(int* data)
+{
+ *data = mouse_coords;
+#else
+int button_read_device(void)
+{
+#endif
+#ifdef HAS_BUTTON_HOLD
+ int hold_button = button_hold();
+
+#ifdef HAVE_BACKLIGHT
+ /* light handling */
+ static int hold_button_old = false;
+ if (hold_button != hold_button_old)
+ {
+ hold_button_old = hold_button;
+ backlight_hold_changed(hold_button);
+ }
+#endif
+
+ if (hold_button)
+ return BUTTON_NONE;
+ else
+#endif
+ gui_message_loop();
+
+ return btn;
+}
+
+
+#ifdef HAVE_TOUCHSCREEN
+extern bool debug_wps;
+void mouse_tick_task(void)
+{
+ static int last_check = 0;
+ int x,y;
+ if (TIME_BEFORE(current_tick, last_check+(HZ/10)))
+ return;
+ last_check = current_tick;
+ if (SDL_GetMouseState(&x, &y) & SDL_BUTTON(SDL_BUTTON_LEFT))
+ {
+ if(background)
+ {
+ x -= UI_LCD_POSX;
+ y -= UI_LCD_POSY;
+
+ if(x<0 || y<0 || x>SIM_LCD_WIDTH || y>SIM_LCD_HEIGHT)
+ return;
+ }
+
+ mouse_coords = (x<<16)|y;
+ button_event(BUTTON_TOUCHSCREEN, true);
+ if (debug_wps)
+ printf("Mouse at: (%d, %d)\n", x, y);
+ }
+}
+#endif
+
+void button_init_device(void)
+{
+ SDL_EnableKeyRepeat(SDL_DEFAULT_REPEAT_DELAY, SDL_DEFAULT_REPEAT_INTERVAL);
+#ifdef HAVE_TOUCHSCREEN
+ tick_add_task(mouse_tick_task);
+#endif
+}
+
+/* Button maps: simulated key, x, y, radius, name */
+/* Run sim with --mapping to get coordinates */
+/* or --debugbuttons to check */
+/* The First matching button is returned */
+struct button_map {
+ int button, x, y, radius;
+ char *description;
+};
+
+#ifdef SANSA_FUZE
+struct button_map bm[] = {
+ { SDLK_KP8, 70, 265, 35, "Scroll Back" },
+ { SDLK_KP9, 141, 255, 31, "Play" },
+ { SDLK_KP_MULTIPLY, 228, 267, 18, "Home" },
+ { SDLK_LEFT, 69, 329, 31, "Left" },
+ { SDLK_SPACE, 141, 330, 20, "Select" },
+ { SDLK_RIGHT, 214, 331, 23, "Right" },
+ { SDLK_KP3, 142, 406, 30, "Menu" },
+ { SDLK_DOWN, 221, 384, 24, "Scroll Fwd" },
+ { SDLK_KP_MINUS, 270, 299, 25, "Power" },
+ { SDLK_h, 269, 358, 26, "Hold" },
+ { 0, 0, 0, 0, "None" }
+};
+#elif defined (SANSA_CLIP)
+struct button_map bm[] = {
+ { SDLK_KP_MULTIPLY, 165, 158, 17, "Home" },
+ { SDLK_KP5, 102, 230, 29, "Select" },
+ { SDLK_KP8, 100, 179, 25, "Play" },
+ { SDLK_KP4, 53, 231, 21, "Left" },
+ { SDLK_KP6, 147, 232, 19, "Right" },
+ { SDLK_KP2, 105, 275, 22, "Menu" },
+ { 0, 0, 0, 0, "None" }
+};
+#elif defined (SANSA_C200) || defined(SANSA_C200V2)
+struct button_map bm[] = {
+
+ { SDLK_KP7, 84, 7, 21, "Vol Down" },
+ { SDLK_KP9, 158, 7, 20, "Vol Up" },
+ { SDLK_KP1, 173, 130, 27, "Record" },
+ { SDLK_KP5, 277, 75, 21, "Select" },
+ { SDLK_KP4, 233, 75, 24, "Left" },
+ { SDLK_KP6, 313, 74, 18, "Right" },
+ { SDLK_KP8, 276, 34, 15, "Play" },
+ { SDLK_KP2, 277, 119, 17, "Down" },
+ { SDLK_KP3, 314, 113, 19, "Menu" },
+ { 0, 0, 0, 0, "None" }
+};
+#elif defined (SANSA_E200V2) || defined(SANSA_E200)
+struct button_map bm[] = {
+ { SDLK_KP7, 5, 92, 18, "Record" },
+ { SDLK_KP9, 128, 295, 43, "Play" },
+ { SDLK_KP4, 42, 380, 33, "Left" },
+ { SDLK_KP5, 129, 378, 36, "Select" },
+ { SDLK_KP6, 218, 383, 30, "Right" },
+ { SDLK_KP3, 129, 461, 29, "Down" },
+ { SDLK_KP1, 55, 464, 20, "Menu" },
+ { SDLK_KP8, 92, 338, 17, "Scroll Back" },
+ { SDLK_KP2, 167, 342, 17, "Scroll Fwd" },
+ { 0, 0, 0, 0, "None" }
+};
+#elif defined (SANSA_M200V4)
+struct button_map bm[] = {
+ { SDLK_KP_PLUS, 54, 14, 16, "Power" },
+ { SDLK_KP7, 96, 13, 12, "Vol Down" },
+ { SDLK_KP9, 139, 14, 14, "Vol Up" },
+ { SDLK_KP5, 260, 82, 20, "Select" },
+ { SDLK_KP8, 258, 35, 30, "Play" },
+ { SDLK_KP4, 214, 84, 25, "Left" },
+ { SDLK_KP6, 300, 83, 24, "Right" },
+ { SDLK_KP2, 262, 125, 28, "Repeat" },
+ { SDLK_h, 113, 151, 21, "Hold" },
+ { 0, 0, 0, 0, "None" }
+};
+#elif defined (IPOD_VIDEO)
+struct button_map bm[] = {
+ { SDLK_KP_PERIOD, 174, 350, 35, "Menu" },
+ { SDLK_KP8, 110, 380, 33, "Scroll Back" },
+ { SDLK_KP2, 234, 377, 34, "Scroll Fwd" },
+ { SDLK_KP4, 78, 438, 47, "Left" },
+ { SDLK_KP5, 172, 435, 43, "Select" },
+ { SDLK_KP6, 262, 438, 52, "Right" },
+ { SDLK_KP_PLUS, 172, 519, 43, "Play" },
+ { 0, 0, 0 , 0, "None" }
+};
+#elif defined (IPOD_MINI) || defined(IPOD_MINI2G)
+struct button_map bm[] = {
+ { SDLK_KP5, 92, 267, 29, "Select" },
+ { SDLK_KP4, 31, 263, 37, "Left" },
+ { SDLK_KP6, 150, 268, 33, "Right" },
+ { SDLK_KP_PERIOD, 93, 209, 30, "Menu" },
+ { SDLK_KP_PLUS, 93, 324, 25, "Play" },
+ { SDLK_KP8, 53, 220, 29, "Scroll Back" },
+ { SDLK_KP2, 134, 219, 31, "Scroll Fwd" },
+ { 0, 0, 0 , 0, "None" }
+};
+#elif defined (IPOD_3G)
+struct button_map bm[] = {
+ { SDLK_KP5, 108, 296, 26, "Select" },
+ { SDLK_KP8, 70, 255, 26, "Scroll Back" },
+ { SDLK_KP2, 149, 256, 28, "Scroll Fwd" },
+ { SDLK_KP4, 27, 186, 22, "Left" },
+ { SDLK_KP_PERIOD, 82, 185, 22, "Menu" },
+ { SDLK_KP_PERIOD, 133, 185, 21, "Play" },
+ { SDLK_KP6, 189, 188, 21, "Right" },
+ { 0, 0, 0 , 0, "None" }
+};
+#elif defined (IPOD_4G)
+struct button_map bm[] = {
+ { SDLK_KP5, 96, 269, 27, "Select" },
+ { SDLK_KP4, 39, 267, 30, "Left" },
+ { SDLK_KP6, 153, 270, 27, "Right" },
+ { SDLK_KP_PERIOD, 96, 219, 30, "Menu" },
+ { SDLK_KP_PLUS, 95, 326, 27, "Play" },
+ { SDLK_KP8, 57, 233, 29, "Scroll Back" },
+ { SDLK_KP2, 132, 226, 29, "Scroll Fwd" },
+ { 0, 0, 0 , 0, "None" }
+};
+#elif defined (IPOD_COLOR)
+struct button_map bm[] = {
+ { SDLK_KP5, 128, 362, 35, "Select" },
+ { SDLK_KP4, 55, 358, 38, "Left" },
+ { SDLK_KP6, 203, 359, 39, "Right" },
+ { SDLK_KP_PERIOD, 128, 282, 34, "Menu" },
+ { SDLK_KP_PLUS, 129, 439, 41, "Play" },
+ { SDLK_KP8, 76, 309, 34, "Scroll Back" },
+ { SDLK_KP2, 182, 311, 45, "Scroll Fwd" },
+ { 0, 0, 0 , 0, "None" }
+};
+#elif defined (IPOD_1G2G)
+struct button_map bm[] = {
+ { SDLK_KP5, 112, 265, 31, "Select" },
+ { SDLK_KP8, 74, 224, 28, "Scroll Back" },
+ { SDLK_KP2, 146, 228, 28, "Scroll Fwd" },
+ /* Dummy button to make crescent shape */
+ { SDLK_y, 112, 265, 76, "None" },
+ { SDLK_KP8, 74, 224, 28, "Scroll Back" },
+ { SDLK_KP2, 146, 228, 28, "Scroll Fwd" },
+ { SDLK_KP6, 159, 268, 64, "Right" },
+ { SDLK_KP4, 62, 266, 62, "Left" },
+ { SDLK_KP_PERIOD, 111, 216, 64, "Menu" },
+ { SDLK_KP_PLUS, 111, 326, 55, "Down" },
+ { 0, 0, 0 , 0, "None" }
+};
+#elif defined (IPOD_NANO)
+struct button_map bm[] = {
+ { SDLK_KP5, 98, 316, 37, "Select" },
+ { SDLK_KP4, 37, 312, 28, "Left" },
+ { SDLK_KP6, 160, 313, 25, "Right" },
+ { SDLK_KP_PERIOD,102, 256, 23, "Menu" },
+ { SDLK_KP_PLUS, 99, 378, 28, "Play" },
+ { SDLK_KP8, 58, 272, 24, "Scroll Back" },
+ { SDLK_KP2, 141, 274, 22, "Scroll Fwd" },
+ { 0, 0, 0 , 0, "None" }
+};
+#elif defined (IPOD_NANO2G)
+struct button_map bm[] = {
+ { SDLK_KP5, 118, 346, 37, "Select" },
+ { SDLK_KP4, 51, 345, 28, "Left" },
+ { SDLK_KP6, 180, 346, 26, "Right" },
+ { SDLK_KP_PERIOD, 114, 286, 23, "Menu" },
+ { SDLK_KP_PLUS, 115, 412, 27, "Down" },
+ { SDLK_KP8, 67, 303, 28, "Scroll Back" },
+ { SDLK_KP2, 163, 303, 27, "Scroll Fwd" },
+ { 0, 0, 0 , 0, "None" }
+};
+#elif defined (COWON_D2)
+struct button_map bm[] = {
+ { SDLK_DELETE, 51, 14, 17, "Power" },
+ { SDLK_h, 138, 14, 16, "Hold" },
+ { SDLK_MINUS, 320, 14, 10, "Minus" },
+ { SDLK_INSERT, 347, 13, 13, "Menu" },
+ { SDLK_KP_PLUS, 374, 14, 12, "Plus" },
+ { 0, 0, 0, 0, "None" }
+};
+#elif defined (IAUDIO_M3)
+struct button_map bm[] = {
+ { SDLK_KP5, 256, 72, 29, "Play" },
+ { SDLK_KP6, 255, 137, 28, "Right" },
+ { SDLK_KP4, 257, 201, 26, "Left" },
+ { SDLK_KP8, 338, 31, 27, "Up" },
+ { SDLK_KP2, 339, 92, 23, "Down" },
+ { SDLK_KP_PERIOD, 336, 50, 23, "Mode" },
+ { SDLK_KP_DIVIDE, 336, 147, 23, "Rec" },
+ { SDLK_h, 336, 212, 30, "Hold" },
+ /* remote */
+ { SDLK_SPACE, 115, 308, 20, "RC Play" },
+ { SDLK_RIGHT, 85, 308, 20, "RC Rew" },
+ { SDLK_LEFT, 143, 308, 20, "RC FF" },
+ { SDLK_UP, 143, 498, 20, "RC Up" },
+ { SDLK_DOWN, 85, 498, 20, "RC Down" },
+ { SDLK_INSERT, 212, 308, 30, "RC Mode" },
+ { SDLK_F1, 275, 308, 25, "RC Rec" },
+ { SDLK_KP_ENTER, 115, 498, 20, "RC Menu" },
+ { 0, 0, 0, 0, "None" }
+};
+#elif defined (IAUDIO_M5)
+struct button_map bm[] = {
+ { SDLK_KP_ENTER, 333, 41, 17, "Enter" },
+ { SDLK_h, 334, 74, 21, "Hold" },
+ { SDLK_KP_DIVIDE, 333, 142, 24, "Record" },
+ { SDLK_KP_PLUS, 332, 213, 20, "Play" },
+ { SDLK_KP5, 250, 291, 19, "Select" },
+ { SDLK_KP8, 249, 236, 32, "Up" },
+ { SDLK_KP4, 194, 292, 29, "Left" },
+ { SDLK_KP6, 297, 290, 27, "Right" },
+ { SDLK_KP2, 252, 335, 28, "Down" },
+ { 0, 0, 0, 0, "None" }
+};
+#elif defined (IAUDIO_7)
+struct button_map bm[] = {
+ { 0, 0, 0, 0, "None" }
+};
+#elif defined (IAUDIO_X5)
+struct button_map bm[] = {
+ { SDLK_KP_ENTER, 275, 38, 17, "Power" },
+ { SDLK_h, 274, 83, 16, "Hold" },
+ { SDLK_KP_DIVIDE, 276, 128, 22, "Record" },
+ { SDLK_KP_PLUS, 274, 186, 22, "Play" },
+ { SDLK_KP5, 200, 247, 16, "Select" },
+ { SDLK_KP8, 200, 206, 16, "Up" },
+ { SDLK_KP4, 163, 248, 19, "Left" },
+ { SDLK_KP6, 225, 247, 24, "Right" },
+ { SDLK_KP2, 199, 279, 20, "Down" },
+ { 0, 0, 0, 0, "None" }
+};
+#elif defined (ARCHOS_PLAYER)
+struct button_map bm[] = {
+ { SDLK_KP_PLUS, 79, 252, 23, "On" },
+ { SDLK_KP_PERIOD, 81, 310, 20, "Menu" },
+ { SDLK_KP8, 154, 237, 28, "Play" },
+ { SDLK_KP4, 121, 282, 23, "Left" },
+ { SDLK_KP6, 187, 282, 22, "Right" },
+ { SDLK_KP2, 157, 312, 20, "Down" },
+ { 0, 0, 0, 0, "None" }
+};
+#elif defined (ARCHOS_RECORDER)
+struct button_map bm[] = {
+ { SDLK_F1, 94, 205, 22, "F1" },
+ { SDLK_F2, 136, 204, 21, "F2" },
+ { SDLK_F3, 174, 204, 24, "F3" },
+ { SDLK_KP_PLUS, 75, 258, 19, "On" },
+ { SDLK_KP_ENTER, 76, 307, 15, "Off" },
+ { SDLK_KP5, 151, 290, 20, "Select" },
+ { SDLK_KP8, 152, 251, 23, "Up" },
+ { SDLK_KP4, 113, 288, 26, "Left" },
+ { SDLK_KP6, 189, 291, 23, "Right" },
+ { SDLK_KP2, 150, 327, 27, "Down" },
+ { 0, 0, 0, 0, "None" }
+};
+#elif defined (ARCHOS_FMRECORDER) || defined (ARCHOS_RECORDERV2)
+struct button_map bm[] = {
+ { SDLK_F1, 88, 210, 28, "F1" },
+ { SDLK_F2, 144, 212, 28, "F2" },
+ { SDLK_F3, 197, 212, 28, "F3" },
+ { SDLK_KP5, 144, 287, 21, "Select" },
+ { SDLK_KP_PLUS, 86, 320, 13, "Menu" },
+ { SDLK_KP_ENTER, 114, 347, 13, "Stop" },
+ { SDLK_y, 144, 288, 31, "None" },
+ { SDLK_KP8, 144, 259, 25, "Up" },
+ { SDLK_KP2, 144, 316, 31, "Down" },
+ { SDLK_KP6, 171, 287, 32, "Right" },
+ { SDLK_KP4, 117, 287, 31, "Left" },
+ { 0, 0, 0, 0, "None" }
+};
+#elif defined (ARCHOS_ONDIOSP) || defined (ARCHOS_ONDIOFM)
+struct button_map bm[] = {
+ { SDLK_KP_ENTER, 75, 23, 30, "Enter" },
+ { SDLK_KP8, 75, 174, 33, "KP8" },
+ { SDLK_KP4, 26, 186, 48, "KP4" },
+ { SDLK_KP6, 118, 196, 32, "KP6" },
+ { SDLK_KP2, 75, 234, 16, "KP2" },
+ { SDLK_KP_PERIOD, 54, 250, 24, "Period" },
+ { 0, 0, 0, 0, "None" }
+};
+#elif defined (IRIVER_H10)
+struct button_map bm[] = {
+ { SDLK_KP_PLUS, 38, 70, 37, "Power" },
+ { SDLK_KP4, 123, 194, 26, "Cancel" },
+ { SDLK_KP6, 257, 195, 34, "Select" },
+ { SDLK_KP8, 190, 221, 28, "Up" },
+ { SDLK_KP2, 192, 320, 27, "Down" },
+ { SDLK_KP_DIVIDE, 349, 49, 20, "Rew" },
+ { SDLK_KP5, 349, 96, 20, "Play" },
+ { SDLK_KP_MULTIPLY, 350, 141, 23, "FF" },
+ { 0, 0, 0, 0, "None" }
+};
+#elif defined (IRIVER_H10_5GB)
+struct button_map bm[] = {
+ { SDLK_KP_PLUS, 34, 76, 23, "Power" },
+ { SDLK_KP4, 106, 222, 28, "Cancel" },
+ { SDLK_KP6, 243, 220, 31, "Select" },
+ { SDLK_KP8, 176, 254, 34, "Up" },
+ { SDLK_KP2, 175, 371, 35, "Down" },
+ { SDLK_KP_DIVIDE, 319, 63, 26, "Rew" },
+ { SDLK_KP5, 320, 124, 26, "Play" },
+ { SDLK_KP_MULTIPLY, 320, 181, 32, "FF" },
+ { 0, 0, 0, 0, "None" }
+};
+#elif defined (IRIVER_H120) || defined (IRIVER_H100)
+struct button_map bm[] = {
+ { SDLK_KP_DIVIDE, 46, 162, 13, "Record" },
+ { SDLK_KP_PLUS, 327, 36, 16, "Play" },
+ { SDLK_KP_ENTER, 330, 99, 18, "Stop" },
+ { SDLK_KP_PERIOD, 330, 163, 18, "AB" },
+ { SDLK_KP5, 186, 227, 27, "5" },
+ { SDLK_KP8, 187, 185, 19, "8" },
+ { SDLK_KP4, 142, 229, 23, "4" },
+ { SDLK_KP6, 231, 229, 22, "6" },
+ { SDLK_KP2, 189, 272, 28, "2" },
+/* Remote Buttons */
+ { SDLK_KP_ENTER, 250, 404, 20, "Stop" },
+ { SDLK_SPACE, 285, 439, 29, "Space" },
+ { SDLK_h, 336, 291, 24, "Hold" },
+ { 0, 0, 0, 0, "None" }
+};
+#elif defined (IRIVER_H300)
+struct button_map bm[] = {
+ { SDLK_KP_PLUS, 56, 335, 20, "Play" },
+ { SDLK_KP8, 140, 304, 29, "Up" },
+ { SDLK_KP_DIVIDE, 233, 331, 23, "Record" },
+ { SDLK_KP_ENTER, 54, 381, 24, "Stop" },
+ { SDLK_KP4, 100, 353, 17, "Left" },
+ { SDLK_KP5, 140, 351, 19, "Navi" },
+ { SDLK_KP6, 185, 356, 19, "Right" },
+ { SDLK_KP_PERIOD, 230, 380, 20, "AB" },
+ { SDLK_KP2, 142, 402, 24, "Down" },
+ { SDLK_KP_ENTER, 211, 479, 21, "Stop" },
+ { SDLK_KP_PLUS, 248, 513, 29, "Play" },
+ { 0, 0, 0, 0, "None" }
+};
+#elif defined (MROBE_500)
+struct button_map bm[] = {
+ { SDLK_KP9, 171, 609, 9, "Play" },
+ { SDLK_KP4, 158, 623, 9, "Left" },
+ { SDLK_KP6, 184, 622, 9, "Right" },
+ { SDLK_KP7, 171, 638, 11, "Menu" },
+ { 0, 0, 0, 0, "None" }
+};
+#elif defined (MROBE_100)
+struct button_map bm[] = {
+ { SDLK_KP7, 80, 233, 30, "Menu" },
+ { SDLK_KP8, 138, 250, 19, "Up" },
+ { SDLK_KP9, 201, 230, 27, "Play" },
+ { SDLK_KP4, 63, 305, 25, "Left" },
+ { SDLK_KP5, 125, 309, 28, "Select" },
+ { SDLK_KP6, 200, 307, 35, "Right" },
+ { SDLK_KP1, 52, 380, 32, "Display" },
+ { SDLK_KP2, 125, 363, 30, "Down" },
+ { SDLK_KP9, 168, 425, 10, "Play" },
+ { SDLK_KP4, 156, 440, 11, "Left" },
+ { SDLK_KP6, 180, 440, 13, "Right" },
+ { SDLK_KP7, 169, 452, 10, "Menu" },
+ { SDLK_KP_MULTIPLY, 222, 15, 16, "Power" },
+ { 0, 0, 0, 0, "None" }
+};
+#elif defined (GIGABEAT_F)
+struct button_map bm[] = {
+ { SDLK_KP_PLUS, 361, 187, 22, "Power" },
+ { SDLK_KP_PERIOD, 361, 270, 17, "Menu" },
+ { SDLK_KP9, 365, 345, 26, "Vol Up" },
+ { SDLK_KP3, 363, 433, 25, "Vol Down" },
+ { SDLK_KP_ENTER, 365, 520, 19, "A" },
+ { SDLK_KP8, 167, 458, 35, "Up" },
+ { SDLK_KP4, 86, 537, 29, "Left" },
+ { SDLK_KP5, 166, 536, 30, "Select" },
+ { SDLK_KP6, 248, 536, 30, "Right" },
+ { SDLK_KP2, 169, 617, 28, "Down" },
+ { 0, 0, 0, 0, "None" }
+};
+#elif defined (GIGABEAT_S)
+struct button_map bm[] = {
+ { SDLK_KP_PLUS, 416, 383, 23, "Play" },
+ { SDLK_KP7, 135, 442, 46, "Back" },
+ { SDLK_KP9, 288, 447, 35, "Menu" },
+ { SDLK_KP8, 214, 480, 32, "Up" },
+ { SDLK_KP4, 128, 558, 33, "Left" },
+ { SDLK_KP5, 214, 556, 34, "Select" },
+ { SDLK_KP6, 293, 558, 35, "Right" },
+ { SDLK_KP2, 214, 637, 38, "Down" },
+ { 0, 0, 0, 0, "None" }
+};
+#elif defined (SAMSUNG_YH820)
+struct button_map bm[] = {
+ { SDLK_KP_PLUS, 330, 53, 23, "Record" },
+ { SDLK_KP7, 132, 208, 21, "Left" },
+ { SDLK_KP5, 182, 210, 18, "Play" },
+ { SDLK_KP9, 234, 211, 22, "Right" },
+ { SDLK_KP8, 182, 260, 15, "Up" },
+ { SDLK_KP4, 122, 277, 29, "Menu" },
+ { SDLK_KP6, 238, 276, 25, "Select" },
+ { SDLK_KP2, 183, 321, 24, "Down" },
+ { 0, 0, 0, 0, "None" }
+};
+#elif defined (SAMSUNG_YH920) || defined (SAMSUNG_YH925)
+struct button_map bm[] = {
+ { SDLK_KP9, 370, 32, 15, "FF" },
+ { SDLK_KP5, 369, 84, 25, "Play" },
+ { SDLK_KP5, 367, 125, 27, "Play" },
+ { SDLK_KP3, 369, 188, 17, "Rew" },
+ { SDLK_KP_PLUS, 370, 330, 30, "Record" },
+ { SDLK_KP4, 146, 252, 32, "Menu" },
+ { SDLK_KP8, 204, 226, 27, "Up" },
+ { SDLK_KP6, 257, 250, 34, "Select" },
+ { SDLK_KP2, 205, 294, 35, "Down" },
+ { 0, 0, 0, 0, "None" }
+};
+#elif defined (ONDA_VX747) || defined (ONDA_VX747P)
+struct button_map bm[] = {
+ { SDLK_MINUS, 113, 583, 28, "Minus" },
+ { SDLK_PLUS, 227, 580, 28, "Plus" },
+ { SDLK_RETURN, 171, 583, 34, "Menu" },
+ { 0, 0, 0, 0, "None" }
+};
+#elif defined (PHILIPS_SA9200)
+struct button_map bm[] = {
+ { SDLK_KP_ENTER, 25, 155, 33, "Power" },
+ { SDLK_PAGEUP, 210, 98, 31, "Vol Up" },
+ { SDLK_PAGEDOWN, 210, 168, 34, "Vol Down" },
+ { SDLK_KP7, 40, 249, 26, "Prev" },
+ { SDLK_KP8, 110, 247, 22, "Up" },
+ { SDLK_KP9, 183, 249, 31, "Next" },
+ { SDLK_KP4, 45, 305, 25, "Left" },
+ { SDLK_KP5, 111, 304, 24, "Play" },
+ { SDLK_KP6, 183, 304, 21, "Right" },
+ { SDLK_KP1, 43, 377, 21, "Menu" },
+ { SDLK_KP2, 112, 371, 24, "Down" },
+ { 0, 0, 0, 0, "None" }
+};
+#elif defined (CREATIVE_ZVM) || defined (CREATIVE_ZVM60GB) || \
+ defined (CREATIVE_ZV)
+struct button_map bm[] = {
+ { SDLK_KP7, 52, 414, 35, "Custom" },
+ { SDLK_KP8, 185, 406, 55, "Up" },
+ { SDLK_KP9, 315, 421, 46, "Play" },
+ { SDLK_KP4, 122, 500, 41, "Left" },
+ { SDLK_KP6, 247, 493, 49, "Right" },
+ { SDLK_KP1, 58, 577, 49, "Back" },
+ { SDLK_KP2, 186, 585, 46, "Down" },
+ { SDLK_KP3, 311, 569, 47, "Menu" },
+ { 0, 0, 0, 0, "None" }
+};
+#elif defined (MPIO_HD200)
+struct button_map bm[] = {
+ { SDLK_ESCAPE, 369, 257, 20, "Rec" },
+ { SDLK_RETURN, 369, 305, 20, "Play/Stop" },
+ { SDLK_UP, 353, 168, 10, "Rew" },
+ { SDLK_DOWN, 353, 198, 10, "FF" },
+ { SDLK_SPACE, 353, 186, 10, "Select" },
+ { SDLK_LEFT, 123, 67, 20, "Vol Down" },
+ { SDLK_RIGHT, 206, 67, 20, "Vol Up" },
+ { SDLK_h, 369, 402, 30, "Hold" },
+ { 0, 0, 0, 0, "None" }
+};
+#else
+struct button_map bm[] = {
+ { 0, 0, 0, 0, ""}
+};
+#endif
+
+static int xy2button( int x, int y)
+{
+ int i;
+ extern bool debug_buttons;
+
+ for ( i = 0; bm[i].button; i++ )
+ /* check distance from center of button < radius */
+ if ( ( (x-bm[i].x)*(x-bm[i].x) ) + ( ( y-bm[i].y)*(y-bm[i].y) ) < bm[i].radius*bm[i].radius ) {
+ if (debug_buttons)
+ printf("Button: %s\n", bm[i].description );
+ return bm[i].button;
+ }
+ return 0;
+}
diff --git a/firmware/target/hosted/sdl/button-sdl.h b/firmware/target/hosted/sdl/button-sdl.h
new file mode 100644
index 0000000000..75a68c49bc
--- /dev/null
+++ b/firmware/target/hosted/sdl/button-sdl.h
@@ -0,0 +1,32 @@
+/***************************************************************************
+ * __________ __ ___.
+ * Open \______ \ ____ ____ | | _\_ |__ _______ ___
+ * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
+ * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
+ * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
+ * \/ \/ \/ \/ \/
+ * $Id$
+ *
+ * Copyright (C) 2009 by Thomas Martitz
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
+ * KIND, either express or implied.
+ *
+ ****************************************************************************/
+
+
+#ifndef __BUTTON_SDL_H__
+#define __BUTTON_SDL_H__
+
+#include <stdbool.h>
+#include "config.h"
+
+bool button_hold(void);
+void button_init_device(void);
+
+#endif /* __BUTTON_SDL_H__ */
diff --git a/firmware/target/hosted/sdl/kernel-sdl.c b/firmware/target/hosted/sdl/kernel-sdl.c
new file mode 100644
index 0000000000..d796921e35
--- /dev/null
+++ b/firmware/target/hosted/sdl/kernel-sdl.c
@@ -0,0 +1,162 @@
+/***************************************************************************
+ * __________ __ ___.
+ * Open \______ \ ____ ____ | | _\_ |__ _______ ___
+ * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
+ * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
+ * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
+ * \/ \/ \/ \/ \/
+ * $Id$
+ *
+ * Copyright (C) 2002 by Felix Arends
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
+ * KIND, either express or implied.
+ *
+ ****************************************************************************/
+
+#include <stdlib.h>
+#include <stdio.h>
+#include <SDL.h>
+#include <SDL_thread.h>
+#include "memory.h"
+#include "system-sdl.h"
+#include "thread-sdl.h"
+#include "kernel.h"
+#include "thread.h"
+#include "panic.h"
+#include "debug.h"
+
+static SDL_TimerID tick_timer_id;
+long start_tick;
+
+/* Condition to signal that "interrupts" may proceed */
+static SDL_cond *sim_thread_cond;
+/* Mutex to serialize changing levels and exclude other threads while
+ * inside a handler */
+static SDL_mutex *sim_irq_mtx;
+static int interrupt_level = HIGHEST_IRQ_LEVEL;
+static int handlers_pending = 0;
+static int status_reg = 0;
+
+/* Nescessary logic:
+ * 1) All threads must pass unblocked
+ * 2) Current handler must always pass unblocked
+ * 3) Threads must be excluded when irq routine is running
+ * 4) No more than one handler routine should execute at a time
+ */
+int set_irq_level(int level)
+{
+ SDL_LockMutex(sim_irq_mtx);
+
+ int oldlevel = interrupt_level;
+
+ if (status_reg == 0 && level == 0 && oldlevel != 0)
+ {
+ /* Not in a handler and "interrupts" are being reenabled */
+ if (handlers_pending > 0)
+ SDL_CondSignal(sim_thread_cond);
+ }
+
+ interrupt_level = level; /* save new level */
+
+ SDL_UnlockMutex(sim_irq_mtx);
+ return oldlevel;
+}
+
+void sim_enter_irq_handler(void)
+{
+ SDL_LockMutex(sim_irq_mtx);
+ handlers_pending++;
+
+ if(interrupt_level != 0)
+ {
+ /* "Interrupts" are disabled. Wait for reenable */
+ SDL_CondWait(sim_thread_cond, sim_irq_mtx);
+ }
+
+ status_reg = 1;
+}
+
+void sim_exit_irq_handler(void)
+{
+ if (--handlers_pending > 0)
+ SDL_CondSignal(sim_thread_cond);
+
+ status_reg = 0;
+ SDL_UnlockMutex(sim_irq_mtx);
+}
+
+static bool sim_kernel_init(void)
+{
+ sim_irq_mtx = SDL_CreateMutex();
+ if (sim_irq_mtx == NULL)
+ {
+ panicf("Cannot create sim_handler_mtx\n");
+ return false;
+ }
+
+ sim_thread_cond = SDL_CreateCond();
+ if (sim_thread_cond == NULL)
+ {
+ panicf("Cannot create sim_thread_cond\n");
+ return false;
+ }
+
+ return true;
+}
+
+void sim_kernel_shutdown(void)
+{
+ SDL_RemoveTimer(tick_timer_id);
+ SDL_DestroyMutex(sim_irq_mtx);
+ SDL_DestroyCond(sim_thread_cond);
+}
+
+Uint32 tick_timer(Uint32 interval, void *param)
+{
+ long new_tick;
+
+ (void) interval;
+ (void) param;
+
+ new_tick = (SDL_GetTicks() - start_tick) / (1000/HZ);
+
+ while(new_tick != current_tick)
+ {
+ sim_enter_irq_handler();
+
+ /* Run through the list of tick tasks - increments tick
+ * on each iteration. */
+ call_tick_tasks();
+
+ sim_exit_irq_handler();
+ }
+
+ return 1;
+}
+
+void tick_start(unsigned int interval_in_ms)
+{
+ if (!sim_kernel_init())
+ {
+ panicf("Could not initialize kernel!");
+ exit(-1);
+ }
+
+ if (tick_timer_id != NULL)
+ {
+ SDL_RemoveTimer(tick_timer_id);
+ tick_timer_id = NULL;
+ }
+ else
+ {
+ start_tick = SDL_GetTicks();
+ }
+
+ tick_timer_id = SDL_AddTimer(interval_in_ms, tick_timer, NULL);
+}
diff --git a/firmware/target/hosted/sdl/lcd-bitmap.c b/firmware/target/hosted/sdl/lcd-bitmap.c
new file mode 100644
index 0000000000..6dfbffff37
--- /dev/null
+++ b/firmware/target/hosted/sdl/lcd-bitmap.c
@@ -0,0 +1,416 @@
+/***************************************************************************
+ * __________ __ ___.
+ * Open \______ \ ____ ____ | | _\_ |__ _______ ___
+ * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
+ * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
+ * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
+ * \/ \/ \/ \/ \/
+ * $Id$
+ *
+ * Copyright (C) 2006 Dan Everton
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
+ * KIND, either express or implied.
+ *
+ ****************************************************************************/
+
+#include "debug.h"
+#include "sim-ui-defines.h"
+#include "system.h"
+#include "lcd-sdl.h"
+#include "screendump.h"
+
+SDL_Surface* lcd_surface;
+
+#if LCD_DEPTH <= 8
+#ifdef HAVE_BACKLIGHT
+SDL_Color lcd_bl_color_dark = {RED_CMP(LCD_BL_DARKCOLOR),
+ GREEN_CMP(LCD_BL_DARKCOLOR),
+ BLUE_CMP(LCD_BL_DARKCOLOR), 0};
+SDL_Color lcd_bl_color_bright = {RED_CMP(LCD_BL_BRIGHTCOLOR),
+ GREEN_CMP(LCD_BL_BRIGHTCOLOR),
+ BLUE_CMP(LCD_BL_BRIGHTCOLOR), 0};
+#ifdef HAVE_LCD_SPLIT
+SDL_Color lcd_bl_color2_dark = {RED_CMP(LCD_BL_DARKCOLOR_2),
+ GREEN_CMP(LCD_BL_DARKCOLOR_2),
+ BLUE_CMP(LCD_BL_DARKCOLOR_2), 0};
+SDL_Color lcd_bl_color2_bright = {RED_CMP(LCD_BL_BRIGHTCOLOR_2),
+ GREEN_CMP(LCD_BL_BRIGHTCOLOR_2),
+ BLUE_CMP(LCD_BL_BRIGHTCOLOR_2), 0};
+#endif
+#endif /* HAVE_BACKLIGHT */
+SDL_Color lcd_color_dark = {RED_CMP(LCD_DARKCOLOR),
+ GREEN_CMP(LCD_DARKCOLOR),
+ BLUE_CMP(LCD_DARKCOLOR), 0};
+SDL_Color lcd_color_bright = {RED_CMP(LCD_BRIGHTCOLOR),
+ GREEN_CMP(LCD_BRIGHTCOLOR),
+ BLUE_CMP(LCD_BRIGHTCOLOR), 0};
+#ifdef HAVE_LCD_SPLIT
+SDL_Color lcd_color2_dark = {RED_CMP(LCD_DARKCOLOR_2),
+ GREEN_CMP(LCD_DARKCOLOR_2),
+ BLUE_CMP(LCD_DARKCOLOR_2), 0};
+SDL_Color lcd_color2_bright = {RED_CMP(LCD_BRIGHTCOLOR_2),
+ GREEN_CMP(LCD_BRIGHTCOLOR_2),
+ BLUE_CMP(LCD_BRIGHTCOLOR_2), 0};
+#endif
+
+#ifdef HAVE_LCD_SPLIT
+#define NUM_SHADES 128
+#else
+#define NUM_SHADES 129
+#endif
+
+#else /* LCD_DEPTH > 8 */
+
+#ifdef HAVE_TRANSFLECTIVE_LCD
+#define BACKLIGHT_OFF_ALPHA 85 /* 1/3 brightness */
+#else
+#define BACKLIGHT_OFF_ALPHA 0 /* pitch black */
+#endif
+
+#endif /* LCD_DEPTH */
+
+#if LCD_DEPTH < 8
+unsigned long (*lcd_ex_getpixel)(int, int) = NULL;
+#endif /* LCD_DEPTH < 8 */
+
+#if LCD_DEPTH == 2
+/* Only defined for positive, non-split LCD for now */
+static const unsigned char colorindex[4] = {128, 85, 43, 0};
+#endif
+
+static unsigned long get_lcd_pixel(int x, int y)
+{
+#if LCD_DEPTH == 1
+#ifdef HAVE_NEGATIVE_LCD
+ return (lcd_framebuffer[y/8][x] & (1 << (y & 7))) ? (NUM_SHADES-1) : 0;
+#else
+ return (lcd_framebuffer[y/8][x] & (1 << (y & 7))) ? 0 : (NUM_SHADES-1);
+#endif
+#elif LCD_DEPTH == 2
+#if LCD_PIXELFORMAT == HORIZONTAL_PACKING
+ return colorindex[(lcd_framebuffer[y][x/4] >> (2 * (~x & 3))) & 3];
+#elif LCD_PIXELFORMAT == VERTICAL_PACKING
+ return colorindex[(lcd_framebuffer[y/4][x] >> (2 * (y & 3))) & 3];
+#elif LCD_PIXELFORMAT == VERTICAL_INTERLEAVED
+ unsigned bits = (lcd_framebuffer[y/8][x] >> (y & 7)) & 0x0101;
+ return colorindex[(bits | (bits >> 7)) & 3];
+#endif
+#elif LCD_DEPTH == 16
+#if LCD_PIXELFORMAT == RGB565SWAPPED
+ unsigned bits = lcd_framebuffer[y][x];
+ return (bits >> 8) | (bits << 8);
+#else
+#if defined(LCD_STRIDEFORMAT) && LCD_STRIDEFORMAT == VERTICAL_STRIDE
+ return *(&lcd_framebuffer[0][0]+LCD_HEIGHT*x+y);
+#else
+ return lcd_framebuffer[y][x];
+#endif
+#endif
+#endif
+}
+
+void lcd_update(void)
+{
+ /* update a full screen rect */
+ lcd_update_rect(0, 0, LCD_WIDTH, LCD_HEIGHT);
+}
+
+void lcd_update_rect(int x_start, int y_start, int width, int height)
+{
+ sdl_update_rect(lcd_surface, x_start, y_start, width, height,
+ LCD_WIDTH, LCD_HEIGHT, get_lcd_pixel);
+ sdl_gui_update(lcd_surface, x_start, y_start, width,
+ height + LCD_SPLIT_LINES, SIM_LCD_WIDTH, SIM_LCD_HEIGHT,
+ background ? UI_LCD_POSX : 0, background? UI_LCD_POSY : 0);
+}
+
+#ifdef HAVE_BACKLIGHT
+void sim_backlight(int value)
+{
+#if LCD_DEPTH <= 8
+ if (value > 0) {
+ sdl_set_gradient(lcd_surface, &lcd_bl_color_dark,
+ &lcd_bl_color_bright, 0, NUM_SHADES);
+#ifdef HAVE_LCD_SPLIT
+ sdl_set_gradient(lcd_surface, &lcd_bl_color2_dark,
+ &lcd_bl_color2_bright, NUM_SHADES, NUM_SHADES);
+#endif
+ } else {
+ sdl_set_gradient(lcd_surface, &lcd_color_dark,
+ &lcd_color_bright, 0, NUM_SHADES);
+#ifdef HAVE_LCD_SPLIT
+ sdl_set_gradient(lcd_surface, &lcd_color2_dark,
+ &lcd_color2_bright, NUM_SHADES, NUM_SHADES);
+#endif
+ }
+#else /* LCD_DEPTH > 8 */
+ SDL_SetAlpha(lcd_surface, SDL_SRCALPHA, (value * 255) / 100);
+#endif /* LCD_DEPTH */
+
+ sdl_gui_update(lcd_surface, 0, 0, SIM_LCD_WIDTH, SIM_LCD_HEIGHT,
+ SIM_LCD_WIDTH, SIM_LCD_HEIGHT,
+ background ? UI_LCD_POSX : 0, background? UI_LCD_POSY : 0);
+}
+#endif /* HAVE_BACKLIGHT */
+
+/* initialise simulator lcd driver */
+void sim_lcd_init(void)
+{
+#if LCD_DEPTH == 16
+ lcd_surface = SDL_CreateRGBSurface(SDL_SWSURFACE,
+ SIM_LCD_WIDTH * display_zoom,
+ SIM_LCD_HEIGHT * display_zoom,
+ LCD_DEPTH, 0, 0, 0, 0);
+#elif LCD_DEPTH <= 8
+ lcd_surface = SDL_CreateRGBSurface(SDL_SWSURFACE,
+ SIM_LCD_WIDTH * display_zoom,
+ SIM_LCD_HEIGHT * display_zoom,
+ 8, 0, 0, 0, 0);
+
+#ifdef HAVE_BACKLIGHT
+ sdl_set_gradient(lcd_surface, &lcd_bl_color_dark,
+ &lcd_bl_color_bright, 0, NUM_SHADES);
+#ifdef HAVE_LCD_SPLIT
+ sdl_set_gradient(lcd_surface, &lcd_bl_color2_dark,
+ &lcd_bl_color2_bright, NUM_SHADES, NUM_SHADES);
+#endif
+#else /* !HAVE_BACKLIGHT */
+ sdl_set_gradient(lcd_surface, &lcd_color_dark,
+ &lcd_color_bright, 0, NUM_SHADES);
+#ifdef HAVE_LCD_SPLIT
+ sdl_set_gradient(lcd_surface, &lcd_color2_dark,
+ &lcd_color2_bright, NUM_SHADES, NUM_SHADES);
+#endif
+#endif /* !HAVE_BACKLIGHT */
+#endif /* LCD_DEPTH */
+}
+
+#if LCD_DEPTH < 8
+void sim_lcd_ex_init(unsigned long (*getpixel)(int, int))
+{
+ lcd_ex_getpixel = getpixel;
+}
+
+void sim_lcd_ex_update_rect(int x_start, int y_start, int width, int height)
+{
+ if (lcd_ex_getpixel) {
+ sdl_update_rect(lcd_surface, x_start, y_start, width, height,
+ LCD_WIDTH, LCD_HEIGHT, lcd_ex_getpixel);
+ sdl_gui_update(lcd_surface, x_start, y_start, width,
+ height + LCD_SPLIT_LINES, SIM_LCD_WIDTH, SIM_LCD_HEIGHT,
+ background ? UI_LCD_POSX : 0,
+ background ? UI_LCD_POSY : 0);
+ }
+}
+#endif
+
+#ifdef HAVE_LCD_COLOR
+/**
+ * |R| |1.000000 -0.000001 1.402000| |Y'|
+ * |G| = |1.000000 -0.334136 -0.714136| |Pb|
+ * |B| |1.000000 1.772000 0.000000| |Pr|
+ * Scaled, normalized, rounded and tweaked to yield RGB 565:
+ * |R| |74 0 101| |Y' - 16| >> 9
+ * |G| = |74 -24 -51| |Cb - 128| >> 8
+ * |B| |74 128 0| |Cr - 128| >> 9
+ */
+#define YFAC (74)
+#define RVFAC (101)
+#define GUFAC (-24)
+#define GVFAC (-51)
+#define BUFAC (128)
+
+static inline int clamp(int val, int min, int max)
+{
+ if (val < min)
+ val = min;
+ else if (val > max)
+ val = max;
+ return val;
+}
+
+void lcd_yuv_set_options(unsigned options)
+{
+ (void)options;
+}
+
+/* Draw a partial YUV colour bitmap - similiar behavior to lcd_blit_yuv
+ in the core */
+void lcd_blit_yuv(unsigned char * const src[3],
+ int src_x, int src_y, int stride,
+ int x, int y, int width, int height)
+{
+ const unsigned char *ysrc, *usrc, *vsrc;
+ int linecounter;
+ fb_data *dst, *row_end;
+ long z;
+
+ /* width and height must be >= 2 and an even number */
+ width &= ~1;
+ linecounter = height >> 1;
+
+#if LCD_WIDTH >= LCD_HEIGHT
+ dst = &lcd_framebuffer[y][x];
+ row_end = dst + width;
+#else
+ dst = &lcd_framebuffer[x][LCD_WIDTH - y - 1];
+ row_end = dst + LCD_WIDTH * width;
+#endif
+
+ z = stride * src_y;
+ ysrc = src[0] + z + src_x;
+ usrc = src[1] + (z >> 2) + (src_x >> 1);
+ vsrc = src[2] + (usrc - src[1]);
+
+ /* stride => amount to jump from end of last row to start of next */
+ stride -= width;
+
+ /* upsampling, YUV->RGB conversion and reduction to RGB565 in one go */
+
+ do
+ {
+ do
+ {
+ int y, cb, cr, rv, guv, bu, r, g, b;
+
+ y = YFAC*(*ysrc++ - 16);
+ cb = *usrc++ - 128;
+ cr = *vsrc++ - 128;
+
+ rv = RVFAC*cr;
+ guv = GUFAC*cb + GVFAC*cr;
+ bu = BUFAC*cb;
+
+ r = y + rv;
+ g = y + guv;
+ b = y + bu;
+
+ if ((unsigned)(r | g | b) > 64*256-1)
+ {
+ r = clamp(r, 0, 64*256-1);
+ g = clamp(g, 0, 64*256-1);
+ b = clamp(b, 0, 64*256-1);
+ }
+
+ *dst = LCD_RGBPACK_LCD(r >> 9, g >> 8, b >> 9);
+
+#if LCD_WIDTH >= LCD_HEIGHT
+ dst++;
+#else
+ dst += LCD_WIDTH;
+#endif
+
+ y = YFAC*(*ysrc++ - 16);
+ r = y + rv;
+ g = y + guv;
+ b = y + bu;
+
+ if ((unsigned)(r | g | b) > 64*256-1)
+ {
+ r = clamp(r, 0, 64*256-1);
+ g = clamp(g, 0, 64*256-1);
+ b = clamp(b, 0, 64*256-1);
+ }
+
+ *dst = LCD_RGBPACK_LCD(r >> 9, g >> 8, b >> 9);
+
+#if LCD_WIDTH >= LCD_HEIGHT
+ dst++;
+#else
+ dst += LCD_WIDTH;
+#endif
+ }
+ while (dst < row_end);
+
+ ysrc += stride;
+ usrc -= width >> 1;
+ vsrc -= width >> 1;
+
+#if LCD_WIDTH >= LCD_HEIGHT
+ row_end += LCD_WIDTH;
+ dst += LCD_WIDTH - width;
+#else
+ row_end -= 1;
+ dst -= LCD_WIDTH*width + 1;
+#endif
+
+ do
+ {
+ int y, cb, cr, rv, guv, bu, r, g, b;
+
+ y = YFAC*(*ysrc++ - 16);
+ cb = *usrc++ - 128;
+ cr = *vsrc++ - 128;
+
+ rv = RVFAC*cr;
+ guv = GUFAC*cb + GVFAC*cr;
+ bu = BUFAC*cb;
+
+ r = y + rv;
+ g = y + guv;
+ b = y + bu;
+
+ if ((unsigned)(r | g | b) > 64*256-1)
+ {
+ r = clamp(r, 0, 64*256-1);
+ g = clamp(g, 0, 64*256-1);
+ b = clamp(b, 0, 64*256-1);
+ }
+
+ *dst = LCD_RGBPACK_LCD(r >> 9, g >> 8, b >> 9);
+
+#if LCD_WIDTH >= LCD_HEIGHT
+ dst++;
+#else
+ dst += LCD_WIDTH;
+#endif
+
+ y = YFAC*(*ysrc++ - 16);
+ r = y + rv;
+ g = y + guv;
+ b = y + bu;
+
+ if ((unsigned)(r | g | b) > 64*256-1)
+ {
+ r = clamp(r, 0, 64*256-1);
+ g = clamp(g, 0, 64*256-1);
+ b = clamp(b, 0, 64*256-1);
+ }
+
+ *dst = LCD_RGBPACK_LCD(r >> 9, g >> 8, b >> 9);
+
+#if LCD_WIDTH >= LCD_HEIGHT
+ dst++;
+#else
+ dst += LCD_WIDTH;
+#endif
+ }
+ while (dst < row_end);
+
+ ysrc += stride;
+ usrc += stride >> 1;
+ vsrc += stride >> 1;
+
+#if LCD_WIDTH >= LCD_HEIGHT
+ row_end += LCD_WIDTH;
+ dst += LCD_WIDTH - width;
+#else
+ row_end -= 1;
+ dst -= LCD_WIDTH*width + 1;
+#endif
+ }
+ while (--linecounter > 0);
+
+#if LCD_WIDTH >= LCD_HEIGHT
+ lcd_update_rect(x, y, width, height);
+#else
+ lcd_update_rect(LCD_WIDTH - y - height, x, height, width);
+#endif
+}
+#endif /* HAVE_LCD_COLOR */
diff --git a/firmware/target/hosted/sdl/lcd-bitmap.h b/firmware/target/hosted/sdl/lcd-bitmap.h
new file mode 100644
index 0000000000..a898744b41
--- /dev/null
+++ b/firmware/target/hosted/sdl/lcd-bitmap.h
@@ -0,0 +1,35 @@
+/***************************************************************************
+ * __________ __ ___.
+ * Open \______ \ ____ ____ | | _\_ |__ _______ ___
+ * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
+ * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
+ * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
+ * \/ \/ \/ \/ \/
+ * $Id$
+ *
+ * Copyright (C) 2006 Dan Everton
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
+ * KIND, either express or implied.
+ *
+ ****************************************************************************/
+
+#ifndef __LCDBITMAP_H__
+#define __LCDBITMAP_H__
+
+#include "lcd.h"
+#include "SDL.h"
+
+void sim_lcd_init(void);
+#if LCD_DEPTH < 8
+void sim_lcd_ex_init(unsigned long (*getpixel)(int, int));
+void sim_lcd_ex_update_rect(int x, int y, int width, int height);
+#endif
+
+#endif /* #ifndef __LCDBITMAP_H__ */
+
diff --git a/firmware/target/hosted/sdl/lcd-charcells.c b/firmware/target/hosted/sdl/lcd-charcells.c
new file mode 100644
index 0000000000..900cbb04dd
--- /dev/null
+++ b/firmware/target/hosted/sdl/lcd-charcells.c
@@ -0,0 +1,198 @@
+/***************************************************************************
+ * __________ __ ___.
+ * Open \______ \ ____ ____ | | _\_ |__ _______ ___
+ * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
+ * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
+ * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
+ * \/ \/ \/ \/ \/
+ * $Id$
+ *
+ * Copyright (C) 2006 Dan Everton
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
+ * KIND, either express or implied.
+ *
+ ****************************************************************************/
+
+#include <string.h>
+#include <unistd.h>
+#include <fcntl.h>
+#include "system.h"
+#include "debug.h"
+#include "lcd.h"
+#include "lcd-charcell.h"
+#include "screendump.h"
+#include "general.h"
+
+#include "lcd-playersim.h"
+#include "sim-ui-defines.h"
+#include "lcd-sdl.h"
+
+/* can't include file.h here */
+#ifndef MAX_PATH
+#define MAX_PATH 260
+#endif
+
+/* extern functions, needed for screendump() */
+extern int sim_creat(const char *name, mode_t mode);
+
+SDL_Surface* lcd_surface;
+
+SDL_Color lcd_bl_color_dark = {RED_CMP(LCD_BL_DARKCOLOR),
+ GREEN_CMP(LCD_BL_DARKCOLOR),
+ BLUE_CMP(LCD_BL_DARKCOLOR), 0};
+SDL_Color lcd_bl_color_bright = {RED_CMP(LCD_BL_BRIGHTCOLOR),
+ GREEN_CMP(LCD_BL_BRIGHTCOLOR),
+ BLUE_CMP(LCD_BL_BRIGHTCOLOR), 0};
+SDL_Color lcd_color_dark = {RED_CMP(LCD_DARKCOLOR),
+ GREEN_CMP(LCD_DARKCOLOR),
+ BLUE_CMP(LCD_DARKCOLOR), 0};
+SDL_Color lcd_color_bright = {RED_CMP(LCD_BRIGHTCOLOR),
+ GREEN_CMP(LCD_BRIGHTCOLOR),
+ BLUE_CMP(LCD_BRIGHTCOLOR), 0};
+
+
+static unsigned long get_lcd_pixel(int x, int y)
+{
+ return sim_lcd_framebuffer[y][x];
+}
+
+void sim_lcd_update_rect(int x_start, int y_start, int width, int height)
+{
+ sdl_update_rect(lcd_surface, x_start, y_start, width, height,
+ SIM_LCD_WIDTH, SIM_LCD_HEIGHT, get_lcd_pixel);
+ sdl_gui_update(lcd_surface, x_start, y_start, width, height,
+ SIM_LCD_WIDTH, SIM_LCD_HEIGHT,
+ background ? UI_LCD_POSX : 0, background ? UI_LCD_POSY : 0);
+}
+
+void lcd_update(void)
+{
+ int x, y;
+
+ for (y = 0; y < lcd_pattern_count; y++)
+ if (lcd_patterns[y].count > 0)
+ sim_lcd_define_pattern(y, lcd_patterns[y].pattern);
+
+ for (y = 0; y < LCD_HEIGHT; y++)
+ for (x = 0; x < LCD_WIDTH; x++)
+ lcd_print_char(x, y, lcd_charbuffer[y][x]);
+
+ if (lcd_cursor.visible)
+ lcd_print_char(lcd_cursor.x, lcd_cursor.y, lcd_cursor.hw_char);
+
+ sim_lcd_update_rect(0, ICON_HEIGHT, SIM_LCD_WIDTH,
+ LCD_HEIGHT*CHAR_HEIGHT*CHAR_PIXEL);
+}
+
+#ifdef HAVE_BACKLIGHT
+void sim_backlight(int value)
+{
+ if (value > 0) {
+ sdl_set_gradient(lcd_surface, &lcd_bl_color_bright,
+ &lcd_bl_color_dark, 0, (1<<LCD_DEPTH));
+ } else {
+ sdl_set_gradient(lcd_surface, &lcd_color_bright,
+ &lcd_color_dark, 0, (1<<LCD_DEPTH));
+ }
+
+ sim_lcd_update_rect(0, 0, SIM_LCD_WIDTH, SIM_LCD_HEIGHT);
+}
+#endif
+
+/* initialise simulator lcd driver */
+void sim_lcd_init(void)
+{
+ lcd_surface = SDL_CreateRGBSurface(SDL_SWSURFACE,
+ SIM_LCD_WIDTH * display_zoom,
+ SIM_LCD_HEIGHT * display_zoom,
+ 8, 0, 0, 0, 0);
+
+ sdl_set_gradient(lcd_surface, &lcd_bl_color_bright,
+ &lcd_bl_color_dark, 0, (1<<LCD_DEPTH));
+}
+
+#define BMP_COMPRESSION 0 /* BI_RGB */
+#define BMP_NUMCOLORS (1 << LCD_DEPTH)
+#define BMP_BPP 1
+#define BMP_LINESIZE (((SIM_LCD_WIDTH + 31) / 32) * 4)
+
+#define BMP_HEADERSIZE (54 + 4 * BMP_NUMCOLORS)
+#define BMP_DATASIZE (BMP_LINESIZE * SIM_LCD_HEIGHT)
+#define BMP_TOTALSIZE (BMP_HEADERSIZE + BMP_DATASIZE)
+
+#define LE16_CONST(x) (x)&0xff, ((x)>>8)&0xff
+#define LE32_CONST(x) (x)&0xff, ((x)>>8)&0xff, ((x)>>16)&0xff, ((x)>>24)&0xff
+
+static const unsigned char bmpheader[] =
+{
+ 0x42, 0x4d, /* 'BM' */
+ LE32_CONST(BMP_TOTALSIZE), /* Total file size */
+ 0x00, 0x00, 0x00, 0x00, /* Reserved */
+ LE32_CONST(BMP_HEADERSIZE), /* Offset to start of pixel data */
+
+ 0x28, 0x00, 0x00, 0x00, /* Size of (2nd) header */
+ LE32_CONST(SIM_LCD_WIDTH), /* Width in pixels */
+ LE32_CONST(SIM_LCD_HEIGHT), /* Height in pixels */
+ 0x01, 0x00, /* Number of planes (always 1) */
+ LE16_CONST(BMP_BPP), /* Bits per pixel 1/4/8/16/24 */
+ LE32_CONST(BMP_COMPRESSION),/* Compression mode */
+ LE32_CONST(BMP_DATASIZE), /* Size of bitmap data */
+ 0xc4, 0x0e, 0x00, 0x00, /* Horizontal resolution (pixels/meter) */
+ 0xc4, 0x0e, 0x00, 0x00, /* Vertical resolution (pixels/meter) */
+ LE32_CONST(BMP_NUMCOLORS), /* Number of used colours */
+ LE32_CONST(BMP_NUMCOLORS), /* Number of important colours */
+
+ BMP_COLOR(LCD_BL_BRIGHTCOLOR),
+ BMP_COLOR(LCD_BL_DARKCOLOR)
+};
+
+void screen_dump(void)
+{
+ int fd;
+ char filename[MAX_PATH];
+ int x, y;
+ static unsigned char line[BMP_LINESIZE];
+
+ create_numbered_filename(filename, "", "dump_", ".bmp", 4
+ IF_CNFN_NUM_(, NULL));
+ DEBUGF("screen_dump\n");
+
+ fd = sim_creat(filename, 0666);
+ if (fd < 0)
+ return;
+
+ write(fd, bmpheader, sizeof(bmpheader));
+ SDL_LockSurface(lcd_surface);
+
+ /* BMP image goes bottom up */
+ for (y = SIM_LCD_HEIGHT - 1; y >= 0; y--)
+ {
+ Uint8 *src = (Uint8 *)lcd_surface->pixels
+ + y * SIM_LCD_WIDTH * display_zoom * display_zoom;
+ unsigned char *dst = line;
+ unsigned dst_mask = 0x80;
+
+ memset(line, 0, sizeof(line));
+ for (x = SIM_LCD_WIDTH; x > 0; x--)
+ {
+ if (*src)
+ *dst |= dst_mask;
+ src += display_zoom;
+ dst_mask >>= 1;
+ if (dst_mask == 0)
+ {
+ dst++;
+ dst_mask = 0x80;
+ }
+ }
+ write(fd, line, sizeof(line));
+ }
+ SDL_UnlockSurface(lcd_surface);
+ close(fd);
+}
diff --git a/firmware/target/hosted/sdl/lcd-charcells.h b/firmware/target/hosted/sdl/lcd-charcells.h
new file mode 100644
index 0000000000..890594f766
--- /dev/null
+++ b/firmware/target/hosted/sdl/lcd-charcells.h
@@ -0,0 +1,34 @@
+/***************************************************************************
+ * __________ __ ___.
+ * Open \______ \ ____ ____ | | _\_ |__ _______ ___
+ * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
+ * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
+ * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
+ * \/ \/ \/ \/ \/
+ * $Id$
+ *
+ * Copyright (C) 2006 Dan Everton
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
+ * KIND, either express or implied.
+ *
+ ****************************************************************************/
+
+#ifndef __LCDCHARCELL_H__
+#define __LCDCHARCELL_H__
+
+#include "lcd.h"
+#include "SDL.h"
+
+#ifdef HAVE_LCD_CHARCELLS
+void sim_lcd_init(void);
+void screen_dump(void);
+#endif
+
+#endif /* #ifndef __LCDCHARCELL_H__ */
+
diff --git a/firmware/target/hosted/sdl/lcd-remote-bitmap.c b/firmware/target/hosted/sdl/lcd-remote-bitmap.c
new file mode 100644
index 0000000000..9972f3e423
--- /dev/null
+++ b/firmware/target/hosted/sdl/lcd-remote-bitmap.c
@@ -0,0 +1,111 @@
+/***************************************************************************
+ * __________ __ ___.
+ * Open \______ \ ____ ____ | | _\_ |__ _______ ___
+ * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
+ * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
+ * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
+ * \/ \/ \/ \/ \/
+ * $Id$
+ *
+ * Copyright (C) 2006 Dan Everton
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
+ * KIND, either express or implied.
+ *
+ ****************************************************************************/
+
+#include "sim-ui-defines.h"
+#include "lcd-sdl.h"
+#include "lcd-remote-bitmap.h"
+#include "screendump.h"
+#include "system.h" /* background */
+
+SDL_Surface *remote_surface = 0;
+
+SDL_Color remote_bl_color_dark = {RED_CMP(LCD_REMOTE_BL_DARKCOLOR),
+ GREEN_CMP(LCD_REMOTE_BL_DARKCOLOR),
+ BLUE_CMP(LCD_REMOTE_BL_DARKCOLOR), 0};
+SDL_Color remote_bl_color_bright = {RED_CMP(LCD_REMOTE_BL_BRIGHTCOLOR),
+ GREEN_CMP(LCD_REMOTE_BL_BRIGHTCOLOR),
+ BLUE_CMP(LCD_REMOTE_BL_BRIGHTCOLOR), 0};
+SDL_Color remote_color_dark = {RED_CMP(LCD_REMOTE_DARKCOLOR),
+ GREEN_CMP(LCD_REMOTE_DARKCOLOR),
+ BLUE_CMP(LCD_REMOTE_DARKCOLOR), 0};
+SDL_Color remote_color_bright = {RED_CMP(LCD_REMOTE_BRIGHTCOLOR),
+ GREEN_CMP(LCD_REMOTE_BRIGHTCOLOR),
+ BLUE_CMP(LCD_REMOTE_BRIGHTCOLOR), 0};
+
+#define NUM_SHADES 129
+
+#if LCD_REMOTE_DEPTH == 2
+/* Only defined for positive, non-split LCD for now */
+static const unsigned char colorindex[4] = {128, 85, 43, 0};
+#endif
+
+static unsigned long get_lcd_remote_pixel(int x, int y)
+{
+#if LCD_REMOTE_DEPTH == 1
+ return lcd_remote_framebuffer[y/8][x] & (1 << (y & 7)) ? 0 : (NUM_SHADES-1);
+#elif LCD_REMOTE_DEPTH == 2
+#if LCD_REMOTE_PIXELFORMAT == VERTICAL_INTERLEAVED
+ unsigned bits = (lcd_remote_framebuffer[y/8][x] >> (y & 7)) & 0x0101;
+ return colorindex[(bits | (bits >> 7)) & 3];
+#endif
+#endif
+}
+
+void lcd_remote_update (void)
+{
+ lcd_remote_update_rect(0, 0, LCD_REMOTE_WIDTH, LCD_REMOTE_HEIGHT);
+}
+
+void lcd_remote_update_rect(int x_start, int y_start, int width, int height)
+{
+ if (remote_surface)
+ {
+ sdl_update_rect(remote_surface, x_start, y_start, width, height,
+ LCD_REMOTE_WIDTH, LCD_REMOTE_HEIGHT, get_lcd_remote_pixel);
+ sdl_gui_update(remote_surface, x_start, y_start, width, height,
+ LCD_REMOTE_WIDTH, LCD_REMOTE_HEIGHT, background ? UI_REMOTE_POSX : 0,
+ background ? UI_REMOTE_POSY : LCD_HEIGHT);
+ }
+}
+
+void sim_remote_backlight(int value)
+{
+ if (remote_surface)
+ {
+ if (value > 0)
+ {
+ sdl_set_gradient(remote_surface, &remote_bl_color_dark,
+ &remote_bl_color_bright, 0, NUM_SHADES);
+ }
+ else
+ {
+ sdl_set_gradient(remote_surface, &remote_color_dark,
+ &remote_color_bright, 0, NUM_SHADES);
+ }
+ sdl_gui_update(remote_surface, 0, 0, LCD_REMOTE_WIDTH, LCD_REMOTE_HEIGHT,
+ LCD_REMOTE_WIDTH, LCD_REMOTE_HEIGHT,
+ background ? UI_REMOTE_POSX : 0,
+ background? UI_REMOTE_POSY : LCD_HEIGHT);
+ }
+}
+
+/* initialise simulator lcd remote driver */
+void sim_lcd_remote_init(void)
+{
+ remote_surface = SDL_CreateRGBSurface(SDL_SWSURFACE,
+ LCD_REMOTE_WIDTH * display_zoom,
+ LCD_REMOTE_HEIGHT * display_zoom,
+ 8, 0, 0, 0, 0);
+
+ sdl_set_gradient(remote_surface, &remote_bl_color_dark,
+ &remote_bl_color_bright, 0, NUM_SHADES);
+}
+
diff --git a/firmware/target/hosted/sdl/lcd-remote-bitmap.h b/firmware/target/hosted/sdl/lcd-remote-bitmap.h
new file mode 100644
index 0000000000..0a92ee6b79
--- /dev/null
+++ b/firmware/target/hosted/sdl/lcd-remote-bitmap.h
@@ -0,0 +1,32 @@
+/***************************************************************************
+ * __________ __ ___.
+ * Open \______ \ ____ ____ | | _\_ |__ _______ ___
+ * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
+ * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
+ * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
+ * \/ \/ \/ \/ \/
+ * $Id$
+ *
+ * Copyright (C) 2006 Dan Everton
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
+ * KIND, either express or implied.
+ *
+ ****************************************************************************/
+
+#ifndef __LCDREMOTE_H__
+#define __LCDREMOTE_H__
+
+#include "lcd.h"
+#include "lcd-remote.h"
+#include "SDL.h"
+
+void sim_lcd_remote_init(void);
+
+#endif /* #ifndef __LCDREMOTE_H__ */
+
diff --git a/firmware/target/hosted/sdl/lcd-sdl.c b/firmware/target/hosted/sdl/lcd-sdl.c
new file mode 100644
index 0000000000..15e4ba95c3
--- /dev/null
+++ b/firmware/target/hosted/sdl/lcd-sdl.c
@@ -0,0 +1,113 @@
+/***************************************************************************
+ * __________ __ ___.
+ * Open \______ \ ____ ____ | | _\_ |__ _______ ___
+ * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
+ * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
+ * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
+ * \/ \/ \/ \/ \/
+ * $Id$
+ *
+ * Copyright (C) 2006 Dan Everton
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
+ * KIND, either express or implied.
+ *
+ ****************************************************************************/
+
+#include <SDL.h>
+#include "lcd-sdl.h"
+#include "sim-ui-defines.h"
+#include "system.h" /* for MIN() and MAX() */
+
+int display_zoom = 1;
+
+void sdl_update_rect(SDL_Surface *surface, int x_start, int y_start, int width,
+ int height, int max_x, int max_y,
+ unsigned long (*getpixel)(int, int))
+{
+ int x, y;
+ int xmax, ymax;
+ SDL_Rect dest;
+
+ ymax = y_start + height;
+ xmax = x_start + width;
+
+ if(xmax > max_x)
+ xmax = max_x;
+ if(ymax >= max_y)
+ ymax = max_y;
+
+ SDL_LockSurface(surface);
+
+ dest.w = display_zoom;
+ dest.h = display_zoom;
+
+ for (x = x_start; x < xmax; x++) {
+ dest.x = x * display_zoom;
+
+#ifdef HAVE_LCD_SPLIT
+ for (y = y_start; y < MIN(ymax, LCD_SPLIT_POS); y++) {
+ dest.y = y * display_zoom;
+
+ SDL_FillRect(surface, &dest, (Uint32)(getpixel(x, y) | 0x80));
+ }
+ for (y = MAX(y_start, LCD_SPLIT_POS); y < ymax; y++) {
+ dest.y = (y + LCD_SPLIT_LINES) * display_zoom ;
+
+ SDL_FillRect(surface, &dest, (Uint32)getpixel(x, y));
+ }
+#else
+ for (y = y_start; y < ymax; y++) {
+ dest.y = y * display_zoom;
+
+ SDL_FillRect(surface, &dest, (Uint32)getpixel(x, y));
+ }
+#endif
+ }
+
+ SDL_UnlockSurface(surface);
+}
+
+void sdl_gui_update(SDL_Surface *surface, int x_start, int y_start, int width,
+ int height, int max_x, int max_y, int ui_x, int ui_y)
+{
+ if (x_start + width > max_x)
+ width = max_x - x_start;
+ if (y_start + height > max_y)
+ height = max_y - y_start;
+
+ SDL_Rect src = {x_start * display_zoom, y_start * display_zoom,
+ width * display_zoom, height * display_zoom};
+ SDL_Rect dest= {(ui_x + x_start) * display_zoom,
+ (ui_y + y_start) * display_zoom,
+ width * display_zoom, height * display_zoom};
+
+ if (surface->flags & SDL_SRCALPHA) /* alpha needs a black background */
+ SDL_FillRect(gui_surface, &dest, 0);
+
+ SDL_BlitSurface(surface, &src, gui_surface, &dest);
+
+ SDL_Flip(gui_surface);
+}
+
+/* set a range of bitmap indices to a gradient from startcolour to endcolour */
+void sdl_set_gradient(SDL_Surface *surface, SDL_Color *start, SDL_Color *end,
+ int first, int steps)
+{
+ int i;
+ SDL_Color palette[steps];
+
+ for (i = 0; i < steps; i++) {
+ palette[i].r = start->r + (end->r - start->r) * i / (steps - 1);
+ palette[i].g = start->g + (end->g - start->g) * i / (steps - 1);
+ palette[i].b = start->b + (end->b - start->b) * i / (steps - 1);
+ }
+
+ SDL_SetPalette(surface, SDL_LOGPAL|SDL_PHYSPAL, palette, first, steps);
+}
+
diff --git a/firmware/target/hosted/sdl/lcd-sdl.h b/firmware/target/hosted/sdl/lcd-sdl.h
new file mode 100644
index 0000000000..1f57b06b95
--- /dev/null
+++ b/firmware/target/hosted/sdl/lcd-sdl.h
@@ -0,0 +1,43 @@
+/***************************************************************************
+ * __________ __ ___.
+ * Open \______ \ ____ ____ | | _\_ |__ _______ ___
+ * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
+ * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
+ * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
+ * \/ \/ \/ \/ \/
+ * $Id$
+ *
+ * Copyright (C) 2006 Dan Everton
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
+ * KIND, either express or implied.
+ *
+ ****************************************************************************/
+
+#ifndef __LCDSDL_H__
+#define __LCDSDL_H__
+
+#include "lcd.h"
+#include "SDL.h"
+
+/* Default display zoom level */
+extern int display_zoom;
+extern SDL_Surface *gui_surface;
+
+void sdl_update_rect(SDL_Surface *surface, int x_start, int y_start, int width,
+ int height, int max_x, int max_y,
+ unsigned long (*getpixel)(int, int));
+
+void sdl_gui_update(SDL_Surface *surface, int x_start, int y_start, int width,
+ int height, int max_x, int max_y, int ui_x, int ui_y);
+
+void sdl_set_gradient(SDL_Surface *surface, SDL_Color *start, SDL_Color *end,
+ int first, int steps);
+
+#endif /* #ifndef __LCDSDL_H__ */
+
diff --git a/firmware/target/hosted/sdl/pcm-sdl.c b/firmware/target/hosted/sdl/pcm-sdl.c
new file mode 100644
index 0000000000..1772db94f4
--- /dev/null
+++ b/firmware/target/hosted/sdl/pcm-sdl.c
@@ -0,0 +1,373 @@
+/***************************************************************************
+ * __________ __ ___.
+ * Open \______ \ ____ ____ | | _\_ |__ _______ ___
+ * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
+ * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
+ * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
+ * \/ \/ \/ \/ \/
+ * $Id$
+ *
+ * Copyright (C) 2005 by Nick Lanham
+ * Copyright (C) 2010 by Thomas Martitz
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
+ * KIND, either express or implied.
+ *
+ ****************************************************************************/
+
+#include "autoconf.h"
+
+#include <stdlib.h>
+#include <stdbool.h>
+#include <SDL.h>
+#include "config.h"
+#include "debug.h"
+#include "sound.h"
+#include "audiohw.h"
+#include "system.h"
+
+#include "pcm.h"
+#include "pcm_sampr.h"
+
+#ifdef DEBUG
+#include <stdio.h>
+extern bool debug_audio;
+#endif
+
+static int sim_volume = 0;
+
+#if CONFIG_CODEC == SWCODEC
+static int cvt_status = -1;
+
+static Uint8* pcm_data;
+static size_t pcm_data_size;
+static size_t pcm_sample_bytes;
+static size_t pcm_channel_bytes;
+
+struct pcm_udata
+{
+ Uint8 *stream;
+ Uint32 num_in;
+ Uint32 num_out;
+#ifdef DEBUG
+ FILE *debug;
+#endif
+} udata;
+
+static SDL_AudioSpec obtained;
+static SDL_AudioCVT cvt;
+
+void pcm_play_lock(void)
+{
+ SDL_LockAudio();
+}
+
+void pcm_play_unlock(void)
+{
+ SDL_UnlockAudio();
+}
+
+static void pcm_dma_apply_settings_nolock(void)
+{
+ cvt_status = SDL_BuildAudioCVT(&cvt, AUDIO_S16SYS, 2, pcm_sampr,
+ obtained.format, obtained.channels, obtained.freq);
+
+ if (cvt_status < 0) {
+ cvt.len_ratio = (double)obtained.freq / (double)pcm_sampr;
+ }
+}
+
+void pcm_dma_apply_settings(void)
+{
+ pcm_play_lock();
+ pcm_dma_apply_settings_nolock();
+ pcm_play_unlock();
+}
+
+void pcm_play_dma_start(const void *addr, size_t size)
+{
+ pcm_dma_apply_settings_nolock();
+
+ pcm_data = (Uint8 *) addr;
+ pcm_data_size = size;
+
+ SDL_PauseAudio(0);
+}
+
+void pcm_play_dma_stop(void)
+{
+ SDL_PauseAudio(1);
+#ifdef DEBUG
+ if (udata.debug != NULL) {
+ fclose(udata.debug);
+ udata.debug = NULL;
+ DEBUGF("Audio debug file closed\n");
+ }
+#endif
+}
+
+void pcm_play_dma_pause(bool pause)
+{
+ if (pause)
+ SDL_PauseAudio(1);
+ else
+ SDL_PauseAudio(0);
+}
+
+size_t pcm_get_bytes_waiting(void)
+{
+ return pcm_data_size;
+}
+
+void write_to_soundcard(struct pcm_udata *udata)
+{
+#ifdef DEBUG
+ if (debug_audio && (udata->debug == NULL)) {
+ udata->debug = fopen("audiodebug.raw", "ab");
+ DEBUGF("Audio debug file open\n");
+ }
+#endif
+ if (cvt.needed) {
+ Uint32 rd = udata->num_in;
+ Uint32 wr = (double)rd * cvt.len_ratio;
+
+ if (wr > udata->num_out) {
+ wr = udata->num_out;
+ rd = (double)wr / cvt.len_ratio;
+
+ if (rd > udata->num_in)
+ {
+ rd = udata->num_in;
+ wr = (double)rd * cvt.len_ratio;
+ }
+ }
+
+ if (wr == 0 || rd == 0)
+ {
+ udata->num_out = udata->num_in = 0;
+ return;
+ }
+
+ if (cvt_status > 0) {
+ cvt.len = rd * pcm_sample_bytes;
+ cvt.buf = (Uint8 *) malloc(cvt.len * cvt.len_mult);
+
+ memcpy(cvt.buf, pcm_data, cvt.len);
+
+ SDL_ConvertAudio(&cvt);
+ SDL_MixAudio(udata->stream, cvt.buf, cvt.len_cvt, sim_volume);
+
+ udata->num_in = cvt.len / pcm_sample_bytes;
+ udata->num_out = cvt.len_cvt / pcm_sample_bytes;
+
+#ifdef DEBUG
+ if (udata->debug != NULL) {
+ fwrite(cvt.buf, sizeof(Uint8), cvt.len_cvt, udata->debug);
+ }
+#endif
+ free(cvt.buf);
+ }
+ else {
+ /* Convert is bad, so do silence */
+ Uint32 num = wr*obtained.channels;
+ udata->num_in = rd;
+ udata->num_out = wr;
+
+ switch (pcm_channel_bytes)
+ {
+ case 1:
+ {
+ Uint8 *stream = udata->stream;
+ while (num-- > 0)
+ *stream++ = obtained.silence;
+ break;
+ }
+ case 2:
+ {
+ Uint16 *stream = (Uint16 *)udata->stream;
+ while (num-- > 0)
+ *stream++ = obtained.silence;
+ break;
+ }
+ }
+#ifdef DEBUG
+ if (udata->debug != NULL) {
+ fwrite(udata->stream, sizeof(Uint8), wr, udata->debug);
+ }
+#endif
+ }
+ } else {
+ udata->num_in = udata->num_out = MIN(udata->num_in, udata->num_out);
+ SDL_MixAudio(udata->stream, pcm_data,
+ udata->num_out * pcm_sample_bytes, sim_volume);
+#ifdef DEBUG
+ if (udata->debug != NULL) {
+ fwrite(pcm_data, sizeof(Uint8), udata->num_out * pcm_sample_bytes,
+ udata->debug);
+ }
+#endif
+ }
+}
+
+void sdl_audio_callback(struct pcm_udata *udata, Uint8 *stream, int len)
+{
+ udata->stream = stream;
+
+ /* Write what we have in the PCM buffer */
+ if (pcm_data_size > 0)
+ goto start;
+
+ /* Audio card wants more? Get some more then. */
+ while (len > 0) {
+ if ((ssize_t)pcm_data_size <= 0) {
+ pcm_data_size = 0;
+
+ if (pcm_callback_for_more)
+ pcm_callback_for_more(&pcm_data, &pcm_data_size);
+ }
+
+ if (pcm_data_size > 0) {
+ start:
+ udata->num_in = pcm_data_size / pcm_sample_bytes;
+ udata->num_out = len / pcm_sample_bytes;
+
+ write_to_soundcard(udata);
+
+ udata->num_in *= pcm_sample_bytes;
+ udata->num_out *= pcm_sample_bytes;
+
+ pcm_data += udata->num_in;
+ pcm_data_size -= udata->num_in;
+ udata->stream += udata->num_out;
+ len -= udata->num_out;
+ } else {
+ DEBUGF("sdl_audio_callback: No Data.\n");
+ pcm_play_dma_stop();
+ pcm_play_dma_stopped_callback();
+ break;
+ }
+ }
+}
+
+const void * pcm_play_dma_get_peak_buffer(int *count)
+{
+ uintptr_t addr = (uintptr_t)pcm_data;
+ *count = pcm_data_size / 4;
+ return (void *)((addr + 2) & ~3);
+}
+
+#ifdef HAVE_RECORDING
+void pcm_rec_lock(void)
+{
+}
+
+void pcm_rec_unlock(void)
+{
+}
+
+void pcm_rec_dma_init(void)
+{
+}
+
+void pcm_rec_dma_close(void)
+{
+}
+
+void pcm_rec_dma_start(void *start, size_t size)
+{
+ (void)start;
+ (void)size;
+}
+
+void pcm_rec_dma_stop(void)
+{
+}
+
+void pcm_rec_dma_record_more(void *start, size_t size)
+{
+ (void)start;
+ (void)size;
+}
+
+unsigned long pcm_rec_status(void)
+{
+ return 0;
+}
+
+const void * pcm_rec_dma_get_peak_buffer(void)
+{
+ return NULL;
+}
+
+#endif /* HAVE_RECORDING */
+
+void pcm_play_dma_init(void)
+{
+ if (SDL_InitSubSystem(SDL_INIT_AUDIO))
+ {
+ DEBUGF("Could not initialize SDL audio subsystem!\n");
+ return;
+ }
+
+ SDL_AudioSpec wanted_spec;
+#ifdef DEBUG
+ udata.debug = NULL;
+ if (debug_audio) {
+ udata.debug = fopen("audiodebug.raw", "wb");
+ DEBUGF("Audio debug file open\n");
+ }
+#endif
+ /* Set 16-bit stereo audio at 44Khz */
+ wanted_spec.freq = 44100;
+ wanted_spec.format = AUDIO_S16SYS;
+ wanted_spec.channels = 2;
+ wanted_spec.samples = 2048;
+ wanted_spec.callback =
+ (void (SDLCALL *)(void *userdata,
+ Uint8 *stream, int len))sdl_audio_callback;
+ wanted_spec.userdata = &udata;
+
+ /* Open the audio device and start playing sound! */
+ if(SDL_OpenAudio(&wanted_spec, &obtained) < 0) {
+ DEBUGF("Unable to open audio: %s\n", SDL_GetError());
+ return;
+ }
+
+ switch (obtained.format)
+ {
+ case AUDIO_U8:
+ case AUDIO_S8:
+ pcm_channel_bytes = 1;
+ break;
+ case AUDIO_U16LSB:
+ case AUDIO_S16LSB:
+ case AUDIO_U16MSB:
+ case AUDIO_S16MSB:
+ pcm_channel_bytes = 2;
+ break;
+ default:
+ DEBUGF("Unknown sample format obtained: %u\n",
+ (unsigned)obtained.format);
+ return;
+ }
+
+ pcm_sample_bytes = obtained.channels * pcm_channel_bytes;
+
+ pcm_dma_apply_settings_nolock();
+}
+
+void pcm_postinit(void)
+{
+}
+
+void pcm_set_mixer_volume(int volume)
+{
+ sim_volume = volume;
+}
+
+#endif /* CONFIG_CODEC == SWCODEC */
diff --git a/firmware/target/hosted/sdl/sim-ui-defines.h b/firmware/target/hosted/sdl/sim-ui-defines.h
new file mode 100644
index 0000000000..567a618fc3
--- /dev/null
+++ b/firmware/target/hosted/sdl/sim-ui-defines.h
@@ -0,0 +1,405 @@
+/***************************************************************************
+ * __________ __ ___.
+ * Open \______ \ ____ ____ | | _\_ |__ _______ ___
+ * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
+ * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
+ * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
+ * \/ \/ \/ \/ \/
+ * $Id$
+ *
+ * Copyright (C) 2006 Dan Everton
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
+ * KIND, either express or implied.
+ *
+ ****************************************************************************/
+
+#ifndef __UISDL_H__
+#define __UISDL_H__
+
+#include <stdbool.h>
+#include "SDL.h"
+#include "config.h"
+
+/* colour definitions are R, G, B */
+
+#if defined(ARCHOS_RECORDER)
+#define UI_TITLE "Jukebox Recorder"
+#define UI_WIDTH 270 /* width of GUI window */
+#define UI_HEIGHT 406 /* height of GUI window */
+#define UI_LCD_POSX 80 /* x position of lcd */
+#define UI_LCD_POSY 104 /* y position of lcd */
+
+#elif defined(ARCHOS_PLAYER)
+#define UI_TITLE "Jukebox Player"
+#define UI_WIDTH 284 /* width of GUI window */
+#define UI_HEIGHT 420 /* height of GUI window */
+#define UI_LCD_POSX 75 /* x position of lcd */
+#define UI_LCD_POSY 116 /* y position of lcd */
+
+#elif defined(ARCHOS_FMRECORDER) || defined(ARCHOS_RECORDERV2)
+#define UI_TITLE "Jukebox FM Recorder"
+#define UI_WIDTH 285 /* width of GUI window */
+#define UI_HEIGHT 414 /* height of GUI window */
+#define UI_LCD_POSX 87 /* x position of lcd */
+#define UI_LCD_POSY 77 /* y position of lcd */
+
+#elif defined(ARCHOS_ONDIOSP) || defined(ARCHOS_ONDIOFM)
+#define UI_TITLE "Ondio"
+#define UI_WIDTH 155 /* width of GUI window */
+#define UI_HEIGHT 334 /* height of GUI window */
+#define UI_LCD_POSX 21 /* x position of lcd */
+#define UI_LCD_POSY 82 /* y position of lcd */
+
+#elif defined(IRIVER_H120) || defined(IRIVER_H100)
+#define UI_TITLE "iriver H1x0"
+#define UI_WIDTH 379 /* width of GUI window */
+#define UI_HEIGHT 508 /* height of GUI window */
+#define UI_LCD_POSX 109 /* x position of lcd */
+#define UI_LCD_POSY 23 /* y position of lcd */
+#define UI_REMOTE_POSX 50 /* x position of remote lcd */
+#define UI_REMOTE_POSY 403 /* y position of remote lcd */
+
+#elif defined(IRIVER_H300)
+#define UI_TITLE "iriver H300"
+#define UI_WIDTH 288 /* width of GUI window */
+#define UI_HEIGHT 581 /* height of GUI window */
+#define UI_LCD_POSX 26 /* x position of lcd */
+#define UI_LCD_POSY 36 /* y position of lcd */
+#define UI_REMOTE_POSX 12 /* x position of remote lcd */
+#define UI_REMOTE_POSY 478 /* y position of remote lcd */
+
+#elif defined(IPOD_1G2G)
+#define UI_TITLE "iPod 1G/2G"
+#define UI_WIDTH 224 /* width of GUI window */
+#define UI_HEIGHT 382 /* height of GUI window */
+#define UI_LCD_POSX 32 /* x position of lcd */
+#define UI_LCD_POSY 12 /* y position of lcd */
+
+#elif defined(IPOD_3G)
+#define UI_TITLE "iPod 3G"
+#define UI_WIDTH 218 /* width of GUI window */
+#define UI_HEIGHT 389 /* height of GUI window */
+#define UI_LCD_POSX 29 /* x position of lcd */
+#define UI_LCD_POSY 16 /* y position of lcd */
+
+#elif defined(IPOD_4G)
+#define UI_TITLE "iPod 4G"
+#define UI_WIDTH 196 /* width of GUI window */
+#define UI_HEIGHT 370 /* height of GUI window */
+#define UI_LCD_POSX 19 /* x position of lcd */
+#define UI_LCD_POSY 14 /* y position of lcd */
+
+#elif defined(IPOD_MINI) || defined(IPOD_MINI2G)
+#define UI_TITLE "iPod mini"
+#define UI_WIDTH 191 /* width of GUI window */
+#define UI_HEIGHT 365 /* height of GUI window */
+#define UI_LCD_POSX 24 /* x position of lcd */
+#define UI_LCD_POSY 17 /* y position of lcd */
+
+#elif defined(IPOD_COLOR)
+#define UI_TITLE "iPod Color"
+#define UI_WIDTH 261 /* width of GUI window */
+#define UI_HEIGHT 493 /* height of GUI window */
+#define UI_LCD_POSX 21 /* x position of lcd */
+#define UI_LCD_POSY 16 /* y position of lcd */
+
+#elif defined(IPOD_NANO)
+#define UI_TITLE "iPod Nano"
+#define UI_WIDTH 199 /* width of GUI window */
+#define UI_HEIGHT 421 /* height of GUI window */
+#define UI_LCD_POSX 13 /* x position of lcd */
+#define UI_LCD_POSY 14 /* y position of lcd */
+
+#elif defined(IPOD_NANO2G)
+#define UI_TITLE "iPod Nano 2G"
+#define UI_WIDTH 235 /* width of GUI window */
+#define UI_HEIGHT 537 /* height of GUI window */
+#define UI_LCD_POSX 29 /* x position of lcd */
+#define UI_LCD_POSY 33 /* y position of lcd */
+
+#elif defined(IPOD_VIDEO)
+#define UI_TITLE "iPod Video"
+#define UI_WIDTH 350 /* width of GUI window */
+#define UI_HEIGHT 591 /* height of GUI window */
+#define UI_LCD_POSX 14 /* x position of lcd */
+#define UI_LCD_POSY 12 /* y position of lcd */
+
+#elif defined(IAUDIO_X5)
+#define UI_TITLE "iAudio X5"
+#define UI_WIDTH 300 /* width of GUI window */
+#define UI_HEIGHT 558 /* height of GUI window */
+#define UI_LCD_POSX 55 /* x position of lcd */
+#define UI_LCD_POSY 61 /* y position of lcd */
+#define UI_REMOTE_POSX 12 /* x position of remote lcd */
+#define UI_REMOTE_POSY 462 /* y position of remote lcd */
+
+#elif defined(IAUDIO_M5)
+#define UI_TITLE "iAudio M5"
+#define UI_WIDTH 374 /* width of GUI window */
+#define UI_HEIGHT 650 /* height of GUI window */
+#define UI_LCD_POSX 82 /* x position of lcd */
+#define UI_LCD_POSY 74 /* y position of lcd */
+#define UI_REMOTE_POSX 59 /* x position of remote lcd */
+#define UI_REMOTE_POSY 509 /* y position of remote lcd */
+
+#elif defined(IAUDIO_M3)
+#define UI_TITLE "iAudio M3"
+#define UI_WIDTH 397 /* width of GUI window */
+#define UI_HEIGHT 501 /* height of GUI window */
+#define UI_LCD_POSX 92 /* x position of lcd */
+#define UI_LCD_POSY 348 /* y position of lcd */
+
+#elif defined(GIGABEAT_F)
+#define UI_TITLE "Toshiba Gigabeat"
+#define UI_WIDTH 401 /* width of GUI window */
+#define UI_HEIGHT 655 /* height of GUI window */
+#define UI_LCD_POSX 48 /* x position of lcd */
+#define UI_LCD_POSY 60 /* y position of lcd */
+
+#elif defined(GIGABEAT_S)
+#define UI_TITLE "Toshiba Gigabeat"
+#define UI_WIDTH 450 /* width of GUI window */
+#define UI_HEIGHT 688 /* height of GUI window */
+#define UI_LCD_POSX 96 /* x position of lcd */
+#define UI_LCD_POSY 90 /* y position of lcd */
+
+#elif defined(MROBE_500)
+#if LCD_WIDTH==320
+#define UI_TITLE "Olympus M:Robe 500"
+#define UI_WIDTH 450 /* width of GUI window */
+#define UI_HEIGHT 350 /* height of GUI window */
+#define UI_LCD_POSX 65 /* x position of lcd */
+#define UI_LCD_POSY 30 /* y position of lcd */
+#define UI_REMOTE_POSX 36 /* x position of remote lcd */
+#define UI_REMOTE_POSY 318 /* y position of remote lcd */
+#else
+#define UI_TITLE "Olympus M:Robe 500"
+#define UI_WIDTH 895 /* width of GUI window */
+#define UI_HEIGHT 646 /* height of GUI window */
+#define UI_LCD_POSX 129 /* x position of lcd */
+#define UI_LCD_POSY 60 /* y position of lcd */
+#define UI_REMOTE_POSX 37 /* x position of remote lcd */
+#define UI_REMOTE_POSY 615 /* y position of remote lcd */
+#endif
+
+#elif defined(IRIVER_H10)
+#define UI_TITLE "iriver H10 20Gb"
+#define UI_WIDTH 392 /* width of GUI window */
+#define UI_HEIGHT 391 /* height of GUI window */
+#define UI_LCD_POSX 111 /* x position of lcd */
+#define UI_LCD_POSY 30 /* y position of lcd */
+
+#elif defined(IRIVER_H10_5GB)
+#define UI_TITLE "iriver H10 5/6Gb"
+#define UI_WIDTH 353 /* width of GUI window */
+#define UI_HEIGHT 460 /* height of GUI window */
+#define UI_LCD_POSX 112 /* x position of lcd */
+#define UI_LCD_POSY 45 /* y position of lcd */
+
+#elif defined(SANSA_E200) || defined(SANSA_E200V2)
+#ifdef SANSA_E200
+#define UI_TITLE "Sansa e200"
+#else
+#define UI_TITLE "Sansa e200v2"
+#endif
+#define UI_WIDTH 260 /* width of GUI window */
+#define UI_HEIGHT 502 /* height of GUI window */
+#define UI_LCD_POSX 42 /* x position of lcd */
+#define UI_LCD_POSY 37 /* y position of lcd */
+
+#elif defined(SANSA_C200) || defined(SANSA_C200V2)
+#ifdef SANSA_C200
+#define UI_TITLE "Sansa c200"
+#else
+#define UI_TITLE "Sansa c200v2"
+#endif
+#define UI_WIDTH 350 /* width of GUI window */
+#define UI_HEIGHT 152 /* height of GUI window */
+#define UI_LCD_POSX 42 /* x position of lcd */
+#define UI_LCD_POSY 35 /* y position of lcd */
+
+#elif defined(IRIVER_IFP7XX)
+#define UI_TITLE "iriver iFP7xx"
+#define UI_WIDTH 425 /* width of GUI window */
+#define UI_HEIGHT 183 /* height of GUI window */
+#define UI_LCD_POSX 115 /* x position of lcd */
+#define UI_LCD_POSY 54 /* y position of lcd */
+
+#elif defined(ARCHOS_AV300)
+#define UI_TITLE "Archos AV300"
+/* We are temporarily using a 2bpp LCD driver and dummy bitmap */
+#define UI_WIDTH 420 /* width of GUI window */
+#define UI_HEIGHT 340 /* height of GUI window */
+#define UI_LCD_POSX 50 /* x position of lcd */
+#define UI_LCD_POSY 50 /* y position of lcd */
+
+#elif defined(MROBE_100)
+#define UI_TITLE "Olympus M:Robe 100"
+#define UI_WIDTH 247 /* width of GUI window */
+#define UI_HEIGHT 462 /* height of GUI window */
+#define UI_LCD_POSX 43 /* x position of lcd */
+#define UI_LCD_POSY 25 /* y position of lcd */
+#define UI_REMOTE_POSX 34 /* x position of remote lcd */
+#define UI_REMOTE_POSY 432 /* y position of remote lcd */
+
+#elif defined(COWON_D2)
+#define UI_TITLE "Cowon D2"
+#define UI_WIDTH 472 /* width of GUI window */
+#define UI_HEIGHT 368 /* height of GUI window */
+#define UI_LCD_POSX 58 /* x position of lcd */
+#define UI_LCD_POSY 67 /* y position of lcd */
+
+#elif defined(IAUDIO_7)
+#define UI_TITLE "iAudio7"
+#define UI_WIDTH 494 /* width of GUI window */
+#define UI_HEIGHT 214 /* height of GUI window */
+#define UI_LCD_POSX 131 /* x position of lcd */
+#define UI_LCD_POSY 38 /* y position of lcd */
+
+#elif defined(CREATIVE_ZVM) || defined(CREATIVE_ZVM60GB)
+#ifdef CREATIVE_ZVM
+ #define UI_TITLE "Creative Zen Vision:M 30GB"
+#else
+ #define UI_TITLE "Creative Zen Vision:M 60GB"
+#endif
+#define UI_WIDTH 383 /* width of GUI window */
+#define UI_HEIGHT 643 /* height of GUI window */
+#define UI_LCD_POSX 31 /* x position of lcd */
+#define UI_LCD_POSY 62 /* y position of lcd */
+
+#elif defined(CREATIVE_ZV)
+#define UI_TITLE "Creative Zen Vision"
+#define UI_WIDTH 1054 /* width of GUI window */
+#define UI_HEIGHT 643 /* height of GUI window */
+#define UI_LCD_POSX 129 /* x position of lcd */
+#define UI_LCD_POSY 85 /* y position of lcd */
+
+#elif defined(MEIZU_M6SL)
+#define UI_TITLE "Meizu M6"
+#define UI_WIDTH 512 /* width of GUI window */
+#define UI_HEIGHT 322 /* height of GUI window */
+#define UI_LCD_POSX 39 /* x position of lcd */
+#define UI_LCD_POSY 38 /* y position of lcd */
+
+#elif defined(SANSA_FUZE) || defined(SANSA_FUZEV2)
+#ifdef SANSA_FUZE
+#define UI_TITLE "Sansa Fuze"
+#else
+#define UI_TITLE "Sansa Fuzev2"
+#endif
+#define UI_WIDTH 279 /* width of GUI window */
+#define UI_HEIGHT 449 /* height of GUI window */
+#define UI_LCD_POSX 30 /* x position of lcd */
+#define UI_LCD_POSY 31 /* y position of lcd */
+
+#elif defined(SANSA_CLIP) || defined(SANSA_CLIPV2)
+#if defined(SANSA_CLIP)
+#define CLIP_VERSION ""
+#elif defined(SANSA_CLIPV2)
+#define CLIP_VERSION "v2"
+#endif
+#define UI_TITLE "Sansa Clip"CLIP_VERSION
+#define UI_WIDTH 205 /* width of GUI window */
+#define UI_HEIGHT 325 /* height of GUI window */
+#define UI_LCD_POSX 38 /* x position of lcd */
+#define UI_LCD_POSY 38 /* y position of lcd */
+
+#elif defined(SANSA_CLIPPLUS)
+#define UI_TITLE "Sansa Clip+"
+#define UI_WIDTH 205 /* width of GUI window */
+#define UI_HEIGHT 325 /* height of GUI window */
+#define UI_LCD_POSX 42 /* x position of lcd */
+#define UI_LCD_POSY 42 /* y position of lcd */
+
+
+
+#elif defined(PHILIPS_SA9200)
+#define UI_TITLE "Philips GoGear SA9200"
+#define UI_WIDTH 233 /* width of GUI window */
+#define UI_HEIGHT 435 /* height of GUI window */
+#define UI_LCD_POSX 50 /* x position of lcd */
+#define UI_LCD_POSY 50 /* y position of lcd */
+
+#elif defined(PHILIPS_HDD1630)
+#define UI_TITLE "Philips GoGear HDD1630"
+#define UI_WIDTH 407 /* width of GUI window */
+#define UI_HEIGHT 391 /* height of GUI window */
+#define UI_LCD_POSX 143 /* x position of lcd */
+#define UI_LCD_POSY 27 /* y position of lcd */
+
+#elif defined(SANSA_M200V4)
+#define UI_TITLE "sansa m200v4"
+#define UI_WIDTH 350 /* width of GUI window */
+#define UI_HEIGHT 168 /* height of GUI window */
+#define UI_LCD_POSX 42 /* x position of lcd */
+#define UI_LCD_POSY 55 /* y position of lcd */
+
+#elif defined(ONDA_VX747) || defined(ONDA_VX747P)
+#ifdef ONDA_VX747
+#define UI_TITLE "Onda VX747"
+#else
+#define UI_TITLE "Onda VX747+"
+#endif
+#define UI_WIDTH 340 /* width of GUI window */
+#define UI_HEIGHT 601 /* height of GUI window */
+#define UI_LCD_POSX 45 /* x position of lcd */
+#define UI_LCD_POSY 90 /* y position of lcd */
+
+#elif defined(ONDA_VX777)
+#define UI_TITLE "Onda VX777"
+#define UI_WIDTH 306 /* width of GUI window */
+#define UI_HEIGHT 558 /* height of GUI window */
+#define UI_LCD_POSX 32 /* x position of lcd */
+#define UI_LCD_POSY 81 /* y position of lcd */
+
+#elif defined(SAMSUNG_YH820)
+#define UI_TITLE "Samsung YH-820"
+#define UI_WIDTH 368 /* width of GUI window */
+#define UI_HEIGHT 428 /* height of GUI window */
+#define UI_LCD_POSX 120 /* x position of lcd */
+#define UI_LCD_POSY 75 /* y position of lcd */
+
+#elif defined(SAMSUNG_YH920) || defined(SAMSUNG_YH925)
+#ifdef SAMSUNG_YH920
+#define UI_TITLE "Samsung YH-920"
+#else
+#define UI_TITLE "Samsung YH-925"
+#endif
+#define UI_WIDTH 408 /* width of GUI window */
+#define UI_HEIGHT 454 /* height of GUI window */
+#define UI_LCD_POSX 124 /* x position of lcd */
+#define UI_LCD_POSY 42 /* y position of lcd */
+
+#elif defined(MINI2440)
+#define UI_TITLE "Mini2440"
+#define UI_WIDTH 441 /* width of GUI window */
+#define UI_HEIGHT 436 /* height of GUI window */
+#define UI_LCD_POSX 148 /* x position of lcd */
+#define UI_LCD_POSY 50 /* y position of lcd */
+
+#elif defined(PBELL_VIBE500)
+#define UI_TITLE "Packard Bell Vibe 500"
+#define UI_WIDTH 287 /* width of GUI window */
+#define UI_HEIGHT 488 /* height of GUI window */
+#define UI_LCD_POSX 64 /* x position of lcd */
+#define UI_LCD_POSY 61 /* y position of lcd */
+
+#elif defined(MPIO_HD200)
+#define UI_TITLE "MPIO HD200"
+#define UI_WIDTH 430 /* width of GUI window */
+#define UI_HEIGHT 479 /* height of GUI window */
+#define UI_LCD_POSX 101
+#define UI_LCD_POSY 195
+
+#elif defined(SIMULATOR)
+#error no UI defines
+#endif
+
+#endif /* #ifndef __UISDL_H__ */
+
diff --git a/firmware/target/hosted/sdl/system-sdl.c b/firmware/target/hosted/sdl/system-sdl.c
new file mode 100644
index 0000000000..693e8d1b57
--- /dev/null
+++ b/firmware/target/hosted/sdl/system-sdl.c
@@ -0,0 +1,236 @@
+/***************************************************************************
+ * __________ __ ___.
+ * Open \______ \ ____ ____ | | _\_ |__ _______ ___
+ * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
+ * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
+ * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
+ * \/ \/ \/ \/ \/
+ * $Id$
+ *
+ * Copyright (C) 2006 by Daniel Everton <dan@iocaine.org>
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
+ * KIND, either express or implied.
+ *
+ ****************************************************************************/
+
+#include <SDL.h>
+#include <stdlib.h>
+#include <string.h>
+#include <setjmp.h>
+#include "system-sdl.h"
+#include "thread-sdl.h"
+#include "sim-ui-defines.h"
+#include "lcd-sdl.h"
+#ifdef HAVE_LCD_BITMAP
+#include "lcd-bitmap.h"
+#elif defined(HAVE_LCD_CHARCELLS)
+#include "lcd-charcells.h"
+#endif
+#ifdef HAVE_REMOTE_LCD
+#include "lcd-remote-bitmap.h"
+#endif
+#include "panic.h"
+#include "debug.h"
+
+SDL_Surface *gui_surface;
+
+bool background = true; /* use backgrounds by default */
+#ifdef HAVE_REMOTE_LCD
+bool showremote = true; /* include remote by default */
+#endif
+bool mapping = false;
+bool debug_buttons = false;
+
+bool lcd_display_redraw = true; /* Used for player simulator */
+char having_new_lcd = true; /* Used for player simulator */
+bool sim_alarm_wakeup = false;
+const char *sim_root_dir = NULL;
+extern int display_zoom;
+
+#ifdef DEBUG
+bool debug_audio = false;
+#endif
+
+bool debug_wps = false;
+int wps_verbose_level = 3;
+
+
+void sys_poweroff(void)
+{
+ /* Order here is relevent to prevent deadlocks and use of destroyed
+ sync primitives by kernel threads */
+ sim_thread_shutdown();
+ sim_kernel_shutdown();
+ SDL_Quit();
+}
+
+void system_init(void)
+{
+ SDL_Surface *picture_surface;
+ int width, height;
+
+ if (SDL_Init(SDL_INIT_VIDEO|SDL_INIT_TIMER))
+ panicf("%s", SDL_GetError());
+
+ /* Try and load the background image. If it fails go without */
+ if (background) {
+ picture_surface = SDL_LoadBMP("UI256.bmp");
+ if (picture_surface == NULL) {
+ background = false;
+ DEBUGF("warn: %s\n", SDL_GetError());
+ }
+ }
+
+ /* Set things up */
+ if (background)
+ {
+ width = UI_WIDTH;
+ height = UI_HEIGHT;
+ }
+ else
+ {
+#ifdef HAVE_REMOTE_LCD
+ if (showremote)
+ {
+ width = SIM_LCD_WIDTH > SIM_REMOTE_WIDTH ? SIM_LCD_WIDTH : SIM_REMOTE_WIDTH;
+ height = SIM_LCD_HEIGHT + SIM_REMOTE_HEIGHT;
+ }
+ else
+#endif
+ {
+ width = SIM_LCD_WIDTH;
+ height = SIM_LCD_HEIGHT;
+ }
+ }
+
+
+ if ((gui_surface = SDL_SetVideoMode(width * display_zoom, height * display_zoom, 24, SDL_HWSURFACE|SDL_DOUBLEBUF)) == NULL) {
+ panicf("%s", SDL_GetError());
+ }
+
+ SDL_WM_SetCaption(UI_TITLE, NULL);
+
+ sim_lcd_init();
+#ifdef HAVE_REMOTE_LCD
+ if (showremote)
+ sim_lcd_remote_init();
+#endif
+
+ if (background && picture_surface != NULL) {
+ SDL_BlitSurface(picture_surface, NULL, gui_surface, NULL);
+ SDL_UpdateRect(gui_surface, 0, 0, 0, 0);
+ }
+}
+
+void system_exception_wait(void)
+{
+ sim_thread_exception_wait();
+}
+
+void system_reboot(void)
+{
+ sim_thread_exception_wait();
+}
+
+void sys_handle_argv(int argc, char *argv[])
+{
+ if (argc >= 1)
+ {
+ int x;
+ for (x = 1; x < argc; x++)
+ {
+#ifdef DEBUG
+ if (!strcmp("--debugaudio", argv[x]))
+ {
+ debug_audio = true;
+ printf("Writing debug audio file.\n");
+ }
+ else
+#endif
+ if (!strcmp("--debugwps", argv[x]))
+ {
+ debug_wps = true;
+ printf("WPS debug mode enabled.\n");
+ }
+ else if (!strcmp("--nobackground", argv[x]))
+ {
+ background = false;
+ printf("Disabling background image.\n");
+ }
+#ifdef HAVE_REMOTE_LCD
+ else if (!strcmp("--noremote", argv[x]))
+ {
+ showremote = false;
+ background = false;
+ printf("Disabling remote image.\n");
+ }
+#endif
+ else if (!strcmp("--old_lcd", argv[x]))
+ {
+ having_new_lcd = false;
+ printf("Using old LCD layout.\n");
+ }
+ else if (!strcmp("--zoom", argv[x]))
+ {
+ x++;
+ if(x < argc)
+ display_zoom=atoi(argv[x]);
+ else
+ display_zoom = 2;
+ printf("Window zoom is %d\n", display_zoom);
+ }
+ else if (!strcmp("--alarm", argv[x]))
+ {
+ sim_alarm_wakeup = true;
+ printf("Simulating alarm wakeup.\n");
+ }
+ else if (!strcmp("--root", argv[x]))
+ {
+ x++;
+ if (x < argc)
+ {
+ sim_root_dir = argv[x];
+ printf("Root directory: %s\n", sim_root_dir);
+ }
+ }
+ else if (!strcmp("--mapping", argv[x]))
+ {
+ mapping = true;
+ printf("Printing click coords with drag radii.\n");
+ }
+ else if (!strcmp("--debugbuttons", argv[x]))
+ {
+ debug_buttons = true;
+ printf("Printing background button clicks.\n");
+ }
+ else
+ {
+ printf("rockboxui\n");
+ printf("Arguments:\n");
+#ifdef DEBUG
+ printf(" --debugaudio \t Write raw PCM data to audiodebug.raw\n");
+#endif
+ printf(" --debugwps \t Print advanced WPS debug info\n");
+ printf(" --nobackground \t Disable the background image\n");
+#ifdef HAVE_REMOTE_LCD
+ printf(" --noremote \t Disable the remote image (will disable backgrounds)\n");
+#endif
+ printf(" --old_lcd \t [Player] simulate old playermodel (ROM version<4.51)\n");
+ printf(" --zoom [VAL]\t Window zoom (will disable backgrounds)\n");
+ printf(" --alarm \t Simulate a wake-up on alarm\n");
+ printf(" --root [DIR]\t Set root directory\n");
+ printf(" --mapping \t Output coordinates and radius for mapping backgrounds\n");
+ exit(0);
+ }
+ }
+ }
+ if (display_zoom > 1) {
+ background = false;
+ }
+}
diff --git a/firmware/target/hosted/sdl/system-sdl.h b/firmware/target/hosted/sdl/system-sdl.h
new file mode 100644
index 0000000000..917e6e89da
--- /dev/null
+++ b/firmware/target/hosted/sdl/system-sdl.h
@@ -0,0 +1,52 @@
+/***************************************************************************
+ * __________ __ ___.
+ * Open \______ \ ____ ____ | | _\_ |__ _______ ___
+ * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
+ * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
+ * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
+ * \/ \/ \/ \/ \/
+ * $Id$
+ *
+ * Copyright (C) 2007 by Michael Sevakis
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
+ * KIND, either express or implied.
+ *
+ ****************************************************************************/
+#ifndef _SYSTEM_SDL_H_
+#define _SYSTEM_SDL_H_
+
+#include <stdbool.h>
+
+#define HIGHEST_IRQ_LEVEL 1
+
+int set_irq_level(int level);
+
+#define disable_irq() \
+ ((void)set_irq_level(HIGHEST_IRQ_LEVEL))
+
+#define enable_irq() \
+ ((void)set_irq_level(0))
+
+#define disable_irq_save() \
+ set_irq_level(HIGHEST_IRQ_LEVEL)
+
+#define restore_irq(level) \
+ ((void)set_irq_level(level))
+
+void sim_enter_irq_handler(void);
+void sim_exit_irq_handler(void);
+void sim_kernel_shutdown(void);
+void sys_poweroff(void);
+void sys_handle_argv(int argc, char *argv[]);
+
+extern bool background; /* True if the background image is enabled */
+extern int display_zoom;
+extern long start_tick;
+
+#endif /* _SYSTEM_SDL_H_ */
diff --git a/firmware/target/hosted/sdl/thread-sdl.c b/firmware/target/hosted/sdl/thread-sdl.c
new file mode 100644
index 0000000000..fbe2621d40
--- /dev/null
+++ b/firmware/target/hosted/sdl/thread-sdl.c
@@ -0,0 +1,610 @@
+/***************************************************************************
+ * __________ __ ___.
+ * Open \______ \ ____ ____ | | _\_ |__ _______ ___
+ * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
+ * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
+ * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
+ * \/ \/ \/ \/ \/
+ * $Id$
+ *
+ * Copyright (C) 2006 Dan Everton
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
+ * KIND, either express or implied.
+ *
+ ****************************************************************************/
+
+#include <stdbool.h>
+#include <time.h>
+#include <SDL.h>
+#include <SDL_thread.h>
+#include <stdlib.h>
+#include <memory.h>
+#include <setjmp.h>
+#include "system-sdl.h"
+#include "thread-sdl.h"
+#include "system.h"
+#include "kernel.h"
+#include "thread.h"
+#include "debug.h"
+
+/* Define this as 1 to show informational messages that are not errors. */
+#define THREAD_SDL_DEBUGF_ENABLED 0
+
+#if THREAD_SDL_DEBUGF_ENABLED
+#define THREAD_SDL_DEBUGF(...) DEBUGF(__VA_ARGS__)
+static char __name[32];
+#define THREAD_SDL_GET_NAME(thread) \
+ ({ thread_get_name(__name, ARRAYLEN(__name), thread); __name; })
+#else
+#define THREAD_SDL_DEBUGF(...)
+#define THREAD_SDL_GET_NAME(thread)
+#endif
+
+#define THREAD_PANICF(str...) \
+ ({ fprintf(stderr, str); exit(-1); })
+
+/* Thread/core entries as in rockbox core */
+static struct core_entry cores[NUM_CORES];
+struct thread_entry threads[MAXTHREADS];
+/* Jump buffers for graceful exit - kernel threads don't stay neatly
+ * in their start routines responding to messages so this is the only
+ * way to get them back in there so they may exit */
+static jmp_buf thread_jmpbufs[MAXTHREADS];
+/* this mutex locks out other Rockbox threads while one runs,
+ * that enables us to simulate a cooperative environment even if
+ * the host is preemptive */
+static SDL_mutex *m;
+static volatile bool threads_exit = false;
+
+extern long start_tick;
+
+void sim_thread_shutdown(void)
+{
+ int i;
+
+ /* Tell all threads jump back to their start routines, unlock and exit
+ gracefully - we'll check each one in turn for it's status. Threads
+ _could_ terminate via remove_thread or multiple threads could exit
+ on each unlock but that is safe. */
+
+ /* Do this before trying to acquire lock */
+ threads_exit = true;
+
+ /* Take control */
+ SDL_LockMutex(m);
+
+ for (i = 0; i < MAXTHREADS; i++)
+ {
+ struct thread_entry *thread = &threads[i];
+ /* exit all current threads, except the main one */
+ if (thread->context.t != NULL)
+ {
+ /* Signal thread on delay or block */
+ SDL_Thread *t = thread->context.t;
+ SDL_SemPost(thread->context.s);
+ SDL_UnlockMutex(m);
+ /* Wait for it to finish */
+ SDL_WaitThread(t, NULL);
+ /* Relock for next thread signal */
+ SDL_LockMutex(m);
+ }
+ }
+
+ SDL_UnlockMutex(m);
+ SDL_DestroyMutex(m);
+}
+
+static void new_thread_id(unsigned int slot_num,
+ struct thread_entry *thread)
+{
+ unsigned int version =
+ (thread->id + (1u << THREAD_ID_VERSION_SHIFT))
+ & THREAD_ID_VERSION_MASK;
+
+ if (version == 0)
+ version = 1u << THREAD_ID_VERSION_SHIFT;
+
+ thread->id = version | (slot_num & THREAD_ID_SLOT_MASK);
+}
+
+static struct thread_entry * find_empty_thread_slot(void)
+{
+ struct thread_entry *thread = NULL;
+ int n;
+
+ for (n = 0; n < MAXTHREADS; n++)
+ {
+ int state = threads[n].state;
+
+ if (state == STATE_KILLED)
+ {
+ thread = &threads[n];
+ break;
+ }
+ }
+
+ return thread;
+}
+
+
+/* Initialize SDL threading */
+void init_threads(void)
+{
+ struct thread_entry *thread;
+ int n;
+
+ memset(cores, 0, sizeof(cores));
+ memset(threads, 0, sizeof(threads));
+
+ m = SDL_CreateMutex();
+
+ if (SDL_LockMutex(m) == -1)
+ {
+ fprintf(stderr, "Couldn't lock mutex\n");
+ return;
+ }
+
+ /* Initialize all IDs */
+ for (n = 0; n < MAXTHREADS; n++)
+ threads[n].id = THREAD_ID_INIT(n);
+
+ /* Slot 0 is reserved for the main thread - initialize it here and
+ then create the SDL thread - it is possible to have a quick, early
+ shutdown try to access the structure. */
+ thread = &threads[0];
+ thread->stack = (uintptr_t *)" ";
+ thread->stack_size = 8;
+ thread->name = "main";
+ thread->state = STATE_RUNNING;
+ thread->context.s = SDL_CreateSemaphore(0);
+ thread->context.t = NULL; /* NULL for the implicit main thread */
+ cores[CURRENT_CORE].running = thread;
+
+ if (thread->context.s == NULL)
+ {
+ fprintf(stderr, "Failed to create main semaphore\n");
+ return;
+ }
+
+ THREAD_SDL_DEBUGF("Main thread: %p\n", thread);
+
+ return;
+}
+
+void sim_thread_exception_wait(void)
+{
+ while (1)
+ {
+ SDL_Delay(HZ/10);
+ if (threads_exit)
+ thread_exit();
+ }
+}
+
+/* A way to yield and leave the threading system for extended periods */
+void sim_thread_lock(void *me)
+{
+ SDL_LockMutex(m);
+ cores[CURRENT_CORE].running = (struct thread_entry *)me;
+
+ if (threads_exit)
+ thread_exit();
+}
+
+void * sim_thread_unlock(void)
+{
+ struct thread_entry *current = cores[CURRENT_CORE].running;
+ SDL_UnlockMutex(m);
+ return current;
+}
+
+struct thread_entry * thread_id_entry(unsigned int thread_id)
+{
+ return (thread_id == THREAD_ID_CURRENT) ?
+ cores[CURRENT_CORE].running :
+ &threads[thread_id & THREAD_ID_SLOT_MASK];
+}
+
+static void add_to_list_l(struct thread_entry **list,
+ struct thread_entry *thread)
+{
+ if (*list == NULL)
+ {
+ /* Insert into unoccupied list */
+ thread->l.next = thread;
+ thread->l.prev = thread;
+ *list = thread;
+ }
+ else
+ {
+ /* Insert last */
+ thread->l.next = *list;
+ thread->l.prev = (*list)->l.prev;
+ thread->l.prev->l.next = thread;
+ (*list)->l.prev = thread;
+ }
+}
+
+static void remove_from_list_l(struct thread_entry **list,
+ struct thread_entry *thread)
+{
+ if (thread == thread->l.next)
+ {
+ /* The only item */
+ *list = NULL;
+ return;
+ }
+
+ if (thread == *list)
+ {
+ /* List becomes next item */
+ *list = thread->l.next;
+ }
+
+ /* Fix links to jump over the removed entry. */
+ thread->l.prev->l.next = thread->l.next;
+ thread->l.next->l.prev = thread->l.prev;
+}
+
+unsigned int thread_get_current(void)
+{
+ return cores[CURRENT_CORE].running->id;
+}
+
+void switch_thread(void)
+{
+ struct thread_entry *current = cores[CURRENT_CORE].running;
+
+ enable_irq();
+
+ switch (current->state)
+ {
+ case STATE_RUNNING:
+ {
+ SDL_UnlockMutex(m);
+ /* Any other thread waiting already will get it first */
+ SDL_LockMutex(m);
+ break;
+ } /* STATE_RUNNING: */
+
+ case STATE_BLOCKED:
+ {
+ int oldlevel;
+
+ SDL_UnlockMutex(m);
+ SDL_SemWait(current->context.s);
+ SDL_LockMutex(m);
+
+ oldlevel = disable_irq_save();
+ current->state = STATE_RUNNING;
+ restore_irq(oldlevel);
+ break;
+ } /* STATE_BLOCKED: */
+
+ case STATE_BLOCKED_W_TMO:
+ {
+ int result, oldlevel;
+
+ SDL_UnlockMutex(m);
+ result = SDL_SemWaitTimeout(current->context.s, current->tmo_tick);
+ SDL_LockMutex(m);
+
+ oldlevel = disable_irq_save();
+
+ if (current->state == STATE_BLOCKED_W_TMO)
+ {
+ /* Timed out */
+ remove_from_list_l(current->bqp, current);
+
+#ifdef HAVE_WAKEUP_EXT_CB
+ if (current->wakeup_ext_cb != NULL)
+ current->wakeup_ext_cb(current);
+#endif
+ current->state = STATE_RUNNING;
+ }
+
+ if (result == SDL_MUTEX_TIMEDOUT)
+ {
+ /* Other signals from an explicit wake could have been made before
+ * arriving here if we timed out waiting for the semaphore. Make
+ * sure the count is reset. */
+ while (SDL_SemValue(current->context.s) > 0)
+ SDL_SemTryWait(current->context.s);
+ }
+
+ restore_irq(oldlevel);
+ break;
+ } /* STATE_BLOCKED_W_TMO: */
+
+ case STATE_SLEEPING:
+ {
+ SDL_UnlockMutex(m);
+ SDL_SemWaitTimeout(current->context.s, current->tmo_tick);
+ SDL_LockMutex(m);
+ current->state = STATE_RUNNING;
+ break;
+ } /* STATE_SLEEPING: */
+ }
+
+ cores[CURRENT_CORE].running = current;
+
+ if (threads_exit)
+ thread_exit();
+}
+
+void sleep_thread(int ticks)
+{
+ struct thread_entry *current = cores[CURRENT_CORE].running;
+ int rem;
+
+ current->state = STATE_SLEEPING;
+
+ rem = (SDL_GetTicks() - start_tick) % (1000/HZ);
+ if (rem < 0)
+ rem = 0;
+
+ current->tmo_tick = (1000/HZ) * ticks + ((1000/HZ)-1) - rem;
+}
+
+void block_thread(struct thread_entry *current)
+{
+ current->state = STATE_BLOCKED;
+ add_to_list_l(current->bqp, current);
+}
+
+void block_thread_w_tmo(struct thread_entry *current, int ticks)
+{
+ current->state = STATE_BLOCKED_W_TMO;
+ current->tmo_tick = (1000/HZ)*ticks;
+ add_to_list_l(current->bqp, current);
+}
+
+unsigned int wakeup_thread(struct thread_entry **list)
+{
+ struct thread_entry *thread = *list;
+
+ if (thread != NULL)
+ {
+ switch (thread->state)
+ {
+ case STATE_BLOCKED:
+ case STATE_BLOCKED_W_TMO:
+ remove_from_list_l(list, thread);
+ thread->state = STATE_RUNNING;
+ SDL_SemPost(thread->context.s);
+ return THREAD_OK;
+ }
+ }
+
+ return THREAD_NONE;
+}
+
+unsigned int thread_queue_wake(struct thread_entry **list)
+{
+ unsigned int result = THREAD_NONE;
+
+ for (;;)
+ {
+ unsigned int rc = wakeup_thread(list);
+
+ if (rc == THREAD_NONE)
+ break;
+
+ result |= rc;
+ }
+
+ return result;
+}
+
+void thread_thaw(unsigned int thread_id)
+{
+ struct thread_entry *thread = thread_id_entry(thread_id);
+
+ if (thread->id == thread_id && thread->state == STATE_FROZEN)
+ {
+ thread->state = STATE_RUNNING;
+ SDL_SemPost(thread->context.s);
+ }
+}
+
+int runthread(void *data)
+{
+ struct thread_entry *current;
+ jmp_buf *current_jmpbuf;
+
+ /* Cannot access thread variables before locking the mutex as the
+ data structures may not be filled-in yet. */
+ SDL_LockMutex(m);
+ cores[CURRENT_CORE].running = (struct thread_entry *)data;
+ current = cores[CURRENT_CORE].running;
+ current_jmpbuf = &thread_jmpbufs[current - threads];
+
+ /* Setup jump for exit */
+ if (setjmp(*current_jmpbuf) == 0)
+ {
+ /* Run the thread routine */
+ if (current->state == STATE_FROZEN)
+ {
+ SDL_UnlockMutex(m);
+ SDL_SemWait(current->context.s);
+ SDL_LockMutex(m);
+ cores[CURRENT_CORE].running = current;
+ }
+
+ if (!threads_exit)
+ {
+ current->context.start();
+ THREAD_SDL_DEBUGF("Thread Done: %d (%s)\n",
+ current - threads, THREAD_SDL_GET_NAME(current));
+ /* Thread routine returned - suicide */
+ }
+
+ thread_exit();
+ }
+ else
+ {
+ /* Unlock and exit */
+ SDL_UnlockMutex(m);
+ }
+
+ return 0;
+}
+
+unsigned int create_thread(void (*function)(void),
+ void* stack, size_t stack_size,
+ unsigned flags, const char *name)
+{
+ struct thread_entry *thread;
+ SDL_Thread* t;
+ SDL_sem *s;
+
+ THREAD_SDL_DEBUGF("Creating thread: (%s)\n", name ? name : "");
+
+ thread = find_empty_thread_slot();
+ if (thread == NULL)
+ {
+ DEBUGF("Failed to find thread slot\n");
+ return 0;
+ }
+
+ s = SDL_CreateSemaphore(0);
+ if (s == NULL)
+ {
+ DEBUGF("Failed to create semaphore\n");
+ return 0;
+ }
+
+ t = SDL_CreateThread(runthread, thread);
+ if (t == NULL)
+ {
+ DEBUGF("Failed to create SDL thread\n");
+ SDL_DestroySemaphore(s);
+ return 0;
+ }
+
+ thread->stack = stack;
+ thread->stack_size = stack_size;
+ thread->name = name;
+ thread->state = (flags & CREATE_THREAD_FROZEN) ?
+ STATE_FROZEN : STATE_RUNNING;
+ thread->context.start = function;
+ thread->context.t = t;
+ thread->context.s = s;
+
+ THREAD_SDL_DEBUGF("New Thread: %d (%s)\n",
+ thread - threads, THREAD_SDL_GET_NAME(thread));
+
+ return thread->id;
+}
+
+#ifndef ALLOW_REMOVE_THREAD
+static void remove_thread(unsigned int thread_id)
+#else
+void remove_thread(unsigned int thread_id)
+#endif
+{
+ struct thread_entry *current = cores[CURRENT_CORE].running;
+ struct thread_entry *thread = thread_id_entry(thread_id);
+
+ SDL_Thread *t;
+ SDL_sem *s;
+
+ if (thread_id != THREAD_ID_CURRENT && thread->id != thread_id)
+ return;
+
+ int oldlevel = disable_irq_save();
+
+ t = thread->context.t;
+ s = thread->context.s;
+ thread->context.t = NULL;
+
+ if (thread != current)
+ {
+ switch (thread->state)
+ {
+ case STATE_BLOCKED:
+ case STATE_BLOCKED_W_TMO:
+ /* Remove thread from object it's waiting on */
+ remove_from_list_l(thread->bqp, thread);
+
+#ifdef HAVE_WAKEUP_EXT_CB
+ if (thread->wakeup_ext_cb != NULL)
+ thread->wakeup_ext_cb(thread);
+#endif
+ break;
+ }
+
+ SDL_SemPost(s);
+ }
+
+ THREAD_SDL_DEBUGF("Removing thread: %d (%s)\n",
+ thread - threads, THREAD_SDL_GET_NAME(thread));
+
+ new_thread_id(thread->id, thread);
+ thread->state = STATE_KILLED;
+ thread_queue_wake(&thread->queue);
+
+ SDL_DestroySemaphore(s);
+
+ if (thread == current)
+ {
+ /* Do a graceful exit - perform the longjmp back into the thread
+ function to return */
+ restore_irq(oldlevel);
+ longjmp(thread_jmpbufs[current - threads], 1);
+ }
+
+ SDL_KillThread(t);
+ restore_irq(oldlevel);
+}
+
+void thread_exit(void)
+{
+ remove_thread(THREAD_ID_CURRENT);
+}
+
+void thread_wait(unsigned int thread_id)
+{
+ struct thread_entry *current = cores[CURRENT_CORE].running;
+ struct thread_entry *thread = thread_id_entry(thread_id);
+
+ if (thread_id == THREAD_ID_CURRENT ||
+ (thread->id == thread_id && thread->state != STATE_KILLED))
+ {
+ current->bqp = &thread->queue;
+ block_thread(current);
+ switch_thread();
+ }
+}
+
+int thread_stack_usage(const struct thread_entry *thread)
+{
+ return 50;
+ (void)thread;
+}
+
+/* Return name if one or ID if none */
+void thread_get_name(char *buffer, int size,
+ struct thread_entry *thread)
+{
+ if (size <= 0)
+ return;
+
+ *buffer = '\0';
+
+ if (thread)
+ {
+ /* Display thread name if one or ID if none */
+ bool named = thread->name && *thread->name;
+ const char *fmt = named ? "%s" : "%08lX";
+ intptr_t name = named ?
+ (intptr_t)thread->name : (intptr_t)thread;
+ snprintf(buffer, size, fmt, name);
+ }
+}
diff --git a/firmware/target/hosted/sdl/thread-sdl.h b/firmware/target/hosted/sdl/thread-sdl.h
new file mode 100644
index 0000000000..9384e6060d
--- /dev/null
+++ b/firmware/target/hosted/sdl/thread-sdl.h
@@ -0,0 +1,32 @@
+/***************************************************************************
+ * __________ __ ___.
+ * Open \______ \ ____ ____ | | _\_ |__ _______ ___
+ * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
+ * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
+ * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
+ * \/ \/ \/ \/ \/
+ * $Id$
+ *
+ * Copyright (C) 2006 Dan Everton
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
+ * KIND, either express or implied.
+ *
+ ****************************************************************************/
+
+#ifndef __THREADSDL_H__
+#define __THREADSDL_H__
+
+/* extra thread functions that only apply when running on hosting platforms */
+void sim_thread_lock(void *me);
+void * sim_thread_unlock(void);
+void sim_thread_exception_wait(void);
+void sim_thread_shutdown(void); /* Shut down all kernel threads gracefully */
+
+#endif /* #ifndef __THREADSDL_H__ */
+
diff --git a/firmware/target/hosted/sdl/timer-sdl.c b/firmware/target/hosted/sdl/timer-sdl.c
new file mode 100644
index 0000000000..369aeab929
--- /dev/null
+++ b/firmware/target/hosted/sdl/timer-sdl.c
@@ -0,0 +1,61 @@
+/***************************************************************************
+* __________ __ ___.
+* Open \______ \ ____ ____ | | _\_ |__ _______ ___
+* Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
+* Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
+* Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
+* \/ \/ \/ \/ \/
+* $Id: timer.h 13806 2007-07-06 21:36:32Z jethead71 $
+*
+* Copyright (C) 2005 Kévin Ferrare
+*
+* This program is free software; you can redistribute it and/or
+* modify it under the terms of the GNU General Public License
+* as published by the Free Software Foundation; either version 2
+* of the License, or (at your option) any later version.
+*
+* This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
+* KIND, either express or implied.
+*
+****************************************************************************/
+
+#include "timer.h"
+#include <SDL_timer.h>
+
+static int timer_prio = -1;
+void (*global_timer_callback)(void);
+SDL_TimerID timerId;
+
+Uint32 SDL_timer_callback(Uint32 interval, void *param){
+ (void)param;
+ global_timer_callback();
+ return(interval);
+}
+
+#define cycles_to_miliseconds(cycles) \
+ ((int)((1000*cycles)/TIMER_FREQ))
+
+bool timer_register(int reg_prio, void (*unregister_callback)(void),
+ long cycles, void (*timer_callback)(void))
+{
+ (void)unregister_callback;
+ if (reg_prio <= timer_prio || cycles == 0)
+ return false;
+ timer_prio=reg_prio;
+ global_timer_callback=timer_callback;
+ timerId=SDL_AddTimer(cycles_to_miliseconds(cycles), SDL_timer_callback, 0);
+ return true;
+}
+
+bool timer_set_period(long cycles)
+{
+ SDL_RemoveTimer (timerId);
+ timerId=SDL_AddTimer(cycles_to_miliseconds(cycles), SDL_timer_callback, 0);
+ return true;
+}
+
+void timer_unregister(void)
+{
+ SDL_RemoveTimer (timerId);
+ timer_prio = -1;
+}