00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034
00035
00059 #include "../StdAfx.h"
00060
00061 #if defined(_WIN32)
00062 #include <process.h>
00063
00064 #include "gui_win32_font.h"
00065 #include "keymap.h"
00066 #include "../Configurator.h"
00067 #include "../VGA.h"
00068 #include "../Keyboard.h"
00069
00070 #include "gui.h"
00071
00072 class bx_win32_gui_c : public bx_gui_c
00073 {
00074 public:
00075 bx_win32_gui_c(CConfigurator* cfg)
00076 {
00077 myCfg = cfg;
00078 bx_keymap = new bx_keymap_c(cfg);
00079 };
00080
00081 virtual void specific_init(unsigned x_tilesize, unsigned y_tilesize);
00082 virtual void text_update(u8* old_text, u8* new_text,
00083 unsigned long cursor_x, unsigned long cursor_y,
00084 bx_vga_tminfo_t tm_info, unsigned rows);
00085 virtual void graphics_tile_update(u8* snapshot, unsigned x, unsigned y);
00086 virtual void handle_events(void);
00087 virtual void flush(void);
00088 virtual void clear_screen(void);
00089 virtual bool palette_change(unsigned index, unsigned red, unsigned green,
00090 unsigned blue);
00091 virtual void dimension_update(unsigned x, unsigned y, unsigned fheight = 0,
00092 unsigned fwidth = 0, unsigned bpp = 8);
00093 virtual void mouse_enabled_changed_specific(bool val);
00094 virtual void exit(void);
00095
00096 virtual void get_capabilities(u16* xres, u16* yres, u16* bpp);
00097 private:
00098 CConfigurator* myCfg;
00099 };
00100
00101
00102
00103 static bx_win32_gui_c* theGui = NULL;
00104 IMPLEMENT_GUI_PLUGIN_CODE(win32)
00105 #define EXIT_GUI_SHUTDOWN 1
00106 #define EXIT_GMH_FAILURE 2
00107 #define EXIT_FONT_BITMAP_ERROR 3
00108 #define EXIT_NORMAL 4
00109 #define EXIT_HEADER_BITMAP_ERROR 5
00110
00111
00112 #define SCANCODE_BUFSIZE 20
00113 #define MOUSE_PRESSED 0x20000000
00114 #define MOUSE_MOTION 0x22000000
00115 #define BX_SYSKEY (KF_UP | KF_REPEAT | KF_ALTDOWN)
00116 void enq_key_event(u32, u32);
00117 void enq_mouse_event(void);
00118
00119 struct QueueEvent
00120 {
00121 u32 key_event;
00122 int mouse_x;
00123 int mouse_y;
00124 int mouse_z;
00125 int mouse_button_state;
00126 };
00127 QueueEvent* deq_key_event(void);
00128
00129 static QueueEvent keyevents[SCANCODE_BUFSIZE];
00130 static unsigned head = 0, tail = 0;
00131 static int mouse_button_state = 0;
00132 static int ms_xdelta = 0, ms_ydelta = 0, ms_zdelta = 0;
00133 static int ms_lastx = 0, ms_lasty = 0;
00134 static int ms_savedx = 0, ms_savedy = 0;
00135 static BOOL mouseCaptureMode, mouseCaptureNew, mouseToggleReq;
00136 static unsigned long workerThread = 0;
00137 static DWORD workerThreadID = 0;
00138 static int mouse_buttons = 3;
00139
00140
00141 static unsigned x_tilesize = 0, y_tilesize = 0;
00142 static BITMAPINFO* bitmap_info = (BITMAPINFO*) 0;
00143 static RGBQUAD* cmap_index;
00144 static HBITMAP MemoryBitmap = NULL;
00145 static HDC MemoryDC = NULL;
00146 static RECT updated_area;
00147 static BOOL updated_area_valid = false;
00148 static HWND desktopWindow;
00149 static RECT desktop;
00150 static BOOL queryFullScreen = false;
00151 static int desktop_x, desktop_y;
00152
00153
00154 static unsigned prev_cursor_x = 0;
00155 static unsigned prev_cursor_y = 0;
00156 static HBITMAP vgafont[256];
00157 static int xChar = 8, yChar = 16;
00158 static unsigned int text_rows = 25, text_cols = 80;
00159 static u8 text_pal_idx[16];
00160
00161 static u8 h_panning = 0, v_panning = 0;
00162 static u16 line_compare = 1023;
00163
00164
00165 static unsigned dimension_x, dimension_y, current_bpp;
00166 static unsigned stretched_x, stretched_y;
00167 static unsigned stretch_factor = 1;
00168 static BOOL BxTextMode = true;
00169 static BOOL fix_size = false;
00170 static HWND hotKeyReceiver = NULL;
00171 static HWND saveParent = NULL;
00172
00173 static char szAppName[] = "ES40 Emulator";
00174 static char szWindowName[] = "ES40 Emulator";
00175
00176 typedef struct
00177 {
00178 HINSTANCE hInstance;
00179
00180 CRITICAL_SECTION drawCS;
00181 CRITICAL_SECTION keyCS;
00182 CRITICAL_SECTION mouseCS;
00183
00184 int kill;
00185 BOOL UIinited;
00186 HWND mainWnd;
00187 HWND simWnd;
00188 } sharedThreadInfo;
00189
00190 sharedThreadInfo stInfo;
00191
00192 LRESULT CALLBACK mainWndProc(HWND, UINT, WPARAM, LPARAM);
00193 LRESULT CALLBACK simWndProc(HWND, UINT, WPARAM, LPARAM);
00194 VOID UIThread(PVOID);
00195 void terminateEmul(int);
00196 void create_vga_font(void);
00197 static unsigned char reverse_bitorder(unsigned char);
00198 void DrawBitmap(HDC, HBITMAP, int, int, int, int, int, int,
00199 DWORD, unsigned char);
00200 void DrawChar(HDC, unsigned char, int, int, unsigned char cColor,
00201 int, int);
00202 void updateUpdated(int, int, int, int);
00203
00204 u32 win32_to_bx_key[2][0x100] =
00205 {
00206 {
00207
00208 0,
00209 BX_KEY_ESC,
00210 BX_KEY_1,
00211 BX_KEY_2,
00212 BX_KEY_3,
00213 BX_KEY_4,
00214 BX_KEY_5,
00215 BX_KEY_6,
00216 BX_KEY_7,
00217 BX_KEY_8,
00218 BX_KEY_9,
00219 BX_KEY_0,
00220 BX_KEY_MINUS,
00221 BX_KEY_EQUALS,
00222 BX_KEY_BACKSPACE,
00223 BX_KEY_TAB,
00224
00225
00226 BX_KEY_Q,
00227 BX_KEY_W,
00228 BX_KEY_E,
00229 BX_KEY_R,
00230 BX_KEY_T,
00231 BX_KEY_Y,
00232 BX_KEY_U,
00233 BX_KEY_I,
00234 BX_KEY_O,
00235 BX_KEY_P,
00236 BX_KEY_LEFT_BRACKET,
00237 BX_KEY_RIGHT_BRACKET,
00238 BX_KEY_ENTER,
00239 BX_KEY_CTRL_L,
00240 BX_KEY_A,
00241 BX_KEY_S,
00242
00243
00244 BX_KEY_D,
00245 BX_KEY_F,
00246 BX_KEY_G,
00247 BX_KEY_H,
00248 BX_KEY_J,
00249 BX_KEY_K,
00250 BX_KEY_L,
00251 BX_KEY_SEMICOLON,
00252 BX_KEY_SINGLE_QUOTE,
00253 BX_KEY_GRAVE,
00254 BX_KEY_SHIFT_L,
00255 BX_KEY_BACKSLASH,
00256 BX_KEY_Z,
00257 BX_KEY_X,
00258 BX_KEY_C,
00259 BX_KEY_V,
00260
00261
00262 BX_KEY_B,
00263 BX_KEY_N,
00264 BX_KEY_M,
00265 BX_KEY_COMMA,
00266 BX_KEY_PERIOD,
00267 BX_KEY_SLASH,
00268 BX_KEY_SHIFT_R,
00269 BX_KEY_KP_MULTIPLY,
00270 BX_KEY_ALT_L,
00271 BX_KEY_SPACE,
00272 BX_KEY_CAPS_LOCK,
00273 BX_KEY_F1,
00274 BX_KEY_F2,
00275 BX_KEY_F3,
00276 BX_KEY_F4,
00277 BX_KEY_F5,
00278
00279
00280 BX_KEY_F6,
00281 BX_KEY_F7,
00282 BX_KEY_F8,
00283 BX_KEY_F9,
00284 BX_KEY_F10,
00285 BX_KEY_PAUSE,
00286 BX_KEY_SCRL_LOCK,
00287 BX_KEY_KP_HOME,
00288 BX_KEY_KP_UP,
00289 BX_KEY_KP_PAGE_UP,
00290 BX_KEY_KP_SUBTRACT,
00291 BX_KEY_KP_LEFT,
00292 BX_KEY_KP_5,
00293 BX_KEY_KP_RIGHT,
00294 BX_KEY_KP_ADD,
00295 BX_KEY_KP_END,
00296
00297
00298 BX_KEY_KP_DOWN,
00299 BX_KEY_KP_PAGE_DOWN,
00300 BX_KEY_KP_INSERT,
00301 BX_KEY_KP_DELETE,
00302 0,
00303 0,
00304 BX_KEY_LEFT_BACKSLASH,
00305 BX_KEY_F11,
00306 BX_KEY_F12,
00307 0,
00308 0,
00309 0,
00310 0,
00311 0,
00312 0,
00313 0,
00314
00315
00316 0,
00317 0,
00318 0,
00319 0,
00320 0,
00321 0,
00322 0,
00323 0,
00324 0,
00325 0,
00326 0,
00327 0,
00328 0,
00329 0,
00330 0,
00331 0,
00332
00333
00334 0,
00335 0,
00336 0,
00337 0,
00338 0,
00339 0,
00340 0,
00341 0,
00342 0,
00343 0,
00344 0,
00345 0,
00346 0,
00347 0,
00348 0,
00349 0,
00350 },
00351 {
00352
00353 0,
00354 0,
00355 0,
00356 0,
00357 0,
00358 0,
00359 0,
00360 0,
00361 0,
00362 0,
00363 0,
00364 0,
00365 0,
00366 0,
00367 0,
00368 0,
00369
00370
00371 0,
00372 0,
00373 0,
00374 0,
00375 0,
00376 0,
00377 0,
00378 0,
00379 0,
00380 0,
00381 0,
00382 0,
00383 BX_KEY_KP_ENTER,
00384 BX_KEY_CTRL_R,
00385 0,
00386 0,
00387
00388
00389 0,
00390 BX_KEY_POWER_CALC,
00391 0,
00392 0,
00393 0,
00394 0,
00395 0,
00396 0,
00397 0,
00398 0,
00399 0,
00400 0,
00401 0,
00402 0,
00403 0,
00404 0,
00405
00406
00407 0,
00408 0,
00409 BX_KEY_INT_HOME,
00410 0,
00411 0,
00412 BX_KEY_KP_DIVIDE,
00413 0,
00414 BX_KEY_PRINT,
00415 BX_KEY_ALT_R,
00416 0,
00417 0,
00418 0,
00419 0,
00420 0,
00421 0,
00422 0,
00423
00424
00425 0,
00426 0,
00427 0,
00428 0,
00429 0,
00430 BX_KEY_NUM_LOCK,
00431 0,
00432 BX_KEY_HOME,
00433 BX_KEY_UP,
00434 BX_KEY_PAGE_UP,
00435 0,
00436 BX_KEY_LEFT,
00437 0,
00438 BX_KEY_RIGHT,
00439 0,
00440 BX_KEY_END,
00441
00442
00443 BX_KEY_DOWN,
00444 BX_KEY_PAGE_DOWN,
00445 BX_KEY_INSERT,
00446 BX_KEY_DELETE,
00447 0,
00448 0,
00449 0,
00450 0,
00451 0,
00452 0,
00453 0,
00454 BX_KEY_WIN_L,
00455 BX_KEY_WIN_R,
00456 BX_KEY_MENU,
00457 BX_KEY_POWER_POWER,
00458 BX_KEY_POWER_SLEEP,
00459
00460
00461 0,
00462 0,
00463 0,
00464 BX_KEY_POWER_WAKE,
00465 0,
00466 BX_KEY_INT_SEARCH,
00467 BX_KEY_INT_FAV,
00468 0,
00469 BX_KEY_INT_STOP,
00470 BX_KEY_INT_FORWARD,
00471 BX_KEY_INT_BACK,
00472 BX_KEY_POWER_MYCOMP,
00473 BX_KEY_INT_MAIL,
00474 0,
00475 0,
00476 0,
00477 }
00478 };
00479
00480
00481 #if defined(__MINGW32__) || defined(_MSC_VER)
00482 VOID CALLBACK MyTimer(HWND, UINT, UINT, DWORD);
00483 void alarm(int);
00484 void bx_signal_handler(int);
00485 #endif
00486 static void processMouseXY(int x, int y, int z, int windows_state,
00487 int implied_state_change)
00488 {
00489 int bx_state;
00490 int old_bx_state;
00491 EnterCriticalSection(&stInfo.mouseCS);
00492 bx_state = ((windows_state & MK_LBUTTON) ? 1 : 0) +
00493 ((windows_state & MK_RBUTTON) ? 2 : 0) +
00494 ((windows_state & MK_MBUTTON) ? 4 : 0);
00495 old_bx_state = bx_state ^ implied_state_change;
00496 if(old_bx_state != mouse_button_state)
00497 {
00498
00499
00500 BX_INFO(("&&&missing mouse state change"));
00501 EnterCriticalSection(&stInfo.keyCS);
00502 enq_mouse_event();
00503 mouse_button_state = old_bx_state;
00504 enq_key_event(mouse_button_state, MOUSE_PRESSED);
00505 LeaveCriticalSection(&stInfo.keyCS);
00506 }
00507
00508 ms_ydelta = ms_savedy - y;
00509 ms_xdelta = x - ms_savedx;
00510 ms_zdelta = z;
00511 ms_lastx = x;
00512 ms_lasty = y;
00513 if(bx_state != mouse_button_state)
00514 {
00515 EnterCriticalSection(&stInfo.keyCS);
00516 enq_mouse_event();
00517 mouse_button_state = bx_state;
00518 enq_key_event(mouse_button_state, MOUSE_PRESSED);
00519 LeaveCriticalSection(&stInfo.keyCS);
00520 }
00521
00522 LeaveCriticalSection(&stInfo.mouseCS);
00523 }
00524
00525 static void resetDelta()
00526 {
00527 EnterCriticalSection(&stInfo.mouseCS);
00528 ms_savedx = ms_lastx;
00529 ms_savedy = ms_lasty;
00530 ms_ydelta = ms_xdelta = ms_zdelta = 0;
00531 LeaveCriticalSection(&stInfo.mouseCS);
00532 }
00533
00534 static void cursorWarped()
00535 {
00536 EnterCriticalSection(&stInfo.mouseCS);
00537 EnterCriticalSection(&stInfo.keyCS);
00538 enq_mouse_event();
00539 LeaveCriticalSection(&stInfo.keyCS);
00540 ms_lastx = stretched_x / 2;
00541 ms_lasty = stretched_y / 2;
00542 ms_savedx = ms_lastx;
00543 ms_savedy = ms_lasty;
00544 LeaveCriticalSection(&stInfo.mouseCS);
00545 }
00546
00547
00548 void terminateEmul(int reason)
00549 {
00550
00551
00552
00553 if(x_tilesize != 0)
00554 {
00555 DeleteCriticalSection(&stInfo.drawCS);
00556 DeleteCriticalSection(&stInfo.keyCS);
00557 DeleteCriticalSection(&stInfo.mouseCS);
00558 }
00559
00560 x_tilesize = 0;
00561
00562 if(MemoryDC)
00563 DeleteDC(MemoryDC);
00564 if(MemoryBitmap)
00565 DeleteObject(MemoryBitmap);
00566
00567 if(bitmap_info)
00568 delete[] (char*) bitmap_info;
00569
00570 for(unsigned c = 0; c < 256; c++)
00571 if(vgafont[c])
00572 DeleteObject(vgafont[c]);
00573
00574 switch(reason)
00575 {
00576 case EXIT_GUI_SHUTDOWN:
00577 FAILURE(Graceful, "Window closed, exiting!");
00578 break;
00579
00580 case EXIT_GMH_FAILURE:
00581 FAILURE(Win32, "GetModuleHandle failure!");
00582 break;
00583
00584 case EXIT_FONT_BITMAP_ERROR:
00585 FAILURE(Win32, "Font bitmap creation failure!");
00586 break;
00587
00588 case EXIT_NORMAL:
00589 break;
00590 }
00591 }
00592
00593
00594
00595
00596
00597
00598
00599
00600
00601
00602 void bx_win32_gui_c::specific_init(unsigned tilewidth, unsigned tileheight)
00603 {
00604 int i;
00605
00606
00607 desktopWindow = GetDesktopWindow();
00608 GetWindowRect(desktopWindow, &desktop);
00609 desktop_x = desktop.right - desktop.left;
00610 desktop_y = desktop.bottom - desktop.top;
00611 hotKeyReceiver = stInfo.simWnd;
00612 BX_INFO(("Desktop Window dimensions: %d x %d", desktop_x, desktop_y));
00613
00614 static RGBQUAD black_quad ={ 0, 0, 0, 0};
00615 stInfo.kill = 0;
00616 stInfo.UIinited = false;
00617 InitializeCriticalSection(&stInfo.drawCS);
00618 InitializeCriticalSection(&stInfo.keyCS);
00619 InitializeCriticalSection(&stInfo.mouseCS);
00620
00621 x_tilesize = tilewidth;
00622 y_tilesize = tileheight;
00623
00624 mouseCaptureMode = false;
00625 mouseCaptureNew = false;
00626 mouseToggleReq = false;
00627
00628 mouse_buttons = GetSystemMetrics(SM_CMOUSEBUTTONS);
00629 BX_INFO(("Number of Mouse Buttons = %d", mouse_buttons));
00630
00631 stInfo.hInstance = GetModuleHandle(NULL);
00632
00633 dimension_x = 640;
00634 dimension_y = 480;
00635 current_bpp = 8;
00636 stretched_x = dimension_x;
00637 stretched_y = dimension_y;
00638 stretch_factor = 1;
00639
00640 for(unsigned c = 0; c < 256; c++)
00641 vgafont[c] = NULL;
00642 create_vga_font();
00643
00644 bitmap_info = (BITMAPINFO*) new char[sizeof(BITMAPINFOHEADER) + 259 * sizeof(RGBQUAD)];
00645 bitmap_info->bmiHeader.biSize = sizeof(BITMAPINFOHEADER);
00646 bitmap_info->bmiHeader.biWidth = x_tilesize;
00647
00648
00649 bitmap_info->bmiHeader.biHeight = -(LONG) y_tilesize;
00650 bitmap_info->bmiHeader.biPlanes = 1;
00651 bitmap_info->bmiHeader.biBitCount = 8;
00652 bitmap_info->bmiHeader.biCompression = BI_RGB;
00653 bitmap_info->bmiHeader.biSizeImage = x_tilesize * y_tilesize * 4;
00654
00655
00656 bitmap_info->bmiHeader.biXPelsPerMeter = 4500;
00657 bitmap_info->bmiHeader.biYPelsPerMeter = 4500;
00658 bitmap_info->bmiHeader.biClrUsed = 256;
00659 bitmap_info->bmiHeader.biClrImportant = 0;
00660 cmap_index = bitmap_info->bmiColors;
00661
00662
00663 cmap_index[0] = black_quad;
00664 for(i = 1; i < 259; i++)
00665 {
00666 cmap_index[i] = cmap_index[0];
00667 }
00668
00669 if(stInfo.hInstance)
00670 workerThread = _beginthread(UIThread, 0, NULL);
00671 else
00672 terminateEmul(EXIT_GMH_FAILURE);
00673
00674
00675 if((stInfo.kill == 0) && (FindWindow(szAppName, NULL) == NULL))
00676 Sleep(500);
00677
00678
00679
00680
00681
00682 if(myCfg->get_bool_value("keyboard.use_mapping"))
00683 {
00684 bx_keymap->loadKeymap(NULL);
00685 }
00686 }
00687
00688 void resize_main_window()
00689 {
00690 RECT R;
00691 unsigned long mainStyle;
00692
00693
00694
00695 if((desktop_y > 0) && (stretched_y >= (unsigned) desktop_y))
00696 {
00697 if(!queryFullScreen)
00698 {
00699 MessageBox(NULL, "Going into fullscreen mode -- Alt-Enter to revert",
00700 "Going fullscreen", MB_APPLMODAL);
00701 queryFullScreen = true;
00702 }
00703
00704
00705 mainStyle = GetWindowLong(stInfo.mainWnd, GWL_STYLE);
00706 mainStyle &= ~(WS_CAPTION | WS_BORDER);
00707 SetWindowLong(stInfo.mainWnd, GWL_STYLE, mainStyle);
00708
00709
00710 if(saveParent = SetParent(stInfo.mainWnd, desktopWindow))
00711 {
00712 BX_DEBUG(("Saved parent window"));
00713 SetWindowPos(stInfo.mainWnd, HWND_TOPMOST, desktop.left, desktop.top,
00714 desktop.right, desktop.bottom, SWP_SHOWWINDOW);
00715 }
00716 }
00717 else
00718 {
00719 if(saveParent)
00720 {
00721 BX_DEBUG(("Restoring parent window"));
00722 SetParent(stInfo.mainWnd, saveParent);
00723 saveParent = NULL;
00724 }
00725
00726
00727 mainStyle = GetWindowLong(stInfo.mainWnd, GWL_STYLE);
00728 mainStyle |= WS_CAPTION | WS_BORDER;
00729 SetWindowLong(stInfo.mainWnd, GWL_STYLE, mainStyle);
00730 SetRect(&R, 0, 0, stretched_x, stretched_y);
00731
00732 DWORD style = GetWindowLong(stInfo.simWnd, GWL_STYLE);
00733 DWORD exstyle = GetWindowLong(stInfo.simWnd, GWL_EXSTYLE);
00734 AdjustWindowRectEx(&R, style, false, exstyle);
00735 style = GetWindowLong(stInfo.mainWnd, GWL_STYLE);
00736 AdjustWindowRect(&R, style, false);
00737 SetWindowPos(stInfo.mainWnd, HWND_TOP, 0, 0, R.right - R.left,
00738 R.bottom - R.top, SWP_NOMOVE | SWP_NOZORDER);
00739 }
00740
00741 fix_size = false;
00742 }
00743
00744
00745 VOID UIThread(PVOID pvoid)
00746 {
00747 MSG msg;
00748 HDC hdc;
00749 WNDCLASS wndclass;
00750 RECT wndRect;
00751
00752 workerThreadID = GetCurrentThreadId();
00753
00754 GetClassInfo(NULL, WC_DIALOG, &wndclass);
00755 wndclass.style = CS_HREDRAW | CS_VREDRAW;
00756 wndclass.lpfnWndProc = mainWndProc;
00757 wndclass.cbClsExtra = 0;
00758 wndclass.cbWndExtra = 0;
00759 wndclass.hInstance = stInfo.hInstance;
00760 wndclass.lpszMenuName = NULL;
00761 wndclass.lpszClassName = szAppName;
00762
00763 RegisterClass(&wndclass);
00764
00765 wndclass.style = CS_HREDRAW | CS_VREDRAW;
00766 wndclass.lpfnWndProc = simWndProc;
00767 wndclass.cbClsExtra = 0;
00768 wndclass.cbWndExtra = 0;
00769 wndclass.hInstance = stInfo.hInstance;
00770 wndclass.hIcon = NULL;
00771 wndclass.hCursor = LoadCursor(NULL, IDC_ARROW);
00772 wndclass.hbrBackground = (HBRUSH) GetStockObject(BLACK_BRUSH);
00773 wndclass.lpszMenuName = NULL;
00774 wndclass.lpszClassName = "SIMWINDOW";
00775
00776 RegisterClass(&wndclass);
00777
00778 SetRect(&wndRect, 0, 0, stretched_x, stretched_y);
00779
00780 DWORD sim_style = WS_CHILD;
00781 DWORD sim_exstyle = WS_EX_CLIENTEDGE;
00782 AdjustWindowRectEx(&wndRect, sim_style, false, sim_exstyle);
00783
00784 DWORD main_style = WS_CAPTION | WS_SYSMENU | WS_MINIMIZEBOX;
00785 AdjustWindowRect(&wndRect, main_style, false);
00786 stInfo.mainWnd = CreateWindow(szAppName, szWindowName, main_style,
00787 CW_USEDEFAULT, CW_USEDEFAULT,
00788 wndRect.right - wndRect.left,
00789 wndRect.bottom - wndRect.top, NULL, NULL,
00790 stInfo.hInstance, NULL);
00791
00792 if(stInfo.mainWnd)
00793 {
00794
00795
00796 stInfo.simWnd = CreateWindowEx(sim_exstyle, "SIMWINDOW", "", sim_style, 0,
00797 0, 0, 0, stInfo.mainWnd, NULL,
00798 stInfo.hInstance, NULL);
00799
00800
00801 if(stInfo.simWnd)
00802 {
00803 HMODULE hm;
00804 hm = GetModuleHandle("USER32");
00805 if(hm)
00806 {
00807 BOOL (WINAPI *enableime) (HWND, BOOL);
00808 enableime = (BOOL(WINAPI *) (HWND, BOOL)) GetProcAddress(hm,
00809 "WINNLSEnableIME");
00810 if(enableime)
00811 {
00812 enableime(stInfo.simWnd, false);
00813 BX_INFO(("IME disabled"));
00814 }
00815 }
00816 }
00817
00818 ShowWindow(stInfo.simWnd, SW_SHOW);
00819 SetFocus(stInfo.simWnd);
00820
00821 ShowCursor(!mouseCaptureMode);
00822
00823 POINT pt = { 0, 0};
00824 ClientToScreen(stInfo.simWnd, &pt);
00825 SetCursorPos(pt.x + stretched_x / 2, pt.y + stretched_y / 2);
00826 cursorWarped();
00827
00828 hdc = GetDC(stInfo.simWnd);
00829 MemoryBitmap = CreateCompatibleBitmap(hdc, BX_MAX_XRES, BX_MAX_YRES);
00830 MemoryDC = CreateCompatibleDC(hdc);
00831 ReleaseDC(stInfo.simWnd, hdc);
00832
00833 if(MemoryBitmap && MemoryDC)
00834 {
00835 resize_main_window();
00836 ShowWindow(stInfo.mainWnd, SW_SHOW);
00837 #if BX_DEBUGGER
00838 if(windebug)
00839 {
00840 InitDebugDialog(stInfo.mainWnd);
00841 }
00842 #endif
00843 stInfo.UIinited = true;
00844
00845 bx_gui->clear_screen();
00846
00847 while(GetMessage(&msg, NULL, 0, 0))
00848 {
00849 TranslateMessage(&msg);
00850 DispatchMessage(&msg);
00851 }
00852 }
00853 }
00854
00855 stInfo.kill = EXIT_GUI_SHUTDOWN;
00856
00857 _endthread();
00858 }
00859
00860 LRESULT CALLBACK mainWndProc(HWND hwnd, UINT iMsg, WPARAM wParam, LPARAM lParam)
00861 {
00862 switch(iMsg)
00863 {
00864 case WM_SETFOCUS:
00865 SetFocus(stInfo.simWnd);
00866 return 0;
00867
00868 case WM_CLOSE:
00869 SendMessage(stInfo.simWnd, WM_CLOSE, 0, 0);
00870 break;
00871
00872 case WM_DESTROY:
00873 PostQuitMessage(0);
00874 return 0;
00875
00876 case WM_SIZE:
00877 {
00878 int x;
00879
00880 int y;
00881
00882
00883
00884 RECT R;
00885
00886
00887 GetClientRect(hwnd, &R);
00888 x = R.right - R.left;
00889 y = R.bottom - R.top;
00890 MoveWindow(stInfo.simWnd, R.left, R.top, x, y, true);
00891 GetClientRect(stInfo.simWnd, &R);
00892 x = R.right - R.left;
00893 y = R.bottom - R.top;
00894 if((x != (int) stretched_x) || (y != (int) stretched_y))
00895 {
00896 BX_ERROR(("Sim client size(%d, %d) != stretched size(%d, %d)!", x, y,
00897 stretched_x, stretched_y));
00898 if(!saveParent)
00899 fix_size = true;
00900 }
00901 }
00902 break;
00903 }
00904
00905 return DefWindowProc(hwnd, iMsg, wParam, lParam);
00906 }
00907
00908 void SetMouseCapture()
00909 {
00910 POINT pt = {0, 0};
00911
00912 if(mouseToggleReq)
00913 {
00914 mouseCaptureMode = mouseCaptureNew;
00915 mouseToggleReq = false;
00916 }
00917 else
00918 {
00919
00920
00921 }
00922
00923 ShowCursor(!mouseCaptureMode);
00924 ShowCursor(!mouseCaptureMode);
00925 ClientToScreen(stInfo.simWnd, &pt);
00926 SetCursorPos(pt.x + stretched_x / 2, pt.y + stretched_y / 2);
00927 cursorWarped();
00928 }
00929
00930 LRESULT CALLBACK simWndProc(HWND hwnd, UINT iMsg, WPARAM wParam, LPARAM lParam)
00931 {
00932 HDC hdc;
00933
00934 HDC hdcMem;
00935 PAINTSTRUCT ps;
00936 POINT pt;
00937 static BOOL mouseModeChange = false;
00938
00939 switch(iMsg)
00940 {
00941 case WM_CREATE:
00942 #if BX_USE_WINDOWS_FONTS
00943 InitFont();
00944 #endif
00945 SetTimer(hwnd, 1, 330, NULL);
00946 return 0;
00947
00948 case WM_TIMER:
00949 if(mouseToggleReq && (GetActiveWindow() == stInfo.mainWnd))
00950 {
00951 SetMouseCapture();
00952 }
00953
00954
00955 if(mouseCaptureMode)
00956 {
00957 pt.x = 0;
00958 pt.y = 0;
00959 ClientToScreen(hwnd, &pt);
00960 SetCursorPos(pt.x + stretched_x / 2, pt.y + stretched_y / 2);
00961 cursorWarped();
00962 }
00963
00964 if(fix_size)
00965 {
00966 resize_main_window();
00967 }
00968
00969 return 0;
00970
00971 case WM_PAINT:
00972 EnterCriticalSection(&stInfo.drawCS);
00973 hdc = BeginPaint(hwnd, &ps);
00974
00975 hdcMem = CreateCompatibleDC(hdc);
00976 SelectObject(hdcMem, MemoryBitmap);
00977
00978 if(stretch_factor == 1)
00979 {
00980 BitBlt(hdc, ps.rcPaint.left, ps.rcPaint.top,
00981 ps.rcPaint.right - ps.rcPaint.left + 1,
00982 ps.rcPaint.bottom - ps.rcPaint.top + 1, hdcMem, ps.rcPaint.left,
00983 ps.rcPaint.top, SRCCOPY);
00984 }
00985 else
00986 {
00987 StretchBlt(hdc, ps.rcPaint.left, ps.rcPaint.top,
00988 ps.rcPaint.right - ps.rcPaint.left + 1,
00989 ps.rcPaint.bottom - ps.rcPaint.top + 1, hdcMem,
00990 ps.rcPaint.left / stretch_factor, ps.rcPaint.top,
00991 (ps.rcPaint.right - ps.rcPaint.left + 1) / stretch_factor,
00992 (ps.rcPaint.bottom - ps.rcPaint.top + 1), SRCCOPY);
00993 }
00994
00995 DeleteDC(hdcMem);
00996 EndPaint(hwnd, &ps);
00997 LeaveCriticalSection(&stInfo.drawCS);
00998 return 0;
00999
01000 case WM_MOUSEMOVE:
01001 if(!mouseModeChange)
01002 {
01003 processMouseXY(LOWORD(lParam), HIWORD(lParam), 0, wParam, 0);
01004 }
01005
01006 return 0;
01007
01008
01009
01010
01011
01012
01013
01014
01015
01016
01017
01018
01019 case WM_LBUTTONDOWN:
01020 case WM_LBUTTONDBLCLK:
01021 case WM_LBUTTONUP:
01022 if(mouse_buttons == 2)
01023 {
01024 if(wParam == (MK_CONTROL | MK_LBUTTON | MK_RBUTTON))
01025 {
01026 mouseCaptureMode = !mouseCaptureMode;
01027 SetMouseCapture();
01028 mouseModeChange = true;
01029 }
01030 else if(mouseModeChange && (iMsg == WM_LBUTTONUP))
01031 {
01032 mouseModeChange = false;
01033 }
01034 else
01035 {
01036 processMouseXY(LOWORD(lParam), HIWORD(lParam), 0, wParam, 1);
01037 }
01038
01039 return 0;
01040 }
01041
01042 processMouseXY(LOWORD(lParam), HIWORD(lParam), 0, wParam, 1);
01043 return 0;
01044
01045 case WM_MBUTTONDOWN:
01046 case WM_MBUTTONDBLCLK:
01047 case WM_MBUTTONUP:
01048 if(wParam == (MK_CONTROL | MK_MBUTTON))
01049 {
01050 mouseCaptureMode = !mouseCaptureMode;
01051 SetMouseCapture();
01052 mouseModeChange = true;
01053 }
01054 else if(mouseModeChange && (iMsg == WM_MBUTTONUP))
01055 {
01056 mouseModeChange = false;
01057 }
01058 else
01059 {
01060 processMouseXY(LOWORD(lParam), HIWORD(lParam), 0, wParam, 4);
01061 }
01062
01063 return 0;
01064
01065 case WM_RBUTTONDOWN:
01066 case WM_RBUTTONDBLCLK:
01067 case WM_RBUTTONUP:
01068 if(mouse_buttons == 2)
01069 {
01070 if(wParam == (MK_CONTROL | MK_LBUTTON | MK_RBUTTON))
01071 {
01072 mouseCaptureMode = !mouseCaptureMode;
01073 SetMouseCapture();
01074 mouseModeChange = true;
01075 }
01076 else if(mouseModeChange && (iMsg == WM_RBUTTONUP))
01077 {
01078 mouseModeChange = false;
01079 }
01080 else
01081 {
01082 processMouseXY(LOWORD(lParam), HIWORD(lParam), 0, wParam, 2);
01083 }
01084
01085 return 0;
01086 }
01087
01088 processMouseXY(LOWORD(lParam), HIWORD(lParam), 0, wParam, 2);
01089 return 0;
01090
01091 case WM_CLOSE:
01092 return DefWindowProc(hwnd, iMsg, wParam, lParam);
01093
01094 case WM_DESTROY:
01095 KillTimer(hwnd, 1);
01096 stInfo.UIinited = false;
01097 #if BX_USE_WINDOWS_FONTS
01098 DestroyFont();
01099 #endif
01100 return 0;
01101
01102 case WM_KEYDOWN:
01103 case WM_SYSKEYDOWN:
01104 EnterCriticalSection(&stInfo.keyCS);
01105 enq_key_event(HIWORD(lParam) & 0x01FF, BX_KEY_PRESSED);
01106 LeaveCriticalSection(&stInfo.keyCS);
01107 return 0;
01108
01109 case WM_KEYUP:
01110 case WM_SYSKEYUP:
01111
01112
01113
01114 if(wParam == VK_RETURN)
01115 {
01116 if((HIWORD(lParam) & BX_SYSKEY) == (KF_ALTDOWN | KF_UP))
01117 {
01118 if(!saveParent)
01119 {
01120 BX_INFO(("entering fullscreen mode"));
01121 theGui->dimension_update(desktop_x, desktop_y, 0, 0, current_bpp);
01122 }
01123 else
01124 {
01125 BX_INFO(("leaving fullscreen mode"));
01126 theGui->dimension_update(dimension_x, desktop_y - 1, 0, 0, current_bpp);
01127 }
01128 }
01129 }
01130 else
01131 {
01132 EnterCriticalSection(&stInfo.keyCS);
01133 enq_key_event(HIWORD(lParam) & 0x01FF, BX_KEY_RELEASED);
01134 LeaveCriticalSection(&stInfo.keyCS);
01135 }
01136
01137 return 0;
01138
01139 case WM_SYSCHAR:
01140
01141
01142
01143 if(wParam == VK_RETURN)
01144 {
01145 if((HIWORD(lParam) & BX_SYSKEY) == KF_ALTDOWN)
01146 {
01147 if(!saveParent)
01148 {
01149 BX_INFO(("entering fullscreen mode"));
01150 theGui->dimension_update(desktop_x, desktop_y, 0, 0, current_bpp);
01151 }
01152 else
01153 {
01154 BX_INFO(("leaving fullscreen mode"));
01155 theGui->dimension_update(dimension_x, desktop_y - 1, 0, 0, current_bpp);
01156 }
01157 }
01158 }
01159
01160 case WM_CHAR:
01161 case WM_DEADCHAR:
01162 case WM_SYSDEADCHAR:
01163 return 0;
01164 }
01165
01166 return DefWindowProc(hwnd, iMsg, wParam, lParam);
01167 }
01168
01169 void enq_key_event(u32 key, u32 press_release)
01170 {
01171 static BOOL alt_pressed_l = false;
01172 static BOOL alt_pressed_r = false;
01173 static BOOL ctrl_pressed_l = false;
01174 static BOOL ctrl_pressed_r = false;
01175 static BOOL shift_pressed_l = false;
01176 static BOOL shift_pressed_r = false;
01177
01178
01179 if(press_release == BX_KEY_PRESSED)
01180 {
01181 switch(key)
01182 {
01183 case 0x1d:
01184 if(ctrl_pressed_l)
01185 return;
01186 ctrl_pressed_l = true;
01187 break;
01188
01189 case 0x2a:
01190 if(shift_pressed_l)
01191 return;
01192 shift_pressed_l = true;
01193 break;
01194
01195 case 0x36:
01196 if(shift_pressed_r)
01197 return;
01198 shift_pressed_r = true;
01199 break;
01200
01201 case 0x38:
01202 if(alt_pressed_l)
01203 return;
01204 alt_pressed_l = true;
01205 break;
01206
01207 case 0x011d:
01208 if(ctrl_pressed_r)
01209 return;
01210 ctrl_pressed_r = true;
01211 break;
01212
01213 case 0x0138:
01214 if(alt_pressed_r)
01215 return;
01216
01217
01218 if(ctrl_pressed_l)
01219 {
01220 enq_key_event(0x1d, BX_KEY_RELEASED);
01221 }
01222
01223 alt_pressed_r = true;
01224 break;
01225 }
01226 }
01227 else
01228 {
01229 switch(key)
01230 {
01231 case 0x1d: if(!ctrl_pressed_l) return; ctrl_pressed_l = false; break;
01232 case 0x2a: shift_pressed_l = false; break;
01233 case 0x36: shift_pressed_r = false; break;
01234 case 0x38: alt_pressed_l = false; break;
01235 case 0x011d: ctrl_pressed_r = false; break;
01236 case 0x0138: alt_pressed_r = false; break;
01237 }
01238 }
01239
01240 if(((tail + 1) % SCANCODE_BUFSIZE) == head)
01241 {
01242 BX_ERROR(("enq_scancode: buffer full"));
01243 return;
01244 }
01245
01246 keyevents[tail].key_event = key | press_release;
01247 tail = (tail + 1) % SCANCODE_BUFSIZE;
01248 }
01249
01250 void enq_mouse_event(void)
01251 {
01252 EnterCriticalSection(&stInfo.mouseCS);
01253 if(ms_xdelta || ms_ydelta || ms_zdelta)
01254 {
01255 if(((tail + 1) % SCANCODE_BUFSIZE) == head)
01256 {
01257 BX_ERROR(("enq_scancode: buffer full"));
01258 return;
01259 }
01260
01261 QueueEvent& current = keyevents[tail];
01262 current.key_event = MOUSE_MOTION;
01263 current.mouse_x = ms_xdelta;
01264 current.mouse_y = ms_ydelta;
01265 current.mouse_z = ms_zdelta;
01266 current.mouse_button_state = mouse_button_state;
01267 resetDelta();
01268 tail = (tail + 1) % SCANCODE_BUFSIZE;
01269 }
01270
01271 LeaveCriticalSection(&stInfo.mouseCS);
01272 }
01273
01274 QueueEvent* deq_key_event(void)
01275 {
01276 QueueEvent* key;
01277
01278 if(head == tail)
01279 {
01280 BX_ERROR(("deq_scancode: buffer empty"));
01281 return((QueueEvent*) 0);
01282 }
01283
01284 key = &keyevents[head];
01285 head = (head + 1) % SCANCODE_BUFSIZE;
01286
01287 return(key);
01288 }
01289
01290
01291
01292
01293
01294
01295
01296 void bx_win32_gui_c::handle_events(void)
01297 {
01298 u32 key;
01299 u32 key_event;
01300
01301 if(stInfo.kill)
01302 terminateEmul(stInfo.kill);
01303
01304
01305 enq_mouse_event();
01306
01307
01308 EnterCriticalSection(&stInfo.keyCS);
01309 while(head != tail)
01310 {
01311 QueueEvent* queue_event = deq_key_event();
01312 if(!queue_event)
01313 break;
01314 key = queue_event->key_event;
01315 if(key == MOUSE_MOTION)
01316 {
01317
01318
01319
01320 }
01321
01322
01323 else if(key & MOUSE_PRESSED)
01324 {
01325
01326
01327 }
01328 else
01329 {
01330 key_event = win32_to_bx_key[(key & 0x100) ? 1 : 0][key & 0xff];
01331 if(key & BX_KEY_RELEASED)
01332 key_event |= BX_KEY_RELEASED;
01333
01334
01335 theKeyboard->gen_scancode(key_event);
01336 }
01337 }
01338
01339 LeaveCriticalSection(&stInfo.keyCS);
01340 }
01341
01342
01343
01344
01345
01346
01347 void bx_win32_gui_c::flush(void)
01348 {
01349 EnterCriticalSection(&stInfo.drawCS);
01350 if(updated_area_valid)
01351 {
01352
01353
01354 updated_area.right++;
01355 updated_area.bottom++;
01356 InvalidateRect(stInfo.simWnd, &updated_area, false);
01357 updated_area_valid = false;
01358 }
01359
01360 LeaveCriticalSection(&stInfo.drawCS);
01361 }
01362
01363
01364
01365
01366
01367 void bx_win32_gui_c::clear_screen(void)
01368 {
01369 HGDIOBJ oldObj;
01370
01371 if(!stInfo.UIinited)
01372 return;
01373
01374 EnterCriticalSection(&stInfo.drawCS);
01375
01376 oldObj = SelectObject(MemoryDC, MemoryBitmap);
01377 PatBlt(MemoryDC, 0, 0, stretched_x, stretched_y, BLACKNESS);
01378 SelectObject(MemoryDC, oldObj);
01379
01380 updateUpdated(0, 0, dimension_x - 1, dimension_y - 1);
01381
01382 LeaveCriticalSection(&stInfo.drawCS);
01383 }
01384
01385
01386
01387
01388
01389
01390
01391
01392
01393
01394
01395
01396
01397
01398
01399
01400
01401
01402
01403
01404
01405 void bx_win32_gui_c::text_update(u8* old_text, u8* new_text,
01406 unsigned long cursor_x, unsigned long cursor_y,
01407 bx_vga_tminfo_t tm_info, unsigned nrows)
01408 {
01409 HDC hdc;
01410 unsigned char data[64];
01411 u8* old_line;
01412 u8 *new_line;
01413 u8 cAttr;
01414 u8 cChar;
01415 unsigned int curs;
01416 unsigned int hchars;
01417 unsigned int i;
01418 unsigned int offset;
01419 unsigned int rows;
01420 unsigned int x;
01421 unsigned int y;
01422 unsigned int xc;
01423 unsigned int yc;
01424 BOOL forceUpdate = false;
01425 #if !BX_USE_WINDOWS_FONTS
01426 u8* text_base;
01427 u8 cfwidth;
01428 u8 cfheight;
01429 u8 cfheight2;
01430 u8 font_col;
01431 u8 font_row;
01432 u8 font_row2;
01433 u8 split_textrow;
01434 u8 split_fontrows;
01435 unsigned int yc2;
01436 unsigned int cs_y;
01437 BOOL split_screen;
01438 #endif
01439 if(!stInfo.UIinited)
01440 return;
01441
01442 EnterCriticalSection(&stInfo.drawCS);
01443
01444 if(charmap_updated)
01445 {
01446 for(unsigned c = 0; c < 256; c++)
01447 {
01448 if(char_changed[c])
01449 {
01450 memset(data, 0, sizeof(data));
01451
01452 BOOL gfxchar = tm_info.line_graphics && ((c & 0xE0) == 0xC0);
01453 for(i = 0; i < (unsigned) yChar; i++)
01454 {
01455 data[i * 2] = vga_charmap[c * 32 + i];
01456 if(gfxchar)
01457 {
01458 data[i * 2 + 1] = (data[i * 2] << 7);
01459 }
01460 }
01461
01462 SetBitmapBits(vgafont[c], 64, data);
01463 char_changed[c] = 0;
01464 }
01465 }
01466
01467 forceUpdate = true;
01468 charmap_updated = 0;
01469 }
01470
01471 for(i = 0; i < 16; i++)
01472 {
01473 text_pal_idx[i] = theVGA->get_actl_palette_idx(i);
01474 }
01475
01476 hdc = GetDC(stInfo.simWnd);
01477
01478 #if !BX_USE_WINDOWS_FONTS
01479 if((tm_info.h_panning != h_panning) || (tm_info.v_panning != v_panning))
01480 {
01481 forceUpdate = 1;
01482 h_panning = tm_info.h_panning;
01483 v_panning = tm_info.v_panning;
01484 }
01485
01486 if(tm_info.line_compare != line_compare)
01487 {
01488 forceUpdate = 1;
01489 line_compare = tm_info.line_compare;
01490 }
01491 #endif
01492
01493
01494 if((prev_cursor_y < text_rows) && (prev_cursor_x < text_cols))
01495 {
01496 curs = prev_cursor_y * tm_info.line_offset + prev_cursor_x * 2;
01497 old_text[curs] = ~new_text[curs];
01498 }
01499
01500 if((tm_info.cs_start <= tm_info.cs_end) && (tm_info.cs_start < yChar)
01501 && (cursor_y < text_rows) && (cursor_x < text_cols))
01502 {
01503 curs = cursor_y * tm_info.line_offset + cursor_x * 2;
01504 old_text[curs] = ~new_text[curs];
01505 }
01506 else
01507 {
01508 curs = 0xffff;
01509 }
01510
01511 #if !BX_USE_WINDOWS_FONTS
01512 rows = text_rows;
01513 if(v_panning)
01514 rows++;
01515 y = 0;
01516 cs_y = 0;
01517 text_base = new_text - tm_info.start_address;
01518 split_textrow = (line_compare + v_panning) / yChar;
01519 split_fontrows = ((line_compare + v_panning) % yChar) + 1;
01520 split_screen = 0;
01521 do
01522 {
01523 hchars = text_cols;
01524 if(h_panning)
01525 hchars++;
01526 if(split_screen)
01527 {
01528 yc = line_compare + cs_y * yChar + 1;
01529 font_row = 0;
01530 if(rows == 1)
01531 {
01532 cfheight = (dimension_y - line_compare - 1) % yChar;
01533 if(cfheight == 0)
01534 cfheight = yChar;
01535 }
01536 else
01537 {
01538 cfheight = yChar;
01539 }
01540 }
01541 else if(v_panning)
01542 {
01543 if(y == 0)
01544 {
01545 yc = 0;
01546 font_row = v_panning;
01547 cfheight = yChar - v_panning;
01548 }
01549 else
01550 {
01551 yc = y * yChar - v_panning;
01552 font_row = 0;
01553 if(rows == 1)
01554 {
01555 cfheight = v_panning;
01556 }
01557 else
01558 {
01559 cfheight = yChar;
01560 }
01561 }
01562 }
01563 else
01564 {
01565 yc = y * yChar;
01566 font_row = 0;
01567 cfheight = yChar;
01568 }
01569
01570 if(!split_screen && (y == split_textrow))
01571 {
01572 if(split_fontrows < cfheight)
01573 cfheight = split_fontrows;
01574 }
01575
01576 new_line = new_text;
01577 old_line = old_text;
01578 x = 0;
01579 offset = cs_y * tm_info.line_offset;
01580 do
01581 {
01582 if(h_panning)
01583 {
01584 if(hchars > text_cols)
01585 {
01586 xc = 0;
01587 font_col = h_panning;
01588 cfwidth = xChar - h_panning;
01589 }
01590 else
01591 {
01592 xc = x * xChar - h_panning;
01593 font_col = 0;
01594 if(hchars == 1)
01595 {
01596 cfwidth = h_panning;
01597 }
01598 else
01599 {
01600 cfwidth = xChar;
01601 }
01602 }
01603 }
01604 else
01605 {
01606 xc = x * xChar;
01607 font_col = 0;
01608 cfwidth = xChar;
01609 }
01610
01611 if(forceUpdate || (old_text[0] != new_text[0])
01612 || (old_text[1] != new_text[1]))
01613 {
01614 cChar = new_text[0];
01615 cAttr = new_text[1];
01616 DrawBitmap(hdc, vgafont[cChar], xc, yc, cfwidth, cfheight, font_col,
01617 font_row, SRCCOPY, cAttr);
01618 if(offset == curs)
01619 {
01620 if(font_row == 0)
01621 {
01622 yc2 = yc + tm_info.cs_start;
01623 font_row2 = tm_info.cs_start;
01624 cfheight2 = tm_info.cs_end - tm_info.cs_start + 1;
01625 }
01626 else
01627 {
01628 if(v_panning > tm_info.cs_start)
01629 {
01630 yc2 = yc;
01631 font_row2 = font_row;
01632 cfheight2 = tm_info.cs_end - v_panning + 1;
01633 }
01634 else
01635 {
01636 yc2 = yc + tm_info.cs_start - v_panning;
01637 font_row2 = tm_info.cs_start;
01638 cfheight2 = tm_info.cs_end - tm_info.cs_start + 1;
01639 }
01640 }
01641
01642 cAttr = ((cAttr >> 4) & 0xF) + ((cAttr & 0xF) << 4);
01643 DrawBitmap(hdc, vgafont[cChar], xc, yc2, cfwidth, cfheight2, font_col,
01644 font_row2, SRCCOPY, cAttr);
01645 }
01646 }
01647
01648 x++;
01649 new_text += 2;
01650 old_text += 2;
01651 offset += 2;
01652 } while(--hchars);
01653 if(!split_screen && (y == split_textrow))
01654 {
01655 new_text = text_base;
01656 forceUpdate = 1;
01657 cs_y = 0;
01658 if(tm_info.split_hpanning)
01659 h_panning = 0;
01660 rows = ((dimension_y - line_compare + yChar - 2) / yChar) + 1;
01661 split_screen = 1;
01662 }
01663 else
01664 {
01665 y++;
01666 cs_y++;
01667 new_text = new_line + tm_info.line_offset;
01668 old_text = old_line + tm_info.line_offset;
01669 }
01670 } while(--rows);
01671
01672 h_panning = tm_info.h_panning;
01673 #else
01674 rows = text_rows;
01675 y = 0;
01676 do
01677 {
01678 hchars = text_cols;
01679 yc = y * yChar;
01680 new_line = new_text;
01681 old_line = old_text;
01682 x = 0;
01683 offset = y * tm_info.line_offset;
01684 do
01685 {
01686 xc = x * xChar;
01687 if(forceUpdate || (old_text[0] != new_text[0])
01688 || (old_text[1] != new_text[1]))
01689 {
01690 cChar = new_text[0];
01691 cAttr = new_text[1];
01692 DrawChar(hdc, cChar, xc, yc, cAttr, 1, 0);
01693 if(offset == curs)
01694 {
01695 DrawChar(hdc, cChar, xc, yc, cAttr, tm_info.cs_start, tm_info.cs_end);
01696 }
01697 }
01698
01699 x++;
01700 new_text += 2;
01701 old_text += 2;
01702 offset += 2;
01703 } while(--hchars);
01704 y++;
01705 new_text = new_line + tm_info.line_offset;
01706 old_text = old_line + tm_info.line_offset;
01707 } while(--rows);
01708 #endif
01709 prev_cursor_x = cursor_x;
01710 prev_cursor_y = cursor_y;
01711
01712 ReleaseDC(stInfo.simWnd, hdc);
01713
01714 LeaveCriticalSection(&stInfo.drawCS);
01715 }
01716
01717
01718
01719
01720
01721
01722
01723
01724 bool bx_win32_gui_c::palette_change(unsigned index, unsigned red, unsigned green,
01725 unsigned blue)
01726 {
01727 if((current_bpp == 16) && (index < 3))
01728 {
01729 cmap_index[256 + index].rgbRed = red;
01730 cmap_index[256 + index].rgbBlue = blue;
01731 cmap_index[256 + index].rgbGreen = green;
01732 return 0;
01733 }
01734 else
01735 {
01736 cmap_index[index].rgbRed = red;
01737 cmap_index[index].rgbBlue = blue;
01738 cmap_index[index].rgbGreen = green;
01739 }
01740
01741 return(1);
01742 }
01743
01744
01745
01746
01747
01748
01749
01750
01751
01752
01753
01754
01755
01756
01757
01758
01759 void bx_win32_gui_c::graphics_tile_update(u8* tile, unsigned x0, unsigned y0)
01760 {
01761 HDC hdc;
01762 HGDIOBJ oldObj;
01763
01764 EnterCriticalSection(&stInfo.drawCS);
01765 hdc = GetDC(stInfo.simWnd);
01766
01767 oldObj = SelectObject(MemoryDC, MemoryBitmap);
01768
01769 StretchDIBits(MemoryDC, x0, y0, x_tilesize, y_tilesize, 0, 0, x_tilesize,
01770 y_tilesize, tile, bitmap_info, DIB_RGB_COLORS, SRCCOPY);
01771
01772 SelectObject(MemoryDC, oldObj);
01773
01774 updateUpdated(x0, y0, x0 + x_tilesize - 1, y0 + y_tilesize - 1);
01775
01776 ReleaseDC(stInfo.simWnd, hdc);
01777 LeaveCriticalSection(&stInfo.drawCS);
01778 }
01779
01780
01781
01782
01783
01784
01785
01786
01787
01788
01789
01790
01791 void bx_win32_gui_c::dimension_update(unsigned x, unsigned y, unsigned fheight,
01792 unsigned fwidth, unsigned bpp)
01793 {
01794 BxTextMode = (fheight > 0);
01795 if(BxTextMode)
01796 {
01797 text_cols = x / fwidth;
01798 text_rows = y / fheight;
01799 xChar = fwidth;
01800 yChar = fheight;
01801 }
01802
01803 if(x == dimension_x && y == dimension_y && bpp == current_bpp)
01804 return;
01805 dimension_x = x;
01806 dimension_y = y;
01807 stretched_x = dimension_x;
01808 stretched_y = dimension_y;
01809 stretch_factor = 1;
01810 if(BxTextMode && (stretched_x < 400))
01811 {
01812 stretched_x *= 2;
01813 stretch_factor *= 2;
01814 }
01815
01816 bitmap_info->bmiHeader.biBitCount = bpp;
01817 if(bpp == 16)
01818 {
01819 bitmap_info->bmiHeader.biCompression = BI_BITFIELDS;
01820
01821 static RGBQUAD red_mask = {0x00, 0xF8, 0x00, 0x00};
01822 static RGBQUAD green_mask = {0xE0, 0x07, 0x00, 0x00};
01823 static RGBQUAD blue_mask = {0x1F, 0x00, 0x00, 0x00};
01824 bitmap_info->bmiColors[256] = bitmap_info->bmiColors[0];
01825 bitmap_info->bmiColors[257] = bitmap_info->bmiColors[1];
01826 bitmap_info->bmiColors[258] = bitmap_info->bmiColors[2];
01827 bitmap_info->bmiColors[0] = red_mask;
01828 bitmap_info->bmiColors[1] = green_mask;
01829 bitmap_info->bmiColors[2] = blue_mask;
01830 }
01831 else
01832 {
01833 if(current_bpp == 16)
01834 {
01835 bitmap_info->bmiColors[0] = bitmap_info->bmiColors[256];
01836 bitmap_info->bmiColors[1] = bitmap_info->bmiColors[257];
01837 bitmap_info->bmiColors[2] = bitmap_info->bmiColors[258];
01838 }
01839
01840 bitmap_info->bmiHeader.biCompression = BI_RGB;
01841 if(bpp == 15)
01842 {
01843 bitmap_info->bmiHeader.biBitCount = 16;
01844 }
01845 }
01846
01847 current_bpp = bpp;
01848
01849 resize_main_window();
01850
01851 BX_INFO(("dimension update x=%d y=%d fontheight=%d fontwidth=%d bpp=%d", x, y,
01852 fheight, fwidth, bpp));
01853
01854 host_xres = x;
01855 host_yres = y;
01856 host_bpp = bpp;
01857 }
01858
01859
01860
01861
01862
01863
01864 void bx_win32_gui_c::exit(void)
01865 {
01866 printf("# In bx_win32_gui_c::exit(void)!\n");
01867
01868
01869 PostMessage(stInfo.mainWnd, WM_CLOSE, 0, 0);
01870
01871
01872 while((stInfo.kill == 0) && (workerThreadID != 0))
01873 Sleep(500);
01874
01875 if(!stInfo.kill)
01876 terminateEmul(EXIT_NORMAL);
01877 }
01878
01879 void create_vga_font(void)
01880 {
01881 unsigned char data[64];
01882
01883
01884 for(unsigned c = 0; c < 256; c++)
01885 {
01886 vgafont[c] = CreateBitmap(9, 32, 1, 1, NULL);
01887 if(!vgafont[c])
01888 terminateEmul(EXIT_FONT_BITMAP_ERROR);
01889 memset(data, 0, sizeof(data));
01890 for(unsigned i = 0; i < 16; i++)
01891 data[i * 2] = reverse_bitorder(bx_vgafont[c].data[i]);
01892 SetBitmapBits(vgafont[c], 64, data);
01893 }
01894 }
01895
01896 unsigned char reverse_bitorder(unsigned char b)
01897 {
01898 unsigned char ret = 0;
01899
01900 for(unsigned i = 0; i < 8; i++)
01901 {
01902 ret |= (b & 0x01) << (7 - i);
01903 b >>= 1;
01904 }
01905
01906 return(ret);
01907 }
01908
01909 COLORREF GetColorRef(unsigned char attr)
01910 {
01911 u8 pal_idx = text_pal_idx[attr];
01912 return RGB(cmap_index[pal_idx].rgbRed, cmap_index[pal_idx].rgbGreen,
01913 cmap_index[pal_idx].rgbBlue);
01914 }
01915
01916 void DrawBitmap(HDC hdc, HBITMAP hBitmap, int xStart, int yStart, int width,
01917 int height, int fcol, int frow, DWORD dwRop, unsigned char cColor)
01918 {
01919 BITMAP bm;
01920 HDC hdcMem;
01921 POINT ptSize;
01922 POINT ptOrg;
01923 HGDIOBJ oldObj;
01924
01925 hdcMem = CreateCompatibleDC(hdc);
01926 SelectObject(hdcMem, hBitmap);
01927 SetMapMode(hdcMem, GetMapMode(hdc));
01928
01929 GetObject(hBitmap, sizeof(BITMAP), (LPVOID) & bm);
01930
01931 ptSize.x = width;
01932 ptSize.y = height;
01933
01934 DPtoLP(hdc, &ptSize, 1);
01935
01936 ptOrg.x = fcol;
01937 ptOrg.y = frow;
01938 DPtoLP(hdcMem, &ptOrg, 1);
01939
01940 oldObj = SelectObject(MemoryDC, MemoryBitmap);
01941
01942
01943
01944
01945
01946 COLORREF crFore = SetTextColor(MemoryDC, GetColorRef((cColor >> 4) & 0xf));
01947 COLORREF crBack = SetBkColor(MemoryDC, GetColorRef(cColor & 0xf));
01948 BitBlt(MemoryDC, xStart, yStart, ptSize.x, ptSize.y, hdcMem, ptOrg.x, ptOrg.y,
01949 dwRop);
01950 SetBkColor(MemoryDC, crBack);
01951 SetTextColor(MemoryDC, crFore);
01952
01953 SelectObject(MemoryDC, oldObj);
01954
01955 updateUpdated(xStart, yStart, ptSize.x + xStart - 1, ptSize.y + yStart - 1);
01956
01957 DeleteDC(hdcMem);
01958 }
01959
01960 void updateUpdated(int x1, int y1, int x2, int y2)
01961 {
01962 x1 *= stretch_factor;
01963 x2 *= stretch_factor;
01964 if(!updated_area_valid)
01965 {
01966 updated_area.left = x1;
01967 updated_area.top = y1;
01968 updated_area.right = x2;
01969 updated_area.bottom = y2;
01970 }
01971 else
01972 {
01973 if(x1 < updated_area.left)
01974 updated_area.left = x1;
01975 if(y1 < updated_area.top)
01976 updated_area.top = y1;
01977 if(x2 > updated_area.right)
01978 updated_area.right = x2;
01979 if(y2 > updated_area.bottom)
01980 updated_area.bottom = y2;
01981 }
01982
01983 updated_area_valid = true;
01984 }
01985
01986 void bx_win32_gui_c::mouse_enabled_changed_specific(bool val)
01987 {
01988 if((val != (bool) mouseCaptureMode) && !mouseToggleReq)
01989 {
01990 mouseToggleReq = true;
01991 mouseCaptureNew = val;
01992 }
01993 }
01994
01995 void bx_win32_gui_c::get_capabilities(u16* xres, u16* yres, u16* bpp)
01996 {
01997 if(desktop_y > 0)
01998 {
01999 *xres = desktop_x;
02000 *yres = desktop_y;
02001 *bpp = 32;
02002 }
02003 else
02004 {
02005 *xres = 1024;
02006 *yres = 768;
02007 *bpp = 32;
02008 }
02009 }
02010 #endif