integrate M-HT's neon scalers
[gpsp.git] / gui.c
diff --git a/gui.c b/gui.c
index 18170f7..fe913a8 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
 
-#ifndef GP2X_BUILD
-#include "gp2x/cpuctrl.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(WIZ_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);
@@ -92,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;
@@ -135,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;
@@ -166,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);
 
@@ -194,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);
 
@@ -208,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);
 
@@ -263,8 +294,6 @@ s32 load_file(u8 **wildcards, u8 *result)
 
     clear_screen(COLOR_BG);
   {
-    u8 print_buffer[81];
-
     while(repeat)
     {
       flip_screen();
@@ -336,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
           {
@@ -356,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)
           {
@@ -372,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
           {
@@ -391,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)
@@ -437,6 +522,9 @@ s32 load_file(u8 **wildcards, u8 *result)
           return_value = -1;
           repeat = 0;
           break;
+
+        default:
+          break;
       }
     }
   }
@@ -480,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;
 };
@@ -651,13 +739,40 @@ u32 gamepad_config_line_to_button[] =
 
 #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(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"
+};
 
 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);
 
@@ -676,7 +791,10 @@ s32 load_game_config_file()
       random_skip = file_options[2] % 2;
       clock_speed = file_options[3];
 
-#ifdef GP2X_BUILD
+#ifdef WIZ_BUILD
+      if(clock_speed > 900)
+        clock_speed = 533;
+#elif defined(GP2X_BUILD)
       if(clock_speed >= 300)
         clock_speed = 200;
 #else
@@ -695,7 +813,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;
       }
 
@@ -709,12 +827,11 @@ s32 load_game_config_file()
 
   current_frameskip_type = auto_frameskip;
   frameskip_value = 4;
-  random_skip = 0;
-#ifdef GP2X_BUILD
-  clock_speed = 200;
-#else
-  clock_speed = 333;
+#ifdef WIZ_BUILD
+  frameskip_value = 1;
 #endif
+  random_skip = 0;
+  clock_speed = default_clock_speed;
 
   for(i = 0; i < 10; i++)
   {
@@ -725,15 +842,13 @@ s32 load_game_config_file()
   return -1;
 }
 
+#define FILE_OPTION_COUNT 24
+
 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);
 
@@ -742,16 +857,17 @@ 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_scale = file_options[0] %
+        (sizeof(scale_options) / sizeof(scale_options[0]));
       screen_filter = file_options[1] % 2;
       global_enable_audio = file_options[2] % 2;
+      screen_filter2 = file_options[23] %
+        (sizeof(filter2_options) / sizeof(filter2_options[0]));
 
 #ifdef PSP_BUILD
       audio_buffer_size_number = file_options[3] % 10;
@@ -771,6 +887,8 @@ s32 load_config_file()
       // key, if not assign to triangle
 
 #ifndef PC_BUILD
+      u32 i;
+      s32 menu_button = -1;
       for(i = 0; i < 16; i++)
       {
         gamepad_config_map[i] = file_options[7 + i] %
@@ -799,10 +917,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);
 
@@ -832,13 +950,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);
 
@@ -846,8 +960,7 @@ 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;
@@ -856,8 +969,10 @@ s32 save_config_file()
     file_options[4] = update_backup_flag;
     file_options[5] = global_enable_analog;
     file_options[6] = analog_sensitivity_level;
+    file_options[23] = screen_filter2;
 
 #ifndef PC_BUILD
+    u32 i;
     for(i = 0; i < 16; i++)
     {
       file_options[7 + i] = gamepad_config_map[i];
@@ -885,16 +1000,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"
@@ -920,8 +1035,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);
   }
@@ -931,22 +1046,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
@@ -958,22 +1069,16 @@ void get_savestate_filename_noshot(u32 slot, u8 *name_buffer)
 
 u32 menu(u16 *original_screen)
 {
+  char print_buffer[81];
   u32 clock_speed_number;
-#ifdef GP2X_BUILD
-  static u32 clock_speed_old = 200;
-#endif
-  u8 print_buffer[81];
-  u32 _current_option = 0;
   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;
@@ -983,7 +1088,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.",
@@ -1009,6 +1115,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)
@@ -1017,19 +1161,15 @@ u32 menu(u16 *original_screen)
 
   void menu_quit()
   {
-  #ifdef PSP_BUILD
-    clock_speed = (clock_speed_number + 1) * 33;
-  #elif defined(GP2X_BUILD)
-    clock_speed = 150 + clock_speed_number * 10;
-  #endif
+    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)
     {
@@ -1041,6 +1181,7 @@ u32 menu(u16 *original_screen)
        return_value = 1;
        repeat = 0;
        reg[CHANGED_PC_STATUS] = 1;
+       menu_update_clock();
     }
     else
     {
@@ -1087,8 +1228,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);
@@ -1149,103 +1290,58 @@ u32 menu(u16 *original_screen)
      current_savestate_filename);
   }
 
-  u8 *yes_no_options[] = { "no", "yes" };
-  u8 *enable_disable_options[] = { "disabled", "enabled" };
+  const char *yes_no_options[] = { "no", "yes" };
+  const char *enable_disable_options[] = { "disabled", "enabled" };
 
-  u8 *scale_options[] =
-  {
-    "unscaled 3:2", "scaled 3:2", "fullscreen"
-#ifdef PSP_BUILD
-    " 16:9"
-#endif
-  };
-
-  u8 *frameskip_options[] = { "automatic", "manual", "off" };
-  u8 *frameskip_variation_options[] = { "uniform", "random" };
+  const char *frameskip_options[] = { "automatic", "manual", "off" };
+  const char *frameskip_variation_options[] = { "uniform", "random" };
 
 #ifndef PSP_BUILD
-  u8 *audio_buffer_options[] =
+  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
-  u8 *audio_buffer_options[] =
+  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
-
-  u8 *update_backup_options[] = { "Exit only", "Automatic" };
-
-#ifdef GP2X_BUILD
-  u8 *clock_speed_options[] =
-  {
-    "150MHz", "160MHz", "170MHz", "180MHz", "190MHz",
-    "200MHz", "210MHz", "220MHz", "230MHz", "240MHz",
-    "250MHz", "260MHz", "270MHz", "280MHz", "290MHz"
-  };
-#else
-  u8 *clock_speed_options[] =
-  {
-    "33MHz", "66MHz", "100MHz", "133MHz", "166MHz", "200MHz", "233MHz",
-    "266MHz", "300MHz", "333MHz"
-  };
 #endif
 
-  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),
-#ifdef WIZ_BUILD
-     2,
-#else
-     3,
-#endif
+     sizeof(scale_options) / sizeof(scale_options[0]),
 #ifndef GP2X_BUILD
-     "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"
+     "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."
+#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,
@@ -1270,8 +1366,8 @@ u32 menu(u16 *original_screen)
 #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."
+     "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,
@@ -1293,7 +1389,8 @@ u32 menu(u16 *original_screen)
      "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.",
+     "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)
@@ -1313,29 +1410,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,
-#ifdef GP2X_BUILD
-     15,
-#else
-     10,
-#endif
+     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.",
+     "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.",
+     "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),
+     "", 12),
     submenu_option(NULL, "Back", "Return to the main menu.", 14)
   };
 
@@ -1405,7 +1502,7 @@ u32 menu(u16 *original_screen)
 
 #endif
 
-#ifdef GP2X_BUILD
+#if defined(GP2X_BUILD) || defined(PND_BUILD)
 
   menu_option_type gamepad_config_options[] =
   {
@@ -1425,10 +1522,18 @@ u32 menu(u16 *original_screen)
     gamepad_config_option("Start        ", 10),
 #endif
     gamepad_config_option("Select       ", 11),
-#ifndef WIZ_BUILD
+#if !defined(WIZ_BUILD) && !defined(PND_BUILD)
     gamepad_config_option("Stick Push   ", 12),
 #endif
+#ifdef PND_BUILD
+    gamepad_config_option("1            ", 12),
+    gamepad_config_option("2            ", 13),
+    gamepad_config_option("3            ", 14),
+    gamepad_config_option("4            ", 15),
+    submenu_option(NULL, "Back", "Return to the main menu.", 16)
+#else
     submenu_option(NULL, "Back", "Return to the main menu.", 14)
+#endif
   };
 
 
@@ -1525,12 +1630,7 @@ u32 menu(u16 *original_screen)
     }
   }
 
-#ifdef PSP_BUILD
-  clock_speed_number = (clock_speed / 33) - 1;
-#elif defined(GP2X_BUILD)
-  clock_speed_number = (clock_speed - 150) / 10;
-#endif
-
+  menu_update_clock();
   video_resolution_large();
 
 #ifndef GP2X_BUILD
@@ -1547,7 +1647,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);
@@ -1592,12 +1692,12 @@ 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);
       }
     }
@@ -1674,26 +1774,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();
-
-  #ifdef PSP_BUILD
-    clock_speed = (clock_speed_number + 1) * 33;
-    scePowerSetClockFrequency(clock_speed, clock_speed, clock_speed / 2);
-  #elif defined(GP2X_BUILD)
-    clock_speed = 150 + clock_speed_number * 10;
-    if (clock_speed != clock_speed_old)
-    {
-      printf("about to set CPU clock to %iMHz\n", clock_speed);
-      set_FCLK(clock_speed);
-      clock_speed_old = clock_speed;
-    }
-  #endif
+  menu_get_clock_speed();
+  set_clock_speed();
 
   SDL_PauseAudio(0);
+  num_skipped_frames = 100;
 
   return return_value;
 }