initial Caanoo port
[gpsp.git] / gui.c
diff --git a/gui.c b/gui.c
index 6eb9ddb..b28392d 100644 (file)
--- a/gui.c
+++ b/gui.c
@@ -16,6 +16,9 @@
  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
  */
 
+#include "common.h"
+#include "font.h"
+
 #ifndef _WIN32_WCE
 
 #include <sys/stat.h>
 
 #endif
 
-#include "common.h"
-#include "font.h"
-
 #define MAX_PATH 1024
 
 // Blatantly stolen and trimmed from MZX (megazeux.sourceforge.net)
 
 #ifdef GP2X_BUILD
 
-#define FILE_LIST_ROWS ((int)((SDL_SCREEN_HEIGHT - 40) / FONT_HEIGHT))
+#define FILE_LIST_ROWS 20
 #define FILE_LIST_POSITION 5
 #define DIR_LIST_POSITION 260
 
 
 #define FILE_LIST_ROWS 25
 #define FILE_LIST_POSITION 5
-#define DIR_LIST_POSITION 360
+#define DIR_LIST_POSITION (resolution_width * 3 / 4)
 
 #endif
 
 #ifdef PSP_BUILD
 
+#define COLOR_BG            color16(2, 8, 10)
+
 #define color16(red, green, blue)                                             \
   (blue << 11) | (green << 5) | red                                           \
 
 #else
 
-#define color16(red, green, blue)                                             \
-  (red << 11) | (green << 5) | blue                                           \
-
-#endif
-
-#ifdef GP2X_BUILD
-
 #define COLOR_BG            color16(0, 0, 0)
 
-#else
-
-#define COLOR_BG            color16(2, 8, 10)
+#define color16(red, green, blue)                                             \
+  (red << 11) | (green << 5) | blue                                           \
 
 #endif
 
 #define COLOR_FRAMESKIP_BAR color16(15, 31, 31)
 #define COLOR_HELP_TEXT     color16(16, 40, 24)
 
+#ifdef PSP_BUILD
+  static const char *clock_speed_options[] =
+  {
+    "33MHz", "66MHz", "100MHz", "133MHz", "166MHz", "200MHz", "233MHz",
+    "266MHz", "300MHz", "333MHz"
+  };
+  #define menu_get_clock_speed() \
+    clock_speed = (clock_speed_number + 1) * 33
+  #define get_clock_speed_number() \
+    clock_speed_number = (clock_speed / 33) - 1
+#elif defined(POLLUX_BUILD)
+  static const char *clock_speed_options[] =
+  {
+    "300MHz", "333MHz", "366MHz", "400MHz", "433MHz",
+    "466MHz", "500MHz", "533MHz", "566MHz", "600MHz",
+    "633MHz", "666MHz", "700MHz", "733MHz", "766MHz",
+    "800MHz", "833MHz", "866MHz", "900MHz"
+  };
+  #define menu_get_clock_speed() \
+    clock_speed = 300 + (clock_speed_number * 3333) / 100
+  #define get_clock_speed_number() \
+    clock_speed_number = (clock_speed - 300) / 33
+#elif defined(GP2X_BUILD)
+  static const char *clock_speed_options[] =
+  {
+    "150MHz", "160MHz", "170MHz", "180MHz", "190MHz",
+    "200MHz", "210MHz", "220MHz", "230MHz", "240MHz",
+    "250MHz", "260MHz", "270MHz", "280MHz", "290MHz"
+  };
+  #define menu_get_clock_speed() \
+    clock_speed = 150 + clock_speed_number * 10
+  #define get_clock_speed_number() \
+    clock_speed_number = (clock_speed - 150) / 10
+#else
+  static const char *clock_speed_options[] =
+  {
+    "0"
+  };
+  #define menu_get_clock_speed()
+  #define get_clock_speed_number()
+#endif
+
+
 int sort_function(const void *dest_str_ptr, const void *src_str_ptr)
 {
   char *dest_str = *((char **)dest_str_ptr);
@@ -88,31 +125,30 @@ int sort_function(const void *dest_str_ptr, const void *src_str_ptr)
   return strcasecmp(dest_str, src_str);
 }
 
-s32 load_file(u8 **wildcards, u8 *result)
+s32 load_file(const char **wildcards, char *result)
 {
   DIR *current_dir;
   struct dirent *current_file;
   struct stat file_info;
-  u8 current_dir_name[MAX_PATH];
-  u8 current_dir_short[81];
+  char current_dir_name[MAX_PATH];
+  char current_dir_short[81];
   u32 current_dir_length;
   u32 total_filenames_allocated;
   u32 total_dirnames_allocated;
-  u8 **file_list;
-  u8 **dir_list;
+  char **file_list;
+  char **dir_list;
   u32 num_files;
   u32 num_dirs;
-  u8 *file_name;
+  char *file_name;
   u32 file_name_length;
   u32 ext_pos = -1;
   u32 chosen_file, chosen_dir;
-  u32 dialog_result = 1;
   s32 return_value = 1;
-  u32 current_file_selection;
-  u32 current_file_scroll_value;
+  s32 current_file_selection;
+  s32 current_file_scroll_value;
   u32 current_dir_selection;
   u32 current_dir_scroll_value;
-  u32 current_file_in_scroll;
+  s32 current_file_in_scroll;
   u32 current_dir_in_scroll;
   u32 current_file_number, current_dir_number;
   u32 current_column = 0;
@@ -131,10 +167,10 @@ s32 load_file(u8 **wildcards, u8 *result)
 
     total_filenames_allocated = 32;
     total_dirnames_allocated = 32;
-    file_list = (u8 **)malloc(sizeof(u8 *) * 32);
-    dir_list = (u8 **)malloc(sizeof(u8 *) * 32);
-    memset(file_list, 0, sizeof(u8 *) * 32);
-    memset(dir_list, 0, sizeof(u8 *) * 32);
+    file_list = (char **)malloc(sizeof(char *) * 32);
+    dir_list = (char **)malloc(sizeof(char *) * 32);
+    memset(file_list, 0, sizeof(char *) * 32);
+    memset(dir_list, 0, sizeof(char *) * 32);
 
     num_files = 0;
     num_dirs = 0;
@@ -162,8 +198,7 @@ s32 load_file(u8 **wildcards, u8 *result)
         {
           if(S_ISDIR(file_info.st_mode))
           {
-            dir_list[num_dirs] =
-             (u8 *)malloc(file_name_length + 1);
+            dir_list[num_dirs] = malloc(file_name_length + 1);
 
             sprintf(dir_list[num_dirs], "%s", file_name);
 
@@ -190,7 +225,7 @@ s32 load_file(u8 **wildcards, u8 *result)
                  wildcards[i]))
                 {
                   file_list[num_files] =
-                   (u8 *)malloc(file_name_length + 1);
+                   malloc(file_name_length + 1);
 
                   sprintf(file_list[num_files], "%s", file_name);
 
@@ -204,26 +239,26 @@ s32 load_file(u8 **wildcards, u8 *result)
 
         if(num_files == total_filenames_allocated)
         {
-          file_list = (u8 **)realloc(file_list, sizeof(u8 *) *
+          file_list = (char **)realloc(file_list, sizeof(char *) *
            total_filenames_allocated * 2);
           memset(file_list + total_filenames_allocated, 0,
-           sizeof(u8 *) * total_filenames_allocated);
+           sizeof(char *) * total_filenames_allocated);
           total_filenames_allocated *= 2;
         }
 
         if(num_dirs == total_dirnames_allocated)
         {
-          dir_list = (u8 **)realloc(dir_list, sizeof(u8 *) *
+          dir_list = (char **)realloc(dir_list, sizeof(char *) *
            total_dirnames_allocated * 2);
           memset(dir_list + total_dirnames_allocated, 0,
-           sizeof(u8 *) * total_dirnames_allocated);
+           sizeof(char *) * total_dirnames_allocated);
           total_dirnames_allocated *= 2;
         }
       }
     } while(current_file);
 
-    qsort((void *)file_list, num_files, sizeof(u8 *), sort_function);
-    qsort((void *)dir_list, num_dirs, sizeof(u8 *), sort_function);
+    qsort((void *)file_list, num_files, sizeof(char *), sort_function);
+    qsort((void *)dir_list, num_dirs, sizeof(char *), sort_function);
 
     closedir(current_dir);
 
@@ -259,8 +294,6 @@ s32 load_file(u8 **wildcards, u8 *result)
 
     clear_screen(COLOR_BG);
   {
-    u8 print_buffer[81];
-
     while(repeat)
     {
       flip_screen();
@@ -332,6 +365,13 @@ s32 load_file(u8 **wildcards, u8 *result)
                 current_file_in_scroll++;
               }
             }
+            else
+            {
+              clear_screen(COLOR_BG);
+              current_file_selection = 0;
+              current_file_scroll_value = 0;
+              current_file_in_scroll = 0;
+            }
           }
           else
           {
@@ -352,6 +392,25 @@ s32 load_file(u8 **wildcards, u8 *result)
 
           break;
 
+        case CURSOR_R:
+          if (current_column != 0)
+            break;
+          clear_screen(COLOR_BG);
+         current_file_selection += FILE_LIST_ROWS;
+          if (current_file_selection > num_files - 1)
+            current_file_selection = num_files - 1;
+          current_file_scroll_value = current_file_selection - FILE_LIST_ROWS / 2;
+          if (current_file_scroll_value < 0)
+          {
+            current_file_scroll_value = 0;
+            current_file_in_scroll = current_file_selection;
+          }
+          else
+          {
+            current_file_in_scroll = FILE_LIST_ROWS / 2;
+          }
+          break;
+
         case CURSOR_UP:
           if(current_column == 0)
           {
@@ -368,6 +427,17 @@ s32 load_file(u8 **wildcards, u8 *result)
                 current_file_in_scroll--;
               }
             }
+            else
+            {
+              clear_screen(COLOR_BG);
+              current_file_selection = num_files - 1;
+              current_file_in_scroll = FILE_LIST_ROWS - 1;
+              if (current_file_in_scroll > num_files - 1)
+                current_file_in_scroll = num_files - 1;
+              current_file_scroll_value = num_files - FILE_LIST_ROWS;
+              if (current_file_scroll_value < 0)
+                current_file_scroll_value = 0;
+            }
           }
           else
           {
@@ -387,7 +457,26 @@ s32 load_file(u8 **wildcards, u8 *result)
           }
           break;
 
-        case CURSOR_RIGHT:
+        case CURSOR_L:
+          if (current_column != 0)
+            break;
+          clear_screen(COLOR_BG);
+         current_file_selection -= FILE_LIST_ROWS;
+          if (current_file_selection < 0)
+            current_file_selection = 0;
+          current_file_scroll_value = current_file_selection - FILE_LIST_ROWS / 2;
+          if (current_file_scroll_value < 0)
+          {
+            current_file_scroll_value = 0;
+            current_file_in_scroll = current_file_selection;
+          }
+          else
+          {
+            current_file_in_scroll = FILE_LIST_ROWS / 2;
+          }
+          break;
+
+         case CURSOR_RIGHT:
           if(current_column == 0)
           {
             if(num_dirs != 0)
@@ -433,6 +522,9 @@ s32 load_file(u8 **wildcards, u8 *result)
           return_value = -1;
           repeat = 0;
           break;
+
+        default:
+          break;
       }
     }
   }
@@ -476,11 +568,11 @@ struct _menu_option_type
   void (* action_function)();
   void (* passive_function)();
   struct _menu_type *sub_menu;
-  char *display_string;
+  const char *display_string;
   void *options;
   u32 *current_option;
   u32 num_options;
-  char *help_string;
+  const char *help_string;
   u32 line_number;
   menu_option_type_enum option_type;
 };
@@ -643,17 +735,62 @@ u32 gamepad_config_line_to_button[] =
 #ifdef GP2X_BUILD
 
 u32 gamepad_config_line_to_button[] =
- { 0, 2, 1, 3, 8, 9, 10, 11, 6, 7, 4, 5 };
+ { 0, 2, 1, 3, 8, 9, 10, 11, 6, 7, 4, 5, 14, 15 };
+
+#endif
+
+#ifdef PND_BUILD
+
+u32 gamepad_config_line_to_button[] =
+ { 0, 2, 1, 3, 8, 9, 10, 11, 6, 7, 4, 5, 12, 13, 14, 15 };
 
 #endif
 
+static const char *scale_options[] =
+{
+#ifdef PSP_BUILD
+  "unscaled 3:2", "scaled 3:2", "fullscreen 16:9"
+#elif defined(WIZ_BUILD)
+  "unscaled 3:2", "scaled 3:2 (slower)",
+  "unscaled 3:2 (anti-tear)", "scaled 3:2 (anti-tear)"
+#elif defined(POLLUX_BUILD)
+  "unscaled 3:2", "scaled 3:2 (slower)"
+#elif defined(PND_BUILD)
+  "unscaled", "2x", "3x", "fullscreen"
+#elif defined(GP2X_BUILD)
+  "unscaled 3:2", "scaled 3:2", "fullscreen", "scaled 3:2 (software)"
+#else
+  "unscaled 3:2"
+#endif
+};
+
+const char *filter2_options[] =
+{
+  "none", "scale2x", "scale3x", "eagle2x"
+};
+
+#ifndef PSP_BUILD
+static const char *audio_buffer_options[] =
+{
+  "16 bytes", "32 bytes", "64 bytes",
+  "128 bytes", "256 bytes", "512 bytes", "1024 bytes", "2048 bytes",
+  "4096 bytes", "8192 bytes", "16284 bytes"
+};
+#else
+const char *audio_buffer_options[] =
+{
+  "3072 bytes", "4096 bytes", "5120 bytes", "6144 bytes", "7168 bytes",
+  "8192 bytes", "9216 bytes", "10240 bytes", "11264 bytes", "12288 bytes"
+};
+#endif
+
 
 s32 load_game_config_file()
 {
-  u8 game_config_filename[512];
+  char game_config_filename[512];
   u32 file_loaded = 0;
   u32 i;
-  change_ext(gamepak_filename, game_config_filename, ".cfg");
+  make_rpath(game_config_filename, sizeof(game_config_filename), ".cfg");
 
   file_open(game_config_file, game_config_filename, read);
 
@@ -672,8 +809,16 @@ s32 load_game_config_file()
       random_skip = file_options[2] % 2;
       clock_speed = file_options[3];
 
+#ifdef POLLUX_BUILD
+      if(clock_speed > 900)
+        clock_speed = 533;
+#elif defined(GP2X_BUILD)
+      if(clock_speed >= 300)
+        clock_speed = 200;
+#else
       if(clock_speed > 333)
         clock_speed = 333;
+#endif
 
       if(clock_speed < 33)
         clock_speed = 33;
@@ -686,7 +831,7 @@ s32 load_game_config_file()
 
       for(i = 0; i < 10; i++)
       {
-        cheats[i].cheat_active = file_options[3 + i] % 2;
+        cheats[i].cheat_active = file_options[4 + i] % 2;
         cheats[i].cheat_name[0] = 0;
       }
 
@@ -700,8 +845,11 @@ s32 load_game_config_file()
 
   current_frameskip_type = auto_frameskip;
   frameskip_value = 4;
+#ifdef POLLUX_BUILD
+  frameskip_value = 1;
+#endif
   random_skip = 0;
-  clock_speed = 333;
+  clock_speed = default_clock_speed;
 
   for(i = 0; i < 10; i++)
   {
@@ -712,15 +860,28 @@ s32 load_game_config_file()
   return -1;
 }
 
+enum file_options {
+  fo_screen_scale = 0,
+  fo_screen_filter,
+  fo_global_enable_audio,
+  fo_audio_buffer_size,
+  fo_update_backup_flag,
+  fo_global_enable_analog,
+  fo_analog_sensitivity_level,
+  fo_screen_filter2,
+  fo_main_option_count,
+};
+
+#ifdef PC_BUILD
+#define PLAT_BUTTON_COUNT 0
+#endif
+#define FILE_OPTION_COUNT (fo_main_option_count + PLAT_BUTTON_COUNT)
+
 s32 load_config_file()
 {
-  u8 config_path[512];
+  char config_path[512];
 
-  #if (defined(PSP_BUILD) || defined(ARM_ARCH)) && !defined(_WIN32_WCE)
-    sprintf(config_path, "%s/%s", main_path, GPSP_CONFIG_FILENAME);
-  #else
-    sprintf(config_path, "%s\\%s", main_path, GPSP_CONFIG_FILENAME);
-  #endif
+  sprintf(config_path, "%s" PATH_SEPARATOR "%s", main_path, GPSP_CONFIG_FILENAME);
 
   file_open(config_file, config_path, read);
 
@@ -729,26 +890,24 @@ s32 load_config_file()
     u32 file_size = file_length(config_path, config_file);
 
     // Sanity check: File size must be the right size
-    if(file_size == 92)
+    if(file_size == FILE_OPTION_COUNT * 4)
     {
       u32 file_options[file_size / 4];
-      u32 i;
-      s32 menu_button = -1;
       file_read_array(config_file, file_options);
 
-      screen_scale = file_options[0] % 3;
-      screen_filter = file_options[1] % 2;
-      global_enable_audio = file_options[2] % 2;
+      screen_scale = file_options[fo_screen_scale] %
+        (sizeof(scale_options) / sizeof(scale_options[0]));
+      screen_filter = file_options[fo_screen_filter] % 2;
+      global_enable_audio = file_options[fo_global_enable_audio] % 2;
+      screen_filter2 = file_options[fo_screen_filter2] %
+        (sizeof(filter2_options) / sizeof(filter2_options[0]));
 
-#ifdef PSP_BUILD
-      audio_buffer_size_number = file_options[3] % 10;
-#else
-      audio_buffer_size_number = file_options[3] % 11;
-#endif
+      audio_buffer_size_number = file_options[fo_audio_buffer_size] %
+        (sizeof(audio_buffer_options) / sizeof(audio_buffer_options[0]));
 
-      update_backup_flag = file_options[4] % 2;
-      global_enable_analog = file_options[5] % 2;
-      analog_sensitivity_level = file_options[6] % 8;
+      update_backup_flag = file_options[fo_update_backup_flag] % 2;
+      global_enable_analog = file_options[fo_global_enable_analog] % 2;
+      analog_sensitivity_level = file_options[fo_analog_sensitivity_level] % 8;
 
 #ifdef PSP_BUILD
     scePowerSetClockFrequency(clock_speed, clock_speed, clock_speed / 2);
@@ -758,9 +917,11 @@ s32 load_config_file()
       // key, if not assign to triangle
 
 #ifndef PC_BUILD
-      for(i = 0; i < 16; i++)
+      u32 i;
+      s32 menu_button = -1;
+      for(i = 0; i < PLAT_BUTTON_COUNT; i++)
       {
-        gamepad_config_map[i] = file_options[7 + i] %
+        gamepad_config_map[i] = file_options[fo_main_option_count + i] %
          (BUTTON_ID_NONE + 1);
 
         if(gamepad_config_map[i] == BUTTON_ID_MENU)
@@ -769,9 +930,9 @@ s32 load_config_file()
         }
       }
 
-      if(menu_button == -1)
+      if(menu_button == -1 && PLAT_MENU_BUTTON >= 0)
       {
-        gamepad_config_map[0] = BUTTON_ID_MENU;
+        gamepad_config_map[PLAT_MENU_BUTTON] = BUTTON_ID_MENU;
       }
 #endif
 
@@ -786,10 +947,10 @@ s32 load_config_file()
 
 s32 save_game_config_file()
 {
-  u8 game_config_filename[512];
+  char game_config_filename[512];
   u32 i;
 
-  change_ext(gamepak_filename, game_config_filename, ".cfg");
+  make_rpath(game_config_filename, sizeof(game_config_filename), ".cfg");
 
   file_open(game_config_file, game_config_filename, write);
 
@@ -819,13 +980,9 @@ s32 save_game_config_file()
 
 s32 save_config_file()
 {
-  u8 config_path[512];
+  char config_path[512];
 
-  #if (defined(PSP_BUILD) || defined(ARM_ARCH)) && !defined(_WIN32_WCE)
-    sprintf(config_path, "%s/%s", main_path, GPSP_CONFIG_FILENAME);
-  #else
-    sprintf(config_path, "%s\\%s", main_path, GPSP_CONFIG_FILENAME);
-  #endif
+  sprintf(config_path, "%s" PATH_SEPARATOR "%s", main_path, GPSP_CONFIG_FILENAME);
 
   file_open(config_file, config_path, write);
 
@@ -833,21 +990,22 @@ s32 save_config_file()
 
   if(file_check_valid(config_file))
   {
-    u32 file_options[23];
-    u32 i;
+    u32 file_options[FILE_OPTION_COUNT];
 
-    file_options[0] = screen_scale;
-    file_options[1] = screen_filter;
-    file_options[2] = global_enable_audio;
-    file_options[3] = audio_buffer_size_number;
-    file_options[4] = update_backup_flag;
-    file_options[5] = global_enable_analog;
-    file_options[6] = analog_sensitivity_level;
+    file_options[fo_screen_scale] = screen_scale;
+    file_options[fo_screen_filter] = screen_filter;
+    file_options[fo_global_enable_audio] = global_enable_audio;
+    file_options[fo_audio_buffer_size] = audio_buffer_size_number;
+    file_options[fo_update_backup_flag] = update_backup_flag;
+    file_options[fo_global_enable_analog] = global_enable_analog;
+    file_options[fo_analog_sensitivity_level] = analog_sensitivity_level;
+    file_options[fo_screen_filter2] = screen_filter2;
 
 #ifndef PC_BUILD
-    for(i = 0; i < 16; i++)
+    u32 i;
+    for(i = 0; i < PLAT_BUTTON_COUNT; i++)
     {
-      file_options[7 + i] = gamepad_config_map[i];
+      file_options[fo_main_option_count + i] = gamepad_config_map[i];
     }
 #endif
 
@@ -872,16 +1030,16 @@ typedef enum
 
 u32 savestate_slot = 0;
 
-void get_savestate_snapshot(u8 *savestate_filename)
+void get_savestate_snapshot(char *savestate_filename)
 {
   u16 snapshot_buffer[240 * 160];
-  u8 savestate_timestamp_string[80];
+  char savestate_timestamp_string[80];
 
   file_open(savestate_file, savestate_filename, read);
 
   if(file_check_valid(savestate_file))
   {
-    u8 weekday_strings[7][11] =
+    const char weekday_strings[7][11] =
     {
       "Sunday", "Monday", "Tuesday", "Wednesday",
       "Thursday", "Friday", "Saturday"
@@ -907,8 +1065,8 @@ void get_savestate_snapshot(u8 *savestate_filename)
   else
   {
     memset(snapshot_buffer, 0, 240 * 160 * 2);
-    print_string_ext("No savestate exists for this slot.",
-     0xFFFF, 0x0000, 15, 75, snapshot_buffer, 240, 0);
+    print_string_ext("No savestate in this slot.",
+     0xFFFF, 0x0000, 15, 75, snapshot_buffer, 240, 0, 0, FONT_HEIGHT);
     print_string("---------- --/--/---- --:--:--          ", COLOR_HELP_TEXT,
      COLOR_BG, 10, 40);
   }
@@ -918,22 +1076,18 @@ void get_savestate_snapshot(u8 *savestate_filename)
 #endif
 }
 
-void get_savestate_filename(u32 slot, u8 *name_buffer)
+void get_savestate_filename_noshot(u32 slot, char *name_buffer)
 {
-  u8 savestate_ext[16];
+  char savestate_ext[16];
 
   sprintf(savestate_ext, "%d.svs", slot);
-  change_ext(gamepak_filename, name_buffer, savestate_ext);
-
-  get_savestate_snapshot(name_buffer);
+  make_rpath(name_buffer, 512, savestate_ext);
 }
 
-void get_savestate_filename_noshot(u32 slot, u8 *name_buffer)
+void get_savestate_filename(u32 slot, char *name_buffer)
 {
-  u8 savestate_ext[16];
-
-  sprintf(savestate_ext, "%d.svs", slot);
-  change_ext(gamepak_filename, name_buffer, savestate_ext);
+  get_savestate_filename_noshot(slot, name_buffer);
+  get_savestate_snapshot(name_buffer);
 }
 
 #ifdef PSP_BUILD
@@ -945,19 +1099,16 @@ void get_savestate_filename_noshot(u32 slot, u8 *name_buffer)
 
 u32 menu(u16 *original_screen)
 {
-  u32 clock_speed_number = (clock_speed / 33) - 1;
-  u8 print_buffer[81];
-  u32 _current_option = 0;
+  char print_buffer[81];
+  u32 clock_speed_number;
   gui_action_type gui_action;
-  menu_enum _current_menu = MAIN_MENU;
   u32 i;
   u32 repeat = 1;
   u32 return_value = 0;
   u32 first_load = 0;
-  u8 savestate_ext[16];
-  u8 current_savestate_filename[512];
-  u8 line_buffer[80];
-  u8 cheat_format_str[10][41];
+  char current_savestate_filename[512];
+  char line_buffer[80];
+  char cheat_format_str[10][41];
 
   menu_type *current_menu;
   menu_option_type *current_option;
@@ -967,7 +1118,8 @@ u32 menu(u16 *original_screen)
   auto void choose_menu();
   auto void clear_help();
 
-  u8 *gamepad_help[] =
+#ifndef PC_BUILD
+  static const char * const gamepad_help[] =
   {
     "Up button on GBA d-pad.",
     "Down button on GBA d-pad.",
@@ -993,6 +1145,44 @@ u32 menu(u16 *original_screen)
     "Does nothing."
   };
 
+  static const char *gamepad_config_buttons[] =
+  {
+    "UP",
+    "DOWN",
+    "LEFT",
+    "RIGHT",
+    "A",
+    "B",
+    "L",
+    "R",
+    "START",
+    "SELECT",
+    "MENU",
+    "FASTFORWARD",
+    "LOAD STATE",
+    "SAVE STATE",
+    "RAPIDFIRE A",
+    "RAPIDFIRE B",
+    "RAPIDFIRE L",
+    "RAPIDFIRE R",
+    "VOLUME UP",
+    "VOLUME DOWN",
+    "DISPLAY FPS",
+    "NOTHING"
+  };
+#endif
+
+  void menu_update_clock()
+  {
+    get_clock_speed_number();
+    if (clock_speed_number < 0 || clock_speed_number >=
+     sizeof(clock_speed_options) / sizeof(clock_speed_options[0]))
+    {
+      clock_speed = default_clock_speed;
+      get_clock_speed_number();
+    }
+  }
+
   void menu_exit()
   {
     if(!first_load)
@@ -1001,15 +1191,15 @@ u32 menu(u16 *original_screen)
 
   void menu_quit()
   {
-    clock_speed = (clock_speed_number + 1) * 33;
+    menu_get_clock_speed();
     save_config_file();
     quit();
   }
 
   void menu_load()
   {
-    u8 *file_ext[] = { ".gba", ".bin", ".zip", NULL };
-    u8 load_filename[512];
+    const char *file_ext[] = { ".gba", ".bin", ".zip", NULL };
+    char load_filename[512];
     save_game_config_file();
     if(load_file(file_ext, load_filename) != -1)
     {
@@ -1021,6 +1211,7 @@ u32 menu(u16 *original_screen)
        return_value = 1;
        repeat = 0;
        reg[CHANGED_PC_STATUS] = 1;
+       menu_update_clock();
     }
     else
     {
@@ -1067,8 +1258,8 @@ u32 menu(u16 *original_screen)
 
   void menu_load_state_file()
   {
-    u8 *file_ext[] = { ".svs", NULL };
-    u8 load_filename[512];
+    const char *file_ext[] = { ".svs", NULL };
+    char load_filename[512];
     if(load_file(file_ext, load_filename) != -1)
     {
       load_state(load_filename);
@@ -1129,104 +1320,75 @@ u32 menu(u16 *original_screen)
      current_savestate_filename);
   }
 
-  u8 *yes_no_options[] = { "no", "yes" };
-  u8 *enable_disable_options[] = { "disabled", "enabled" };
-
-  u8 *scale_options[] =
-  {
-    "unscaled 3:2", "scaled 3:2", "fullscreen 16:9"
-  };
-
-  u8 *frameskip_options[] = { "automatic", "manual", "off" };
-  u8 *frameskip_variation_options[] = { "uniform", "random" };
-
-#ifndef PSP_BUILD
-  u8 *audio_buffer_options[] =
-  {
-    "16 bytes", "32 bytes", "64 bytes",
-    "128 bytes", "256 bytes", "512 bytes", "1024 bytes", "2048 bytes",
-    "4096 bytes", "8192 bytes", "16284 bytes"
-  };
-#else
-  u8 *audio_buffer_options[] =
-  {
-    "3072 bytes", "4096 bytes", "5120 bytes", "6144 bytes", "7168 bytes",
-    "8192 bytes", "9216 bytes", "10240 bytes", "11264 bytes", "12288 bytes"
-  };
-
-#endif
+  const char *yes_no_options[] = { "no", "yes" };
+  const char *enable_disable_options[] = { "disabled", "enabled" };
 
-  u8 *update_backup_options[] = { "Exit only", "Automatic" };
+  const char *frameskip_options[] = { "automatic", "manual", "off" };
+  const char *frameskip_variation_options[] = { "uniform", "random" };
 
-  u8 *clock_speed_options[] =
-  {
-    "33MHz", "66MHz", "100MHz", "133MHz", "166MHz", "200MHz", "233MHz",
-    "266MHz", "300MHz", "333MHz"
-  };
-
-  u8 *gamepad_config_buttons[] =
-  {
-    "UP",
-    "DOWN",
-    "LEFT",
-    "RIGHT",
-    "A",
-    "B",
-    "L",
-    "R",
-    "START",
-    "SELECT",
-    "MENU",
-    "FASTFORWARD",
-    "LOAD STATE",
-    "SAVE STATE",
-    "RAPIDFIRE A",
-    "RAPIDFIRE B",
-    "RAPIDFIRE L",
-    "RAPIDFIRE R",
-    "VOLUME UP",
-    "VOLUME DOWN",
-    "DISPLAY FPS",
-    "NOTHING"
-  };
+  static const char *update_backup_options[] = { "Exit only", "Automatic" };
 
   // Marker for help information, don't go past this mark (except \n)------*
   menu_option_type graphics_sound_options[] =
   {
     string_selection_option(NULL, "Display scaling", scale_options,
-     (u32 *)(&screen_scale), 3,
-     "Determines how the GBA screen is resized in relation to the entire\n"
-     "screen. Select unscaled 3:2 for GBA resolution, scaled 3:2 for GBA\n"
+     (u32 *)(&screen_scale),
+     sizeof(scale_options) / sizeof(scale_options[0]),
+#ifndef GP2X_BUILD
+     "Determines how the GBA screen is resized in relation to the\n"
+     "entire screen."
+#ifdef PSP_BUILD
+     " Select unscaled 3:2 for GBA resolution, scaled 3:2 for GBA\n"
      "aspect ratio scaled to fill the height of the PSP screen, and\n"
-     "fullscreen to fill the entire PSP screen.", 2),
+     "fullscreen to fill the entire PSP screen."
+#endif
+#endif
+     "", 2),
+#ifndef GP2X_BUILD
     string_selection_option(NULL, "Screen filtering", yes_no_options,
      (u32 *)(&screen_filter), 2,
-     "Determines whether or not bilinear filtering should be used when\n"
+     "Determines whether or not filtering should be used when\n"
      "scaling the screen. Selecting this will produce a more even and\n"
      "smooth image, at the cost of being blurry and having less vibrant\n"
      "colors.", 3),
+#endif
+#ifdef PND_BUILD
+    string_selection_option(NULL, "Scaling filter", filter2_options,
+     (u32 *)(&screen_filter2),
+     sizeof(filter2_options) / sizeof(filter2_options[0]),
+     "Optional pixel art scaling filter", 4),
+#endif
     string_selection_option(NULL, "Frameskip type", frameskip_options,
      (u32 *)(&current_frameskip_type), 3,
-     "Determines what kind of frameskipping should be employed.\n"
+#ifndef GP2X_BUILD
+     "Determines what kind of frameskipping to use.\n"
      "Frameskipping may improve emulation speed of many games.\n"
+#endif
      "Off: Do not skip any frames.\n"
-     "Auto: Skip up to N frames (see next option) as needed.\n"
-     "Manual: Always render only 1 out of N + 1 frames.", 5),
+     "Auto: Skip up to N frames (see next opt) as needed.\n"
+     "Manual: Always render only 1 out of N + 1 frames."
+     , 5),
     numeric_selection_option(NULL, "Frameskip value", &frameskip_value, 100,
+#ifndef GP2X_BUILD
      "For auto frameskip, determines the maximum number of frames that\n"
      "are allowed to be skipped consecutively.\n"
      "For manual frameskip, determines the number of frames that will\n"
-     "always be skipped.", 6),
+     "always be skipped."
+#endif
+     "", 6),
     string_selection_option(NULL, "Framskip variation",
      frameskip_variation_options, &random_skip, 2,
+#ifndef GP2X_BUILD
      "If objects in the game flicker at a regular rate certain manual\n"
      "frameskip values may cause them to normally disappear. Change this\n"
-     "value to 'random' to avoid this. Do not use otherwise, as it tends to\n"
-     "make the image quality worse, especially in high motion games.", 7),
+     "value to 'random' to avoid this. Do not use otherwise, as it tends\n"
+     "to make the image quality worse, especially in high motion games."
+#endif
+     "", 7),
     string_selection_option(NULL, "Audio output", yes_no_options,
      &global_enable_audio, 2,
-     "Select 'no' to turn off all audio output. This will not result in a\n"
-     "significant change in performance.", 9),
+     "Select 'no' to turn off all audio output. This will\n"
+     "not result in a significant change in performance.", 9),
 #ifndef PSP_BUILD
     string_selection_option(NULL, "Audio buffer", audio_buffer_options,
              &audio_buffer_size_number, 11,
@@ -1235,10 +1397,16 @@ u32 menu(u16 *original_screen)
              &audio_buffer_size_number, 10,
 #endif
 
+#ifdef PSP_BUILD
      "Set the size (in bytes) of the audio buffer. Larger values may result\n"
      "in slightly better performance at the cost of latency; the lowest\n"
      "value will give the most responsive audio.\n"
      "This option requires gpSP to be restarted before it will take effect.",
+#else
+     "Set the size (in bytes) of the audio buffer.\n"
+     "This option requires gpSP restart to take effect.\n"
+     "Settable values may be limited by SDL implementation.",
+#endif
      10),
     submenu_option(NULL, "Back", "Return to the main menu.", 12)
   };
@@ -1257,17 +1425,29 @@ u32 menu(u16 *original_screen)
     cheat_option(7),
     cheat_option(8),
     cheat_option(9),
+#if defined(PSP_BUILD) || defined(GP2X_BUILD)
     string_selection_option(NULL, "Clock speed",
-     clock_speed_options, &clock_speed_number, 10,
-     "Change the clock speed of the device. Higher clock speed will yield\n"
-     "better performance, but will use drain battery life further.", 11),
+     clock_speed_options, &clock_speed_number,
+     sizeof(clock_speed_options) / sizeof(clock_speed_options[0]),
+     "Change the clock speed of the device. Higher clock\n"
+     "speed will yield better performance, but will drain\n"
+     "battery life further.", 11),
+#endif
     string_selection_option(NULL, "Update backup",
      update_backup_options, &update_backup_flag, 2,
+#ifdef GP2X_BUILD
+     "Determines when in-game save files should be\n"
+     "written back to SD card."
+#else
      "Determines when in-game save files should be written back to\n"
-     "memstick. If set to 'automatic' writebacks will occur shortly after\n"
-     "the game's backup is altered. On 'exit only' it will only be written\n"
-     "back when you exit from this menu (NOT from using the home button).\n"
-     "Use the latter with extreme care.", 12),
+     "card. If set to 'automatic' writebacks will occur shortly after\n"
+     "the game's backup is altered. On 'exit only' it will only be\n"
+     "written back when you exit from this menu.\n"
+#ifdef PSP
+     "(NOT from using the home button), use the latter with extreme care."
+#endif
+#endif
+     "", 12),
     submenu_option(NULL, "Back", "Return to the main menu.", 14)
   };
 
@@ -1277,17 +1457,20 @@ u32 menu(u16 *original_screen)
   {
     numeric_selection_action_hide_option(menu_load_state, menu_change_state,
      "Load savestate from current slot", &savestate_slot, 10,
-     "Select to load the game state from the current slot for this game.\n"
+     "Select to load the game state from the current slot\n"
+     "for this game.\n"
      "Press left + right to change the current slot.", 6),
     numeric_selection_action_hide_option(menu_save_state, menu_change_state,
      "Save savestate to current slot", &savestate_slot, 10,
-     "Select to save the game state to the current slot for this game.\n"
+     "Select to save the game state to the current slot\n"
+     "for this game.\n"
      "Press left + right to change the current slot.", 7),
     numeric_selection_action_hide_option(menu_load_state_file,
       menu_change_state,
      "Load savestate from file", &savestate_slot, 10,
      "Restore gameplay from a savestate file.\n"
-     "Note: The same file used to save the state must be present.\n", 9),
+     "Note: The same file used to save the state must be\n"
+     "present.\n", 9),
     numeric_selection_option(menu_change_state,
      "Current savestate slot", &savestate_slot, 10,
      "Change the current savestate slot.\n", 11),
@@ -1334,7 +1517,7 @@ u32 menu(u16 *original_screen)
 
 #endif
 
-#ifdef GP2X_BUILD
+#if defined(GP2X_BUILD) || defined(PND_BUILD)
 
   menu_option_type gamepad_config_options[] =
   {
@@ -1348,14 +1531,42 @@ u32 menu(u16 *original_screen)
     gamepad_config_option("Y            ", 7),
     gamepad_config_option("Left Trigger ", 8),
     gamepad_config_option("Right Trigger", 9),
+#ifdef WIZ_BUILD
+    gamepad_config_option("Menu         ", 10),
+    gamepad_config_option("Select       ", 11),
+#elif defined(POLLUX_BUILD)
+    gamepad_config_option("I            ", 10),
+    gamepad_config_option("II           ", 11),
+    gamepad_config_option("Push         ", 12),
+    gamepad_config_option("Home         ", 13),
+#elif defined(PND_BUILD)
     gamepad_config_option("Start        ", 10),
     gamepad_config_option("Select       ", 11),
-    submenu_option(NULL, "Back", "Return to the main menu.", 13)
+    gamepad_config_option("1            ", 12),
+    gamepad_config_option("2            ", 13),
+    gamepad_config_option("3            ", 14),
+    gamepad_config_option("4            ", 15),
+#else // GP2X
+    gamepad_config_option("Start        ", 10),
+    gamepad_config_option("Select       ", 11),
+    gamepad_config_option("Stick Push   ", 12),
+#endif
+#ifdef PND_BUILD
+    submenu_option(NULL, "Back", "Return to the main menu.", 16)
+#else
+    submenu_option(NULL, "Back", "Return to the main menu.", 14)
+#endif
   };
 
 
   menu_option_type analog_config_options[] =
   {
+#if defined(POLLUX_BUILD)
+    numeric_selection_option(NULL, "Analog sensitivity",
+     &analog_sensitivity_level, 10,
+     "Determine sensitivity/responsiveness of the analog input.\n"
+     "Lower numbers are less sensitive.", 8),
+#endif
     submenu_option(NULL, "Back", "Return to the main menu.", 11)
   };
 
@@ -1381,39 +1592,42 @@ u32 menu(u16 *original_screen)
   menu_option_type main_options[] =
   {
     submenu_option(&graphics_sound_menu, "Graphics and Sound options",
-     "Select to set display parameters and frameskip behavior,\n"
-     "audio on/off, audio buffer size, and audio filtering.", 0),
+     "Select to set display parameters and frameskip\n"
+     "behavior, audio on/off, buffer size, and filtering.", 0),
     numeric_selection_action_option(menu_load_state, NULL,
      "Load state from slot", &savestate_slot, 10,
-     "Select to load the game state from the current slot for this game,\n"
-     "if it exists (see the extended menu for more information)\n"
+     "Select to load the game state from the current slot\n"
+     "for this game, if it exists.\n"
      "Press left + right to change the current slot.", 2),
     numeric_selection_action_option(menu_save_state, NULL,
      "Save state to slot", &savestate_slot, 10,
-     "Select to save the game state to the current slot for this game.\n"
-     "See the extended menu for more information.\n"
+     "Select to save the game state to the current slot\n"
+     "for this game. See the extended menu for more info.\n"
      "Press left + right to change the current slot.", 3),
     submenu_option(&savestate_menu, "Savestate options",
-     "Select to enter a menu for loading, saving, and viewing the\n"
-     "currently active savestate for this game (or to load a savestate\n"
-     "file from another game)", 4),
+     "Select to enter a menu for loading, saving, and\n"
+     "viewing the currently active savestate for this game\n"
+     "(or to load a savestate file from another game)", 4),
     submenu_option(&gamepad_config_menu, "Configure gamepad input",
-     "Select to change the in-game behavior of the PSP buttons and d-pad.",
-     6),
+     "Select to change the in-game behavior of buttons\n"
+     "and d-pad.", 6),
+#ifndef WIZ_BUILD
     submenu_option(&analog_config_menu, "Configure analog input",
-     "Select to change the in-game behavior of the PSP analog nub.", 7),
+     "Select to change the in-game behavior of the analog nub.", 7),
+#endif
     submenu_option(&cheats_misc_menu, "Cheats and Miscellaneous options",
-     "Select to manage cheats, set backup behavior, and set device clock\n"
-     "speed.", 9),
+     "Select to manage cheats, set backup behavior,\n"
+     "and set device clock speed.", 9),
     action_option(menu_load, NULL, "Load new game",
-     "Select to load a new game (will exit a game if currently playing).",
-     11),
+     "Select to load a new game\n"
+     "(will exit a game if currently playing).", 11),
     action_option(menu_restart, NULL, "Restart game",
-     "Select to reset the GBA with the current game loaded.", 12),
+     "Select to reset the GBA with the current game\n"
+     "loaded.", 12),
     action_option(menu_exit, NULL, "Return to game",
      "Select to exit this menu and resume gameplay.", 13),
     action_option(menu_quit, NULL, "Exit gpSP",
-     "Select to exit gpSP and return to the PSP XMB/loader.", 15)
+     "Select to exit gpSP and return to the menu.", 15)
   };
 
   make_menu(main, submenu_main, NULL);
@@ -1440,10 +1654,11 @@ u32 menu(u16 *original_screen)
   {
     for(i = 0; i < 6; i++)
     {
-      print_string_pad(" ", COLOR_BG, COLOR_BG, 30, 210 + (i * 10), 70);
+      print_string_pad(" ", COLOR_BG, COLOR_BG, 8, 210 + (i * 10), 70);
     }
   }
 
+  menu_update_clock();
   video_resolution_large();
 
 #ifndef GP2X_BUILD
@@ -1460,7 +1675,7 @@ u32 menu(u16 *original_screen)
     first_load = 1;
     memset(original_screen, 0x00, 240 * 160 * 2);
     print_string_ext("No game loaded yet.", 0xFFFF, 0x0000,
-     60, 75,original_screen, 240, 0);
+     60, 75,original_screen, 240, 0, 0, FONT_HEIGHT);
   }
 
   choose_menu(&main_menu);
@@ -1505,18 +1720,18 @@ u32 menu(u16 *original_screen)
 
       if(display_option == current_option)
       {
-        print_string_pad(line_buffer, COLOR_ACTIVE_ITEM, COLOR_BG, 10,
+        print_string_pad(line_buffer, COLOR_ACTIVE_ITEM, COLOR_BG, 6,
          (display_option->line_number * 10) + 40, 36);
       }
       else
       {
-        print_string_pad(line_buffer, COLOR_INACTIVE_ITEM, COLOR_BG, 10,
+        print_string_pad(line_buffer, COLOR_INACTIVE_ITEM, COLOR_BG, 6,
          (display_option->line_number * 10) + 40, 36);
       }
     }
 
     print_string(current_option->help_string, COLOR_HELP_TEXT,
-     COLOR_BG, 30, 210);
+     COLOR_BG, 8, 210);
 
     flip_screen();
 
@@ -1587,19 +1802,19 @@ u32 menu(u16 *original_screen)
         if(current_option->option_type & SUBMENU_OPTION)
           choose_menu(current_option->sub_menu);
         break;
+
+      default:
+        break;
     }
   }
 
   set_gba_resolution(screen_scale);
   video_resolution_small();
-
-  clock_speed = (clock_speed_number + 1) * 33;
-
-  #ifdef PSP_BUILD
-    scePowerSetClockFrequency(clock_speed, clock_speed, clock_speed / 2);
-  #endif
+  menu_get_clock_speed();
+  set_clock_speed();
 
   SDL_PauseAudio(0);
+  num_skipped_frames = 100;
 
   return return_value;
 }