OSDN Git Service

[VM][General] Merge Upstream 20180530.
[csp-qt/common_source_project-fm7.git] / source / src / win32 / winmain.cpp
index 11cdea5..85ae925 100644 (file)
 // emulation core
 EMU* emu;
 
-// timing control
-#define MAX_SKIP_FRAMES 10
-
-int get_interval()
-{
-       static int accum = 0;
-       accum += emu->get_frame_interval();
-       int interval = accum >> 10;
-       accum -= interval << 10;
-       return interval;
-}
-
 // menu
 HMENU hMenu = NULL;
 bool now_menuloop = false;
 
-void update_menu(HWND hWnd, HMENU hMenu, int pos);
+void update_menu(HWND hWnd, HMENU hMenu);
 void show_menu_bar(HWND hWnd);
 void hide_menu_bar(HWND hWnd);
 
+// status bar
+HWND hStatus = NULL;
+bool status_bar_visible = false;
+
+#ifdef USE_FLOPPY_DISK
+uint32_t fd_status = 0x80000000;
+#endif
+#ifdef USE_QUICK_DISK
+uint32_t qd_status = 0x80000000;
+#endif
+#ifdef USE_HARD_DISK
+uint32_t hd_status = 0x80000000;
+#endif
+#ifdef USE_COMPACT_DISC
+uint32_t cd_status = 0x80000000;
+#endif
+#ifdef USE_LASER_DISC
+uint32_t ld_status = 0x80000000;
+#endif
+#if defined(USE_TAPE) && !defined(TAPE_BINARY_ONLY)
+_TCHAR tape_status[1024] = _T("uninitialized");
+#endif
+
+void show_status_bar(HWND hWnd);
+void hide_status_bar(HWND hWnd);
+int get_status_bar_height();
+bool get_status_bar_updated();
+void update_status_bar(HINSTANCE hInstance, LPDRAWITEMSTRUCT lpDrawItem);
+
 // file
-#ifdef USE_CART1
+#ifdef USE_CART
 void open_cart_dialog(HWND hWnd, int drv);
 void open_recent_cart(int drv, int index);
 #endif
-#ifdef USE_FD1
+#ifdef USE_FLOPPY_DISK
 void open_floppy_disk_dialog(HWND hWnd, int drv);
 void open_floppy_disk(int drv, const _TCHAR* path, int bank);
 void open_recent_floppy_disk(int drv, int index);
 void select_d88_bank(int drv, int index);
 void close_floppy_disk(int drv);
 #endif
-#ifdef USE_QD1
+#ifdef USE_QUICK_DISK
 void open_quick_disk_dialog(HWND hWnd, int drv);
 void open_recent_quick_disk(int drv, int index);
 #endif
+#ifdef USE_HARD_DISK
+void open_hard_disk_dialog(HWND hWnd, int drv);
+void open_recent_hard_disk(int drv, int index);
+#endif
 #ifdef USE_TAPE
-void open_tape_dialog(HWND hWnd, bool play);
-void open_recent_tape(int index);
+void open_tape_dialog(HWND hWnd, int drv, bool play);
+void open_recent_tape(int drv, int index);
+#endif
+#ifdef USE_COMPACT_DISC
+void open_compact_disc_dialog(HWND hWnd, int drv);
+void open_recent_compact_disc(int drv, int index);
 #endif
 #ifdef USE_LASER_DISC
-void open_laser_disc_dialog(HWND hWnd);
-void open_recent_laser_disc(int index);
+void open_laser_disc_dialog(HWND hWnd, int drv);
+void open_recent_laser_disc(int drv, int index);
 #endif
-#ifdef USE_BINARY_FILE1
+#ifdef USE_BINARY_FILE
 void open_binary_dialog(HWND hWnd, int drv, bool load);
 void open_recent_binary(int drv, int index);
 #endif
-#if defined(USE_CART1) || defined(USE_FD1) || defined(USE_TAPE) || defined(USE_LASER_DISC) || defined(USE_BINARY_FILE1)
+#ifdef USE_BUBBLE
+void open_bubble_casette_dialog(HWND hWnd, int drv);
+void open_recent_bubble_casette(int drv, int index);
+#endif
+#if defined(USE_CART) || defined(USE_FLOPPY_DISK) || defined(USE_HARD_DISK) || defined(USE_TAPE) || defined(USE_COMPACT_DISC) || defined(USE_LASER_DISC) || defined(USE_BINARY_FILE) || defined(USE_BUBBLE)
 #define SUPPORT_DRAG_DROP
 #endif
 #ifdef SUPPORT_DRAG_DROP
@@ -88,8 +117,8 @@ int desktop_bpp;
 int prev_window_mode = 0;
 bool now_fullscreen = false;
 
-#define MAX_WINDOW     8
-#define MAX_FULLSCREEN 32
+#define MAX_WINDOW     10
+#define MAX_FULLSCREEN 50
 
 int screen_mode_count;
 int screen_mode_width[MAX_FULLSCREEN];
@@ -114,7 +143,7 @@ BOOL CALLBACK JoyWndProc(HWND hDlg, UINT iMsg, WPARAM wParam, LPARAM lParam);
 // buttons
 #ifdef ONE_BOARD_MICRO_COMPUTER
 void create_buttons(HWND hWnd);
-void release_buttons();
+void draw_button(HDC hDC, UINT index, UINT pressed);
 #endif
 
 // misc
@@ -162,6 +191,13 @@ void update_socket(int ch, WPARAM wParam, LPARAM lParam)
 }
 #endif
 
+#ifdef USE_STATE
+const _TCHAR *state_file_path(int num)
+{
+       return create_local_path(_T("%s.sta%d"), _T(CONFIG_NAME), num);
+}
+#endif
+
 // ----------------------------------------------------------------------------
 // window main
 // ----------------------------------------------------------------------------
@@ -188,7 +224,8 @@ int WINAPI _tWinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPTSTR szCmdL
        wndclass.cbWndExtra = 0;
        wndclass.hInstance = hInstance;
        wndclass.hIcon = LoadIcon(hInstance, MAKEINTRESOURCE(IDI_ICON1));
-       wndclass.hCursor = 0;
+//     wndclass.hCursor = 0;
+       wndclass.hCursor = LoadCursor(NULL, IDC_ARROW);
        wndclass.hbrBackground = (HBRUSH)GetStockObject(BLACK_BRUSH);
        wndclass.lpszMenuName = MAKEINTRESOURCE(IDR_MENU1);
        wndclass.lpszClassName = _T("CWINDOW");
@@ -213,13 +250,19 @@ int WINAPI _tWinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPTSTR szCmdL
        ShowWindow(hWnd, iCmdShow);
        UpdateWindow(hWnd);
        
-       // show menu
+       // show menu bar
        show_menu_bar(hWnd);
        
+       // show status bar
+       if(config.show_status_bar) {
+               show_status_bar(hWnd);
+       }
+       
+       int status_bar_height = get_status_bar_height();
        RECT rect_tmp;
        GetClientRect(hWnd, &rect_tmp);
-       if(rect_tmp.bottom != WINDOW_HEIGHT) {
-               rect.bottom += WINDOW_HEIGHT - rect_tmp.bottom;
+       if(rect_tmp.bottom != WINDOW_HEIGHT + status_bar_height) {
+               rect.bottom += WINDOW_HEIGHT + status_bar_height - rect_tmp.bottom;
                dest_y = (int)((desktop_height - (rect.bottom - rect.top)) / 2);
                dest_y = (dest_y < 0) ? 0 : dest_y;
                SetWindowPos(hWnd, NULL, dest_x, dest_y, rect.right - rect.left, rect.bottom - rect.top, SWP_NOZORDER);
@@ -230,20 +273,17 @@ int WINAPI _tWinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPTSTR szCmdL
        
        // restore screen mode
        if(config.window_mode >= 0 && config.window_mode < MAX_WINDOW) {
-               PostMessage(hWnd, WM_COMMAND, ID_SCREEN_WINDOW1 + config.window_mode, 0L);
+               PostMessage(hWnd, WM_COMMAND, ID_SCREEN_WINDOW + config.window_mode, 0L);
        } else if(config.window_mode >= MAX_WINDOW && config.window_mode < screen_mode_count + MAX_WINDOW) {
-               PostMessage(hWnd, WM_COMMAND, ID_SCREEN_FULLSCREEN1 + config.window_mode - MAX_WINDOW, 0L);
+               PostMessage(hWnd, WM_COMMAND, ID_SCREEN_FULLSCREEN + config.window_mode - MAX_WINDOW, 0L);
        } else {
                config.window_mode = 0;
-               PostMessage(hWnd, WM_COMMAND, ID_SCREEN_WINDOW1, 0L);
+               PostMessage(hWnd, WM_COMMAND, ID_SCREEN_WINDOW, 0L);
        }
        
        // accelerator
        HACCEL hAccel = LoadAccelerators(hInstance, MAKEINTRESOURCE(IDR_ACCELERATOR1));
        
-       // disable ime
-       ImmAssociateContext(hWnd, 0);
-       
        // initialize emulation core
        emu = new EMU(hWnd, hInstance);
        emu->set_host_window_size(WINDOW_WIDTH, WINDOW_HEIGHT, true);
@@ -268,8 +308,9 @@ int WINAPI _tWinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPTSTR szCmdL
        // main loop
        int total_frames = 0, draw_frames = 0, skip_frames = 0;
        DWORD next_time = 0;
-       DWORD update_fps_time = 0;
        bool prev_skip = false;
+       DWORD update_fps_time = 0;
+       DWORD update_status_bar_time = 0;
        DWORD disable_screen_saver_time = 0;
        MSG msg;
        
@@ -293,16 +334,17 @@ int WINAPI _tWinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPTSTR szCmdL
                        total_frames += run_frames;
                        
                        // timing controls
-                       int interval = 0, sleep_period = 0;
-//                     for(int i = 0; i < run_frames; i++) {
-                               interval += get_interval();
-//                     }
-                       bool now_skip = emu->is_frame_skippable() && !emu->is_video_recording();
+                       int sleep_period = 0;
+                       bool now_skip = (config.full_speed || emu->is_frame_skippable()) && !emu->is_video_recording() && !emu->is_sound_recording();
                        
                        if((prev_skip && !now_skip) || next_time == 0) {
                                next_time = timeGetTime();
                        }
                        if(!now_skip) {
+                               static int accum = 0;
+                               accum += emu->get_frame_interval();
+                               int interval = accum >> 10;
+                               accum -= interval << 10;
                                next_time += interval;
                        }
                        prev_skip = now_skip;
@@ -317,8 +359,8 @@ int WINAPI _tWinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPTSTR szCmdL
                                if((int)(next_time - current_time) >= 10) {
                                        sleep_period = next_time - current_time;
                                }
-                       } else if(++skip_frames > MAX_SKIP_FRAMES) {
-                               // update window at least once per 10 frames
+                       } else if(++skip_frames > (int)emu->get_frame_rate()) {
+                               // update window at least once per 1 sec in virtual machine time
                                draw_frames += emu->draw_screen();
                                skip_frames = 0;
                                next_time = timeGetTime();
@@ -327,23 +369,35 @@ int WINAPI _tWinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPTSTR szCmdL
                        
                        // calc frame rate
                        DWORD current_time = timeGetTime();
-                       if(update_fps_time <= current_time && update_fps_time != 0) {
-                               int ratio = (int)(100.0 * (double)draw_frames / (double)total_frames + 0.5);
-                               if(emu->message_count > 0) {
-                                       SetWindowText(hWnd, create_string(_T("%s - %s"), _T(DEVICE_NAME), emu->message));
-                                       emu->message_count--;
-                               } else if(now_skip) {
-                                       SetWindowText(hWnd, create_string(_T("%s - Skip Frames"), _T(DEVICE_NAME)));
-                               } else {
-                                       SetWindowText(hWnd, create_string(_T("%s - %d fps (%d %%)"), _T(DEVICE_NAME), draw_frames, ratio));
-                               }
-                               update_fps_time += 1000;
-                               total_frames = draw_frames = 0;
-                       }
                        if(update_fps_time <= current_time) {
+                               if(update_fps_time != 0) {
+                                       if(emu->message_count > 0) {
+                                               SetWindowText(hWnd, create_string(_T("%s - %s"), _T(DEVICE_NAME), emu->message));
+                                               emu->message_count--;
+                                       } else if(now_skip) {
+                                               int ratio = (int)(100.0 * (double)total_frames / emu->get_frame_rate() + 0.5);
+                                               SetWindowText(hWnd, create_string(_T("%s - Skip Frames (%d %%)"), _T(DEVICE_NAME), ratio));
+                                       } else {
+                                               int ratio = (int)(100.0 * (double)draw_frames / (double)total_frames + 0.5);
+                                               SetWindowText(hWnd, create_string(_T("%s - %d fps (%d %%)"), _T(DEVICE_NAME), draw_frames, ratio));
+                                       }
+                                       update_fps_time += 1000;
+                                       total_frames = draw_frames = 0;
+                               }
                                update_fps_time = current_time + 1000;
                        }
                        
+                       // update status bar
+                       if(update_status_bar_time <= current_time) {
+                               if(hStatus != NULL && status_bar_visible) {
+                                       if(get_status_bar_updated()) {
+                                               SendMessage(hStatus, SB_SETTEXT, (WPARAM)0 | SBT_OWNERDRAW, (LPARAM)NULL);
+//                                             InvalidateRect(hStatus, NULL, FALSE);
+                                       }
+                               }
+                               update_status_bar_time = current_time + 200;
+                       }
+                       
                        // disable screen saver
                        if(disable_screen_saver_time <= current_time) {
                                SetThreadExecutionState(ES_DISPLAY_REQUIRED);
@@ -370,6 +424,9 @@ int WINAPI _tWinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPTSTR szCmdL
 
 LRESULT CALLBACK WndProc(HWND hWnd, UINT iMsg, WPARAM wParam, LPARAM lParam)
 {
+       static HINSTANCE hInstance;
+       static HIMC himcPrev = 0;
+       
        switch(iMsg) {
        case WM_CREATE:
                if(config.disable_dwm && win8_or_later) {
@@ -381,6 +438,8 @@ LRESULT CALLBACK WndProc(HWND hWnd, UINT iMsg, WPARAM wParam, LPARAM lParam)
 #ifdef SUPPORT_DRAG_DROP
                DragAcceptFiles(hWnd, TRUE);
 #endif
+               hInstance = (HINSTANCE)GetWindowLong(hWnd, GWL_HINSTANCE);
+               timeBeginPeriod(1);
                break;
        case WM_CLOSE:
 #ifdef USE_NOTIFY_POWER_OFF
@@ -399,11 +458,13 @@ LRESULT CALLBACK WndProc(HWND hWnd, UINT iMsg, WPARAM wParam, LPARAM lParam)
                        ChangeDisplaySettings(NULL, 0);
                }
                now_fullscreen = false;
-#ifdef ONE_BOARD_MICRO_COMPUTER
-               release_buttons();
-#endif
                if(hMenu != NULL && IsMenu(hMenu)) {
                        DestroyMenu(hMenu);
+                       hMenu = NULL;
+               }
+               if(hStatus != NULL) {
+                       DestroyWindow(hStatus);
+                       hStatus = NULL;
                }
                DestroyWindow(hWnd);
                // release emulation core
@@ -412,17 +473,29 @@ LRESULT CALLBACK WndProc(HWND hWnd, UINT iMsg, WPARAM wParam, LPARAM lParam)
                        emu = NULL;
                }
                save_config(create_local_path(_T("%s.ini"), _T(CONFIG_NAME)));
+               timeEndPeriod(1);
                return 0;
        case WM_DESTROY:
                PostQuitMessage(0);
                return 0;
-#ifdef ONE_BOARD_MICRO_COMPUTER
+       case WM_ACTIVATE:
+               // thanks PC8801MA\89ü
+               if(LOWORD(wParam) != WA_INACTIVE) {
+                       himcPrev = ImmAssociateContext(hWnd, 0);
+               } else {
+                       ImmAssociateContext(hWnd, himcPrev);
+               }
+               break;
        case WM_SIZE:
+               if(hStatus != NULL) {
+                       SendMessage(hStatus, WM_SIZE, wParam, lParam);
+               }
+#ifdef ONE_BOARD_MICRO_COMPUTER
                if(emu) {
                        emu->reload_bitmap();
                }
-               break;
 #endif
+               break;
        case WM_KILLFOCUS:
                if(emu) {
                        emu->key_lost_focus();
@@ -432,10 +505,34 @@ LRESULT CALLBACK WndProc(HWND hWnd, UINT iMsg, WPARAM wParam, LPARAM lParam)
                if(emu) {
                        PAINTSTRUCT ps;
                        HDC hdc = BeginPaint(hWnd, &ps);
+#ifdef ONE_BOARD_MICRO_COMPUTER
+                       // check if self invalidate or not
+                       int left = 0, top = 0, right = 0, bottom = 0;
+                       emu->get_invalidated_rect(&left, &top, &right, &bottom);
+                       if(ps.rcPaint.left != left || ps.rcPaint.top != top || ps.rcPaint.right != right || ps.rcPaint.bottom != bottom) {
+                               emu->reload_bitmap();
+                       }
+#endif
                        emu->update_screen(hdc);
                        EndPaint(hWnd, &ps);
                }
                return 0;
+       case WM_DRAWITEM:
+               {
+                       LPDRAWITEMSTRUCT lpDrawItem = (LPDRAWITEMSTRUCT)lParam;
+                       if(lpDrawItem->CtlID == ID_STATUS) {
+                               if(emu) {
+                                       update_status_bar(hInstance, lpDrawItem);
+                               }
+                       } else {
+                               #ifdef ONE_BOARD_MICRO_COMPUTER
+//                                     if(lpDrawItem->itemAction & (ODA_DRAWENTIRE | ODA_SELECT)) {
+                                               draw_button(lpDrawItem->hDC, (UINT)wParam - ID_BUTTON, lpDrawItem->itemState & ODS_SELECTED);
+//                                     }
+                               #endif
+                       }
+               }
+               return TRUE;
        case WM_MOVING:
                if(emu) {
                        emu->suspend();
@@ -443,19 +540,22 @@ LRESULT CALLBACK WndProc(HWND hWnd, UINT iMsg, WPARAM wParam, LPARAM lParam)
                break;
        case WM_KEYDOWN:
                if(emu) {
+                       bool extended = ((HIWORD(lParam) & 0x100) != 0);
                        bool repeat = ((HIWORD(lParam) & 0x4000) != 0);
-                       emu->key_down(LOBYTE(wParam), repeat);
+                       emu->key_down(LOBYTE(wParam), extended, repeat);
                }
                break;
        case WM_KEYUP:
                if(emu) {
-                       emu->key_up(LOBYTE(wParam));
+                       bool extended = ((HIWORD(lParam) & 0x100) != 0);
+                       emu->key_up(LOBYTE(wParam), extended);
                }
                break;
        case WM_SYSKEYDOWN:
                if(emu) {
+                       bool extended = ((HIWORD(lParam) & 0x100) != 0);
                        bool repeat = ((HIWORD(lParam) & 0x4000) != 0);
-                       emu->key_down(LOBYTE(wParam), repeat);
+                       emu->key_down(LOBYTE(wParam), extended, repeat);
                }
 #ifdef USE_ALT_F10_KEY
                return 0;       // not activate menu when hit ALT/F10
@@ -464,13 +564,19 @@ LRESULT CALLBACK WndProc(HWND hWnd, UINT iMsg, WPARAM wParam, LPARAM lParam)
 #endif
        case WM_SYSKEYUP:
                if(emu) {
-                       emu->key_up(LOBYTE(wParam));
+                       bool extended = ((HIWORD(lParam) & 0x100) != 0);
+                       emu->key_up(LOBYTE(wParam), extended);
                }
 #ifdef USE_ALT_F10_KEY
                return 0;       // not activate menu when hit ALT/F10
 #else
                break;
 #endif
+       case WM_CHAR:
+               if(emu) {
+                       emu->key_char(LOBYTE(wParam));
+               }
+               break;
 #ifdef USE_ALT_F10_KEY
        case WM_SYSCHAR:
                return 0;       // not activate menu when hit ALT/F10
@@ -479,7 +585,7 @@ LRESULT CALLBACK WndProc(HWND hWnd, UINT iMsg, WPARAM wParam, LPARAM lParam)
                if(emu) {
                        emu->suspend();
                }
-               update_menu(hWnd, (HMENU)wParam, LOWORD(lParam));
+               update_menu(hWnd, (HMENU)wParam);
                break;
        case WM_ENTERMENULOOP:
                now_menuloop = true;
@@ -537,73 +643,15 @@ LRESULT CALLBACK WndProc(HWND hWnd, UINT iMsg, WPARAM wParam, LPARAM lParam)
                        }
                        break;
 #endif
-#ifdef USE_STATE
-               case ID_SAVE_STATE:
-                       if(emu) {
-                               emu->save_state();
-                       }
-                       break;
-               case ID_LOAD_STATE:
-                       if(emu) {
-                               emu->load_state();
-                       }
-                       break;
-#endif
-#ifdef USE_BOOT_MODE
-               case ID_BOOT_MODE0: case ID_BOOT_MODE1: case ID_BOOT_MODE2: case ID_BOOT_MODE3:
-               case ID_BOOT_MODE4: case ID_BOOT_MODE5: case ID_BOOT_MODE6: case ID_BOOT_MODE7:
-                       config.boot_mode = LOWORD(wParam) - ID_BOOT_MODE0;
-                       if(emu) {
-                               emu->update_config();
-                       }
-                       break;
-#endif
-#ifdef USE_CPU_TYPE
-               case ID_CPU_TYPE0: case ID_CPU_TYPE1: case ID_CPU_TYPE2: case ID_CPU_TYPE3:
-               case ID_CPU_TYPE4: case ID_CPU_TYPE5: case ID_CPU_TYPE6: case ID_CPU_TYPE7:
-                       config.cpu_type = LOWORD(wParam) - ID_CPU_TYPE0;
-                       // need to recreate vm class instance
-//                     if(emu) {
-//                             emu->update_config();
-//                     }
-                       break;
-#endif
                case ID_CPU_POWER0: case ID_CPU_POWER1: case ID_CPU_POWER2: case ID_CPU_POWER3: case ID_CPU_POWER4:
                        config.cpu_power = LOWORD(wParam) - ID_CPU_POWER0;
                        if(emu) {
                                emu->update_config();
                        }
                        break;
-#ifdef USE_DIPSWITCH
-               case ID_DIPSWITCH0:  case ID_DIPSWITCH1:  case ID_DIPSWITCH2:  case ID_DIPSWITCH3: 
-               case ID_DIPSWITCH4:  case ID_DIPSWITCH5:  case ID_DIPSWITCH6:  case ID_DIPSWITCH7: 
-               case ID_DIPSWITCH8:  case ID_DIPSWITCH9:  case ID_DIPSWITCH10: case ID_DIPSWITCH11:
-               case ID_DIPSWITCH12: case ID_DIPSWITCH13: case ID_DIPSWITCH14: case ID_DIPSWITCH15:
-               case ID_DIPSWITCH16: case ID_DIPSWITCH17: case ID_DIPSWITCH18: case ID_DIPSWITCH19:
-               case ID_DIPSWITCH20: case ID_DIPSWITCH21: case ID_DIPSWITCH22: case ID_DIPSWITCH23:
-               case ID_DIPSWITCH24: case ID_DIPSWITCH25: case ID_DIPSWITCH26: case ID_DIPSWITCH27:
-               case ID_DIPSWITCH28: case ID_DIPSWITCH29: case ID_DIPSWITCH30: case ID_DIPSWITCH31:
-                       config.dipswitch ^= (1 << (LOWORD(wParam) - ID_DIPSWITCH0));
-                       break;
-#endif
-#ifdef USE_PRINTER_TYPE
-               case ID_PRINTER_TYPE0: case ID_PRINTER_TYPE1: case ID_PRINTER_TYPE2: case ID_PRINTER_TYPE3:
-                       config.printer_device_type = LOWORD(wParam) - ID_PRINTER_TYPE0;
-                       break;
-#endif
-#ifdef USE_DEVICE_TYPE
-               case ID_DEVICE_TYPE0: case ID_DEVICE_TYPE1: case ID_DEVICE_TYPE2: case ID_DEVICE_TYPE3:
-                       config.device_type = LOWORD(wParam) - ID_DEVICE_TYPE0;
-                       break;
-#endif
-#ifdef USE_DRIVE_TYPE
-               case ID_DRIVE_TYPE0: case ID_DRIVE_TYPE1: case ID_DRIVE_TYPE2: case ID_DRIVE_TYPE3:
-                       config.drive_type = LOWORD(wParam) - ID_DRIVE_TYPE0;
-                       if(emu) {
-                               emu->update_config();
-                       }
+               case ID_FULL_SPEED:
+                       config.full_speed = !config.full_speed;
                        break;
-#endif
 #ifdef USE_AUTO_KEY
                case ID_AUTOKEY_START:
                        if(emu) {
@@ -615,9 +663,21 @@ LRESULT CALLBACK WndProc(HWND hWnd, UINT iMsg, WPARAM wParam, LPARAM lParam)
                                emu->stop_auto_key();
                        }
                        break;
+               case ID_ROMAJI_TO_KANA:
+                       if(emu) {
+                               if(!config.romaji_to_kana) {
+                                       emu->set_auto_key_char(1); // start
+                                       config.romaji_to_kana = true;
+                               } else {
+                                       emu->set_auto_key_char(0); // end
+                                       config.romaji_to_kana = false;
+                               }
+                       }
+                       break;
 #endif
 #ifdef USE_DEBUGGER
                case ID_OPEN_DEBUGGER0: case ID_OPEN_DEBUGGER1: case ID_OPEN_DEBUGGER2: case ID_OPEN_DEBUGGER3:
+               case ID_OPEN_DEBUGGER4: case ID_OPEN_DEBUGGER5: case ID_OPEN_DEBUGGER6: case ID_OPEN_DEBUGGER7:
                        if(emu) {
                                emu->open_debugger(LOWORD(wParam) - ID_OPEN_DEBUGGER0);
                        }
@@ -628,435 +688,696 @@ LRESULT CALLBACK WndProc(HWND hWnd, UINT iMsg, WPARAM wParam, LPARAM lParam)
                        }
                        break;
 #endif
-               case ID_EXIT:
-                       SendMessage(hWnd, WM_CLOSE, 0, 0L);
-                       break;
-#ifdef USE_CART1
-               #define CART_MENU_ITEMS(drv, ID_OPEN_CART, ID_CLOSE_CART, ID_RECENT_CART) \
-               case ID_OPEN_CART: \
-                       if(emu) { \
-                               open_cart_dialog(hWnd, drv); \
-                       } \
-                       break; \
-               case ID_CLOSE_CART: \
-                       if(emu) { \
-                               emu->close_cart(drv); \
-                       } \
-                       break; \
-               case ID_RECENT_CART + 0: case ID_RECENT_CART + 1: case ID_RECENT_CART + 2: case ID_RECENT_CART + 3: \
-               case ID_RECENT_CART + 4: case ID_RECENT_CART + 5: case ID_RECENT_CART + 6: case ID_RECENT_CART + 7: \
-                       if(emu) { \
-                               open_recent_cart(drv, LOWORD(wParam) - ID_RECENT_CART); \
-                       } \
-                       break;
-               CART_MENU_ITEMS(0, ID_OPEN_CART1, ID_CLOSE_CART1, ID_RECENT_CART1)
-#endif
-#ifdef USE_CART2
-               CART_MENU_ITEMS(1, ID_OPEN_CART2, ID_CLOSE_CART2, ID_RECENT_CART2)
-#endif
-#ifdef USE_FD1
-               #define FD_MENU_ITEMS(drv, ID_OPEN_FD, ID_CLOSE_FD, ID_WRITE_PROTECT_FD, ID_CORRECT_TIMING_FD, ID_IGNORE_CRC_FD, ID_RECENT_FD, ID_SELECT_D88_BANK, ID_EJECT_D88_BANK) \
-               case ID_OPEN_FD: \
-                       if(emu) { \
-                               open_floppy_disk_dialog(hWnd, drv); \
-                       } \
-                       break; \
-               case ID_CLOSE_FD: \
-                       if(emu) { \
-                               close_floppy_disk(drv); \
-                       } \
-                       break; \
-               case ID_WRITE_PROTECT_FD: \
-                       if(emu) { \
-                               emu->is_floppy_disk_protected(drv, !emu->is_floppy_disk_protected(drv)); \
-                       } \
-                       break; \
-               case ID_CORRECT_TIMING_FD: \
-                       config.correct_disk_timing[drv] = !config.correct_disk_timing[drv]; \
-                       break; \
-               case ID_IGNORE_CRC_FD: \
-                       config.ignore_disk_crc[drv] = !config.ignore_disk_crc[drv]; \
-                       break; \
-               case ID_RECENT_FD + 0: case ID_RECENT_FD + 1: case ID_RECENT_FD + 2: case ID_RECENT_FD + 3: \
-               case ID_RECENT_FD + 4: case ID_RECENT_FD + 5: case ID_RECENT_FD + 6: case ID_RECENT_FD + 7: \
-                       if(emu) { \
-                               open_recent_floppy_disk(drv, LOWORD(wParam) - ID_RECENT_FD); \
-                       } \
-                       break; \
-               case ID_SELECT_D88_BANK +  0: case ID_SELECT_D88_BANK +  1: case ID_SELECT_D88_BANK +  2: case ID_SELECT_D88_BANK +  3: \
-               case ID_SELECT_D88_BANK +  4: case ID_SELECT_D88_BANK +  5: case ID_SELECT_D88_BANK +  6: case ID_SELECT_D88_BANK +  7: \
-               case ID_SELECT_D88_BANK +  8: case ID_SELECT_D88_BANK +  9: case ID_SELECT_D88_BANK + 10: case ID_SELECT_D88_BANK + 11: \
-               case ID_SELECT_D88_BANK + 12: case ID_SELECT_D88_BANK + 13: case ID_SELECT_D88_BANK + 14: case ID_SELECT_D88_BANK + 15: \
-               case ID_SELECT_D88_BANK + 16: case ID_SELECT_D88_BANK + 17: case ID_SELECT_D88_BANK + 18: case ID_SELECT_D88_BANK + 19: \
-               case ID_SELECT_D88_BANK + 20: case ID_SELECT_D88_BANK + 21: case ID_SELECT_D88_BANK + 22: case ID_SELECT_D88_BANK + 23: \
-               case ID_SELECT_D88_BANK + 24: case ID_SELECT_D88_BANK + 25: case ID_SELECT_D88_BANK + 26: case ID_SELECT_D88_BANK + 27: \
-               case ID_SELECT_D88_BANK + 28: case ID_SELECT_D88_BANK + 29: case ID_SELECT_D88_BANK + 30: case ID_SELECT_D88_BANK + 31: \
-               case ID_SELECT_D88_BANK + 32: case ID_SELECT_D88_BANK + 33: case ID_SELECT_D88_BANK + 34: case ID_SELECT_D88_BANK + 35: \
-               case ID_SELECT_D88_BANK + 36: case ID_SELECT_D88_BANK + 37: case ID_SELECT_D88_BANK + 38: case ID_SELECT_D88_BANK + 39: \
-               case ID_SELECT_D88_BANK + 40: case ID_SELECT_D88_BANK + 41: case ID_SELECT_D88_BANK + 42: case ID_SELECT_D88_BANK + 43: \
-               case ID_SELECT_D88_BANK + 44: case ID_SELECT_D88_BANK + 45: case ID_SELECT_D88_BANK + 46: case ID_SELECT_D88_BANK + 47: \
-               case ID_SELECT_D88_BANK + 48: case ID_SELECT_D88_BANK + 49: case ID_SELECT_D88_BANK + 50: case ID_SELECT_D88_BANK + 51: \
-               case ID_SELECT_D88_BANK + 52: case ID_SELECT_D88_BANK + 53: case ID_SELECT_D88_BANK + 54: case ID_SELECT_D88_BANK + 55: \
-               case ID_SELECT_D88_BANK + 56: case ID_SELECT_D88_BANK + 57: case ID_SELECT_D88_BANK + 58: case ID_SELECT_D88_BANK + 59: \
-               case ID_SELECT_D88_BANK + 60: case ID_SELECT_D88_BANK + 61: case ID_SELECT_D88_BANK + 62: case ID_SELECT_D88_BANK + 63: \
-                       if(emu) { \
-                               select_d88_bank(drv, LOWORD(wParam) - ID_SELECT_D88_BANK) ; \
-                       } \
-                       break; \
-               case ID_EJECT_D88_BANK: \
-                       if(emu) { \
-                               select_d88_bank(drv, -1) ; \
-                       } \
-                       break;
-               FD_MENU_ITEMS(0, ID_OPEN_FD1, ID_CLOSE_FD1, ID_WRITE_PROTECT_FD1, ID_CORRECT_TIMING_FD1, ID_IGNORE_CRC_FD1, ID_RECENT_FD1, ID_SELECT_D88_BANK1, ID_EJECT_D88_BANK1)
-#endif
-#ifdef USE_FD2
-               FD_MENU_ITEMS(1, ID_OPEN_FD2, ID_CLOSE_FD2, ID_WRITE_PROTECT_FD2, ID_CORRECT_TIMING_FD2, ID_IGNORE_CRC_FD2, ID_RECENT_FD2, ID_SELECT_D88_BANK2, ID_EJECT_D88_BANK2)
-#endif
-#ifdef USE_FD3
-               FD_MENU_ITEMS(2, ID_OPEN_FD3, ID_CLOSE_FD3, ID_WRITE_PROTECT_FD3, ID_CORRECT_TIMING_FD3, ID_IGNORE_CRC_FD3, ID_RECENT_FD3, ID_SELECT_D88_BANK3, ID_EJECT_D88_BANK3)
-#endif
-#ifdef USE_FD4
-               FD_MENU_ITEMS(3, ID_OPEN_FD4, ID_CLOSE_FD4, ID_WRITE_PROTECT_FD4, ID_CORRECT_TIMING_FD4, ID_IGNORE_CRC_FD4, ID_RECENT_FD4, ID_SELECT_D88_BANK4, ID_EJECT_D88_BANK4)
-#endif
-#ifdef USE_FD5
-               FD_MENU_ITEMS(4, ID_OPEN_FD5, ID_CLOSE_FD5, ID_WRITE_PROTECT_FD5, ID_CORRECT_TIMING_FD5, ID_IGNORE_CRC_FD5, ID_RECENT_FD5, ID_SELECT_D88_BANK5, ID_EJECT_D88_BANK5)
-#endif
-#ifdef USE_FD6
-               FD_MENU_ITEMS(5, ID_OPEN_FD6, ID_CLOSE_FD6, ID_WRITE_PROTECT_FD6, ID_CORRECT_TIMING_FD6, ID_IGNORE_CRC_FD6, ID_RECENT_FD6, ID_SELECT_D88_BANK6, ID_EJECT_D88_BANK6)
-#endif
-#ifdef USE_FD7
-               FD_MENU_ITEMS(6, ID_OPEN_FD7, ID_CLOSE_FD7, ID_WRITE_PROTECT_FD7, ID_CORRECT_TIMING_FD7, ID_IGNORE_CRC_FD7, ID_RECENT_FD7, ID_SELECT_D88_BANK7, ID_EJECT_D88_BANK7)
-#endif
-#ifdef USE_FD8
-               FD_MENU_ITEMS(7, ID_OPEN_FD8, ID_CLOSE_FD8, ID_WRITE_PROTECT_FD8, ID_CORRECT_TIMING_FD8, ID_IGNORE_CRC_FD8, ID_RECENT_FD8, ID_SELECT_D88_BANK8, ID_EJECT_D88_BANK8)
-#endif
-#ifdef USE_QD1
-               #define QD_MENU_ITEMS(drv, ID_OPEN_QD, ID_CLOSE_QD, ID_RECENT_QD) \
-               case ID_OPEN_QD: \
-                       if(emu) { \
-                               open_quick_disk_dialog(hWnd, drv); \
-                       } \
-                       break; \
-               case ID_CLOSE_QD: \
-                       if(emu) { \
-                               emu->close_quick_disk(drv); \
-                       } \
-                       break; \
-               case ID_RECENT_QD + 0: case ID_RECENT_QD + 1: case ID_RECENT_QD + 2: case ID_RECENT_QD + 3: \
-               case ID_RECENT_QD + 4: case ID_RECENT_QD + 5: case ID_RECENT_QD + 6: case ID_RECENT_QD + 7: \
-                       if(emu) { \
-                               open_recent_quick_disk(drv, LOWORD(wParam) - ID_RECENT_QD); \
-                       } \
-                       break;
-               QD_MENU_ITEMS(0, ID_OPEN_QD1, ID_CLOSE_QD1, ID_RECENT_QD1)
-#endif
-#ifdef USE_QD2
-               QD_MENU_ITEMS(1, ID_OPEN_QD2, ID_CLOSE_QD2, ID_RECENT_QD2)
-#endif
-#ifdef USE_TAPE
-               case ID_PLAY_TAPE:
+#ifdef USE_STATE
+               case ID_SAVE_STATE0: case ID_SAVE_STATE1: case ID_SAVE_STATE2: case ID_SAVE_STATE3: case ID_SAVE_STATE4:
+               case ID_SAVE_STATE5: case ID_SAVE_STATE6: case ID_SAVE_STATE7: case ID_SAVE_STATE8: case ID_SAVE_STATE9:
                        if(emu) {
-                               open_tape_dialog(hWnd, true);
+                               emu->save_state(state_file_path(LOWORD(wParam) - ID_SAVE_STATE0));
                        }
                        break;
-               case ID_REC_TAPE:
+               case ID_LOAD_STATE0: case ID_LOAD_STATE1: case ID_LOAD_STATE2: case ID_LOAD_STATE3: case ID_LOAD_STATE4:
+               case ID_LOAD_STATE5: case ID_LOAD_STATE6: case ID_LOAD_STATE7: case ID_LOAD_STATE8: case ID_LOAD_STATE9:
                        if(emu) {
-                               open_tape_dialog(hWnd, false);
+                               emu->load_state(state_file_path(LOWORD(wParam) - ID_LOAD_STATE0));
                        }
                        break;
-               case ID_CLOSE_TAPE:
+#endif
+               case ID_EXIT:
+                       SendMessage(hWnd, WM_CLOSE, 0, 0L);
+                       break;
+#ifdef USE_BOOT_MODE
+               case ID_VM_BOOT_MODE0: case ID_VM_BOOT_MODE1: case ID_VM_BOOT_MODE2: case ID_VM_BOOT_MODE3:
+               case ID_VM_BOOT_MODE4: case ID_VM_BOOT_MODE5: case ID_VM_BOOT_MODE6: case ID_VM_BOOT_MODE7:
+                       config.boot_mode = LOWORD(wParam) - ID_VM_BOOT_MODE0;
                        if(emu) {
-                               emu->close_tape();
+                               emu->update_config();
                        }
                        break;
-               case ID_PLAY_TAPE_SOUND:
-                       config.tape_sound = !config.tape_sound;
+#endif
+#ifdef USE_CPU_TYPE
+               case ID_VM_CPU_TYPE0: case ID_VM_CPU_TYPE1: case ID_VM_CPU_TYPE2: case ID_VM_CPU_TYPE3:
+               case ID_VM_CPU_TYPE4: case ID_VM_CPU_TYPE5: case ID_VM_CPU_TYPE6: case ID_VM_CPU_TYPE7:
+                       config.cpu_type = LOWORD(wParam) - ID_VM_CPU_TYPE0;
+                       // need to recreate vm class instance
+//                     if(emu) {
+//                             emu->update_config();
+//                     }
                        break;
-               case ID_USE_WAVE_SHAPER:
-                       config.wave_shaper = !config.wave_shaper;
+#endif
+#ifdef USE_DIPSWITCH
+               case ID_VM_DIPSWITCH0:  case ID_VM_DIPSWITCH1:  case ID_VM_DIPSWITCH2:  case ID_VM_DIPSWITCH3: 
+               case ID_VM_DIPSWITCH4:  case ID_VM_DIPSWITCH5:  case ID_VM_DIPSWITCH6:  case ID_VM_DIPSWITCH7: 
+               case ID_VM_DIPSWITCH8:  case ID_VM_DIPSWITCH9:  case ID_VM_DIPSWITCH10: case ID_VM_DIPSWITCH11:
+               case ID_VM_DIPSWITCH12: case ID_VM_DIPSWITCH13: case ID_VM_DIPSWITCH14: case ID_VM_DIPSWITCH15:
+               case ID_VM_DIPSWITCH16: case ID_VM_DIPSWITCH17: case ID_VM_DIPSWITCH18: case ID_VM_DIPSWITCH19:
+               case ID_VM_DIPSWITCH20: case ID_VM_DIPSWITCH21: case ID_VM_DIPSWITCH22: case ID_VM_DIPSWITCH23:
+               case ID_VM_DIPSWITCH24: case ID_VM_DIPSWITCH25: case ID_VM_DIPSWITCH26: case ID_VM_DIPSWITCH27:
+               case ID_VM_DIPSWITCH28: case ID_VM_DIPSWITCH29: case ID_VM_DIPSWITCH30: case ID_VM_DIPSWITCH31:
+                       config.dipswitch ^= (1 << (LOWORD(wParam) - ID_VM_DIPSWITCH0));
                        break;
-               case ID_DIRECT_LOAD_MZT:
-                       config.direct_load_mzt = !config.direct_load_mzt;
+#endif
+#ifdef USE_DEVICE_TYPE
+               case ID_VM_DEVICE_TYPE0: case ID_VM_DEVICE_TYPE1: case ID_VM_DEVICE_TYPE2: case ID_VM_DEVICE_TYPE3:
+               case ID_VM_DEVICE_TYPE4: case ID_VM_DEVICE_TYPE5: case ID_VM_DEVICE_TYPE6: case ID_VM_DEVICE_TYPE7:
+                       config.device_type = LOWORD(wParam) - ID_VM_DEVICE_TYPE0;
                        break;
-               case ID_RECENT_TAPE + 0: case ID_RECENT_TAPE + 1: case ID_RECENT_TAPE + 2: case ID_RECENT_TAPE + 3:
-               case ID_RECENT_TAPE + 4: case ID_RECENT_TAPE + 5: case ID_RECENT_TAPE + 6: case ID_RECENT_TAPE + 7:
+#endif
+#ifdef USE_DRIVE_TYPE
+               case ID_VM_DRIVE_TYPE0: case ID_VM_DRIVE_TYPE1: case ID_VM_DRIVE_TYPE2: case ID_VM_DRIVE_TYPE3:
+               case ID_VM_DRIVE_TYPE4: case ID_VM_DRIVE_TYPE5: case ID_VM_DRIVE_TYPE6: case ID_VM_DRIVE_TYPE7:
+                       config.drive_type = LOWORD(wParam) - ID_VM_DRIVE_TYPE0;
                        if(emu) {
-                               open_recent_tape(LOWORD(wParam) - ID_RECENT_TAPE);
+                               emu->update_config();
                        }
                        break;
 #endif
-#ifdef USE_TAPE_BUTTON
-               case ID_PLAY_BUTTON:
+#ifdef USE_KEYBOARD_TYPE
+               case ID_VM_KEYBOARD_TYPE0: case ID_VM_KEYBOARD_TYPE1: case ID_VM_KEYBOARD_TYPE2: case ID_VM_KEYBOARD_TYPE3:
+               case ID_VM_KEYBOARD_TYPE4: case ID_VM_KEYBOARD_TYPE5: case ID_VM_KEYBOARD_TYPE6: case ID_VM_KEYBOARD_TYPE7:
+                       config.keyboard_type = LOWORD(wParam) - ID_VM_KEYBOARD_TYPE0;
                        if(emu) {
-                               emu->push_play();
+                               emu->update_config();
                        }
                        break;
-               case ID_STOP_BUTTON:
+#endif
+#ifdef USE_MOUSE_TYPE
+               case ID_VM_MOUSE_TYPE0: case ID_VM_MOUSE_TYPE1: case ID_VM_MOUSE_TYPE2: case ID_VM_MOUSE_TYPE3:
+               case ID_VM_MOUSE_TYPE4: case ID_VM_MOUSE_TYPE5: case ID_VM_MOUSE_TYPE6: case ID_VM_MOUSE_TYPE7:
+                       config.mouse_type = LOWORD(wParam) - ID_VM_MOUSE_TYPE0;
                        if(emu) {
-                               emu->push_stop();
+                               emu->update_config();
                        }
                        break;
-               case ID_FAST_FORWARD:
+#endif
+#ifdef USE_JOYSTICK_TYPE
+               case ID_VM_JOYSTICK_TYPE0: case ID_VM_JOYSTICK_TYPE1: case ID_VM_JOYSTICK_TYPE2: case ID_VM_JOYSTICK_TYPE3:
+               case ID_VM_JOYSTICK_TYPE4: case ID_VM_JOYSTICK_TYPE5: case ID_VM_JOYSTICK_TYPE6: case ID_VM_JOYSTICK_TYPE7:
+                       config.joystick_type = LOWORD(wParam) - ID_VM_JOYSTICK_TYPE0;
                        if(emu) {
-                               emu->push_fast_forward();
+                               emu->update_config();
                        }
                        break;
-               case ID_FAST_REWIND:
-                       if(emu) {
-                               emu->push_fast_rewind();
-                       }
+#endif
+#ifdef USE_SOUND_TYPE
+               case ID_VM_SOUND_TYPE0: case ID_VM_SOUND_TYPE1: case ID_VM_SOUND_TYPE2: case ID_VM_SOUND_TYPE3:
+               case ID_VM_SOUND_TYPE4: case ID_VM_SOUND_TYPE5: case ID_VM_SOUND_TYPE6: case ID_VM_SOUND_TYPE7:
+                       config.sound_type = LOWORD(wParam) - ID_VM_SOUND_TYPE0;
+                       //if(emu) {
+                       //      emu->update_config();
+                       //}
                        break;
-               case ID_APSS_FORWARD:
+#endif
+#ifdef USE_FLOPPY_DISK
+               case ID_VM_SOUND_NOISE_FDD:
+                       config.sound_noise_fdd = !config.sound_noise_fdd;
                        if(emu) {
-                               emu->push_apss_forward();
+                               emu->update_config();
                        }
                        break;
-               case ID_APSS_REWIND:
+#endif
+#ifdef USE_TAPE
+               case ID_VM_SOUND_NOISE_CMT:
+                       config.sound_noise_cmt = !config.sound_noise_cmt;
                        if(emu) {
-                               emu->push_apss_rewind();
+                               emu->update_config();
                        }
                        break;
-#endif
-#ifdef USE_TAPE_BAUD
-               case ID_TAPE_BAUD_LOW:
-                       config.baud_high = false;
-                       break;
-               case ID_TAPE_BAUD_HIGH:
-                       config.baud_high = true;
+               case ID_VM_SOUND_PLAY_TAPE:
+                       config.sound_play_tape = !config.sound_play_tape;
                        break;
 #endif
-#ifdef USE_LASER_DISC
-               case ID_OPEN_LASER_DISC:
-                       if(emu) {
-                               open_laser_disc_dialog(hWnd);
-                       }
-                       break;
-               case ID_CLOSE_LASER_DISC:
+#ifdef USE_MONITOR_TYPE
+               case ID_VM_MONITOR_TYPE0: case ID_VM_MONITOR_TYPE1: case ID_VM_MONITOR_TYPE2: case ID_VM_MONITOR_TYPE3:
+               case ID_VM_MONITOR_TYPE4: case ID_VM_MONITOR_TYPE5: case ID_VM_MONITOR_TYPE6: case ID_VM_MONITOR_TYPE7:
+                       config.monitor_type = LOWORD(wParam) - ID_VM_MONITOR_TYPE0;
                        if(emu) {
-                               emu->close_laser_disc();
+#ifdef ONE_BOARD_MICRO_COMPUTER
+                               emu->reload_bitmap();
+                               emu->invalidate_screen();
+#endif
+                               emu->update_config();
                        }
                        break;
-               case ID_RECENT_LASER_DISC + 0: case ID_RECENT_LASER_DISC + 1: case ID_RECENT_LASER_DISC + 2: case ID_RECENT_LASER_DISC + 3:
-               case ID_RECENT_LASER_DISC + 4: case ID_RECENT_LASER_DISC + 5: case ID_RECENT_LASER_DISC + 6: case ID_RECENT_LASER_DISC + 7:
+#endif
+#ifdef USE_SCANLINE
+               case ID_VM_MONITOR_SCANLINE:
+                       config.scan_line = !config.scan_line;
                        if(emu) {
-                               open_recent_laser_disc(LOWORD(wParam) - ID_RECENT_LASER_DISC);
+                               emu->update_config();
                        }
                        break;
 #endif
-#ifdef USE_BINARY_FILE1
-               #define BINARY_MENU_ITEMS(drv, ID_LOAD_BINARY, ID_SAVE_BINARY, ID_RECENT_BINARY) \
-               case ID_LOAD_BINARY: \
-                       if(emu) { \
-                               open_binary_dialog(hWnd, drv, true); \
-                       } \
-                       break; \
-               case ID_SAVE_BINARY: \
-                       if(emu) { \
-                               open_binary_dialog(hWnd, drv, false); \
-                       } \
-                       break; \
-               case ID_RECENT_BINARY + 0: case ID_RECENT_BINARY + 1: case ID_RECENT_BINARY + 2: case ID_RECENT_BINARY + 3: \
-               case ID_RECENT_BINARY + 4: case ID_RECENT_BINARY + 5: case ID_RECENT_BINARY + 6: case ID_RECENT_BINARY + 7: \
-                       if(emu) { \
-                               open_recent_binary(drv, LOWORD(wParam) - ID_RECENT_BINARY); \
-                       } \
+#ifdef USE_PRINTER_TYPE
+               case ID_VM_PRINTER_TYPE0: case ID_VM_PRINTER_TYPE1: case ID_VM_PRINTER_TYPE2: case ID_VM_PRINTER_TYPE3:
+               case ID_VM_PRINTER_TYPE4: case ID_VM_PRINTER_TYPE5: case ID_VM_PRINTER_TYPE6: case ID_VM_PRINTER_TYPE7:
+                       config.printer_type = LOWORD(wParam) - ID_VM_PRINTER_TYPE0;
                        break;
-               BINARY_MENU_ITEMS(0, ID_LOAD_BINARY1, ID_SAVE_BINARY1, ID_RECENT_BINARY1)
 #endif
-#ifdef USE_BINARY_FILE2
-               BINARY_MENU_ITEMS(1, ID_LOAD_BINARY2, ID_SAVE_BINARY2, ID_RECENT_BINARY2)
-#endif
-               case ID_SCREEN_REC60: case ID_SCREEN_REC30: case ID_SCREEN_REC15:
+               case ID_HOST_REC_MOVIE_60FPS: case ID_HOST_REC_MOVIE_30FPS: case ID_HOST_REC_MOVIE_15FPS:
                        if(emu) {
                                static const int fps[3] = {60, 30, 15};
                                emu->start_record_sound();
-                               if(!emu->start_record_video(fps[LOWORD(wParam) - ID_SCREEN_REC60])) {
+                               if(!emu->start_record_video(fps[LOWORD(wParam) - ID_HOST_REC_MOVIE_60FPS])) {
                                        emu->stop_record_sound();
                                }
                        }
                        break;
-               case ID_SCREEN_STOP:
+               case ID_HOST_REC_SOUND:
+                       if(emu) {
+                               emu->start_record_sound();
+                       }
+                       break;
+               case ID_HOST_REC_STOP:
                        if(emu) {
                                emu->stop_record_video();
                                emu->stop_record_sound();
                        }
                        break;
-               case ID_SCREEN_CAPTURE:
+               case ID_HOST_CAPTURE_SCREEN:
                        if(emu) {
                                emu->capture_screen();
                        }
                        break;
-               case ID_SCREEN_WINDOW1: case ID_SCREEN_WINDOW2: case ID_SCREEN_WINDOW3: case ID_SCREEN_WINDOW4:
-               case ID_SCREEN_WINDOW5: case ID_SCREEN_WINDOW6: case ID_SCREEN_WINDOW7: case ID_SCREEN_WINDOW8:
+               case ID_HOST_USE_D3D9:
+                       config.use_d3d9 = !config.use_d3d9;
+                       if(emu) {
+                               emu->set_host_window_size(-1, -1, !now_fullscreen);
+                       }
+                       break;
+               case ID_HOST_WAIT_VSYNC:
+                       config.wait_vsync = !config.wait_vsync;
                        if(emu) {
-                               set_window(hWnd, LOWORD(wParam) - ID_SCREEN_WINDOW1);
+                               emu->set_host_window_size(-1, -1, !now_fullscreen);
                        }
                        break;
-               case ID_SCREEN_FULLSCREEN1:  case ID_SCREEN_FULLSCREEN2:  case ID_SCREEN_FULLSCREEN3:  case ID_SCREEN_FULLSCREEN4:
-               case ID_SCREEN_FULLSCREEN5:  case ID_SCREEN_FULLSCREEN6:  case ID_SCREEN_FULLSCREEN7:  case ID_SCREEN_FULLSCREEN8:
-               case ID_SCREEN_FULLSCREEN9:  case ID_SCREEN_FULLSCREEN10: case ID_SCREEN_FULLSCREEN11: case ID_SCREEN_FULLSCREEN12:
-               case ID_SCREEN_FULLSCREEN13: case ID_SCREEN_FULLSCREEN14: case ID_SCREEN_FULLSCREEN15: case ID_SCREEN_FULLSCREEN16:
-               case ID_SCREEN_FULLSCREEN17: case ID_SCREEN_FULLSCREEN18: case ID_SCREEN_FULLSCREEN19: case ID_SCREEN_FULLSCREEN20:
-               case ID_SCREEN_FULLSCREEN21: case ID_SCREEN_FULLSCREEN22: case ID_SCREEN_FULLSCREEN23: case ID_SCREEN_FULLSCREEN24:
-               case ID_SCREEN_FULLSCREEN25: case ID_SCREEN_FULLSCREEN26: case ID_SCREEN_FULLSCREEN27: case ID_SCREEN_FULLSCREEN28:
-               case ID_SCREEN_FULLSCREEN29: case ID_SCREEN_FULLSCREEN30: case ID_SCREEN_FULLSCREEN31: case ID_SCREEN_FULLSCREEN32:
+               case ID_HOST_USE_DINPUT:
+                       config.use_dinput = !config.use_dinput;
+                       break;
+               case ID_HOST_DISABLE_DWM:
+                       config.disable_dwm = !config.disable_dwm;
+                       break;
+               case ID_HOST_SHOW_STATUS_BAR:
+                       config.show_status_bar = !config.show_status_bar;
+                       if(emu) {
+                               if(!now_fullscreen) {
+                                       set_window(hWnd, prev_window_mode);
+                               }
+                       }
+                       break;
+               case ID_SCREEN_WINDOW + 0: case ID_SCREEN_WINDOW + 1: case ID_SCREEN_WINDOW + 2: case ID_SCREEN_WINDOW + 3: case ID_SCREEN_WINDOW + 4:
+               case ID_SCREEN_WINDOW + 5: case ID_SCREEN_WINDOW + 6: case ID_SCREEN_WINDOW + 7: case ID_SCREEN_WINDOW + 8: case ID_SCREEN_WINDOW + 9:
+                       if(emu) {
+                               set_window(hWnd, LOWORD(wParam) - ID_SCREEN_WINDOW);
+                       }
+                       break;
+               case ID_SCREEN_FULLSCREEN +  0: case ID_SCREEN_FULLSCREEN +  1: case ID_SCREEN_FULLSCREEN +  2: case ID_SCREEN_FULLSCREEN +  3: case ID_SCREEN_FULLSCREEN +  4:
+               case ID_SCREEN_FULLSCREEN +  5: case ID_SCREEN_FULLSCREEN +  6: case ID_SCREEN_FULLSCREEN +  7: case ID_SCREEN_FULLSCREEN +  8: case ID_SCREEN_FULLSCREEN +  9:
+               case ID_SCREEN_FULLSCREEN + 10: case ID_SCREEN_FULLSCREEN + 11: case ID_SCREEN_FULLSCREEN + 12: case ID_SCREEN_FULLSCREEN + 13: case ID_SCREEN_FULLSCREEN + 14:
+               case ID_SCREEN_FULLSCREEN + 15: case ID_SCREEN_FULLSCREEN + 16: case ID_SCREEN_FULLSCREEN + 17: case ID_SCREEN_FULLSCREEN + 18: case ID_SCREEN_FULLSCREEN + 19:
+               case ID_SCREEN_FULLSCREEN + 20: case ID_SCREEN_FULLSCREEN + 21: case ID_SCREEN_FULLSCREEN + 22: case ID_SCREEN_FULLSCREEN + 23: case ID_SCREEN_FULLSCREEN + 24:
+               case ID_SCREEN_FULLSCREEN + 25: case ID_SCREEN_FULLSCREEN + 26: case ID_SCREEN_FULLSCREEN + 27: case ID_SCREEN_FULLSCREEN + 28: case ID_SCREEN_FULLSCREEN + 29:
+               case ID_SCREEN_FULLSCREEN + 30: case ID_SCREEN_FULLSCREEN + 31: case ID_SCREEN_FULLSCREEN + 32: case ID_SCREEN_FULLSCREEN + 33: case ID_SCREEN_FULLSCREEN + 34:
+               case ID_SCREEN_FULLSCREEN + 35: case ID_SCREEN_FULLSCREEN + 36: case ID_SCREEN_FULLSCREEN + 37: case ID_SCREEN_FULLSCREEN + 38: case ID_SCREEN_FULLSCREEN + 39:
+               case ID_SCREEN_FULLSCREEN + 40: case ID_SCREEN_FULLSCREEN + 41: case ID_SCREEN_FULLSCREEN + 42: case ID_SCREEN_FULLSCREEN + 43: case ID_SCREEN_FULLSCREEN + 44:
+               case ID_SCREEN_FULLSCREEN + 45: case ID_SCREEN_FULLSCREEN + 46: case ID_SCREEN_FULLSCREEN + 47: case ID_SCREEN_FULLSCREEN + 48: case ID_SCREEN_FULLSCREEN + 49:
                        if(emu && !now_fullscreen) {
-                               set_window(hWnd, LOWORD(wParam) - ID_SCREEN_FULLSCREEN1 + MAX_WINDOW);
+                               set_window(hWnd, LOWORD(wParam) - ID_SCREEN_FULLSCREEN + MAX_WINDOW);
                        }
                        break;
-               case ID_SCREEN_WINDOW_STRETCH1: case ID_SCREEN_WINDOW_STRETCH2:
-                       config.window_stretch_type = LOWORD(wParam) - ID_SCREEN_WINDOW_STRETCH1;
+               case ID_SCREEN_WINDOW_STRETCH:
+               case ID_SCREEN_WINDOW_ASPECT:
+                       config.window_stretch_type = LOWORD(wParam) - ID_SCREEN_WINDOW_STRETCH;
                        if(emu) {
                                if(!now_fullscreen) {
                                        set_window(hWnd, prev_window_mode);
                                }
                        }
                        break;
-               case ID_SCREEN_FULLSCREEN_STRETCH1: case ID_SCREEN_FULLSCREEN_STRETCH2: case ID_SCREEN_FULLSCREEN_STRETCH3: case ID_SCREEN_FULLSCREEN_STRETCH4:
-                       config.fullscreen_stretch_type = LOWORD(wParam) - ID_SCREEN_FULLSCREEN_STRETCH1;
+               case ID_SCREEN_FULLSCREEN_DOTBYDOT:
+               case ID_SCREEN_FULLSCREEN_STRETCH:
+               case ID_SCREEN_FULLSCREEN_ASPECT:
+               case ID_SCREEN_FULLSCREEN_FILL:
+                       config.fullscreen_stretch_type = LOWORD(wParam) - ID_SCREEN_FULLSCREEN_DOTBYDOT;
                        if(emu) {
                                if(now_fullscreen) {
                                        emu->set_host_window_size(-1, -1, false);
                                }
                        }
                        break;
-               case ID_SCREEN_USE_D3D9:
-                       config.use_d3d9 = !config.use_d3d9;
+//#ifdef USE_SCREEN_ROTATE
+               case ID_SCREEN_ROTATE_0: case ID_SCREEN_ROTATE_90: case ID_SCREEN_ROTATE_180: case ID_SCREEN_ROTATE_270:
+                       config.rotate_type = LOWORD(wParam) - ID_SCREEN_ROTATE_0;
                        if(emu) {
-                               emu->set_host_window_size(-1, -1, !now_fullscreen);
+                               if(now_fullscreen) {
+                                       emu->set_host_window_size(-1, -1, false);
+                               } else {
+                                       set_window(hWnd, prev_window_mode);
+                               }
                        }
                        break;
-               case ID_SCREEN_WAIT_VSYNC:
-                       config.wait_vsync = !config.wait_vsync;
-                       if(emu) {
-                               emu->set_host_window_size(-1, -1, !now_fullscreen);
-                       }
+//#endif
+#ifdef USE_SCREEN_FILTER
+               case ID_FILTER_RGB:
+                       config.filter_type = SCREEN_FILTER_RGB;
                        break;
-               // accelerator
-               case ID_ACCEL_SCREEN:
+               case ID_FILTER_RF:
+                       config.filter_type = SCREEN_FILTER_RF;
+                       break;
+               case ID_FILTER_NONE:
+                       config.filter_type = SCREEN_FILTER_NONE;
+                       break;
+#endif
+               case ID_SOUND_FREQ0: case ID_SOUND_FREQ1: case ID_SOUND_FREQ2: case ID_SOUND_FREQ3:
+               case ID_SOUND_FREQ4: case ID_SOUND_FREQ5: case ID_SOUND_FREQ6: case ID_SOUND_FREQ7:
+                       config.sound_frequency = LOWORD(wParam) - ID_SOUND_FREQ0;
                        if(emu) {
-                               emu->suspend();
-                               set_window(hWnd, now_fullscreen ? prev_window_mode : -1);
+                               emu->update_config();
                        }
                        break;
-#ifdef USE_MOUSE
-               case ID_ACCEL_MOUSE:
+               case ID_SOUND_LATE0: case ID_SOUND_LATE1: case ID_SOUND_LATE2: case ID_SOUND_LATE3: case ID_SOUND_LATE4:
+                       config.sound_latency = LOWORD(wParam) - ID_SOUND_LATE0;
                        if(emu) {
-                               emu->toggle_mouse();
+                               emu->update_config();
                        }
                        break;
-#endif
-#ifdef USE_MONITOR_TYPE
-               case ID_SCREEN_MONITOR_TYPE0: case ID_SCREEN_MONITOR_TYPE1: case ID_SCREEN_MONITOR_TYPE2: case ID_SCREEN_MONITOR_TYPE3:
-               case ID_SCREEN_MONITOR_TYPE4: case ID_SCREEN_MONITOR_TYPE5: case ID_SCREEN_MONITOR_TYPE6: case ID_SCREEN_MONITOR_TYPE7:
-                       config.monitor_type = LOWORD(wParam) - ID_SCREEN_MONITOR_TYPE0;
+               case ID_SOUND_STRICT_RENDER: case ID_SOUND_LIGHT_RENDER:
+                       config.sound_strict_rendering = (LOWORD(wParam) == ID_SOUND_STRICT_RENDER);
                        if(emu) {
                                emu->update_config();
                        }
                        break;
-#endif
-#ifdef USE_CRT_FILTER
-               case ID_SCREEN_CRT_FILTER:
-                       config.crt_filter = !config.crt_filter;
+#ifdef USE_SOUND_VOLUME
+               case ID_SOUND_VOLUME:
+                       DialogBoxParam((HINSTANCE)GetModuleHandle(0), MAKEINTRESOURCE(IDD_VOLUME), hWnd, VolumeWndProc, 0);
                        break;
 #endif
-#ifdef USE_SCANLINE
-               case ID_SCREEN_SCANLINE:
-                       config.scan_line = !config.scan_line;
-                       if(emu) {
-                               emu->update_config();
+#ifdef USE_JOYSTICK
+               case ID_INPUT_JOYSTICK0: case ID_INPUT_JOYSTICK1: case ID_INPUT_JOYSTICK2: case ID_INPUT_JOYSTICK3:
+               case ID_INPUT_JOYSTICK4: case ID_INPUT_JOYSTICK5: case ID_INPUT_JOYSTICK6: case ID_INPUT_JOYSTICK7:
+                       {
+                               LONG index = LOWORD(wParam) - ID_INPUT_JOYSTICK0;
+                               DialogBoxParam((HINSTANCE)GetModuleHandle(0), MAKEINTRESOURCE(IDD_JOYSTICK), hWnd, JoyWndProc, (LPARAM)&index);
                        }
                        break;
 #endif
-#ifdef USE_SCREEN_ROTATE
-               case ID_SCREEN_ROTATE_0: case ID_SCREEN_ROTATE_90: case ID_SCREEN_ROTATE_180: case ID_SCREEN_ROTATE_270:
-                       config.rotate_type = LOWORD(wParam) - ID_SCREEN_ROTATE_0;
+#ifdef USE_VIDEO_CAPTURE
+               case ID_CAPTURE_FILTER:
                        if(emu) {
-                               if(now_fullscreen) {
-                                       emu->set_host_window_size(-1, -1, false);
-                               } else {
-                                       set_window(hWnd, prev_window_mode);
-                               }
+                               emu->show_capture_dev_filter();
                        }
                        break;
-#endif
-               case ID_SOUND_REC:
+               case ID_CAPTURE_PIN:
                        if(emu) {
-                               emu->start_record_sound();
+                               emu->show_capture_dev_pin();
                        }
                        break;
-               case ID_SOUND_STOP:
+               case ID_CAPTURE_SOURCE:
                        if(emu) {
-                               emu->stop_record_sound();
+                               emu->show_capture_dev_source();
                        }
                        break;
-               case ID_SOUND_FREQ0: case ID_SOUND_FREQ1: case ID_SOUND_FREQ2: case ID_SOUND_FREQ3:
-               case ID_SOUND_FREQ4: case ID_SOUND_FREQ5: case ID_SOUND_FREQ6: case ID_SOUND_FREQ7:
-                       config.sound_frequency = LOWORD(wParam) - ID_SOUND_FREQ0;
+               case ID_CAPTURE_CLOSE:
                        if(emu) {
-                               emu->update_config();
+                               emu->close_capture_dev();
                        }
                        break;
-               case ID_SOUND_LATE0: case ID_SOUND_LATE1: case ID_SOUND_LATE2: case ID_SOUND_LATE3: case ID_SOUND_LATE4:
-                       config.sound_latency = LOWORD(wParam) - ID_SOUND_LATE0;
+               case ID_CAPTURE_DEVICE + 0: case ID_CAPTURE_DEVICE + 1: case ID_CAPTURE_DEVICE + 2: case ID_CAPTURE_DEVICE + 3:
+               case ID_CAPTURE_DEVICE + 4: case ID_CAPTURE_DEVICE + 5: case ID_CAPTURE_DEVICE + 6: case ID_CAPTURE_DEVICE + 7:
                        if(emu) {
-                               emu->update_config();
+                               emu->open_capture_dev(LOWORD(wParam) - ID_CAPTURE_DEVICE, false);
                        }
                        break;
-#ifdef USE_SOUND_DEVICE_TYPE
-               case ID_SOUND_DEVICE_TYPE0: case ID_SOUND_DEVICE_TYPE1: case ID_SOUND_DEVICE_TYPE2: case ID_SOUND_DEVICE_TYPE3:
-               case ID_SOUND_DEVICE_TYPE4: case ID_SOUND_DEVICE_TYPE5: case ID_SOUND_DEVICE_TYPE6: case ID_SOUND_DEVICE_TYPE7:
-                       config.sound_device_type = LOWORD(wParam) - ID_SOUND_DEVICE_TYPE0;
-                       //if(emu) {
-                       //      emu->update_config();
-                       //}
+#endif
+#ifdef USE_CART
+       #if USE_CART >= 1
+               #define CART_MENU_ITEMS(drv, ID_OPEN_CART, ID_CLOSE_CART, ID_RECENT_CART) \
+               case ID_OPEN_CART: \
+                       if(emu) { \
+                               open_cart_dialog(hWnd, drv); \
+                       } \
+                       break; \
+               case ID_CLOSE_CART: \
+                       if(emu) { \
+                               emu->close_cart(drv); \
+                       } \
+                       break; \
+               case ID_RECENT_CART + 0: case ID_RECENT_CART + 1: case ID_RECENT_CART + 2: case ID_RECENT_CART + 3: \
+               case ID_RECENT_CART + 4: case ID_RECENT_CART + 5: case ID_RECENT_CART + 6: case ID_RECENT_CART + 7: \
+                       if(emu) { \
+                               open_recent_cart(drv, LOWORD(wParam) - ID_RECENT_CART); \
+                       } \
+                       break;
+               CART_MENU_ITEMS(0, ID_OPEN_CART1, ID_CLOSE_CART1, ID_RECENT_CART1)
+       #endif
+       #if USE_CART >= 2
+               CART_MENU_ITEMS(1, ID_OPEN_CART2, ID_CLOSE_CART2, ID_RECENT_CART2)
+       #endif
+#endif
+#ifdef USE_FLOPPY_DISK
+       #if USE_FLOPPY_DISK >= 1
+               #define FD_MENU_ITEMS(drv, ID_OPEN_FD, ID_CLOSE_FD, ID_WRITE_PROTECT_FD, ID_CORRECT_TIMING_FD, ID_IGNORE_CRC_FD, ID_RECENT_FD, ID_SELECT_D88_BANK, ID_EJECT_D88_BANK) \
+               case ID_OPEN_FD: \
+                       if(emu) { \
+                               open_floppy_disk_dialog(hWnd, drv); \
+                       } \
+                       break; \
+               case ID_CLOSE_FD: \
+                       if(emu) { \
+                               close_floppy_disk(drv); \
+                       } \
+                       break; \
+               case ID_WRITE_PROTECT_FD: \
+                       if(emu) { \
+                               emu->is_floppy_disk_protected(drv, !emu->is_floppy_disk_protected(drv)); \
+                       } \
+                       break; \
+               case ID_CORRECT_TIMING_FD: \
+                       config.correct_disk_timing[drv] = !config.correct_disk_timing[drv]; \
+                       break; \
+               case ID_IGNORE_CRC_FD: \
+                       config.ignore_disk_crc[drv] = !config.ignore_disk_crc[drv]; \
+                       break; \
+               case ID_RECENT_FD + 0: case ID_RECENT_FD + 1: case ID_RECENT_FD + 2: case ID_RECENT_FD + 3: \
+               case ID_RECENT_FD + 4: case ID_RECENT_FD + 5: case ID_RECENT_FD + 6: case ID_RECENT_FD + 7: \
+                       if(emu) { \
+                               open_recent_floppy_disk(drv, LOWORD(wParam) - ID_RECENT_FD); \
+                       } \
+                       break; \
+               case ID_SELECT_D88_BANK +  0: case ID_SELECT_D88_BANK +  1: case ID_SELECT_D88_BANK +  2: case ID_SELECT_D88_BANK +  3: \
+               case ID_SELECT_D88_BANK +  4: case ID_SELECT_D88_BANK +  5: case ID_SELECT_D88_BANK +  6: case ID_SELECT_D88_BANK +  7: \
+               case ID_SELECT_D88_BANK +  8: case ID_SELECT_D88_BANK +  9: case ID_SELECT_D88_BANK + 10: case ID_SELECT_D88_BANK + 11: \
+               case ID_SELECT_D88_BANK + 12: case ID_SELECT_D88_BANK + 13: case ID_SELECT_D88_BANK + 14: case ID_SELECT_D88_BANK + 15: \
+               case ID_SELECT_D88_BANK + 16: case ID_SELECT_D88_BANK + 17: case ID_SELECT_D88_BANK + 18: case ID_SELECT_D88_BANK + 19: \
+               case ID_SELECT_D88_BANK + 20: case ID_SELECT_D88_BANK + 21: case ID_SELECT_D88_BANK + 22: case ID_SELECT_D88_BANK + 23: \
+               case ID_SELECT_D88_BANK + 24: case ID_SELECT_D88_BANK + 25: case ID_SELECT_D88_BANK + 26: case ID_SELECT_D88_BANK + 27: \
+               case ID_SELECT_D88_BANK + 28: case ID_SELECT_D88_BANK + 29: case ID_SELECT_D88_BANK + 30: case ID_SELECT_D88_BANK + 31: \
+               case ID_SELECT_D88_BANK + 32: case ID_SELECT_D88_BANK + 33: case ID_SELECT_D88_BANK + 34: case ID_SELECT_D88_BANK + 35: \
+               case ID_SELECT_D88_BANK + 36: case ID_SELECT_D88_BANK + 37: case ID_SELECT_D88_BANK + 38: case ID_SELECT_D88_BANK + 39: \
+               case ID_SELECT_D88_BANK + 40: case ID_SELECT_D88_BANK + 41: case ID_SELECT_D88_BANK + 42: case ID_SELECT_D88_BANK + 43: \
+               case ID_SELECT_D88_BANK + 44: case ID_SELECT_D88_BANK + 45: case ID_SELECT_D88_BANK + 46: case ID_SELECT_D88_BANK + 47: \
+               case ID_SELECT_D88_BANK + 48: case ID_SELECT_D88_BANK + 49: case ID_SELECT_D88_BANK + 50: case ID_SELECT_D88_BANK + 51: \
+               case ID_SELECT_D88_BANK + 52: case ID_SELECT_D88_BANK + 53: case ID_SELECT_D88_BANK + 54: case ID_SELECT_D88_BANK + 55: \
+               case ID_SELECT_D88_BANK + 56: case ID_SELECT_D88_BANK + 57: case ID_SELECT_D88_BANK + 58: case ID_SELECT_D88_BANK + 59: \
+               case ID_SELECT_D88_BANK + 60: case ID_SELECT_D88_BANK + 61: case ID_SELECT_D88_BANK + 62: case ID_SELECT_D88_BANK + 63: \
+                       if(emu) { \
+                               select_d88_bank(drv, LOWORD(wParam) - ID_SELECT_D88_BANK) ; \
+                       } \
+                       break; \
+               case ID_EJECT_D88_BANK: \
+                       if(emu) { \
+                               select_d88_bank(drv, -1) ; \
+                       } \
+                       break;
+               FD_MENU_ITEMS(0, ID_OPEN_FD1, ID_CLOSE_FD1, ID_WRITE_PROTECT_FD1, ID_CORRECT_TIMING_FD1, ID_IGNORE_CRC_FD1, ID_RECENT_FD1, ID_SELECT_D88_BANK1, ID_EJECT_D88_BANK1)
+       #endif
+       #if USE_FLOPPY_DISK >= 2
+               FD_MENU_ITEMS(1, ID_OPEN_FD2, ID_CLOSE_FD2, ID_WRITE_PROTECT_FD2, ID_CORRECT_TIMING_FD2, ID_IGNORE_CRC_FD2, ID_RECENT_FD2, ID_SELECT_D88_BANK2, ID_EJECT_D88_BANK2)
+       #endif
+       #if USE_FLOPPY_DISK >= 3
+               FD_MENU_ITEMS(2, ID_OPEN_FD3, ID_CLOSE_FD3, ID_WRITE_PROTECT_FD3, ID_CORRECT_TIMING_FD3, ID_IGNORE_CRC_FD3, ID_RECENT_FD3, ID_SELECT_D88_BANK3, ID_EJECT_D88_BANK3)
+       #endif
+       #if USE_FLOPPY_DISK >= 4
+               FD_MENU_ITEMS(3, ID_OPEN_FD4, ID_CLOSE_FD4, ID_WRITE_PROTECT_FD4, ID_CORRECT_TIMING_FD4, ID_IGNORE_CRC_FD4, ID_RECENT_FD4, ID_SELECT_D88_BANK4, ID_EJECT_D88_BANK4)
+       #endif
+       #if USE_FLOPPY_DISK >= 5
+               FD_MENU_ITEMS(4, ID_OPEN_FD5, ID_CLOSE_FD5, ID_WRITE_PROTECT_FD5, ID_CORRECT_TIMING_FD5, ID_IGNORE_CRC_FD5, ID_RECENT_FD5, ID_SELECT_D88_BANK5, ID_EJECT_D88_BANK5)
+       #endif
+       #if USE_FLOPPY_DISK >= 6
+               FD_MENU_ITEMS(5, ID_OPEN_FD6, ID_CLOSE_FD6, ID_WRITE_PROTECT_FD6, ID_CORRECT_TIMING_FD6, ID_IGNORE_CRC_FD6, ID_RECENT_FD6, ID_SELECT_D88_BANK6, ID_EJECT_D88_BANK6)
+       #endif
+       #if USE_FLOPPY_DISK >= 7
+               FD_MENU_ITEMS(6, ID_OPEN_FD7, ID_CLOSE_FD7, ID_WRITE_PROTECT_FD7, ID_CORRECT_TIMING_FD7, ID_IGNORE_CRC_FD7, ID_RECENT_FD7, ID_SELECT_D88_BANK7, ID_EJECT_D88_BANK7)
+       #endif
+       #if USE_FLOPPY_DISK >= 8
+               FD_MENU_ITEMS(7, ID_OPEN_FD8, ID_CLOSE_FD8, ID_WRITE_PROTECT_FD8, ID_CORRECT_TIMING_FD8, ID_IGNORE_CRC_FD8, ID_RECENT_FD8, ID_SELECT_D88_BANK8, ID_EJECT_D88_BANK8)
+       #endif
+#endif
+#ifdef USE_QUICK_DISK
+       #if USE_QUICK_DISK >= 1
+               #define QD_MENU_ITEMS(drv, ID_OPEN_QD, ID_CLOSE_QD, ID_RECENT_QD) \
+               case ID_OPEN_QD: \
+                       if(emu) { \
+                               open_quick_disk_dialog(hWnd, drv); \
+                       } \
+                       break; \
+               case ID_CLOSE_QD: \
+                       if(emu) { \
+                               emu->close_quick_disk(drv); \
+                       } \
+                       break; \
+               case ID_RECENT_QD + 0: case ID_RECENT_QD + 1: case ID_RECENT_QD + 2: case ID_RECENT_QD + 3: \
+               case ID_RECENT_QD + 4: case ID_RECENT_QD + 5: case ID_RECENT_QD + 6: case ID_RECENT_QD + 7: \
+                       if(emu) { \
+                               open_recent_quick_disk(drv, LOWORD(wParam) - ID_RECENT_QD); \
+                       } \
+                       break;
+               QD_MENU_ITEMS(0, ID_OPEN_QD1, ID_CLOSE_QD1, ID_RECENT_QD1)
+       #endif
+       #if USE_QUICK_DISK >= 2
+               QD_MENU_ITEMS(1, ID_OPEN_QD2, ID_CLOSE_QD2, ID_RECENT_QD2)
+       #endif
+#endif
+#ifdef USE_HARD_DISK
+       #if USE_HARD_DISK >= 1
+               #define HD_MENU_ITEMS(drv, ID_OPEN_HD, ID_CLOSE_HD, ID_RECENT_HD) \
+               case ID_OPEN_HD: \
+                       if(emu) { \
+                               open_hard_disk_dialog(hWnd, drv); \
+                       } \
+                       break; \
+               case ID_CLOSE_HD: \
+                       if(emu) { \
+                               emu->close_hard_disk(drv); \
+                       } \
+                       break; \
+               case ID_RECENT_HD + 0: case ID_RECENT_HD + 1: case ID_RECENT_HD + 2: case ID_RECENT_HD + 3: \
+               case ID_RECENT_HD + 4: case ID_RECENT_HD + 5: case ID_RECENT_HD + 6: case ID_RECENT_HD + 7: \
+                       if(emu) { \
+                               open_recent_hard_disk(drv, LOWORD(wParam) - ID_RECENT_HD); \
+                       } \
+                       break;
+               HD_MENU_ITEMS(0, ID_OPEN_HD1, ID_CLOSE_HD1, ID_RECENT_HD1)
+       #endif
+       #if USE_HARD_DISK >= 2
+               HD_MENU_ITEMS(1, ID_OPEN_HD2, ID_CLOSE_HD2, ID_RECENT_HD2)
+       #endif
+       #if USE_HARD_DISK >= 3
+               HD_MENU_ITEMS(2, ID_OPEN_HD3, ID_CLOSE_HD3, ID_RECENT_HD3)
+       #endif
+       #if USE_HARD_DISK >= 4
+               HD_MENU_ITEMS(3, ID_OPEN_HD4, ID_CLOSE_HD4, ID_RECENT_HD4)
+       #endif
+       #if USE_HARD_DISK >= 5
+               HD_MENU_ITEMS(4, ID_OPEN_HD5, ID_CLOSE_HD5, ID_RECENT_HD5)
+       #endif
+       #if USE_HARD_DISK >= 6
+               HD_MENU_ITEMS(5, ID_OPEN_HD6, ID_CLOSE_HD6, ID_RECENT_HD6)
+       #endif
+       #if USE_HARD_DISK >= 7
+               HD_MENU_ITEMS(6, ID_OPEN_HD7, ID_CLOSE_HD7, ID_RECENT_HD7)
+       #endif
+       #if USE_HARD_DISK >= 8
+               HD_MENU_ITEMS(7, ID_OPEN_HD8, ID_CLOSE_HD8, ID_RECENT_HD8)
+       #endif
+#endif
+#ifdef USE_TAPE
+       #if USE_TAPE >= 1
+               #define TAPE_MENU_ITEMS(drv, ID_PLAY_TAPE, ID_REC_TAPE, ID_CLOSE_TAPE, ID_PLAY_BUTTON, ID_STOP_BUTTON, ID_FAST_FORWARD, ID_FAST_REWIND, ID_APSS_FORWARD, ID_APSS_REWIND, ID_USE_WAVE_SHAPER, ID_DIRECT_LOAD_MZT, ID_TAPE_BAUD_LOW, ID_TAPE_BAUD_HIGH, ID_RECENT_TAPE) \
+               case ID_PLAY_TAPE: \
+                       if(emu) { \
+                               open_tape_dialog(hWnd, drv, true); \
+                       } \
+                       break; \
+               case ID_REC_TAPE: \
+                       if(emu) { \
+                               open_tape_dialog(hWnd, drv, false); \
+                       } \
+                       break; \
+               case ID_CLOSE_TAPE: \
+                       if(emu) { \
+                               emu->close_tape(drv); \
+                       } \
+                       break; \
+               case ID_PLAY_BUTTON: \
+                       if(emu) { \
+                               emu->push_play(drv); \
+                       } \
+                       break; \
+               case ID_STOP_BUTTON: \
+                       if(emu) { \
+                               emu->push_stop(drv); \
+                       } \
+                       break; \
+               case ID_FAST_FORWARD: \
+                       if(emu) { \
+                               emu->push_fast_forward(drv); \
+                       } \
+                       break; \
+               case ID_FAST_REWIND: \
+                       if(emu) { \
+                               emu->push_fast_rewind(drv); \
+                       } \
+                       break; \
+               case ID_APSS_FORWARD: \
+                       if(emu) { \
+                               emu->push_apss_forward(drv); \
+                       } \
+                       break; \
+               case ID_APSS_REWIND: \
+                       if(emu) { \
+                               emu->push_apss_rewind(drv); \
+                       } \
+                       break; \
+               case ID_USE_WAVE_SHAPER: \
+                       config.wave_shaper[drv] = !config.wave_shaper[drv]; \
+                       break; \
+               case ID_DIRECT_LOAD_MZT: \
+                       config.direct_load_mzt[drv] = !config.direct_load_mzt[drv]; \
+                       break; \
+               case ID_TAPE_BAUD_LOW: \
+                       config.baud_high[drv] = false; \
+                       break; \
+               case ID_TAPE_BAUD_HIGH: \
+                       config.baud_high[drv] = true; \
+                       break; \
+               case ID_RECENT_TAPE + 0: case ID_RECENT_TAPE + 1: case ID_RECENT_TAPE + 2: case ID_RECENT_TAPE + 3: \
+               case ID_RECENT_TAPE + 4: case ID_RECENT_TAPE + 5: case ID_RECENT_TAPE + 6: case ID_RECENT_TAPE + 7: \
+                       if(emu) { \
+                               open_recent_tape(drv, LOWORD(wParam) - ID_RECENT_TAPE); \
+                       } \
+                       break;
+               TAPE_MENU_ITEMS(0, ID_PLAY_TAPE1, ID_REC_TAPE1, ID_CLOSE_TAPE1, ID_PLAY_BUTTON1, ID_STOP_BUTTON1, ID_FAST_FORWARD1, ID_FAST_REWIND1, ID_APSS_FORWARD1, ID_APSS_REWIND1, ID_USE_WAVE_SHAPER1, ID_DIRECT_LOAD_MZT1, ID_TAPE_BAUD_LOW1, ID_TAPE_BAUD_HIGH1, ID_RECENT_TAPE1)
+       #endif
+       #if USE_TAPE >= 2
+               TAPE_MENU_ITEMS(1, ID_PLAY_TAPE2, ID_REC_TAPE2, ID_CLOSE_TAPE2, ID_PLAY_BUTTON2, ID_STOP_BUTTON2, ID_FAST_FORWARD2, ID_FAST_REWIND2, ID_APSS_FORWARD2, ID_APSS_REWIND2, ID_USE_WAVE_SHAPER2, ID_DIRECT_LOAD_MZT2, ID_TAPE_BAUD_LOW2, ID_TAPE_BAUD_HIGH2, ID_RECENT_TAPE2)
+       #endif
+#endif
+#ifdef USE_COMPACT_DISC
+       #if USE_COMPACT_DISC >= 1
+               #define COMPACT_DISC_MENU_ITEMS(drv, ID_OPEN_COMPACT_DISC, ID_CLOSE_COMPACT_DISC, ID_RECENT_COMPACT_DISC) \
+               case ID_OPEN_COMPACT_DISC: \
+                       if(emu) { \
+                               open_compact_disc_dialog(hWnd, drv); \
+                       } \
+                       break; \
+               case ID_CLOSE_COMPACT_DISC: \
+                       if(emu) { \
+                               emu->close_compact_disc(drv); \
+                       } \
+                       break; \
+               case ID_RECENT_COMPACT_DISC + 0: case ID_RECENT_COMPACT_DISC + 1: case ID_RECENT_COMPACT_DISC + 2: case ID_RECENT_COMPACT_DISC + 3: \
+               case ID_RECENT_COMPACT_DISC + 4: case ID_RECENT_COMPACT_DISC + 5: case ID_RECENT_COMPACT_DISC + 6: case ID_RECENT_COMPACT_DISC + 7: \
+                       if(emu) { \
+                               open_recent_compact_disc(drv, LOWORD(wParam) - ID_RECENT_COMPACT_DISC); \
+                       } \
+                       break;
+               COMPACT_DISC_MENU_ITEMS(0, ID_OPEN_COMPACT_DISC1, ID_CLOSE_COMPACT_DISC1, ID_RECENT_COMPACT_DISC1)
+       #endif
+       #if USE_COMPACT_DISC >= 2
+               COMPACT_DISC_MENU_ITEMS(1, ID_OPEN_COMPACT_DISC2, ID_CLOSE_COMPACT_DISC2, ID_RECENT_COMPACT_DISC2)
+       #endif
+#endif
+#ifdef USE_LASER_DISC
+       #if USE_LASER_DISC >= 1
+               #define LASER_DISC_MENU_ITEMS(drv, ID_OPEN_LASER_DISC, ID_CLOSE_LASER_DISC, ID_RECENT_LASER_DISC) \
+               case ID_OPEN_LASER_DISC: \
+                       if(emu) { \
+                               open_laser_disc_dialog(hWnd, drv); \
+                       } \
+                       break; \
+               case ID_CLOSE_LASER_DISC: \
+                       if(emu) { \
+                               emu->close_laser_disc(drv); \
+                       } \
+                       break; \
+               case ID_RECENT_LASER_DISC + 0: case ID_RECENT_LASER_DISC + 1: case ID_RECENT_LASER_DISC + 2: case ID_RECENT_LASER_DISC + 3: \
+               case ID_RECENT_LASER_DISC + 4: case ID_RECENT_LASER_DISC + 5: case ID_RECENT_LASER_DISC + 6: case ID_RECENT_LASER_DISC + 7: \
+                       if(emu) { \
+                               open_recent_laser_disc(drv, LOWORD(wParam) - ID_RECENT_LASER_DISC); \
+                       } \
+                       break;
+               LASER_DISC_MENU_ITEMS(0, ID_OPEN_LASER_DISC1, ID_CLOSE_LASER_DISC1, ID_RECENT_LASER_DISC1)
+       #endif
+       #if USE_LASER_DISC >= 2
+               LASER_DISC_MENU_ITEMS(1, ID_OPEN_LASER_DISC2, ID_CLOSE_LASER_DISC2, ID_RECENT_LASER_DISC2)
+       #endif
+#endif
+#ifdef USE_BINARY_FILE
+       #if USE_BINARY_FILE >= 1
+               #define BINARY_MENU_ITEMS(drv, ID_LOAD_BINARY, ID_SAVE_BINARY, ID_RECENT_BINARY) \
+               case ID_LOAD_BINARY: \
+                       if(emu) { \
+                               open_binary_dialog(hWnd, drv, true); \
+                       } \
+                       break; \
+               case ID_SAVE_BINARY: \
+                       if(emu) { \
+                               open_binary_dialog(hWnd, drv, false); \
+                       } \
+                       break; \
+               case ID_RECENT_BINARY + 0: case ID_RECENT_BINARY + 1: case ID_RECENT_BINARY + 2: case ID_RECENT_BINARY + 3: \
+               case ID_RECENT_BINARY + 4: case ID_RECENT_BINARY + 5: case ID_RECENT_BINARY + 6: case ID_RECENT_BINARY + 7: \
+                       if(emu) { \
+                               open_recent_binary(drv, LOWORD(wParam) - ID_RECENT_BINARY); \
+                       } \
                        break;
+               BINARY_MENU_ITEMS(0, ID_LOAD_BINARY1, ID_SAVE_BINARY1, ID_RECENT_BINARY1)
+       #endif
+       #if USE_BINARY_FILE >= 2
+               BINARY_MENU_ITEMS(1, ID_LOAD_BINARY2, ID_SAVE_BINARY2, ID_RECENT_BINARY2)
+       #endif
 #endif
-#ifdef USE_SOUND_VOLUME
-               case ID_SOUND_VOLUME:
-                       DialogBoxParam((HINSTANCE)GetModuleHandle(0), MAKEINTRESOURCE(IDD_VOLUME), hWnd, VolumeWndProc, 0);
+#ifdef USE_BUBBLE
+       #if USE_BUBBLE >= 1
+               #define BUBBLE_CASETTE_MENU_ITEMS(drv, ID_OPEN_BUBBLE, ID_CLOSE_BUBBLE, ID_RECENT_BUBBLE) \
+               case ID_OPEN_BUBBLE: \
+                       if(emu) { \
+                               open_bubble_casette_dialog(hWnd, drv); \
+                       } \
+                       break; \
+               case ID_CLOSE_BUBBLE: \
+                       if(emu) { \
+                               emu->close_bubble_casette(drv); \
+                       } \
+                       break; \
+               case ID_RECENT_BUBBLE + 0: case ID_RECENT_BUBBLE + 1: case ID_RECENT_BUBBLE + 2: case ID_RECENT_BUBBLE + 3: \
+               case ID_RECENT_BUBBLE + 4: case ID_RECENT_BUBBLE + 5: case ID_RECENT_BUBBLE + 6: case ID_RECENT_BUBBLE + 7: \
+                       if(emu) { \
+                               open_recent_bubble_casette(drv, LOWORD(wParam) - ID_RECENT_BUBBLE); \
+                       } \
                        break;
+               BUBBLE_CASETTE_MENU_ITEMS(0, ID_OPEN_BUBBLE1, ID_CLOSE_BUBBLE1, ID_RECENT_BUBBLE1)
+       #endif
+       #if USE_BUBBLE >= 2
+               BUBBLE_CASETTE_MENU_ITEMS(1, ID_OPEN_BUBBLE2, ID_CLOSE_BUBBLE2, ID_RECENT_BUBBLE2)
+       #endif
 #endif
-#ifdef USE_VIDEO_CAPTURE
-               case ID_CAPTURE_FILTER:
-                       if(emu) {
-                               emu->show_capture_dev_filter();
-                       }
-                       break;
-               case ID_CAPTURE_PIN:
-                       if(emu) {
-                               emu->show_capture_dev_pin();
-                       }
-                       break;
-               case ID_CAPTURE_SOURCE:
-                       if(emu) {
-                               emu->show_capture_dev_source();
-                       }
-                       break;
-               case ID_CAPTURE_CLOSE:
+               case ID_ACCEL_SCREEN:
                        if(emu) {
-                               emu->close_capture_dev();
+                               emu->suspend();
+                               set_window(hWnd, now_fullscreen ? prev_window_mode : -1);
                        }
                        break;
-               case ID_CAPTURE_DEVICE1: case ID_CAPTURE_DEVICE2: case ID_CAPTURE_DEVICE3: case ID_CAPTURE_DEVICE4:
-               case ID_CAPTURE_DEVICE5: case ID_CAPTURE_DEVICE6: case ID_CAPTURE_DEVICE7: case ID_CAPTURE_DEVICE8:
+#ifdef USE_MOUSE
+               case ID_ACCEL_MOUSE:
                        if(emu) {
-                               emu->open_capture_dev(LOWORD(wParam) - ID_CAPTURE_DEVICE1, false);
+                               emu->toggle_mouse();
                        }
                        break;
 #endif
-               case ID_INPUT_USE_DINPUT:
-                       config.use_direct_input = !config.use_direct_input;
-                       break;
-               case ID_INPUT_DISABLE_DWM:
-                       config.disable_dwm = !config.disable_dwm;
+               case ID_ACCEL_SPEED:
+                       config.full_speed = !config.full_speed;
                        break;
-#ifdef USE_JOYSTICK
-               case ID_INPUT_JOYSTICK0: case ID_INPUT_JOYSTICK1: case ID_INPUT_JOYSTICK2: case ID_INPUT_JOYSTICK3:
-                       {
-                               LONG index = LOWORD(wParam) - ID_INPUT_JOYSTICK0;
-                               DialogBoxParam((HINSTANCE)GetModuleHandle(0), MAKEINTRESOURCE(IDD_JOYSTICK), hWnd, JoyWndProc, (LPARAM)&index);
+#ifdef USE_AUTO_KEY
+               case ID_ACCEL_ROMAJI:
+                       if(emu) {
+                               if(!config.romaji_to_kana) {
+                                       emu->set_auto_key_char(1); // start
+                                       config.romaji_to_kana = true;
+                               } else {
+                                       emu->set_auto_key_char(0); // end
+                                       config.romaji_to_kana = false;
+                               }
                        }
                        break;
 #endif
@@ -1084,44 +1405,13 @@ LRESULT CALLBACK WndProc(HWND hWnd, UINT iMsg, WPARAM wParam, LPARAM lParam)
 // menu
 // ----------------------------------------------------------------------------
 
-#ifdef MENU_POS_CONTROL
 void update_control_menu(HMENU hMenu)
 {
-#ifdef USE_BOOT_MODE
-       if(config.boot_mode >= 0 && config.boot_mode < USE_BOOT_MODE) {
-               CheckMenuRadioItem(hMenu, ID_BOOT_MODE0, ID_BOOT_MODE0 + USE_BOOT_MODE - 1, ID_BOOT_MODE0 + config.boot_mode, MF_BYCOMMAND);
-       }
-#endif
-#ifdef USE_CPU_TYPE
-       if(config.cpu_type >= 0 && config.cpu_type < USE_CPU_TYPE) {
-               CheckMenuRadioItem(hMenu, ID_CPU_TYPE0, ID_CPU_TYPE0 + USE_CPU_TYPE - 1, ID_CPU_TYPE0 + config.cpu_type, MF_BYCOMMAND);
-       }
-#endif
        if(config.cpu_power >= 0 && config.cpu_power < 5) {
                CheckMenuRadioItem(hMenu, ID_CPU_POWER0, ID_CPU_POWER4, ID_CPU_POWER0 + config.cpu_power, MF_BYCOMMAND);
        }
-#ifdef USE_DIPSWITCH
-       for(int i = 0; i < 32; i++) {
-               CheckMenuItem(hMenu, ID_DIPSWITCH0 + i, (config.dipswitch & (1 << i)) ? MF_CHECKED : MF_UNCHECKED);
-       }
-#endif
-#ifdef USE_PRINTER_TYPE
-       if(config.printer_device_type >= 0 && config.printer_device_type < USE_PRINTER_TYPE) {
-               CheckMenuRadioItem(hMenu, ID_PRINTER_TYPE0, ID_PRINTER_TYPE0 + USE_PRINTER_TYPE - 1, ID_PRINTER_TYPE0 + config.printer_device_type, MF_BYCOMMAND);
-       }
-#endif
-#ifdef USE_DEVICE_TYPE
-       if(config.device_type >= 0 && config.device_type < USE_DEVICE_TYPE) {
-               CheckMenuRadioItem(hMenu, ID_DEVICE_TYPE0, ID_DEVICE_TYPE0 + USE_DEVICE_TYPE - 1, ID_DEVICE_TYPE0 + config.device_type, MF_BYCOMMAND);
-       }
-#endif
-#ifdef USE_DRIVE_TYPE
-       if(config.drive_type >= 0 && config.drive_type < USE_DRIVE_TYPE) {
-               CheckMenuRadioItem(hMenu, ID_DRIVE_TYPE0, ID_DRIVE_TYPE0 + USE_DRIVE_TYPE - 1, ID_DRIVE_TYPE0 + config.drive_type, MF_BYCOMMAND);
-       }
-#endif
+       CheckMenuItem(hMenu, ID_FULL_SPEED, config.full_speed ? MF_CHECKED : MF_UNCHECKED);
 #ifdef USE_AUTO_KEY
-       // auto key
        bool now_paste = true, now_stop = true;
        if(emu) {
                now_paste = emu->is_auto_key_running();
@@ -1129,19 +1419,91 @@ void update_control_menu(HMENU hMenu)
        }
        EnableMenuItem(hMenu, ID_AUTOKEY_START, now_paste ? MF_GRAYED : MF_ENABLED);
        EnableMenuItem(hMenu, ID_AUTOKEY_STOP, now_stop ? MF_GRAYED : MF_ENABLED);
+       CheckMenuItem(hMenu, ID_ROMAJI_TO_KANA, config.romaji_to_kana ? MF_CHECKED : MF_UNCHECKED);
 #endif
 #ifdef USE_DEBUGGER
-       // debugger
-       EnableMenuItem(hMenu, ID_OPEN_DEBUGGER0, emu && !emu->now_debugging && emu->is_debugger_enabled(0) ? MF_ENABLED : MF_GRAYED);
-       EnableMenuItem(hMenu, ID_OPEN_DEBUGGER1, emu && !emu->now_debugging && emu->is_debugger_enabled(1) ? MF_ENABLED : MF_GRAYED);
-       EnableMenuItem(hMenu, ID_OPEN_DEBUGGER2, emu && !emu->now_debugging && emu->is_debugger_enabled(2) ? MF_ENABLED : MF_GRAYED);
-       EnableMenuItem(hMenu, ID_OPEN_DEBUGGER3, emu && !emu->now_debugging && emu->is_debugger_enabled(3) ? MF_ENABLED : MF_GRAYED);
+       for(int i = 0; i < 8; i++) {
+               EnableMenuItem(hMenu, ID_OPEN_DEBUGGER0 + i, emu && !emu->now_debugging && emu->is_debugger_enabled(i) ? MF_ENABLED : MF_GRAYED);
+       }
        EnableMenuItem(hMenu, ID_CLOSE_DEBUGGER, emu &&  emu->now_debugging                                ? MF_ENABLED : MF_GRAYED);
 #endif
 }
+
+#ifdef USE_STATE
+void update_save_state_menu(HMENU hMenu)
+{
+       HANDLE hFile;
+       FILETIME ftWrite;
+       FILETIME ftLocal;
+       SYSTEMTIME st;
+       _TCHAR buf[64];
+       MENUITEMINFO info;
+       
+       ZeroMemory(&info, sizeof(info));
+       info.cbSize = sizeof(info);
+       info.fMask = MIIM_TYPE;
+       info.fType = MFT_STRING;
+       info.dwTypeData = buf;
+       
+       for(int i = 0; i < 10; i++) {
+               if((hFile = CreateFile(state_file_path(i), GENERIC_READ, 0, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, 0)) != INVALID_HANDLE_VALUE){
+                       GetFileTime(hFile, NULL, NULL, &ftWrite);
+                       FileTimeToLocalFileTime(&ftWrite, &ftLocal);
+                       FileTimeToSystemTime(&ftLocal, &st);
+//                     if(st.wHour < 12) {
+//                             my_stprintf_s(buf, 64, _T("%d:  %04d-%02d-%02d  %02d:%02d:%02d AM"), i, st.wYear, st.wMonth, st.wDay, st.wHour % 12, st.wMinute, st.wSecond);
+//                     } else {
+//                             my_stprintf_s(buf, 64, _T("%d:  %04d-%02d-%02d  %02d:%02d:%02d PM"), i, st.wYear, st.wMonth, st.wDay, st.wHour % 12, st.wMinute, st.wSecond);
+//                     }
+                       my_stprintf_s(buf, 64, _T("%d:  %04d-%02d-%02d  %02d:%02d:%02d"), i, st.wYear, st.wMonth, st.wDay, st.wHour, st.wMinute, st.wSecond);
+                       CloseHandle(hFile);
+               } else {
+//                     my_stprintf_s(buf, 64, _T("%d: ----/--/-- --:--:--"), i);
+                       my_stprintf_s(buf, 64, _T("%d: (No Data)"), i);
+               }
+               SetMenuItemInfo(hMenu, ID_SAVE_STATE0 + i, FALSE, &info);
+       }
+}
+
+void update_load_state_menu(HMENU hMenu)
+{
+       HANDLE hFile;
+       FILETIME ftWrite;
+       FILETIME ftLocal;
+       SYSTEMTIME st;
+       _TCHAR buf[64];
+       MENUITEMINFO info;
+       
+       ZeroMemory(&info, sizeof(info));
+       info.cbSize = sizeof(info);
+       info.fMask = MIIM_TYPE;
+       info.fType = MFT_STRING;
+       info.dwTypeData = buf;
+       
+       for(int i = 0; i < 10; i++) {
+               if((hFile = CreateFile(state_file_path(i), GENERIC_READ, 0, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, 0)) != INVALID_HANDLE_VALUE){
+                       GetFileTime(hFile, NULL, NULL, &ftWrite);
+                       FileTimeToLocalFileTime(&ftWrite, &ftLocal);
+                       FileTimeToSystemTime(&ftLocal, &st);
+//                     if(st.wHour < 12) {
+//                             my_stprintf_s(buf, 64, _T("%d:  %04d-%02d-%02d  %02d:%02d:%02d AM"), i, st.wYear, st.wMonth, st.wDay, st.wHour % 12, st.wMinute, st.wSecond);
+//                     } else {
+//                             my_stprintf_s(buf, 64, _T("%d:  %04d-%02d-%02d  %02d:%02d:%02d PM"), i, st.wYear, st.wMonth, st.wDay, st.wHour % 12, st.wMinute, st.wSecond);
+//                     }
+                       my_stprintf_s(buf, 64, _T("%d:  %04d-%02d-%02d  %02d:%02d:%02d"), i, st.wYear, st.wMonth, st.wDay, st.wHour, st.wMinute, st.wSecond);
+                       EnableMenuItem(hMenu, ID_LOAD_STATE0 + i, MF_ENABLED);
+                       CloseHandle(hFile);
+               } else {
+//                     my_stprintf_s(buf, 64, _T("%d: ----/--/-- --:--:--"), i);
+                       my_stprintf_s(buf, 64, _T("%d: (No Data)"), i);
+                       EnableMenuItem(hMenu, ID_LOAD_STATE0 + i, MF_GRAYED);
+               }
+               SetMenuItemInfo(hMenu, ID_LOAD_STATE0 + i, FALSE, &info);
+       }
+}
 #endif
 
-#ifdef MENU_POS_CART1
+#ifdef USE_CART
 void update_cart_menu(HMENU hMenu, int drv, UINT ID_RECENT_CART, UINT ID_CLOSE_CART)
 {
        bool flag = false;
@@ -1161,7 +1523,7 @@ void update_cart_menu(HMENU hMenu, int drv, UINT ID_RECENT_CART, UINT ID_CLOSE_C
 }
 #endif
 
-#ifdef MENU_POS_FD1
+#ifdef USE_FLOPPY_DISK
 void update_floppy_disk_menu(HMENU hMenu, int drv, UINT ID_RECENT_FD, UINT ID_D88_FILE_PATH, UINT ID_SELECT_D88_BANK, UINT ID_EJECT_D88_BANK, UINT ID_CLOSE_FD, UINT ID_WRITE_PROTECT_FD, UINT ID_CORRECT_TIMING_FD, UINT ID_IGNORE_CRC_FD)
 {
        static int recent_menu_pos[] = {-1, -1, -1, -1, -1, -1, -1, -1};
@@ -1202,7 +1564,7 @@ void update_floppy_disk_menu(HMENU hMenu, int drv, UINT ID_RECENT_FD, UINT ID_D8
 }
 #endif
 
-#ifdef MENU_POS_QD1
+#ifdef USE_QUICK_DISK
 void update_quick_disk_menu(HMENU hMenu, int drv, UINT ID_RECENT_QD, UINT ID_CLOSE_QD)
 {
        bool flag = false;
@@ -1222,61 +1584,96 @@ void update_quick_disk_menu(HMENU hMenu, int drv, UINT ID_RECENT_QD, UINT ID_CLO
 }
 #endif
 
-#ifdef MENU_POS_TAPE
-void update_tape_menu(HMENU hMenu)
+#ifdef USE_HARD_DISK
+void update_hard_disk_menu(HMENU hMenu, int drv, UINT ID_RECENT_HD, UINT ID_CLOSE_HD)
+{
+       bool flag = false;
+       for(int i = 0; i < MAX_HISTORY; i++) {
+               DeleteMenu(hMenu, ID_RECENT_HD + i, MF_BYCOMMAND);
+       }
+       for(int i = 0; i < MAX_HISTORY; i++) {
+               if(_tcsicmp(config.recent_hard_disk_path[drv][i], _T(""))) {
+                       AppendMenu(hMenu, MF_STRING, ID_RECENT_HD + i, config.recent_hard_disk_path[drv][i]);
+                       flag = true;
+               }
+       }
+       if(!flag) {
+               AppendMenu(hMenu, MF_GRAYED | MF_STRING, ID_RECENT_HD, _T("None"));
+       }
+       EnableMenuItem(hMenu, ID_CLOSE_HD, emu->is_hard_disk_inserted(drv) ? MF_ENABLED : MF_GRAYED);
+}
+#endif
+
+#ifdef USE_TAPE
+void update_tape_menu(HMENU hMenu, int drv, UINT ID_RECENT_TAPE, UINT ID_CLOSE_TAPE, UINT ID_PLAY_BUTTON, UINT ID_STOP_BUTTON, UINT ID_FAST_FORWARD, UINT ID_FAST_REWIND, UINT ID_APSS_FORWARD, UINT ID_APSS_REWIND, UINT ID_USE_WAVE_SHAPER, UINT ID_DIRECT_LOAD_MZT, UINT ID_TAPE_BAUD_LOW, UINT ID_TAPE_BAUD_HIGH)
 {
        bool flag = false;
        for(int i = 0; i < MAX_HISTORY; i++) {
                DeleteMenu(hMenu, ID_RECENT_TAPE + i, MF_BYCOMMAND);
        }
        for(int i = 0; i < MAX_HISTORY; i++) {
-               if(_tcsicmp(config.recent_tape_path[i], _T(""))) {
-                       AppendMenu(hMenu, MF_STRING, ID_RECENT_TAPE + i, config.recent_tape_path[i]);
+               if(_tcsicmp(config.recent_tape_path[drv][i], _T(""))) {
+                       AppendMenu(hMenu, MF_STRING, ID_RECENT_TAPE + i, config.recent_tape_path[drv][i]);
                        flag = true;
                }
        }
        if(!flag) {
                AppendMenu(hMenu, MF_GRAYED | MF_STRING, ID_RECENT_TAPE, _T("None"));
        }
-       EnableMenuItem(hMenu, ID_CLOSE_TAPE, emu->is_tape_inserted() ? MF_ENABLED : MF_GRAYED);
-#ifdef USE_TAPE_BUTTON
-       EnableMenuItem(hMenu, ID_PLAY_BUTTON, emu->is_tape_inserted() ? MF_ENABLED : MF_GRAYED);
-       EnableMenuItem(hMenu, ID_STOP_BUTTON, emu->is_tape_inserted() ? MF_ENABLED : MF_GRAYED);
-       EnableMenuItem(hMenu, ID_FAST_FORWARD, emu->is_tape_inserted() ? MF_ENABLED : MF_GRAYED);
-       EnableMenuItem(hMenu, ID_FAST_REWIND, emu->is_tape_inserted() ? MF_ENABLED : MF_GRAYED);
-       EnableMenuItem(hMenu, ID_APSS_FORWARD, emu->is_tape_inserted() ? MF_ENABLED : MF_GRAYED);
-       EnableMenuItem(hMenu, ID_APSS_REWIND, emu->is_tape_inserted() ? MF_ENABLED : MF_GRAYED);
-#endif
-       CheckMenuItem(hMenu, ID_PLAY_TAPE_SOUND, config.tape_sound ? MF_CHECKED : MF_UNCHECKED);
-       CheckMenuItem(hMenu, ID_USE_WAVE_SHAPER, config.wave_shaper ? MF_CHECKED : MF_UNCHECKED);
-       CheckMenuItem(hMenu, ID_DIRECT_LOAD_MZT, config.direct_load_mzt ? MF_CHECKED : MF_UNCHECKED);
-#ifdef USE_TAPE_BAUD
-       CheckMenuRadioItem(hMenu, ID_TAPE_BAUD_LOW, ID_TAPE_BAUD_HIGH, !config.baud_high ? ID_TAPE_BAUD_LOW : ID_TAPE_BAUD_HIGH, MF_BYCOMMAND);
+       EnableMenuItem(hMenu, ID_CLOSE_TAPE, emu->is_tape_inserted(drv) ? MF_ENABLED : MF_GRAYED);
+       EnableMenuItem(hMenu, ID_PLAY_BUTTON, emu->is_tape_inserted(drv) ? MF_ENABLED : MF_GRAYED);
+       EnableMenuItem(hMenu, ID_STOP_BUTTON, emu->is_tape_inserted(drv) ? MF_ENABLED : MF_GRAYED);
+       EnableMenuItem(hMenu, ID_FAST_FORWARD, emu->is_tape_inserted(drv) ? MF_ENABLED : MF_GRAYED);
+       EnableMenuItem(hMenu, ID_FAST_REWIND, emu->is_tape_inserted(drv) ? MF_ENABLED : MF_GRAYED);
+       EnableMenuItem(hMenu, ID_APSS_FORWARD, emu->is_tape_inserted(drv) ? MF_ENABLED : MF_GRAYED);
+       EnableMenuItem(hMenu, ID_APSS_REWIND, emu->is_tape_inserted(drv) ? MF_ENABLED : MF_GRAYED);
+       CheckMenuItem(hMenu, ID_USE_WAVE_SHAPER, config.wave_shaper[drv] ? MF_CHECKED : MF_UNCHECKED);
+       CheckMenuItem(hMenu, ID_DIRECT_LOAD_MZT, config.direct_load_mzt[drv] ? MF_CHECKED : MF_UNCHECKED);
+       CheckMenuRadioItem(hMenu, ID_TAPE_BAUD_LOW, ID_TAPE_BAUD_HIGH, !config.baud_high[drv] ? ID_TAPE_BAUD_LOW : ID_TAPE_BAUD_HIGH, MF_BYCOMMAND);
+}
 #endif
+
+#ifdef USE_COMPACT_DISC
+void update_compact_disc_menu(HMENU hMenu, int drv, UINT ID_RECENT_COMPACT_DISC, UINT ID_CLOSE_COMPACT_DISC)
+{
+       bool flag = false;
+       for(int i = 0; i < MAX_HISTORY; i++) {
+               DeleteMenu(hMenu, ID_RECENT_COMPACT_DISC + i, MF_BYCOMMAND);
+       }
+       for(int i = 0; i < MAX_HISTORY; i++) {
+               if(_tcsicmp(config.recent_compact_disc_path[drv][i], _T(""))) {
+                       AppendMenu(hMenu, MF_STRING, ID_RECENT_COMPACT_DISC + i, config.recent_compact_disc_path[drv][i]);
+                       flag = true;
+               }
+       }
+       if(!flag) {
+               AppendMenu(hMenu, MF_GRAYED | MF_STRING, ID_RECENT_COMPACT_DISC, _T("None"));
+       }
+       EnableMenuItem(hMenu, ID_CLOSE_COMPACT_DISC, emu->is_compact_disc_inserted(drv) ? MF_ENABLED : MF_GRAYED);
 }
 #endif
 
-#ifdef MENU_POS_LASER_DISC
-void update_laser_disc_menu(HMENU hMenu)
+#ifdef USE_LASER_DISC
+void update_laser_disc_menu(HMENU hMenu, int drv, UINT ID_RECENT_LASER_DISC, UINT ID_CLOSE_LASER_DISC)
 {
        bool flag = false;
        for(int i = 0; i < MAX_HISTORY; i++) {
                DeleteMenu(hMenu, ID_RECENT_LASER_DISC + i, MF_BYCOMMAND);
        }
        for(int i = 0; i < MAX_HISTORY; i++) {
-               if(_tcsicmp(config.recent_laser_disc_path[i], _T(""))) {
-                       AppendMenu(hMenu, MF_STRING, ID_RECENT_LASER_DISC + i, config.recent_laser_disc_path[i]);
+               if(_tcsicmp(config.recent_laser_disc_path[drv][i], _T(""))) {
+                       AppendMenu(hMenu, MF_STRING, ID_RECENT_LASER_DISC + i, config.recent_laser_disc_path[drv][i]);
                        flag = true;
                }
        }
        if(!flag) {
                AppendMenu(hMenu, MF_GRAYED | MF_STRING, ID_RECENT_LASER_DISC, _T("None"));
        }
-       EnableMenuItem(hMenu, ID_CLOSE_LASER_DISC, emu->is_laser_disc_inserted() ? MF_ENABLED : MF_GRAYED);
+       EnableMenuItem(hMenu, ID_CLOSE_LASER_DISC, emu->is_laser_disc_inserted(drv) ? MF_ENABLED : MF_GRAYED);
 }
 #endif
 
-#ifdef MENU_POS_BINARY1
+#ifdef USE_BINARY_FILE
 void update_binary_menu(HMENU hMenu, int drv, UINT ID_RECENT_BINARY)
 {
        bool flag = false;
@@ -1295,22 +1692,168 @@ void update_binary_menu(HMENU hMenu, int drv, UINT ID_RECENT_BINARY)
 }
 #endif
 
-#ifdef MENU_POS_SCREEN
-void update_screen_menu(HMENU hMenu)
+#ifdef USE_BUBBLE
+void update_bubble_casette_menu(HMENU hMenu, int drv, UINT ID_RECENT_BUBBLE)
+{
+       bool flag = false;
+       for(int i = 0; i < MAX_HISTORY; i++) {
+               DeleteMenu(hMenu, ID_RECENT_BUBBLE + i, MF_BYCOMMAND);
+       }
+       for(int i = 0; i < MAX_HISTORY; i++) {
+               if(_tcsicmp(config.recent_bubble_casette_path[drv][i], _T(""))) {
+                       AppendMenu(hMenu, MF_STRING, ID_RECENT_BUBBLE + i, config.recent_bubble_casette_path[drv][i]);
+                       flag = true;
+               }
+       }
+       if(!flag) {
+               AppendMenu(hMenu, MF_GRAYED | MF_STRING, ID_RECENT_BUBBLE, _T("None"));
+       }
+}
+#endif
+
+#ifdef USE_BOOT_MODE
+void update_vm_boot_menu(HMENU hMenu)
+{
+       if(config.boot_mode >= 0 && config.boot_mode < USE_BOOT_MODE) {
+               CheckMenuRadioItem(hMenu, ID_VM_BOOT_MODE0, ID_VM_BOOT_MODE0 + USE_BOOT_MODE - 1, ID_VM_BOOT_MODE0 + config.boot_mode, MF_BYCOMMAND);
+       }
+}
+#endif
+
+#ifdef USE_CPU_TYPE
+void update_vm_cpu_menu(HMENU hMenu)
+{
+       if(config.cpu_type >= 0 && config.cpu_type < USE_CPU_TYPE) {
+               CheckMenuRadioItem(hMenu, ID_VM_CPU_TYPE0, ID_VM_CPU_TYPE0 + USE_CPU_TYPE - 1, ID_VM_CPU_TYPE0 + config.cpu_type, MF_BYCOMMAND);
+       }
+}
+#endif
+
+#ifdef USE_DIPSWITCH
+void update_vm_dipswitch_menu(HMENU hMenu)
+{
+       for(int i = 0; i < 32; i++) {
+               CheckMenuItem(hMenu, ID_VM_DIPSWITCH0 + i, (config.dipswitch & (1 << i)) ? MF_CHECKED : MF_UNCHECKED);
+       }
+}
+#endif
+
+#ifdef USE_DEVICE_TYPE
+void update_vm_device_menu(HMENU hMenu)
+{
+       if(config.device_type >= 0 && config.device_type < USE_DEVICE_TYPE) {
+               CheckMenuRadioItem(hMenu, ID_VM_DEVICE_TYPE0, ID_VM_DEVICE_TYPE0 + USE_DEVICE_TYPE - 1, ID_VM_DEVICE_TYPE0 + config.device_type, MF_BYCOMMAND);
+       }
+}
+#endif
+
+#ifdef USE_DRIVE_TYPE
+void update_vm_drive_menu(HMENU hMenu)
+{
+       if(config.drive_type >= 0 && config.drive_type < USE_DRIVE_TYPE) {
+               CheckMenuRadioItem(hMenu, ID_VM_DRIVE_TYPE0, ID_VM_DRIVE_TYPE0 + USE_DRIVE_TYPE - 1, ID_VM_DRIVE_TYPE0 + config.drive_type, MF_BYCOMMAND);
+       }
+}
+#endif
+
+#ifdef USE_KEYBOARD_TYPE
+void update_vm_keyboard_menu(HMENU hMenu)
+{
+       if(config.keyboard_type >= 0 && config.keyboard_type < USE_KEYBOARD_TYPE) {
+               CheckMenuRadioItem(hMenu, ID_VM_KEYBOARD_TYPE0, ID_VM_KEYBOARD_TYPE0 + USE_KEYBOARD_TYPE - 1, ID_VM_KEYBOARD_TYPE0 + config.keyboard_type, MF_BYCOMMAND);
+       }
+}
+#endif
+
+#ifdef USE_MOUSE_TYPE
+void update_vm_mouse_menu(HMENU hMenu)
+{
+       if(config.mouse_type >= 0 && config.mouse_type < USE_MOUSE_TYPE) {
+               CheckMenuRadioItem(hMenu, ID_VM_MOUSE_TYPE0, ID_VM_MOUSE_TYPE0 + USE_MOUSE_TYPE - 1, ID_VM_MOUSE_TYPE0 + config.mouse_type, MF_BYCOMMAND);
+       }
+}
+#endif
+
+#ifdef USE_JOYSTICK_TYPE
+void update_vm_joystick_menu(HMENU hMenu)
+{
+       if(config.joystick_type >= 0 && config.joystick_type < USE_JOYSTICK_TYPE) {
+               CheckMenuRadioItem(hMenu, ID_VM_JOYSTICK_TYPE0, ID_VM_JOYSTICK_TYPE0 + USE_JOYSTICK_TYPE - 1, ID_VM_JOYSTICK_TYPE0 + config.joystick_type, MF_BYCOMMAND);
+       }
+}
+#endif
+
+#if defined(USE_SOUND_TYPE) || defined(USE_FLOPPY_DISK) || defined(USE_TAPE)
+void update_vm_sound_menu(HMENU hMenu)
+{
+#ifdef USE_SOUND_TYPE
+       if(config.sound_type >= 0 && config.sound_type < USE_SOUND_TYPE) {
+               CheckMenuRadioItem(hMenu, ID_VM_SOUND_TYPE0, ID_VM_SOUND_TYPE0 + USE_SOUND_TYPE - 1, ID_VM_SOUND_TYPE0 + config.sound_type, MF_BYCOMMAND);
+       }
+#endif
+#ifdef USE_FLOPPY_DISK
+       CheckMenuItem(hMenu, ID_VM_SOUND_NOISE_FDD, config.sound_noise_fdd ? MF_CHECKED : MF_UNCHECKED);
+#endif
+#ifdef USE_TAPE
+       CheckMenuItem(hMenu, ID_VM_SOUND_NOISE_CMT, config.sound_noise_cmt ? MF_CHECKED : MF_UNCHECKED);
+       CheckMenuItem(hMenu, ID_VM_SOUND_PLAY_TAPE, config.sound_play_tape ? MF_CHECKED : MF_UNCHECKED);
+#endif
+}
+#endif
+
+#if defined(USE_MONITOR_TYPE) || defined(USE_SCANLINE)
+void update_vm_monitor_menu(HMENU hMenu)
+{
+#ifdef USE_MONITOR_TYPE
+       if(config.monitor_type >= 0 && config.monitor_type < USE_MONITOR_TYPE) {
+               CheckMenuRadioItem(hMenu, ID_VM_MONITOR_TYPE0, ID_VM_MONITOR_TYPE0 + USE_MONITOR_TYPE - 1, ID_VM_MONITOR_TYPE0 + config.monitor_type, MF_BYCOMMAND);
+       }
+#endif
+#ifdef USE_SCANLINE
+       CheckMenuItem(hMenu, ID_VM_MONITOR_SCANLINE, config.scan_line ? MF_CHECKED : MF_UNCHECKED);
+#endif
+}
+#endif
+
+#ifdef USE_PRINTER_TYPE
+void update_vm_printer_menu(HMENU hMenu)
+{
+       if(config.printer_type >= 0 && config.printer_type < USE_PRINTER_TYPE) {
+               CheckMenuRadioItem(hMenu, ID_VM_PRINTER_TYPE0, ID_VM_PRINTER_TYPE0 + USE_PRINTER_TYPE - 1, ID_VM_PRINTER_TYPE0 + config.printer_type, MF_BYCOMMAND);
+       }
+}
+#endif
+
+void update_host_menu(HMENU hMenu)
 {
-       // recording
        bool now_rec = true, now_stop = true;
        if(emu) {
-               now_rec = emu->is_video_recording();
+               now_rec = emu->is_video_recording() || emu->is_sound_recording();
                now_stop = !now_rec;
        }
-       EnableMenuItem(hMenu, ID_SCREEN_REC60, now_rec ? MF_GRAYED : MF_ENABLED);
-       EnableMenuItem(hMenu, ID_SCREEN_REC30, now_rec ? MF_GRAYED : MF_ENABLED);
-       EnableMenuItem(hMenu, ID_SCREEN_REC15, now_rec ? MF_GRAYED : MF_ENABLED);
-       EnableMenuItem(hMenu, ID_SCREEN_STOP, now_stop ? MF_GRAYED : MF_ENABLED);
+       EnableMenuItem(hMenu, ID_HOST_REC_MOVIE_60FPS, now_rec ? MF_GRAYED : MF_ENABLED);
+       EnableMenuItem(hMenu, ID_HOST_REC_MOVIE_30FPS, now_rec ? MF_GRAYED : MF_ENABLED);
+       EnableMenuItem(hMenu, ID_HOST_REC_MOVIE_15FPS, now_rec ? MF_GRAYED : MF_ENABLED);
+       EnableMenuItem(hMenu, ID_HOST_REC_SOUND, now_rec ? MF_GRAYED : MF_ENABLED);
+       EnableMenuItem(hMenu, ID_HOST_REC_STOP, now_stop ? MF_GRAYED : MF_ENABLED);
+       
+       CheckMenuItem(hMenu, ID_HOST_USE_D3D9, config.use_d3d9 ? MF_CHECKED : MF_UNCHECKED);
+       CheckMenuItem(hMenu, ID_HOST_WAIT_VSYNC, config.wait_vsync ? MF_CHECKED : MF_UNCHECKED);
+       EnableMenuItem(hMenu, ID_HOST_WAIT_VSYNC, config.use_d3d9 ? MF_ENABLED : MF_GRAYED);
+       
+       CheckMenuItem(hMenu, ID_HOST_USE_DINPUT, config.use_dinput ? MF_CHECKED : MF_UNCHECKED);
        
-       // screen mode
-       UINT last = ID_SCREEN_WINDOW1;
+       CheckMenuItem(hMenu, ID_HOST_DISABLE_DWM, config.disable_dwm ? MF_CHECKED : MF_UNCHECKED);
+       EnableMenuItem(hMenu, ID_HOST_DISABLE_DWM, win8_or_later ? MF_ENABLED : MF_GRAYED);
+       
+       CheckMenuItem(hMenu, ID_HOST_SHOW_STATUS_BAR, config.show_status_bar ? MF_CHECKED : MF_UNCHECKED);
+}
+
+#ifndef ONE_BOARD_MICRO_COMPUTER
+void update_host_screen_menu(HMENU hMenu)
+{
+       UINT position = 0;
+       UINT last = ID_SCREEN_WINDOW;
        _TCHAR buf[64];
        MENUITEMINFO info;
        
@@ -1320,111 +1863,106 @@ void update_screen_menu(HMENU hMenu)
        info.fType = MFT_STRING;
        info.dwTypeData = buf;
        
-       for(int i = 1; i < MAX_WINDOW; i++) {
-               DeleteMenu(hMenu, ID_SCREEN_WINDOW1 + i, MF_BYCOMMAND);
+       for(int i = 0; i < MAX_WINDOW; i++) {
+               DeleteMenu(hMenu, ID_SCREEN_WINDOW + i, MF_BYCOMMAND);
        }
-       for(int i = 1; i < MAX_WINDOW; i++) {
-               if(emu && emu->get_window_width(i) <= desktop_width && emu->get_window_height(i) <= desktop_height) {
+       for(int i = 0; i < MAX_FULLSCREEN; i++) {
+               DeleteMenu(hMenu, ID_SCREEN_FULLSCREEN + i, MF_BYCOMMAND);
+       }
+       for(int i = 0; i < MAX_WINDOW; i++) {
+               if(i == 0 || (emu && emu->get_window_mode_width(i) <= desktop_width && emu->get_window_mode_height(i) <= desktop_height)) {
                        my_stprintf_s(buf, 64, _T("Window x%d"), i + 1);
-                       InsertMenu(hMenu, ID_SCREEN_FULLSCREEN1, MF_BYCOMMAND | MF_STRING, ID_SCREEN_WINDOW1 + i, buf);
-                       last = ID_SCREEN_WINDOW1 + i;
+                       InsertMenu(hMenu, position++, MF_BYPOSITION | MF_STRING, ID_SCREEN_WINDOW + i, buf);
+                       last = ID_SCREEN_WINDOW + i;
                }
        }
        for(int i = 0; i < MAX_FULLSCREEN; i++) {
                if(i < screen_mode_count) {
                        my_stprintf_s(buf, 64, _T("Fullscreen %dx%d"), screen_mode_width[i], screen_mode_height[i]);
-                       SetMenuItemInfo(hMenu, ID_SCREEN_FULLSCREEN1 + i, FALSE, &info);
-                       EnableMenuItem(hMenu, ID_SCREEN_FULLSCREEN1 + i, now_fullscreen ? MF_GRAYED : MF_ENABLED);
-                       last = ID_SCREEN_FULLSCREEN1 + i;
-               } else {
-                       DeleteMenu(hMenu, ID_SCREEN_FULLSCREEN1 + i, MF_BYCOMMAND);
+                       InsertMenu(hMenu, position++, MF_BYPOSITION | MF_STRING, ID_SCREEN_FULLSCREEN + i, buf);
+                       EnableMenuItem(hMenu, ID_SCREEN_FULLSCREEN + i, now_fullscreen ? MF_GRAYED : MF_ENABLED);
+                       last = ID_SCREEN_FULLSCREEN + i;
                }
        }
        if(config.window_mode >= 0 && config.window_mode < MAX_WINDOW) {
-               CheckMenuRadioItem(hMenu, ID_SCREEN_WINDOW1, last, ID_SCREEN_WINDOW1 + config.window_mode, MF_BYCOMMAND);
+               CheckMenuRadioItem(hMenu, ID_SCREEN_WINDOW, last, ID_SCREEN_WINDOW + config.window_mode, MF_BYCOMMAND);
        } else if(config.window_mode >= MAX_WINDOW && config.window_mode < screen_mode_count + MAX_WINDOW) {
-               CheckMenuRadioItem(hMenu, ID_SCREEN_WINDOW1, last, ID_SCREEN_FULLSCREEN1 + config.window_mode - MAX_WINDOW, MF_BYCOMMAND);
+               CheckMenuRadioItem(hMenu, ID_SCREEN_WINDOW, last, ID_SCREEN_FULLSCREEN + config.window_mode - MAX_WINDOW, MF_BYCOMMAND);
        }
-       CheckMenuItem(hMenu, ID_SCREEN_USE_D3D9, config.use_d3d9 ? MF_CHECKED : MF_UNCHECKED);
-       CheckMenuItem(hMenu, ID_SCREEN_WAIT_VSYNC, config.wait_vsync ? MF_CHECKED : MF_UNCHECKED);
        
        my_stprintf_s(buf, 64, _T("Window: Aspect Ratio %d:%d"), emu->get_vm_window_width(), emu->get_vm_window_height());
-       SetMenuItemInfo(hMenu, ID_SCREEN_WINDOW_STRETCH1, FALSE, &info);
+       SetMenuItemInfo(hMenu, ID_SCREEN_WINDOW_STRETCH, FALSE, &info);
        my_stprintf_s(buf, 64, _T("Window: Aspect Ratio %d:%d"), emu->get_vm_window_width_aspect(), emu->get_vm_window_height_aspect());
-       SetMenuItemInfo(hMenu, ID_SCREEN_WINDOW_STRETCH2, FALSE, &info);
-       CheckMenuRadioItem(hMenu, ID_SCREEN_WINDOW_STRETCH1, ID_SCREEN_WINDOW_STRETCH2, ID_SCREEN_WINDOW_STRETCH1 + config.window_stretch_type, MF_BYCOMMAND);
+       SetMenuItemInfo(hMenu, ID_SCREEN_WINDOW_ASPECT, FALSE, &info);
+       CheckMenuRadioItem(hMenu, ID_SCREEN_WINDOW_STRETCH, ID_SCREEN_WINDOW_ASPECT, ID_SCREEN_WINDOW_STRETCH + config.window_stretch_type, MF_BYCOMMAND);
        
        my_stprintf_s(buf, 64, _T("Fullscreen: Dot By Dot"));
-       SetMenuItemInfo(hMenu, ID_SCREEN_FULLSCREEN_STRETCH1, FALSE, &info);
+       SetMenuItemInfo(hMenu, ID_SCREEN_FULLSCREEN_DOTBYDOT, FALSE, &info);
        my_stprintf_s(buf, 64, _T("Fullscreen: Stretch (Aspect Ratio %d:%d)"), emu->get_vm_window_width(), emu->get_vm_window_height());
-       SetMenuItemInfo(hMenu, ID_SCREEN_FULLSCREEN_STRETCH2, FALSE, &info);
+       SetMenuItemInfo(hMenu, ID_SCREEN_FULLSCREEN_STRETCH, FALSE, &info);
        my_stprintf_s(buf, 64, _T("Fullscreen: Stretch (Aspect Ratio %d:%d)"), emu->get_vm_window_width_aspect(), emu->get_vm_window_height_aspect());
-       SetMenuItemInfo(hMenu, ID_SCREEN_FULLSCREEN_STRETCH3, FALSE, &info);
+       SetMenuItemInfo(hMenu, ID_SCREEN_FULLSCREEN_ASPECT, FALSE, &info);
        my_stprintf_s(buf, 64, _T("Fullscreen: Stretch (Fill)"));
-       SetMenuItemInfo(hMenu, ID_SCREEN_FULLSCREEN_STRETCH4, FALSE, &info);
-       CheckMenuRadioItem(hMenu, ID_SCREEN_FULLSCREEN_STRETCH1, ID_SCREEN_FULLSCREEN_STRETCH4, ID_SCREEN_FULLSCREEN_STRETCH1 + config.fullscreen_stretch_type, MF_BYCOMMAND);
+       SetMenuItemInfo(hMenu, ID_SCREEN_FULLSCREEN_FILL, FALSE, &info);
+       CheckMenuRadioItem(hMenu, ID_SCREEN_FULLSCREEN_DOTBYDOT, ID_SCREEN_FULLSCREEN_FILL, ID_SCREEN_FULLSCREEN_DOTBYDOT + config.fullscreen_stretch_type, MF_BYCOMMAND);
        
-#ifdef USE_MONITOR_TYPE
-       if(config.monitor_type >= 0 && config.monitor_type < USE_MONITOR_TYPE) {
-               CheckMenuRadioItem(hMenu, ID_SCREEN_MONITOR_TYPE0, ID_SCREEN_MONITOR_TYPE0 + USE_MONITOR_TYPE - 1, ID_SCREEN_MONITOR_TYPE0 + config.monitor_type, MF_BYCOMMAND);
-       }
-#endif
-#ifdef USE_CRT_FILTER
-       CheckMenuItem(hMenu, ID_SCREEN_CRT_FILTER, config.crt_filter ? MF_CHECKED : MF_UNCHECKED);
-#endif
-#ifdef USE_SCANLINE
-       CheckMenuItem(hMenu, ID_SCREEN_SCANLINE, config.scan_line ? MF_CHECKED : MF_UNCHECKED);
-#endif
-#ifdef USE_SCREEN_ROTATE
+//#ifdef USE_SCREEN_ROTATE
        CheckMenuRadioItem(hMenu, ID_SCREEN_ROTATE_0, ID_SCREEN_ROTATE_270, ID_SCREEN_ROTATE_0 + config.rotate_type, MF_BYCOMMAND);
-#endif
+//#endif
 }
 #endif
 
-#ifdef MENU_POS_SOUND
-void update_sound_menu(HMENU hMenu)
+#ifdef USE_SCREEN_FILTER
+void update_host_filter_menu(HMENU hMenu)
 {
-       bool now_rec = false, now_stop = false;
-       if(emu) {
-               now_rec = emu->is_sound_recording();
-               now_stop = !now_rec;
+       switch(config.filter_type) {
+       case SCREEN_FILTER_RGB:
+               CheckMenuRadioItem(hMenu, ID_FILTER_RGB, ID_FILTER_NONE, ID_FILTER_RGB,  MF_BYCOMMAND);
+               break;
+       case SCREEN_FILTER_RF:
+               CheckMenuRadioItem(hMenu, ID_FILTER_RGB, ID_FILTER_NONE, ID_FILTER_RF,   MF_BYCOMMAND);
+               break;
+       default:
+               CheckMenuRadioItem(hMenu, ID_FILTER_RGB, ID_FILTER_NONE, ID_FILTER_NONE, MF_BYCOMMAND);
+               break;
        }
-       EnableMenuItem(hMenu, ID_SOUND_REC, now_rec ? MF_GRAYED : MF_ENABLED);
-       EnableMenuItem(hMenu, ID_SOUND_STOP, now_stop ? MF_GRAYED : MF_ENABLED);
-       
+}
+#endif
+
+void update_host_sound_menu(HMENU hMenu)
+{
        if(config.sound_frequency >= 0 && config.sound_frequency < 8) {
                CheckMenuRadioItem(hMenu, ID_SOUND_FREQ0, ID_SOUND_FREQ7, ID_SOUND_FREQ0 + config.sound_frequency, MF_BYCOMMAND);
        }
        if(config.sound_latency >= 0 && config.sound_latency < 5) {
                CheckMenuRadioItem(hMenu, ID_SOUND_LATE0, ID_SOUND_LATE4, ID_SOUND_LATE0 + config.sound_latency, MF_BYCOMMAND);
        }
-#ifdef USE_SOUND_DEVICE_TYPE
-       if(config.sound_device_type >= 0 && config.sound_device_type < USE_SOUND_DEVICE_TYPE) {
-               CheckMenuRadioItem(hMenu, ID_SOUND_DEVICE_TYPE0, ID_SOUND_DEVICE_TYPE0 + USE_SOUND_DEVICE_TYPE - 1, ID_SOUND_DEVICE_TYPE0 + config.sound_device_type, MF_BYCOMMAND);
-       }
-#endif
+       CheckMenuRadioItem(hMenu, ID_SOUND_STRICT_RENDER, ID_SOUND_LIGHT_RENDER, config.sound_strict_rendering ? ID_SOUND_STRICT_RENDER : ID_SOUND_LIGHT_RENDER, MF_BYCOMMAND);
+}
+
+void update_host_input_menu(HMENU hMenu)
+{
 }
-#endif
 
-#ifdef MENU_POS_CAPTURE
-void update_capture_menu(HMENU hMenu)
+#ifdef USE_VIDEO_CAPTURE
+void update_host_capture_menu(HMENU hMenu)
 {
        int num_devs = emu->get_num_capture_devs();
        int cur_index = emu->get_cur_capture_dev_index();
        
        for(int i = 0; i < 8; i++) {
-               DeleteMenu(hMenu, ID_CAPTURE_DEVICE1 + i, MF_BYCOMMAND);
+               DeleteMenu(hMenu, ID_CAPTURE_DEVICE + i, MF_BYCOMMAND);
        }
        for(int i = 0; i < 8; i++) {
                if(num_devs >= i + 1) {
-                       AppendMenu(hMenu, MF_STRING, ID_CAPTURE_DEVICE1 + i, emu->get_capture_dev_name(i));
+                       AppendMenu(hMenu, MF_STRING, ID_CAPTURE_DEVICE + i, emu->get_capture_dev_name(i));
                }
        }
        if(num_devs == 0) {
-               AppendMenu(hMenu, MF_GRAYED | MF_STRING, ID_CAPTURE_DEVICE1, _T("None"));
+               AppendMenu(hMenu, MF_GRAYED | MF_STRING, ID_CAPTURE_DEVICE, _T("None"));
        }
        if(cur_index != -1) {
-               CheckMenuRadioItem(hMenu, ID_CAPTURE_DEVICE1, ID_CAPTURE_DEVICE1, ID_CAPTURE_DEVICE1 + cur_index, MF_BYCOMMAND);
+               CheckMenuRadioItem(hMenu, ID_CAPTURE_DEVICE, ID_CAPTURE_DEVICE + num_devs - 1, ID_CAPTURE_DEVICE + cur_index, MF_BYCOMMAND);
        }
        EnableMenuItem(hMenu, ID_CAPTURE_FILTER, (cur_index != -1) ? MF_ENABLED : MF_GRAYED);
        EnableMenuItem(hMenu, ID_CAPTURE_PIN, (cur_index != -1) ? MF_ENABLED : MF_GRAYED);
@@ -1433,122 +1971,222 @@ void update_capture_menu(HMENU hMenu)
 }
 #endif
 
-#ifdef MENU_POS_INPUT
-void update_input_menu(HMENU hMenu)
-{
-       CheckMenuItem(hMenu, ID_INPUT_USE_DINPUT, config.use_direct_input ? MF_CHECKED : MF_UNCHECKED);
-       CheckMenuItem(hMenu, ID_INPUT_DISABLE_DWM, config.disable_dwm ? MF_CHECKED : MF_UNCHECKED);
-       EnableMenuItem(hMenu, ID_INPUT_DISABLE_DWM, win8_or_later ? MF_ENABLED : MF_GRAYED);
-}
-#endif
-
-void update_menu(HWND hWnd, HMENU hMenu, int pos)
+void update_menu(HWND hWnd, HMENU hMenu)
 {
-       switch(pos) {
-#ifdef MENU_POS_CONTROL
-       case MENU_POS_CONTROL:
+       int count = GetMenuItemCount(hMenu);
+       UINT id = -1;
+       for(int pos = 0; pos < count; pos++) {
+               if((id = GetMenuItemID(hMenu, pos)) != -1) {
+                       break;
+               }
+       }
+       if(id >= ID_CONTROL_MENU_START && id <= ID_CONTROL_MENU_END) {
                update_control_menu(hMenu);
-               break;
-#endif
-#ifdef MENU_POS_CART1
-       case MENU_POS_CART1:
+#ifdef USE_STATE
+       } else if(id >= ID_SAVE_MENU_START && id <= ID_SAVE_MENU_END) {
+               update_save_state_menu(hMenu);
+       } else if(id >= ID_LOAD_MENU_START && id <= ID_LOAD_MENU_END) {
+               update_load_state_menu(hMenu);
+#endif
+#ifdef USE_CART
+#if USE_CART >= 1
+       } else if(id >= ID_CART1_MENU_START && id <= ID_CART1_MENU_END) {
                update_cart_menu(hMenu, 0, ID_RECENT_CART1, ID_CLOSE_CART1);
-               break;
 #endif
-#ifdef MENU_POS_CART2
-       case MENU_POS_CART2:
+#if USE_CART >= 2
+       } else if(id >= ID_CART2_MENU_START && id <= ID_CART2_MENU_END) {
                update_cart_menu(hMenu, 1, ID_RECENT_CART2, ID_CLOSE_CART2);
-               break;
 #endif
-#ifdef MENU_POS_FD1
-       case MENU_POS_FD1:
+#endif
+#ifdef USE_FLOPPY_DISK
+#if USE_FLOPPY_DISK >= 1
+       } else if(id >= ID_FD1_MENU_START && id <= ID_FD1_MENU_END) {
                update_floppy_disk_menu(hMenu, 0, ID_RECENT_FD1, ID_D88_FILE_PATH1, ID_SELECT_D88_BANK1, ID_EJECT_D88_BANK1, ID_CLOSE_FD1, ID_WRITE_PROTECT_FD1, ID_CORRECT_TIMING_FD1, ID_IGNORE_CRC_FD1);
-               break;
 #endif
-#ifdef MENU_POS_FD2
-       case MENU_POS_FD2:
+#if USE_FLOPPY_DISK >= 2
+       } else if(id >= ID_FD2_MENU_START && id <= ID_FD2_MENU_END) {
                update_floppy_disk_menu(hMenu, 1, ID_RECENT_FD2, ID_D88_FILE_PATH2, ID_SELECT_D88_BANK2, ID_EJECT_D88_BANK2, ID_CLOSE_FD2, ID_WRITE_PROTECT_FD2, ID_CORRECT_TIMING_FD2, ID_IGNORE_CRC_FD2);
-               break;
 #endif
-#ifdef MENU_POS_FD3
-       case MENU_POS_FD3:
+#if USE_FLOPPY_DISK >= 3
+       } else if(id >= ID_FD3_MENU_START && id <= ID_FD3_MENU_END) {
                update_floppy_disk_menu(hMenu, 2, ID_RECENT_FD3, ID_D88_FILE_PATH3, ID_SELECT_D88_BANK3, ID_EJECT_D88_BANK3, ID_CLOSE_FD3, ID_WRITE_PROTECT_FD3, ID_CORRECT_TIMING_FD3, ID_IGNORE_CRC_FD3);
-               break;
 #endif
-#ifdef MENU_POS_FD4
-       case MENU_POS_FD4:
+#if USE_FLOPPY_DISK >= 4
+       } else if(id >= ID_FD4_MENU_START && id <= ID_FD4_MENU_END) {
                update_floppy_disk_menu(hMenu, 3, ID_RECENT_FD4, ID_D88_FILE_PATH4, ID_SELECT_D88_BANK4, ID_EJECT_D88_BANK4, ID_CLOSE_FD4, ID_WRITE_PROTECT_FD4, ID_CORRECT_TIMING_FD4, ID_IGNORE_CRC_FD4);
-               break;
 #endif
-#ifdef MENU_POS_FD5
-       case MENU_POS_FD5:
+#if USE_FLOPPY_DISK >= 5
+       } else if(id >= ID_FD5_MENU_START && id <= ID_FD5_MENU_END) {
                update_floppy_disk_menu(hMenu, 4, ID_RECENT_FD5, ID_D88_FILE_PATH5, ID_SELECT_D88_BANK5, ID_EJECT_D88_BANK5, ID_CLOSE_FD5, ID_WRITE_PROTECT_FD5, ID_CORRECT_TIMING_FD5, ID_IGNORE_CRC_FD5);
-               break;
 #endif
-#ifdef MENU_POS_FD6
-       case MENU_POS_FD6:
+#if USE_FLOPPY_DISK >= 6
+       } else if(id >= ID_FD6_MENU_START && id <= ID_FD6_MENU_END) {
                update_floppy_disk_menu(hMenu, 5, ID_RECENT_FD6, ID_D88_FILE_PATH6, ID_SELECT_D88_BANK6, ID_EJECT_D88_BANK6, ID_CLOSE_FD6, ID_WRITE_PROTECT_FD6, ID_CORRECT_TIMING_FD6, ID_IGNORE_CRC_FD6);
-               break;
 #endif
-#ifdef MENU_POS_FD7
-       case MENU_POS_FD7:
+#if USE_FLOPPY_DISK >= 7
+       } else if(id >= ID_FD7_MENU_START && id <= ID_FD7_MENU_END) {
                update_floppy_disk_menu(hMenu, 6, ID_RECENT_FD7, ID_D88_FILE_PATH7, ID_SELECT_D88_BANK7, ID_EJECT_D88_BANK7, ID_CLOSE_FD7, ID_WRITE_PROTECT_FD7, ID_CORRECT_TIMING_FD7, ID_IGNORE_CRC_FD7);
-               break;
 #endif
-#ifdef MENU_POS_FD8
-       case MENU_POS_FD8:
+#if USE_FLOPPY_DISK >= 8
+       } else if(id >= ID_FD8_MENU_START && id <= ID_FD8_MENU_END) {
                update_floppy_disk_menu(hMenu, 7, ID_RECENT_FD8, ID_D88_FILE_PATH8, ID_SELECT_D88_BANK8, ID_EJECT_D88_BANK8, ID_CLOSE_FD8, ID_WRITE_PROTECT_FD8, ID_CORRECT_TIMING_FD8, ID_IGNORE_CRC_FD8);
-               break;
 #endif
-#ifdef MENU_POS_QD1
-       case MENU_POS_QD1:
+#endif
+#ifdef USE_QUICK_DISK
+#if USE_QUICK_DISK >= 1
+       } else if(id >= ID_QD1_MENU_START && id <= ID_QD1_MENU_END) {
                update_quick_disk_menu(hMenu, 0, ID_RECENT_QD1, ID_CLOSE_QD1);
-               break;
 #endif
-#ifdef MENU_POS_QD2
-       case MENU_POS_QD2:
+#if USE_QUICK_DISK >= 2
+       } else if(id >= ID_QD2_MENU_START && id <= ID_QD2_MENU_END) {
                update_quick_disk_menu(hMenu, 1, ID_RECENT_QD2, ID_CLOSE_QD2);
-               break;
 #endif
-#ifdef MENU_POS_TAPE
-       case MENU_POS_TAPE:
-               update_tape_menu(hMenu);
-               break;
 #endif
-#ifdef MENU_POS_LASER_DISC
-       case MENU_POS_LASER_DISC:
-               update_laser_disc_menu(hMenu);
-               break;
+#ifdef USE_HARD_DISK
+#if USE_HARD_DISK >= 1
+       } else if(id >= ID_HD1_MENU_START && id <= ID_HD1_MENU_END) {
+               update_hard_disk_menu(hMenu, 0, ID_RECENT_HD1, ID_CLOSE_HD1);
+#endif
+#if USE_HARD_DISK >= 2
+       } else if(id >= ID_HD2_MENU_START && id <= ID_HD2_MENU_END) {
+               update_hard_disk_menu(hMenu, 1, ID_RECENT_HD2, ID_CLOSE_HD2);
+#endif
+#if USE_HARD_DISK >= 3
+       } else if(id >= ID_HD3_MENU_START && id <= ID_HD3_MENU_END) {
+               update_hard_disk_menu(hMenu, 2, ID_RECENT_HD3, ID_CLOSE_HD3);
+#endif
+#if USE_HARD_DISK >= 4
+       } else if(id >= ID_HD4_MENU_START && id <= ID_HD4_MENU_END) {
+               update_hard_disk_menu(hMenu, 3, ID_RECENT_HD4, ID_CLOSE_HD4);
+#endif
+#if USE_HARD_DISK >= 5
+       } else if(id >= ID_HD5_MENU_START && id <= ID_HD5_MENU_END) {
+               update_hard_disk_menu(hMenu, 4, ID_RECENT_HD5, ID_CLOSE_HD5);
+#endif
+#if USE_HARD_DISK >= 6
+       } else if(id >= ID_HD6_MENU_START && id <= ID_HD6_MENU_END) {
+               update_hard_disk_menu(hMenu, 5, ID_RECENT_HD6, ID_CLOSE_HD6);
+#endif
+#if USE_HARD_DISK >= 7
+       } else if(id >= ID_HD7_MENU_START && id <= ID_HD7_MENU_END) {
+               update_hard_disk_menu(hMenu, 6, ID_RECENT_HD7, ID_CLOSE_HD7);
+#endif
+#if USE_HARD_DISK >= 8
+       } else if(id >= ID_HD8_MENU_START && id <= ID_HD8_MENU_END) {
+               update_hard_disk_menu(hMenu, 7, ID_RECENT_HD8, ID_CLOSE_HD8);
+#endif
+#endif
+#ifdef USE_TAPE
+#if USE_TAPE >= 1
+       } else if(id >= ID_TAPE1_MENU_START && id <= ID_TAPE1_MENU_END) {
+               update_tape_menu(hMenu, 0, ID_RECENT_TAPE1, ID_CLOSE_TAPE1, ID_PLAY_BUTTON1, ID_STOP_BUTTON1, ID_FAST_FORWARD1, ID_FAST_REWIND1, ID_APSS_FORWARD1, ID_APSS_REWIND1, ID_USE_WAVE_SHAPER1, ID_DIRECT_LOAD_MZT1, ID_TAPE_BAUD_LOW1, ID_TAPE_BAUD_HIGH1);
+#endif
+#if USE_TAPE >= 2
+       } else if(id >= ID_TAPE2_MENU_START && id <= ID_TAPE2_MENU_END) {
+               update_tape_menu(hMenu, 1, ID_RECENT_TAPE2, ID_CLOSE_TAPE2, ID_PLAY_BUTTON2, ID_STOP_BUTTON2, ID_FAST_FORWARD2, ID_FAST_REWIND2, ID_APSS_FORWARD2, ID_APSS_REWIND2, ID_USE_WAVE_SHAPER2, ID_DIRECT_LOAD_MZT2, ID_TAPE_BAUD_LOW2, ID_TAPE_BAUD_HIGH2);
+#endif
+#endif
+#ifdef USE_COMPACT_DISC
+#if USE_COMPACT_DISC >= 1
+       } else if(id >= ID_COMPACT_DISC1_MENU_START && id <= ID_COMPACT_DISC1_MENU_END) {
+               update_compact_disc_menu(hMenu, 0, ID_RECENT_COMPACT_DISC1, ID_CLOSE_COMPACT_DISC1);
 #endif
-#ifdef MENU_POS_BINARY1
-       case MENU_POS_BINARY1:
+#if USE_COMPACT_DISC >= 2
+       } else if(id >= ID_COMPACT_DISC2_MENU_START && id <= ID_COMPACT_DISC2_MENU_END) {
+               update_compact_disc_menu(hMenu, 1, ID_RECENT_COMPACT_DISC2, ID_CLOSE_COMPACT_DISC2);
+#endif
+#endif
+#ifdef USE_LASER_DISC
+#if USE_LASER_DISC >= 1
+       } else if(id >= ID_LASER_DISC1_MENU_START && id <= ID_LASER_DISC1_MENU_END) {
+               update_laser_disc_menu(hMenu, 0, ID_RECENT_LASER_DISC1, ID_CLOSE_LASER_DISC1);
+#endif
+#if USE_LASER_DISC >= 2
+       } else if(id >= ID_LASER_DISC2_MENU_START && id <= ID_LASER_DISC2_MENU_END) {
+               update_laser_disc_menu(hMenu, 1, ID_RECENT_LASER_DISC2, ID_CLOSE_LASER_DISC2);
+#endif
+#endif
+#ifdef USE_BINARY_FILE
+#if USE_BINARY_FILE >= 1
+       } else if(id >= ID_BINARY1_MENU_START && id <= ID_BINARY1_MENU_END) {
                update_binary_menu(hMenu, 0, ID_RECENT_BINARY1);
-               break;
 #endif
-#ifdef MENU_POS_BINARY2
-       case MENU_POS_BINARY2:
+#if USE_BINARY_FILE >= 2
+       } else if(id >= ID_BINARY2_MENU_START && id <= ID_BINARY2_MENU_END) {
                update_binary_menu(hMenu, 1, ID_RECENT_BINARY2);
-               break;
 #endif
-#ifdef MENU_POS_SCREEN
-       case MENU_POS_SCREEN:
-               update_screen_menu(hMenu);
-               break;
 #endif
-#ifdef MENU_POS_SOUND
-       case MENU_POS_SOUND:
-               update_sound_menu(hMenu);
-               break;
+#ifdef USE_BUBBLE
+#if USE_BUBBLE >= 1
+       } else if(id >= ID_BUBBLE1_MENU_START && id <= ID_BUBBLE1_MENU_END) {
+               update_bubble_casette_menu(hMenu, 0, ID_RECENT_BUBBLE1);
 #endif
-#ifdef MENU_POS_CAPTURE
-       case MENU_POS_CAPTURE:
-               update_capture_menu(hMenu);
-               break;
+#if USE_BUBBLE >= 2
+       } else if(id >= ID_BUBBLE2_MENU_START && id <= ID_BUBBLE2_MENU_END) {
+               update_bubble_casette_menu(hMenu, 1, ID_RECENT_BUBBLE2);
 #endif
-#ifdef MENU_POS_INPUT
-       case MENU_POS_INPUT:
-               update_input_menu(hMenu);
-               break;
+#endif
+#ifdef USE_BOOT_MODE
+       } else if(id >= ID_VM_BOOT_MENU_START && id <= ID_VM_BOOT_MENU_END) {
+                update_vm_boot_menu(hMenu);
+#endif
+#ifdef USE_CPU_TYPE
+       } else if(id >= ID_VM_CPU_MENU_START && id <= ID_VM_CPU_MENU_END) {
+                update_vm_cpu_menu(hMenu);
+#endif
+#ifdef USE_DIPSWITCH
+       } else if(id >= ID_VM_DIPSWITCH_MENU_START && id <= ID_VM_DIPSWITCH_MENU_END) {
+                update_vm_dipswitch_menu(hMenu);
+#endif
+#ifdef USE_DEVICE_TYPE
+       } else if(id >= ID_VM_DEVICE_MENU_START && id <= ID_VM_DEVICE_MENU_END) {
+                update_vm_device_menu(hMenu);
+#endif
+#ifdef USE_DRIVE_TYPE
+       } else if(id >= ID_VM_DRIVE_MENU_START && id <= ID_VM_DRIVE_MENU_END) {
+                update_vm_drive_menu(hMenu);
+#endif
+#ifdef USE_KEYBOARD_TYPE
+       } else if(id >= ID_VM_KEYBOARD_MENU_START && id <= ID_VM_KEYBOARD_MENU_END) {
+                update_vm_keyboard_menu(hMenu);
+#endif
+#ifdef USE_MOUSE_TYPE
+       } else if(id >= ID_VM_MOUSE_MENU_START && id <= ID_VM_MOUSE_MENU_END) {
+                update_vm_mouse_menu(hMenu);
+#endif
+#ifdef USE_JOYSTICK_TYPE
+       } else if(id >= ID_VM_JOYSTICK_MENU_START && id <= ID_VM_JOYSTICK_MENU_END) {
+                update_vm_joystick_menu(hMenu);
+#endif
+#if defined(USE_SOUND_TYPE) || defined(USE_FLOPPY_DISK) || defined(USE_TAPE)
+       } else if(id >= ID_VM_SOUND_MENU_START && id <= ID_VM_SOUND_MENU_END) {
+                update_vm_sound_menu(hMenu);
+#endif
+#if defined(USE_MONITOR_TYPE) || defined(USE_SCANLINE)
+       } else if(id >= ID_VM_MONITOR_MENU_START && id <= ID_VM_MONITOR_MENU_END) {
+                update_vm_monitor_menu(hMenu);
+#endif
+#ifdef USE_PRINTER_TYPE
+       } else if(id >= ID_VM_PRINTER_MENU_START && id <= ID_VM_PRINTER_MENU_START) {
+                update_vm_printer_menu(hMenu);
+#endif
+       } else if(id >= ID_HOST_MENU_START && id <= ID_HOST_MENU_END) {
+               update_host_menu(hMenu);
+#ifndef ONE_BOARD_MICRO_COMPUTER
+       } else if(id >= ID_SCREEN_MENU_START && id <= ID_SCREEN_MENU_END) {
+               update_host_screen_menu(hMenu);
+#endif
+#ifdef USE_SCREEN_FILTER
+       } else if(id >= ID_FILTER_MENU_START && id <= ID_FILTER_MENU_END) {
+               update_host_filter_menu(hMenu);
+#endif
+       } else if(id >= ID_SOUND_MENU_START && id <= ID_SOUND_MENU_END) {
+               update_host_sound_menu(hMenu);
+       } else if(id >= ID_INPUT_MENU_START && id <= ID_INPUT_MENU_END) {
+               update_host_input_menu(hMenu);
+#ifdef USE_VIDEO_CAPTURE
+       } else if(id >= ID_CAPTURE_MENU_START && id <= ID_CAPTURE_MENU_END) {
+               update_host_capture_menu(hMenu);
 #endif
        }
        DrawMenuBar(hWnd);
@@ -1572,6 +2210,211 @@ void hide_menu_bar(HWND hWnd)
 }
 
 // ----------------------------------------------------------------------------
+// status bar
+// ----------------------------------------------------------------------------
+
+void show_status_bar(HWND hWnd)
+{
+//#if defined(USE_FLOPPY_DISK) || defined(USE_QUICK_DISK) || defined(USE_HARD_DISK) || defined(USE_COMPACT_DISC) || defined(USE_LASER_DISC) || (defined(USE_TAPE) && !defined(TAPE_BINARY_ONLY))
+       if(hStatus == NULL) {
+               InitCommonControls();
+               hStatus = CreateStatusWindow(WS_CHILD | WS_VISIBLE | CCS_BOTTOM, NULL, hWnd, ID_STATUS);
+               SendMessage(hStatus, SB_SETTEXT, (WPARAM)0 | SBT_OWNERDRAW, (LPARAM)NULL);
+       }
+       ShowWindow(hStatus, SW_SHOW);
+//#endif
+       status_bar_visible = true;
+}
+
+void hide_status_bar(HWND hWnd)
+{
+       if(hStatus != NULL) {
+               ShowWindow(hStatus, SW_HIDE);
+       }
+       status_bar_visible = false;
+}
+
+int get_status_bar_height()
+{
+       if(hStatus != NULL && status_bar_visible) {
+               RECT rect;
+               GetWindowRect(hStatus, &rect);
+               return rect.bottom - rect.top;
+       }
+       return 0;
+}
+
+bool get_status_bar_updated()
+{
+       bool updated = false;
+       
+#ifdef USE_FLOPPY_DISK
+       uint32_t new_fd_status = emu->is_floppy_disk_accessed();
+       if(fd_status != new_fd_status) {
+               updated = true;
+               fd_status = new_fd_status;
+       }
+#endif
+#ifdef USE_QUICK_DISK
+       uint32_t new_qd_status = emu->is_quick_disk_accessed();
+       if(qd_status != new_qd_status) {
+               updated = true;
+               qd_status = new_qd_status;
+       }
+#endif
+#ifdef USE_HARD_DISK
+       uint32_t new_hd_status = emu->is_hard_disk_accessed();
+       if(hd_status != new_hd_status) {
+               updated = true;
+               hd_status = new_hd_status;
+       }
+#endif
+#ifdef USE_COMPACT_DISC
+       uint32_t new_cd_status = emu->is_compact_disc_accessed();
+       if(cd_status != new_cd_status) {
+               updated = true;
+               cd_status = new_cd_status;
+       }
+#endif
+#ifdef USE_LASER_DISC
+       uint32_t new_ld_status = emu->is_laser_disc_accessed();
+       if(ld_status != new_ld_status) {
+               updated = true;
+               ld_status = new_ld_status;
+       }
+#endif
+#if defined(USE_TAPE) && !defined(TAPE_BINARY_ONLY)
+       _TCHAR new_tape_status[array_length(tape_status)] = {0};
+       for(int drv = 0; drv < USE_TAPE; drv++) {
+               const _TCHAR* message = emu->get_tape_message(drv);
+               if(message != NULL) {
+                       my_tcscpy_s(new_tape_status, array_length(new_tape_status), message);
+                       break;
+               }
+       }
+       if(_tcsicmp(tape_status, new_tape_status) != 0) {
+               updated = true;
+               my_tcscpy_s(tape_status, array_length(tape_status), new_tape_status);
+       }
+#endif
+       return updated;
+}
+
+void update_status_bar(HINSTANCE hInstance, LPDRAWITEMSTRUCT lpDrawItem)
+{
+       TEXTMETRIC tm;
+       GetTextMetrics(lpDrawItem->hDC, &tm);
+       int text_top = (lpDrawItem->rcItem.top + lpDrawItem->rcItem.bottom) / 2 - tm.tmHeight / 2;
+       int draw_left = lpDrawItem->rcItem.left;
+       
+       SetTextColor(lpDrawItem->hDC, RGB(0, 0, 0));
+       SetBkMode(lpDrawItem->hDC, TRANSPARENT);
+       
+       #if defined(USE_FLOPPY_DISK) || defined(USE_QUICK_DISK) || defined(USE_HARD_DISK) || defined(USE_COMPACT_DISC) || defined(USE_LASER_DISC)
+       {
+               HDC hdcMem = CreateCompatibleDC(lpDrawItem->hDC);
+               HBITMAP hBitmap[2];
+               BITMAP bmp[2];
+               hBitmap[0] = LoadBitmap(hInstance, _T("IDI_BITMAP_ACCESS_OFF"));
+               hBitmap[1] = LoadBitmap(hInstance, _T("IDI_BITMAP_ACCESS_ON" ));
+               
+               if(hBitmap[0] != NULL && hBitmap[1] != NULL) {
+                       GetObject(hBitmap[0], sizeof(BITMAP), &bmp[0]);
+                       GetObject(hBitmap[1], sizeof(BITMAP), &bmp[1]);
+                       
+                       int bmp_width = bmp[0].bmWidth;
+                       int bmp_height = bmp[0].bmHeight;
+                       int bmp_top = (lpDrawItem->rcItem.top + lpDrawItem->rcItem.bottom) / 2 - bmp_height / 2;
+                       SIZE size;
+                       
+                       #ifdef USE_FLOPPY_DISK
+                               TextOut(lpDrawItem->hDC, draw_left, text_top, _T("FD:"), 3);
+                               GetTextExtentPoint32(lpDrawItem->hDC, _T("FD:"), 3, &size);
+                               draw_left += size.cx + 4;
+                               
+                               for(int i = 0; i < USE_FLOPPY_DISK; i++) {
+                                       int idx = (fd_status >> i) & 1;
+                                       SelectObject(hdcMem, hBitmap[idx]);
+                                       TransparentBlt(lpDrawItem->hDC, draw_left, bmp_top, bmp_width, bmp_height, hdcMem, 0, 0, bmp_width, bmp_height, 0);
+                                       draw_left += bmp_width + 2;
+                               }
+                               draw_left += 8;
+                       #endif
+                       #ifdef USE_QUICK_DISK
+                               TextOut(lpDrawItem->hDC, draw_left, text_top, _T("QD:"), 3);
+                               GetTextExtentPoint32(lpDrawItem->hDC, _T("QD:"), 3, &size);
+                               draw_left += size.cx + 4;
+                               
+                               for(int i = 0; i < USE_QUICK_DISK; i++) {
+                                       int idx = (qd_status >> i) & 1;
+                                       SelectObject(hdcMem, hBitmap[idx]);
+                                       TransparentBlt(lpDrawItem->hDC, draw_left, bmp_top, bmp_width, bmp_height, hdcMem, 0, 0, bmp_width, bmp_height, 0);
+                                       draw_left += bmp_width + 2;
+                               }
+                               draw_left += 8;
+                       #endif
+                       #ifdef USE_HARD_DISK
+                               TextOut(lpDrawItem->hDC, draw_left, text_top, _T("HD:"), 3);
+                               GetTextExtentPoint32(lpDrawItem->hDC, _T("HD:"), 3, &size);
+                               draw_left += size.cx + 4;
+                               
+                               for (int i = 0; i < USE_HARD_DISK; i++) {
+                                       int idx = (hd_status >> i) & 1;
+                                       SelectObject(hdcMem, hBitmap[idx]);
+                                       TransparentBlt(lpDrawItem->hDC, draw_left, bmp_top, bmp_width, bmp_height, hdcMem, 0, 0, bmp_width, bmp_height, 0);
+                                       draw_left += bmp_width + 2;
+                               }
+                               draw_left += 8;
+                       #endif
+                       #ifdef USE_COMPACT_DISC
+                               TextOut(lpDrawItem->hDC, draw_left, text_top, _T("CD:"), 3);
+                               GetTextExtentPoint32(lpDrawItem->hDC, _T("CD:"), 3, &size);
+                               draw_left += size.cx + 4;
+                               
+                               for (int i = 0; i < USE_COMPACT_DISC; i++) {
+                                       int idx = (cd_status >> i) & 1;
+                                       SelectObject(hdcMem, hBitmap[idx]);
+                                       TransparentBlt(lpDrawItem->hDC, draw_left, bmp_top, bmp_width, bmp_height, hdcMem, 0, 0, bmp_width, bmp_height, 0);
+                                       draw_left += bmp_width + 2;
+                               }
+                               draw_left += 8;
+                       #endif
+                       #ifdef USE_LASER_DISC
+                               TextOut(lpDrawItem->hDC, draw_left, text_top, _T("LD:"), 3);
+                               GetTextExtentPoint32(lpDrawItem->hDC, _T("LD:"), 3, &size);
+                               draw_left += size.cx + 4;
+                               
+                               for (int i = 0; i < USE_LASER_DISC; i++) {
+                                       int idx = (ld_status >> i) & 1;
+                                       SelectObject(hdcMem, hBitmap[idx]);
+                                       TransparentBlt(lpDrawItem->hDC, draw_left, bmp_top, bmp_width, bmp_height, hdcMem, 0, 0, bmp_width, bmp_height, 0);
+                                       draw_left += bmp_width + 2;
+                               }
+                               draw_left += 8;
+                       #endif
+               }
+               if(hBitmap[0] != NULL) {
+                       DeleteObject(hBitmap[0]);
+               }
+               if(hBitmap[1] != NULL) {
+                       DeleteObject(hBitmap[1]);
+               }
+               DeleteDC(hdcMem);
+       }
+       #endif
+       #if defined(USE_TAPE) && !defined(TAPE_BINARY_ONLY)
+       {
+               SIZE size;
+               
+               TextOut(lpDrawItem->hDC, draw_left, text_top, _T("CMT:"), 4);
+               GetTextExtentPoint32(lpDrawItem->hDC, _T("CMT:"), 4, &size);
+               draw_left += size.cx + 4;
+               TextOut(lpDrawItem->hDC, draw_left, text_top, tape_status, _tcslen(tape_status));
+       }
+       #endif
+}
+
+// ----------------------------------------------------------------------------
 // file
 // ----------------------------------------------------------------------------
 
@@ -1589,12 +2432,15 @@ void hide_menu_bar(HWND hWnd)
        my_tcscpy_s(recent[0], _MAX_PATH, path); \
 }
 
-#ifdef USE_CART1
+#ifdef USE_CART
 void open_cart_dialog(HWND hWnd, int drv)
 {
        _TCHAR* path = get_open_file_name(
                hWnd,
-#if defined(_GAMEGEAR)
+#if defined(_COLECOVISION)
+               _T("Supported Files (*.rom;*.bin;*.hex;*.col)\0*.rom;*.bin;*.hex;*.col\0All Files (*.*)\0*.*\0\0"),
+               _T("Game Cartridge"),
+#elif defined(_GAMEGEAR)
                _T("Supported Files (*.rom;*.bin;*.hex;*.gg;*.col)\0*.rom;*.bin;*.hex;*.gg;*.col\0All Files (*.*)\0*.*\0\0"),
                _T("Game Cartridge"),
 #elif defined(_MASTERSYSTEM)
@@ -1606,6 +2452,9 @@ void open_cart_dialog(HWND hWnd, int drv)
 #elif defined(_PCENGINE) || defined(_X1TWIN)
                _T("Supported Files (*.rom;*.bin;*.hex;*.pce)\0*.rom;*.bin;*.hex;*.pce\0All Files (*.*)\0*.*\0\0"),
                _T("HuCARD"),
+#elif defined(_SC3000)
+               _T("Supported Files (*.rom;*.bin;*.hex;*.sc;*.sg)\0*.rom;*.bin;*.hex;*.sc;*.sg\0All Files (*.*)\0*.*\0\0"),
+               _T("Game Cartridge"),
 #else
                _T("Supported Files (*.rom;*.bin;*.hex)\0*.rom;*.bin;*.hex\0All Files (*.*)\0*.*\0\0"), 
                _T("Game Cartridge"),
@@ -1631,12 +2480,12 @@ void open_recent_cart(int drv, int index)
 }
 #endif
 
-#ifdef USE_FD1
+#ifdef USE_FLOPPY_DISK
 void open_floppy_disk_dialog(HWND hWnd, int drv)
 {
        _TCHAR* path = get_open_file_name(
                hWnd,
-               _T("Supported Files (*.d88;*.d77;*.1dd;*.td0;*.imd;*.dsk;*.fdi;*.hdm;*.tfd;*.xdf;*.2d;*.sf7;*.img;*.ima;*.vfd)\0*.d88;*.d77;*.1dd;*.td0;*.imd;*.dsk;*.fdi;*.hdm;*.tfd;*.xdf;*.2d;*.sf7;*.img;*.ima;*.vfd\0All Files (*.*)\0*.*\0\0"),
+               _T("Supported Files (*.d88;*.d77;*.1dd;*.td0;*.imd;*.dsk;*.nfd;*.fdi;*.hdm;*.hd5;*.hd4;*.hdb;*.dd9;*.dd6;*.tfd;*.xdf;*.2d;*.sf7;*.img;*.ima;*.vfd)\0*.d88;*.d77;*.1dd;*.td0;*.imd;*.dsk;*.nfd;*.fdi;*.hdm;*.hd5;*.hd4;*.hdb;*.dd9;*.dd6;*.tfd;*.xdf;*.2d;*.sf7;*.img;*.ima;*.vfd\0All Files (*.*)\0*.*\0\0"),
                _T("Floppy Disk"),
                config.initial_floppy_disk_dir, _MAX_PATH
        );
@@ -1683,8 +2532,8 @@ void open_floppy_disk(int drv, const _TCHAR* path, int bank)
                delete fio;
        }
        emu->open_floppy_disk(drv, path, bank);
-#ifdef USE_FD2
-       if((drv & 1) == 0 && drv + 1 < MAX_FD && bank + 1 < emu->d88_file[drv].bank_num) {
+#if USE_FLOPPY_DISK >= 2
+       if((drv & 1) == 0 && drv + 1 < USE_FLOPPY_DISK && bank + 1 < emu->d88_file[drv].bank_num) {
                open_floppy_disk(drv + 1, path, bank + 1);
        }
 #endif
@@ -1718,7 +2567,7 @@ void close_floppy_disk(int drv)
 }
 #endif
 
-#ifdef USE_QD1
+#ifdef USE_QUICK_DISK
 void open_quick_disk_dialog(HWND hWnd, int drv)
 {
        _TCHAR* path = get_open_file_name(
@@ -1746,59 +2595,126 @@ void open_recent_quick_disk(int drv, int index)
 }
 #endif
 
+#ifdef USE_HARD_DISK
+void open_hard_disk_dialog(HWND hWnd, int drv)
+{
+       _TCHAR* path = get_open_file_name(
+               hWnd,
+               _T("Supported Files (*.thd;*.nhd;*.hdi;*.hdd;*.dat)\0*.thd;*.nhd;*.hdi;*.hdd;*.dat\0All Files (*.*)\0*.*\0\0"),
+               _T("Hard Disk"),
+               config.initial_hard_disk_dir, _MAX_PATH
+       );
+       if(path) {
+               UPDATE_HISTORY(path, config.recent_hard_disk_path[drv]);
+               my_tcscpy_s(config.initial_hard_disk_dir, _MAX_PATH, get_parent_dir(path));
+               emu->open_hard_disk(drv, path);
+       }
+}
+
+void open_recent_hard_disk(int drv, int index)
+{
+       _TCHAR path[_MAX_PATH];
+       my_tcscpy_s(path, _MAX_PATH, config.recent_hard_disk_path[drv][index]);
+       for(int i = index; i > 0; i--) {
+               my_tcscpy_s(config.recent_hard_disk_path[drv][i], _MAX_PATH, config.recent_hard_disk_path[drv][i - 1]);
+       }
+       my_tcscpy_s(config.recent_hard_disk_path[drv][0], _MAX_PATH, path);
+       emu->open_hard_disk(drv, path);
+}
+#endif
+
 #ifdef USE_TAPE
-void open_tape_dialog(HWND hWnd, bool play)
+void open_tape_dialog(HWND hWnd, int drv, bool play)
 {
        _TCHAR* path = get_open_file_name(
                hWnd,
 #if defined(_PC6001) || defined(_PC6001MK2) || defined(_PC6001MK2SR) || defined(_PC6601) || defined(_PC6601SR)
-               _T("Supported Files (*.wav;*.cas;*.p6;*.p6t)\0*.wav;*.cas;*.p6;*.p6t\0All Files (*.*)\0*.*\0\0"),
+               play ? _T("Supported Files (*.wav;*.cas;*.p6;*.p6t;*.gz)\0*.wav;*.cas;*.p6;*.p6t;*.gz\0All Files (*.*)\0*.*\0\0")
+                    : _T("Supported Files (*.wav;*.cas;*.p6;*.p6t)\0*.wav;*.cas;*.p6;*.p6t\0All Files (*.*)\0*.*\0\0"),
 #elif defined(_PC8001SR) || defined(_PC8801MA) || defined(_PC98DO)
                play ? _T("Supported Files (*.cas;*.cmt;*.n80;*.t88)\0*.cas;*.cmt;*.n80;*.t88\0All Files (*.*)\0*.*\0\0")
                     : _T("Supported Files (*.cas;*.cmt)\0*.cas;*.cmt\0All Files (*.*)\0*.*\0\0"),
 #elif defined(_MZ80A) || defined(_MZ80K) || defined(_MZ1200) || defined(_MZ700) || defined(_MZ800) || defined(_MZ1500)
-               play ? _T("Supported Files (*.wav;*.cas;*.mzt;*.mzf;*.m12)\0*.wav;*.cas;*.mzt;*.mzf;*.m12\0All Files (*.*)\0*.*\0\0")
+               play ? _T("Supported Files (*.wav;*.cas;*.mzt;*.mzf;*.m12;*.gz)\0*.wav;*.cas;*.mzt;*.mzf;*.m12;*.gz\0All Files (*.*)\0*.*\0\0")
                     : _T("Supported Files (*.wav;*.cas)\0*.wav;*.cas\0All Files (*.*)\0*.*\0\0"),
 #elif defined(_MZ80B) || defined(_MZ2000) || defined(_MZ2200)
-               play ? _T("Supported Files (*.wav;*.cas;*.mzt;*.mzf;*.mti;*.mtw;*.dat)\0*.wav;*.cas;*.mzt;*.mzf;*.mti;*.mtw;*.dat\0All Files (*.*)\0*.*\0\0")
+               play ? _T("Supported Files (*.wav;*.cas;*.mzt;*.mzf;*.mti;*.mtw;*.dat;*.gz)\0*.wav;*.cas;*.mzt;*.mzf;*.mti;*.mtw;*.dat;*.gz\0All Files (*.*)\0*.*\0\0")
                     : _T("Supported Files (*.wav;*.cas)\0*.wav;*.cas\0All Files (*.*)\0*.*\0\0"),
 #elif defined(_X1) || defined(_X1TWIN) || defined(_X1TURBO) || defined(_X1TURBOZ)
-               _T("Supported Files (*.wav;*.cas;*.tap)\0*.wav;*.cas;*.tap\0All Files (*.*)\0*.*\0\0"),
+               play ? _T("Supported Files (*.wav;*.cas;*.tap;*.gz)\0*.wav;*.cas;*.tap;*.gz\0All Files (*.*)\0*.*\0\0")
+                    : _T("Supported Files (*.wav;*.cas;*.tap)\0*.wav;*.cas;*.tap\0All Files (*.*)\0*.*\0\0"),
 #elif defined(_FM8) || defined(_FM7) || defined(_FMNEW7) || defined(_FM77_VARIANTS) || defined(_FM77AV_VARIANTS)
-               _T("Supported Files (*.wav;*.cas;*.t77)\0*.wav;*.cas;*.t77\0All Files (*.*)\0*.*\0\0"),
-#elif defined(TAPE_BINARY_ONLY)
-               _T("Supported Files (*.cas;*.cmt)\0*.cas;*.cmt\0All Files (*.*)\0*.*\0\0"),
+               play ? _T("Supported Files (*.wav;*.cas;*.t77;*.gz)\0*.wav;*.cas;*.t77;*.gz\0All Files (*.*)\0*.*\0\0")
+                    : _T("Supported Files (*.wav;*.cas;*.t77)\0*.wav;*.cas;*.t77\0All Files (*.*)\0*.*\0\0"),
+#elif defined(_BMJR)
+               play ? _T("Supported Files (*.wav;*.cas;*.bin;*.gz)\0*.wav;*.cas;*.bin;*.gz\0All Files (*.*)\0*.*\0\0")
+                    : _T("Supported Files (*.wav;*.cas)\0*.wav;*.cas\0All Files (*.*)\0*.*\0\0"),
+#elif defined(_TK80BS)
+               drv == 1 ? _T("Supported Files (*.cas;*.cmt)\0*.cas;*.cmt\0All Files (*.*)\0*.*\0\0")
+               : play   ? _T("Supported Files (*.wav;*.cas;*.gz)\0*.wav;*.cas;*.gz\0All Files (*.*)\0*.*\0\0")
+                        : _T("Supported Files (*.wav;*.cas)\0*.wav;*.cas\0All Files (*.*)\0*.*\0\0"),
+#elif !defined(TAPE_BINARY_ONLY)
+               play ? _T("Supported Files (*.wav;*.cas;*.gz)\0*.wav;*.cas;*.gz\0All Files (*.*)\0*.*\0\0")
+                    : _T("Supported Files (*.wav;*.cas)\0*.wav;*.cas\0All Files (*.*)\0*.*\0\0"),
 #else
-               _T("Supported Files (*.wav;*.cas)\0*.wav;*.cas\0All Files (*.*)\0*.*\0\0"),
+               _T("Supported Files (*.cas;*.cmt)\0*.cas;*.cmt\0All Files (*.*)\0*.*\0\0"),
 #endif
                play ? _T("Data Recorder Tape [Play]") : _T("Data Recorder Tape [Rec]"),
                config.initial_tape_dir, _MAX_PATH
        );
        if(path) {
-               UPDATE_HISTORY(path, config.recent_tape_path);
+               UPDATE_HISTORY(path, config.recent_tape_path[drv]);
                my_tcscpy_s(config.initial_tape_dir, _MAX_PATH, get_parent_dir(path));
                if(play) {
-                       emu->play_tape(path);
+                       emu->play_tape(drv, path);
                } else {
-                       emu->rec_tape(path);
+                       emu->rec_tape(drv, path);
                }
        }
 }
 
-void open_recent_tape(int index)
+void open_recent_tape(int drv, int index)
+{
+       _TCHAR path[_MAX_PATH];
+       my_tcscpy_s(path, _MAX_PATH, config.recent_tape_path[drv][index]);
+       for(int i = index; i > 0; i--) {
+               my_tcscpy_s(config.recent_tape_path[drv][i], _MAX_PATH, config.recent_tape_path[drv][i - 1]);
+       }
+       my_tcscpy_s(config.recent_tape_path[drv][0], _MAX_PATH, path);
+       emu->play_tape(drv, path);
+}
+#endif
+
+#ifdef USE_COMPACT_DISC
+void open_compact_disc_dialog(HWND hWnd, int drv)
+{
+       _TCHAR* path = get_open_file_name(
+               hWnd,
+               _T("Supported Files (*.ccd;*.cue)\0*.ccd;*.cue\0All Files (*.*)\0*.*\0\0"),
+               _T("Compact Disc"),
+               config.initial_compact_disc_dir, _MAX_PATH
+       );
+       if(path) {
+               UPDATE_HISTORY(path, config.recent_compact_disc_path[drv]);
+               my_tcscpy_s(config.initial_compact_disc_dir, _MAX_PATH, get_parent_dir(path));
+               emu->open_compact_disc(drv, path);
+       }
+}
+
+void open_recent_compact_disc(int drv, int index)
 {
        _TCHAR path[_MAX_PATH];
-       my_tcscpy_s(path, _MAX_PATH, config.recent_tape_path[index]);
+       my_tcscpy_s(path, _MAX_PATH, config.recent_compact_disc_path[drv][index]);
        for(int i = index; i > 0; i--) {
-               my_tcscpy_s(config.recent_tape_path[i], _MAX_PATH, config.recent_tape_path[i - 1]);
+               my_tcscpy_s(config.recent_compact_disc_path[drv][i], _MAX_PATH, config.recent_compact_disc_path[drv][i - 1]);
        }
-       my_tcscpy_s(config.recent_tape_path[0], _MAX_PATH, path);
-       emu->play_tape(path);
+       my_tcscpy_s(config.recent_compact_disc_path[drv][0], _MAX_PATH, path);
+       emu->open_compact_disc(drv, path);
 }
 #endif
 
 #ifdef USE_LASER_DISC
-void open_laser_disc_dialog(HWND hWnd)
+void open_laser_disc_dialog(HWND hWnd, int drv)
 {
        _TCHAR* path = get_open_file_name(
                hWnd,
@@ -1807,25 +2723,25 @@ void open_laser_disc_dialog(HWND hWnd)
                config.initial_laser_disc_dir, _MAX_PATH
        );
        if(path) {
-               UPDATE_HISTORY(path, config.recent_laser_disc_path);
+               UPDATE_HISTORY(path, config.recent_laser_disc_path[drv]);
                my_tcscpy_s(config.initial_laser_disc_dir, _MAX_PATH, get_parent_dir(path));
-               emu->open_laser_disc(path);
+               emu->open_laser_disc(drv, path);
        }
 }
 
-void open_recent_laser_disc(int index)
+void open_recent_laser_disc(int drv, int index)
 {
        _TCHAR path[_MAX_PATH];
-       my_tcscpy_s(path, _MAX_PATH, config.recent_laser_disc_path[index]);
+       my_tcscpy_s(path, _MAX_PATH, config.recent_laser_disc_path[drv][index]);
        for(int i = index; i > 0; i--) {
-               my_tcscpy_s(config.recent_laser_disc_path[i], _MAX_PATH, config.recent_laser_disc_path[i - 1]);
+               my_tcscpy_s(config.recent_laser_disc_path[drv][i], _MAX_PATH, config.recent_laser_disc_path[drv][i - 1]);
        }
-       my_tcscpy_s(config.recent_laser_disc_path[0], _MAX_PATH, path);
-       emu->open_laser_disc(path);
+       my_tcscpy_s(config.recent_laser_disc_path[drv][0], _MAX_PATH, path);
+       emu->open_laser_disc(drv, path);
 }
 #endif
 
-#ifdef USE_BINARY_FILE1
+#ifdef USE_BINARY_FILE
 void open_binary_dialog(HWND hWnd, int drv, bool load)
 {
        _TCHAR* path = get_open_file_name(
@@ -1861,6 +2777,34 @@ void open_recent_binary(int drv, int index)
 }
 #endif
 
+#ifdef USE_BUBBLE
+void open_bubble_casette_dialog(HWND hWnd, int drv)
+{
+       _TCHAR* path = get_open_file_name(
+               hWnd,
+               _T("Supported Files (*.b77;*.bbl)\0*.b77;*.bbl\0All Files (*.*)\0*.*\0\0"),
+               _T("Bubble Casette"),
+               config.initial_bubble_casette_dir, _MAX_PATH
+       );
+       if(path) {
+               UPDATE_HISTORY(path, config.recent_bubble_casette_path[drv]);
+               my_tcscpy_s(config.initial_bubble_casette_dir, _MAX_PATH, get_parent_dir(path));
+               emu->open_bubble_casette(drv, path, 0);
+       }
+}
+
+void open_recent_bubble_casette(int drv, int index)
+{
+       _TCHAR path[_MAX_PATH];
+       my_tcscpy_s(path, _MAX_PATH, config.recent_bubble_casette_path[drv][index]);
+       for(int i = index; i > 0; i--) {
+               my_tcscpy_s(config.recent_bubble_casette_path[drv][i], _MAX_PATH, config.recent_bubble_casette_path[drv][i - 1]);
+       }
+       my_tcscpy_s(config.recent_bubble_casette_path[drv][0], _MAX_PATH, path);
+       emu->open_bubble_casette(drv, path, 0);
+}
+#endif
+
 #ifdef SUPPORT_DRAG_DROP
 void open_dropped_file(HDROP hDrop)
 {
@@ -1874,10 +2818,12 @@ void open_dropped_file(HDROP hDrop)
 
 void open_any_file(const _TCHAR* path)
 {
-#if defined(USE_CART1)
+#if defined(USE_CART)
        if(check_file_extension(path, _T(".rom")) || 
           check_file_extension(path, _T(".bin")) || 
           check_file_extension(path, _T(".hex")) || 
+          check_file_extension(path, _T(".sc" )) || 
+          check_file_extension(path, _T(".sg" )) || 
           check_file_extension(path, _T(".gg" )) || 
           check_file_extension(path, _T(".col")) || 
           check_file_extension(path, _T(".sms")) || 
@@ -1889,15 +2835,21 @@ void open_any_file(const _TCHAR* path)
                return;
        }
 #endif
-#if defined(USE_FD1)
+#if defined(USE_FLOPPY_DISK)
        if(check_file_extension(path, _T(".d88")) || 
           check_file_extension(path, _T(".d77")) || 
           check_file_extension(path, _T(".1dd")) || 
           check_file_extension(path, _T(".td0")) || 
           check_file_extension(path, _T(".imd")) || 
           check_file_extension(path, _T(".dsk")) || 
+          check_file_extension(path, _T(".nfd")) || 
           check_file_extension(path, _T(".fdi")) || 
           check_file_extension(path, _T(".hdm")) || 
+          check_file_extension(path, _T(".hd5")) || 
+          check_file_extension(path, _T(".hd4")) || 
+          check_file_extension(path, _T(".hdb")) || 
+          check_file_extension(path, _T(".dd9")) || 
+          check_file_extension(path, _T(".dd6")) || 
           check_file_extension(path, _T(".tfd")) || 
           check_file_extension(path, _T(".xdf")) || 
           check_file_extension(path, _T(".2d" )) || 
@@ -1911,6 +2863,17 @@ void open_any_file(const _TCHAR* path)
                return;
        }
 #endif
+#if defined(USE_HARD_DISK)
+       if(check_file_extension(path, _T(".thd")) || 
+          check_file_extension(path, _T(".nhd")) || 
+          check_file_extension(path, _T(".hdi")) || 
+          check_file_extension(path, _T(".hdd"))) {
+               UPDATE_HISTORY(path, config.recent_hard_disk_path[0]);
+               my_tcscpy_s(config.initial_hard_disk_dir, _MAX_PATH, get_parent_dir(path));
+               emu->open_hard_disk(0, path);
+               return;
+       }
+#endif
 #if defined(USE_TAPE)
        if(check_file_extension(path, _T(".wav")) || 
           check_file_extension(path, _T(".cas")) || 
@@ -1926,9 +2889,18 @@ void open_any_file(const _TCHAR* path)
           check_file_extension(path, _T(".mtw")) || 
           check_file_extension(path, _T(".tap")) || 
           check_file_extension(path, _T(".t77"))) {
-               UPDATE_HISTORY(path, config.recent_tape_path);
+               UPDATE_HISTORY(path, config.recent_tape_path[0]);
                my_tcscpy_s(config.initial_tape_dir, _MAX_PATH, get_parent_dir(path));
-               emu->play_tape(path);
+               emu->play_tape(0, path);
+               return;
+       }
+#endif
+#if defined(USE_COMPACT_DISC)
+       if(check_file_extension(path, _T(".ccd" )) || 
+          check_file_extension(path, _T(".cue" ))) {
+               UPDATE_HISTORY(path, config.recent_compact_disc_path[0]);
+               my_tcscpy_s(config.initial_compact_disc_dir, _MAX_PATH, get_parent_dir(path));
+               emu->open_compact_disc(0, path);
                return;
        }
 #endif
@@ -1939,13 +2911,13 @@ void open_any_file(const _TCHAR* path)
           check_file_extension(path, _T(".mp4" )) || 
           check_file_extension(path, _T(".wmv" )) || 
           check_file_extension(path, _T(".ogv" ))) {
-               UPDATE_HISTORY(path, config.recent_laser_disc_path);
+               UPDATE_HISTORY(path, config.recent_laser_disc_path[0]);
                my_tcscpy_s(config.initial_laser_disc_dir, _MAX_PATH, get_parent_dir(path));
-               emu->open_laser_disc(path);
+               emu->open_laser_disc(0, path);
                return;
        }
 #endif
-#if defined(USE_BINARY_FILE1)
+#if defined(USE_BINARY_FILE)
        if(check_file_extension(path, _T(".ram")) || 
           check_file_extension(path, _T(".bin")) || 
           check_file_extension(path, _T(".hex"))) {
@@ -1955,6 +2927,15 @@ void open_any_file(const _TCHAR* path)
                return;
        }
 #endif
+#if defined(USE_BUBBLE)
+       if(check_file_extension(path, _T(".b77")) || 
+          check_file_extension(path, _T(".bbl"))) {
+               UPDATE_HISTORY(path, config.recent_bubble_casette_path[0]);
+               my_tcscpy_s(config.initial_bubble_casette_dir, _MAX_PATH, get_parent_dir(path));
+               emu->open_bubble_casette(0, path, 0);
+               return;
+       }
+#endif
 }
 #endif
 
@@ -2053,8 +3034,8 @@ void set_window(HWND hWnd, int mode)
        
        if(mode >= 0 && mode < MAX_WINDOW) {
                // window
-               int width = emu->get_window_width(mode);
-               int height = emu->get_window_height(mode);
+               int width = emu->get_window_mode_width(mode);
+               int height = emu->get_window_mode_height(mode);
                RECT rect = {0, 0, width, height};
                AdjustWindowRect(&rect, WS_OVERLAPPED | WS_CAPTION | WS_SYSMENU | WS_MINIMIZEBOX | WS_VISIBLE, TRUE);
                int dest_x = (int)((desktop_width - (rect.right - rect.left)) / 2);
@@ -2068,16 +3049,25 @@ void set_window(HWND hWnd, int mode)
                        SetWindowPos(hWnd, HWND_TOP, dest_x, dest_y, rect.right - rect.left, rect.bottom - rect.top, SWP_SHOWWINDOW);
                        now_fullscreen = false;
                        
-                       // show menu
+                       // show menu bar
                        show_menu_bar(hWnd);
+                       
                } else {
                        SetWindowPos(hWnd, NULL, dest_x, dest_y, rect.right - rect.left, rect.bottom - rect.top, SWP_NOZORDER);
                }
+               if(config.show_status_bar) {
+                       // show status bar
+                       show_status_bar(hWnd);
+               } else {
+                       // hide status bar
+                       hide_status_bar(hWnd);
+               }
                
+               int status_bar_height = get_status_bar_height();
                RECT rect_tmp;
                GetClientRect(hWnd, &rect_tmp);
-               if(rect_tmp.bottom != height) {
-                       rect.bottom += height - rect_tmp.bottom;
+               if(rect_tmp.bottom != height + status_bar_height) {
+                       rect.bottom += height + status_bar_height - rect_tmp.bottom;
                        dest_y = (int)((desktop_height - (rect.bottom - rect.top)) / 2);
                        dest_y = (dest_y < 0) ? 0 : dest_y;
                        SetWindowPos(hWnd, NULL, dest_x, dest_y, rect.right - rect.left, rect.bottom - rect.top, SWP_NOZORDER);
@@ -2117,9 +3107,12 @@ void set_window(HWND hWnd, int mode)
                        }
                        config.window_mode = mode;
                        
-                       // remove menu
+                       // hide menu bar
                        hide_menu_bar(hWnd);
                        
+                       // hide status bar
+                       hide_status_bar(hWnd);
+                       
                        // set screen size to emu class
                        emu->set_host_window_size(width, height, false);
                }
@@ -2131,284 +3124,20 @@ void set_window(HWND hWnd, int mode)
 // ----------------------------------------------------------------------------
 
 #ifdef USE_AUTO_KEY
-static const int auto_key_table_base[][2] = {
-       // 0x100: shift
-       // 0x200: kana
-       // 0x400: alphabet
-       // 0x800: ALPHABET
-       {0x0d,  0x000 | 0x0d},  // Enter
-       {0x20,  0x000 | 0x20},  // ' '
-#ifdef AUTO_KEY_US
-       {0x21,  0x100 | 0x31},  // '!'
-       {0x22,  0x100 | 0xba},  // '"'
-       {0x23,  0x100 | 0x33},  // '#'
-       {0x24,  0x100 | 0x34},  // '$'
-       {0x25,  0x100 | 0x35},  // '%'
-       {0x26,  0x100 | 0x37},  // '&'
-       {0x27,  0x000 | 0xba},  // '''
-       {0x28,  0x100 | 0x39},  // '('
-       {0x29,  0x100 | 0x30},  // ')'
-       {0x2a,  0x100 | 0x38},  // '*'
-       {0x2b,  0x100 | 0xde},  // '+'
-       {0x2c,  0x000 | 0xbc},  // ','
-       {0x2d,  0x000 | 0xbd},  // '-'
-       {0x2e,  0x000 | 0xbe},  // '.'
-       {0x2f,  0x000 | 0xbf},  // '/'
-#else
-       {0x21,  0x100 | 0x31},  // '!'
-       {0x22,  0x100 | 0x32},  // '"'
-       {0x23,  0x100 | 0x33},  // '#'
-       {0x24,  0x100 | 0x34},  // '$'
-       {0x25,  0x100 | 0x35},  // '%'
-       {0x26,  0x100 | 0x36},  // '&'
-       {0x27,  0x100 | 0x37},  // '''
-       {0x28,  0x100 | 0x38},  // '('
-       {0x29,  0x100 | 0x39},  // ')'
-       {0x2a,  0x100 | 0xba},  // '*'
-       {0x2b,  0x100 | 0xbb},  // '+'
-       {0x2c,  0x000 | 0xbc},  // ','
-       {0x2d,  0x000 | 0xbd},  // '-'
-       {0x2e,  0x000 | 0xbe},  // '.'
-       {0x2f,  0x000 | 0xbf},  // '/'
-#endif
-       {0x30,  0x000 | 0x30},  // '0'
-       {0x31,  0x000 | 0x31},  // '1'
-       {0x32,  0x000 | 0x32},  // '2'
-       {0x33,  0x000 | 0x33},  // '3'
-       {0x34,  0x000 | 0x34},  // '4'
-       {0x35,  0x000 | 0x35},  // '5'
-       {0x36,  0x000 | 0x36},  // '6'
-       {0x37,  0x000 | 0x37},  // '7'
-       {0x38,  0x000 | 0x38},  // '8'
-       {0x39,  0x000 | 0x39},  // '9'
-#ifdef AUTO_KEY_US
-       {0x3a,  0x100 | 0xbb},  // ':'
-       {0x3b,  0x000 | 0xbb},  // ';'
-       {0x3c,  0x100 | 0xbc},  // '<'
-       {0x3d,  0x000 | 0xde},  // '='
-       {0x3e,  0x100 | 0xbe},  // '>'
-       {0x3f,  0x100 | 0xbf},  // '?'
-       {0x40,  0x100 | 0x32},  // '@'
-#else
-       {0x3a,  0x000 | 0xba},  // ':'
-       {0x3b,  0x000 | 0xbb},  // ';'
-       {0x3c,  0x100 | 0xbc},  // '<'
-       {0x3d,  0x100 | 0xbd},  // '='
-       {0x3e,  0x100 | 0xbe},  // '>'
-       {0x3f,  0x100 | 0xbf},  // '?'
-       {0x40,  0x000 | 0xc0},  // '@'
-#endif
-       {0x41,  0x400 | 0x41},  // 'A'
-       {0x42,  0x400 | 0x42},  // 'B'
-       {0x43,  0x400 | 0x43},  // 'C'
-       {0x44,  0x400 | 0x44},  // 'D'
-       {0x45,  0x400 | 0x45},  // 'E'
-       {0x46,  0x400 | 0x46},  // 'F'
-       {0x47,  0x400 | 0x47},  // 'G'
-       {0x48,  0x400 | 0x48},  // 'H'
-       {0x49,  0x400 | 0x49},  // 'I'
-       {0x4a,  0x400 | 0x4a},  // 'J'
-       {0x4b,  0x400 | 0x4b},  // 'K'
-       {0x4c,  0x400 | 0x4c},  // 'L'
-       {0x4d,  0x400 | 0x4d},  // 'M'
-       {0x4e,  0x400 | 0x4e},  // 'N'
-       {0x4f,  0x400 | 0x4f},  // 'O'
-       {0x50,  0x400 | 0x50},  // 'P'
-       {0x51,  0x400 | 0x51},  // 'Q'
-       {0x52,  0x400 | 0x52},  // 'R'
-       {0x53,  0x400 | 0x53},  // 'S'
-       {0x54,  0x400 | 0x54},  // 'T'
-       {0x55,  0x400 | 0x55},  // 'U'
-       {0x56,  0x400 | 0x56},  // 'V'
-       {0x57,  0x400 | 0x57},  // 'W'
-       {0x58,  0x400 | 0x58},  // 'X'
-       {0x59,  0x400 | 0x59},  // 'Y'
-       {0x5a,  0x400 | 0x5a},  // 'Z'
-#ifdef AUTO_KEY_US
-       {0x5b,  0x000 | 0xc0},  // '['
-       {0x5c,  0x000 | 0xe2},  // '\'
-       {0x5d,  0x000 | 0xdb},  // ']'
-       {0x5e,  0x100 | 0x36},  // '^'
-       {0x5f,  0x100 | 0xbd},  // '_'
-       {0x60,  0x000 | 0xdd},  // '`'
-#else
-       {0x5b,  0x000 | 0xdb},  // '['
-       {0x5c,  0x000 | 0xdc},  // '\'
-       {0x5d,  0x000 | 0xdd},  // ']'
-       {0x5e,  0x000 | 0xde},  // '^'
-       {0x5f,  0x100 | 0xe2},  // '_'
-       {0x60,  0x100 | 0xc0},  // '`'
-#endif
-       {0x61,  0x800 | 0x41},  // 'a'
-       {0x62,  0x800 | 0x42},  // 'b'
-       {0x63,  0x800 | 0x43},  // 'c'
-       {0x64,  0x800 | 0x44},  // 'd'
-       {0x65,  0x800 | 0x45},  // 'e'
-       {0x66,  0x800 | 0x46},  // 'f'
-       {0x67,  0x800 | 0x47},  // 'g'
-       {0x68,  0x800 | 0x48},  // 'h'
-       {0x69,  0x800 | 0x49},  // 'i'
-       {0x6a,  0x800 | 0x4a},  // 'j'
-       {0x6b,  0x800 | 0x4b},  // 'k'
-       {0x6c,  0x800 | 0x4c},  // 'l'
-       {0x6d,  0x800 | 0x4d},  // 'm'
-       {0x6e,  0x800 | 0x4e},  // 'n'
-       {0x6f,  0x800 | 0x4f},  // 'o'
-       {0x70,  0x800 | 0x50},  // 'p'
-       {0x71,  0x800 | 0x51},  // 'q'
-       {0x72,  0x800 | 0x52},  // 'r'
-       {0x73,  0x800 | 0x53},  // 's'
-       {0x74,  0x800 | 0x54},  // 't'
-       {0x75,  0x800 | 0x55},  // 'u'
-       {0x76,  0x800 | 0x56},  // 'v'
-       {0x77,  0x800 | 0x57},  // 'w'
-       {0x78,  0x800 | 0x58},  // 'x'
-       {0x79,  0x800 | 0x59},  // 'y'
-       {0x7a,  0x800 | 0x5a},  // 'z'
-#ifdef AUTO_KEY_US
-       {0x7b,  0x100 | 0xc0},  // '{'
-       {0x7c,  0x100 | 0xe2},  // '|'
-       {0x7d,  0x100 | 0xdb},  // '}'
-       {0x7e,  0x100 | 0xdd},  // '~'
-#else
-       {0x7b,  0x100 | 0xdb},  // '{'
-       {0x7c,  0x100 | 0xdc},  // '|'
-       {0x7d,  0x100 | 0xdd},  // '}'
-       {0x7e,  0x100 | 0xde},  // '~'
-#endif
-       {0xa1,  0x300 | 0xbe},  // '
-       {0xa2,  0x300 | 0xdb},  // '
-       {0xa3,  0x300 | 0xdd},  // '
-       {0xa4,  0x300 | 0xbc},  // '
-       {0xa5,  0x300 | 0xbf},  // '¥'
-       {0xa6,  0x300 | 0x30},  // '¦'
-       {0xa7,  0x300 | 0x33},  // '§'
-       {0xa8,  0x300 | 0x45},  // '¨'
-       {0xa9,  0x300 | 0x34},  // '©'
-       {0xaa,  0x300 | 0x35},  // 'ª'
-       {0xab,  0x300 | 0x36},  // '«'
-       {0xac,  0x300 | 0x37},  // '¬'
-       {0xad,  0x300 | 0x38},  // '­'
-       {0xae,  0x300 | 0x39},  // '®'
-       {0xaf,  0x300 | 0x5a},  // '¯'
-       {0xb0,  0x200 | 0xdc},  // '°'
-       {0xb1,  0x200 | 0x33},  // '±'
-       {0xb2,  0x200 | 0x45},  // '²'
-       {0xb3,  0x200 | 0x34},  // '³'
-       {0xb4,  0x200 | 0x35},  // '´'
-       {0xb5,  0x200 | 0x36},  // 'µ'
-       {0xb6,  0x200 | 0x54},  // '¶'
-       {0xb7,  0x200 | 0x47},  // '·'
-       {0xb8,  0x200 | 0x48},  // '¸'
-       {0xb9,  0x200 | 0xba},  // '¹'
-       {0xba,  0x200 | 0x42},  // 'º'
-       {0xbb,  0x200 | 0x58},  // '»'
-       {0xbc,  0x200 | 0x44},  // '¼'
-       {0xbd,  0x200 | 0x52},  // '½'
-       {0xbe,  0x200 | 0x50},  // '¾'
-       {0xbf,  0x200 | 0x43},  // '¿'
-       {0xc0,  0x200 | 0x51},  // 'À'
-       {0xc1,  0x200 | 0x41},  // 'Á'
-       {0xc2,  0x200 | 0x5a},  // 'Â'
-       {0xc3,  0x200 | 0x57},  // 'Ã'
-       {0xc4,  0x200 | 0x53},  // 'Ä'
-       {0xc5,  0x200 | 0x55},  // 'Å'
-       {0xc6,  0x200 | 0x49},  // 'Æ'
-       {0xc7,  0x200 | 0x31},  // 'Ç'
-       {0xc8,  0x200 | 0xbc},  // 'È'
-       {0xc9,  0x200 | 0x4b},  // 'É'
-       {0xca,  0x200 | 0x46},  // 'Ê'
-       {0xcb,  0x200 | 0x56},  // 'Ë'
-       {0xcc,  0x200 | 0x32},  // 'Ì'
-       {0xcd,  0x200 | 0xde},  // 'Í'
-       {0xce,  0x200 | 0xbd},  // 'Î'
-       {0xcf,  0x200 | 0x4a},  // 'Ï'
-       {0xd0,  0x200 | 0x4e},  // 'Ð'
-       {0xd1,  0x200 | 0xdd},  // 'Ñ'
-       {0xd2,  0x200 | 0xbf},  // 'Ò'
-       {0xd3,  0x200 | 0x4d},  // 'Ó'
-       {0xd4,  0x200 | 0x37},  // 'Ô'
-       {0xd5,  0x200 | 0x38},  // 'Õ'
-       {0xd6,  0x200 | 0x39},  // 'Ö'
-       {0xd7,  0x200 | 0x4f},  // '×'
-       {0xd8,  0x200 | 0x4c},  // 'Ø'
-       {0xd9,  0x200 | 0xbe},  // 'Ù'
-       {0xda,  0x200 | 0xbb},  // 'Ú'
-       {0xdb,  0x200 | 0xe2},  // 'Û'
-       {0xdc,  0x200 | 0x30},  // 'Ü'
-       {0xdd,  0x200 | 0x59},  // 'Ý'
-       {0xde,  0x200 | 0xc0},  // 'Þ'
-       {0xdf,  0x200 | 0xdb},  // 'ß'
-       {-1, -1},
-};
-
 void start_auto_key()
 {
        if(OpenClipboard(NULL)) {
                HANDLE hClip = GetClipboardData(CF_TEXT);
                if(hClip) {
-                       static int auto_key_table[256];
-                       static bool initialized = false;
-                       
-                       if(!initialized) {
-                               memset(auto_key_table, 0, sizeof(auto_key_table));
-                               for(int i = 0;; i++) {
-                                       if(auto_key_table_base[i][0] == -1) {
-                                               break;
-                                       }
-                                       auto_key_table[auto_key_table_base[i][0]] = auto_key_table_base[i][1];
-                               }
-#ifdef USE_VM_AUTO_KEY_TABLE
-                               for(int i = 0;; i++) {
-                                       if(vm_auto_key_table_base[i][0] == -1) {
-                                               break;
-                                       }
-                                       auto_key_table[vm_auto_key_table_base[i][0]] = vm_auto_key_table_base[i][1];
-                               }
-#endif
-                               initialized = true;
-                       }
-                       
-                       FIFO* auto_key_buffer = emu->get_auto_key_buffer();
-                       auto_key_buffer->clear();
-                       
                        char* buf = (char*)GlobalLock(hClip);
-                       int size = strlen(buf), prev_kana = 0;
+                       int size = strlen(buf);
                        
-                       for(int i = 0; i < size; i++) {
-                               int code = buf[i] & 0xff;
-                               if((0x81 <= code && code <= 0x9f) || 0xe0 <= code) {
-                                       i++;    // kanji ?
-                                       continue;
-                               } else if(code == 0xa) {
-                                       continue;       // cr-lf
-                               }
-                               if((code = auto_key_table[code]) != 0) {
-                                       int kana = code & 0x200;
-                                       if(prev_kana != kana) {
-                                               auto_key_buffer->write(0xf2);
-                                       }
-                                       prev_kana = kana;
-#if defined(USE_AUTO_KEY_NO_CAPS)
-                                       if((code & 0x100) && !(code & (0x400 | 0x800))) {
-#elif defined(USE_AUTO_KEY_CAPS)
-                                       if(code & (0x100 | 0x800)) {
-#else
-                                       if(code & (0x100 | 0x400)) {
-#endif
-                                               auto_key_buffer->write((code & 0xff) | 0x100);
-                                       } else {
-                                               auto_key_buffer->write(code & 0xff);
-                                       }
-                               }
-                       }
-                       if(prev_kana) {
-                               auto_key_buffer->write(0xf2);
+                       if(size > 0) {
+                               emu->stop_auto_key();
+                               emu->set_auto_key_list(buf, size);
+                               emu->start_auto_key();
                        }
                        GlobalUnlock(hClip);
-                       
-                       emu->stop_auto_key();
-                       emu->start_auto_key();
                }
                CloseClipboard();
        }
@@ -2702,7 +3431,6 @@ BOOL CALLBACK JoyWndProc(HWND hDlg, UINT iMsg, WPARAM wParam, LPARAM lParam)
 
 #ifdef ONE_BOARD_MICRO_COMPUTER
 #define MAX_FONT_SIZE 32
-HFONT hFont[MAX_FONT_SIZE];
 HWND hButton[MAX_BUTTONS];
 WNDPROC ButtonOldProc[MAX_BUTTONS];
 
@@ -2712,17 +3440,44 @@ LRESULT CALLBACK ButtonSubProc(HWND hWnd, UINT iMsg, WPARAM wParam, LPARAM lPara
                if(hWnd == hButton[i]) {
                        switch(iMsg) {
                        case WM_KEYDOWN:
+                               if(emu) {
+                                       bool extended = ((HIWORD(lParam) & 0x100) != 0);
+                                       bool repeat = ((HIWORD(lParam) & 0x4000) != 0);
+                                       emu->key_down(LOBYTE(wParam), extended, repeat);
+                               }
+                               break;
                        case WM_SYSKEYDOWN:
                                if(emu) {
-                                       emu->key_down(LOBYTE(wParam), false);
+                                       bool extended = ((HIWORD(lParam) & 0x100) != 0);
+                                       bool repeat = ((HIWORD(lParam) & 0x4000) != 0);
+                                       emu->key_down(LOBYTE(wParam), extended, repeat);
                                }
-                               return 0;
+#ifdef USE_ALT_F10_KEY
+                               return 0;       // not activate menu when hit ALT/F10
+#else
+                               break;
+#endif
                        case WM_KEYUP:
+                               if(emu) {
+                                       bool extended = ((HIWORD(lParam) & 0x100) != 0);
+                                       emu->key_up(LOBYTE(wParam), extended);
+                               }
+                               break;
                        case WM_SYSKEYUP:
                                if(emu) {
-                                       emu->key_up(LOBYTE(wParam));
+                                       bool extended = ((HIWORD(lParam) & 0x100) != 0);
+                                       emu->key_up(LOBYTE(wParam), extended);
                                }
-                               return 0;
+#ifdef USE_ALT_F10_KEY
+                               return 0;       // not activate menu when hit ALT/F10
+#else
+                               break;
+#endif
+                       case WM_CHAR:
+                               if(emu) {
+                                       emu->key_char(LOBYTE(wParam));
+                               }
+                               break;
                        }
                        return CallWindowProc(ButtonOldProc[i], hWnd, iMsg, wParam, lParam);
                }
@@ -2732,45 +3487,72 @@ LRESULT CALLBACK ButtonSubProc(HWND hWnd, UINT iMsg, WPARAM wParam, LPARAM lPara
 
 void create_buttons(HWND hWnd)
 {
-       memset(hFont, 0, sizeof(hFont));
        for(int i = 0; i < MAX_BUTTONS; i++) {
-               hButton[i] = CreateWindow(_T("BUTTON"), vm_buttons[i].caption,
-                                         WS_CHILD | WS_VISIBLE | BS_PUSHBUTTON | (_tcsstr(vm_buttons[i].caption, _T("\n")) ? BS_MULTILINE : 0),
+               hButton[i] = CreateWindow(_T("BUTTON"), NULL/*vm_buttons[i].caption*/,
+                                         WS_CHILD | WS_VISIBLE | BS_PUSHBUTTON | BS_OWNERDRAW/*(_tcsstr(vm_buttons[i].caption, _T("\n")) ? BS_MULTILINE : 0)*/,
                                          vm_buttons[i].x, vm_buttons[i].y,
                                          vm_buttons[i].width, vm_buttons[i].height,
                                          hWnd, (HMENU)(ID_BUTTON + i), (HINSTANCE)GetModuleHandle(0), NULL);
                ButtonOldProc[i] = (WNDPROC)(LONG_PTR)GetWindowLong(hButton[i], GWL_WNDPROC);
                SetWindowLong(hButton[i], GWL_WNDPROC, (LONG)(LONG_PTR)ButtonSubProc);
-               //HFONT hFont = GetWindowFont(hButton[i]);
-               if(!hFont[vm_buttons[i].font_size]) {
-                       LOGFONT logfont;
-                       logfont.lfEscapement = 0;
-                       logfont.lfOrientation = 0;
-                       logfont.lfWeight = FW_NORMAL;
-                       logfont.lfItalic = FALSE;
-                       logfont.lfUnderline = FALSE;
-                       logfont.lfStrikeOut = FALSE;
-                       logfont.lfCharSet = DEFAULT_CHARSET;
-                       logfont.lfOutPrecision = OUT_TT_PRECIS;
-                       logfont.lfClipPrecision = CLIP_DEFAULT_PRECIS;
-                       logfont.lfQuality = DEFAULT_QUALITY;
-                       logfont.lfPitchAndFamily = FIXED_PITCH | FF_DONTCARE;
-                       my_tcscpy_s(logfont.lfFaceName, LF_FACESIZE, _T("Arial"));
-                       logfont.lfHeight = vm_buttons[i].font_size;
-                       logfont.lfWidth = vm_buttons[i].font_size >> 1;
-                       hFont[vm_buttons[i].font_size] = CreateFontIndirect(&logfont);
-               }
-               SetWindowFont(hButton[i], hFont[vm_buttons[i].font_size], TRUE);
        }
 }
 
-void release_buttons()
+void draw_button(HDC hDC, UINT index, UINT pressed)
 {
-       for(int i = 0; i < MAX_FONT_SIZE; i++) {
-               if(hFont[i]) {
-                       DeleteObject(hFont[i]);
+       HINSTANCE hInstance = (HINSTANCE)GetModuleHandle(0);
+       _TCHAR name[24];
+       
+       _stprintf(name, _T("IDI_BITMAP_BUTTON%02d"), index);
+#if 1
+       // load png from resource
+       HRSRC hResource = FindResource(hInstance, name, _T("IMAGE"));
+       if(hResource != NULL) {
+               const void* pResourceData = LockResource(LoadResource(hInstance, hResource));
+               if(pResourceData != NULL) {
+                       DWORD dwResourceSize = SizeofResource(hInstance, hResource);
+                       HGLOBAL hResourceBuffer = GlobalAlloc(GMEM_MOVEABLE, dwResourceSize);
+                       if(hResourceBuffer != NULL) {
+                               void* pResourceBuffer = GlobalLock(hResourceBuffer);
+                               if(pResourceBuffer != NULL) {
+                                       CopyMemory(pResourceBuffer, pResourceData, dwResourceSize);
+                                       IStream* pIStream = NULL;
+                                       if(CreateStreamOnHGlobal(hResourceBuffer, FALSE, &pIStream) == S_OK) {
+                                               Gdiplus::Bitmap *pBitmap = Gdiplus::Bitmap::FromStream(pIStream);
+                                               if(pBitmap != NULL) {
+                                                       Gdiplus::Graphics graphics(hDC);
+                                                       if(pressed) {
+                                                               graphics.DrawImage(pBitmap, 2,  2, pBitmap->GetWidth() - 2, pBitmap->GetHeight() - 2);
+                                                       } else {
+                                                               graphics.DrawImage(pBitmap, 1, 1);
+                                                       }
+                                                       delete pBitmap;
+                                               }
+                                       }
+                               }
+                               GlobalUnlock(hResourceBuffer);
+                       }
+                       GlobalFree(hResourceBuffer);
                }
        }
+#else
+       // load bitmap from resource
+       HDC hmdc = CreateCompatibleDC(hDC);
+       HBITMAP hBitmap = LoadBitmap(hInstance, name);
+       BITMAP bmp;
+       GetObject(hBitmap, sizeof(BITMAP), &bmp);
+       int w = (int)bmp.bmWidth;
+       int h = (int)bmp.bmHeight;
+       HBITMAP hOldBitmap = (HBITMAP)SelectObject(hmdc, hBitmap);
+       if(pressed) {
+               StretchBlt(hDC, 2, 2, w - 2, h - 2, hmdc, 0, 0, w, h, SRCCOPY);
+       } else {
+               BitBlt(hDC, 1, 1, w, h, hmdc, 0, 0, SRCCOPY);
+       }
+       SelectObject(hmdc, hOldBitmap);
+       DeleteObject(hBitmap);
+       DeleteDC(hmdc);
+#endif
 }
 #endif