/************************************************************************** * DSemu: Window initialisation and message handling (win.c) * * Released under the terms of the BSD Public Licence * * Imran Nazar (tf@oopsilon.com), 2004 * **************************************************************************/ #include #include #include #include "defs.h" #include "res.h" #include "win.h" #include "emu.h" #include "vtbl.h" #define WNDDEBUG u8 cursANDmask[]={ 0x00,0xFF,0x00,0x7F,0x00,0x3F,0x00,0x1F, 0x00,0x0F,0x00,0x07,0x00,0x03,0x00,0x01, 0x80,0x00,0xC0,0x01,0xE0,0x03,0xF0,0x07, 0xF8,0x0F,0xFC,0x1F,0xFE,0x3F,0xFF,0x7F, }; u8 cursXORmask[]={ 0xFF,0x00,0xE0,0x80,0xF0,0x40,0xB8,0x20, 0x9C,0x10,0x8E,0x08,0x87,0x04,0x83,0x82, 0x41,0xC1,0x20,0xE2,0x10,0x74,0x08,0x38, 0x04,0x10,0x02,0x20,0x01,0x40,0x00,0x80, }; LRESULT CALLBACK WinProc(HWND, UINT, WPARAM, LPARAM); BOOL CALLBACK WinAboutProc(HWND, UINT, WPARAM, LPARAM); BOOL CALLBACK WinConfProc(HWND, UINT, WPARAM, LPARAM); LRESULT CALLBACK WinEditProc(HWND, UINT, WPARAM, LPARAM); char INIfile[MAX_PATH*2]; struct { HWND hWnd; int key; WNDPROC OldEditProc; } KeyEdits[10]; void ResizeWin(HWND, int, int); HWND hWndMain; extern EMUVTBL *emu; int LoadAndRun=0, LoadDS=0; #define REGCLASS(name,menu,curs,proc) \ wc.cbSize = sizeof(wc); \ wc.style = CS_VREDRAW | CS_HREDRAW; \ wc.lpfnWndProc = (proc); \ wc.cbClsExtra = 0; \ wc.cbWndExtra = 0; \ wc.hInstance = hInst; \ wc.hIcon = LoadImage(hInst,MAKEINTRESOURCE(ID_DSICON32),IMAGE_ICON,32,32,0); \ wc.hCursor = (curs); \ wc.hbrBackground = (HBRUSH)GetStockObject(BLACK_BRUSH); \ wc.lpszMenuName = (menu); \ wc.lpszClassName = (name); \ wc.hIconSm = LoadImage(hInst,MAKEINTRESOURCE(ID_DSICON16),IMAGE_ICON,16,16,0); \ if(!RegisterClassEx(&wc)) return NULL //------------------------------------------------------------------------- // Function: WinInit(HINSTANCE, int) // Purpose: Register a window class, bring a window up. // Comments: This is just here to get WinMain a bit tidier. HWND WinInit(HINSTANCE hInst, int nCmdShow) { char szWndMain[]="DSWndMain"; char szTitle[] = DSEMU_VERSION_STR; int inipathlen; char loadrun[256]; WNDCLASSEX wc; HCURSOR hCursTouch; HWND hWnd; inipathlen=strstr(logvt->file,"\\log.txt")-logvt->file; strncpy(INIfile, logvt->file, inipathlen); INIfile[inipathlen]=0; sprintf(INIfile, "%s\\dsemu.ini", INIfile); GetPrivateProfileString("General","LoadAndRun","0",loadrun,16,INIfile); LoadAndRun=strtol(loadrun,NULL,10); if(LoadAndRun!=1) LoadAndRun=0; hCursTouch=CreateCursor(hInst,0,0,16,16,cursANDmask,cursXORmask); REGCLASS(szWndMain,MAKEINTRESOURCE(ID_MENU),LoadCursor(NULL,IDC_ARROW),WinProc); // Make a window in the normal style. hWnd = CreateWindowEx(0, // Extended style - None szWndMain, // Window class to fall in szTitle, // Window title //WS_POPUP | //WS_CAPTION | WS_SYSMENU | WS_SIZEBOX | WS_MINIMIZEBOX | //WS_VISIBLE | //WS_OVERLAPPED | WS_CLIPCHILDREN, // CW_USEDEFAULT, // Let Windows pick the CW_USEDEFAULT, // best values for the CW_USEDEFAULT, // position and size of CW_USEDEFAULT, // the window NULL, // No parent window NULL, // No menu hInst, // Assign to this process NULL); // No params to WM_CREATE if(!hWnd) return NULL; hWndMain=hWnd; accelTable=LoadAccelerators(hInst, MAKEINTRESOURCE(ID_ACCEL)); if(!accelTable) return NULL; InitCommonControls(); // Finally, put the window on screen. ShowWindow(hWnd, nCmdShow); UpdateWindow(hWnd); DragAcceptFiles(hWnd, TRUE); // Log notification of window creation. logvt->append("WND: Initialised."); return hWnd; } //------------------------------------------------------------------------- // Function: WinProc(HWND, UINT, WPARAM, LPARAM) // Purpose: Window message callback processor // Comments: We don't handle much. Most of the processing is in WinMain. LRESULT CALLBACK WinProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam) { static HWND hStatus; static HMENU hMenu; int nStatBars[]={50,-1},cnt,a; static UINT timerID; OPENFILENAME ofn; PAINTSTRUCT ps; static char filename[MAX_PATH] = ""; char str[MAX_PATH*2], strout[MAX_PATH*2]; switch(msg) { // When the window is made, make a child status bar. case WM_CREATE: hMenu = GetMenu(hWnd); CheckMenuItem(hMenu, ID_MENU_VIEW_GPU, MF_BYCOMMAND|MF_UNCHECKED); CheckMenuItem(hMenu, ID_MENU_VIEW_FPS, MF_BYCOMMAND|MF_UNCHECKED); CheckMenuItem(hMenu, ID_MENU_VIEW_PAL, MF_BYCOMMAND|MF_UNCHECKED); CheckMenuItem(hMenu, ID_MENU_VIEW_DBG, MF_BYCOMMAND|MF_UNCHECKED); CheckMenuItem(hMenu, ID_MENU_VIEW_MEM, MF_BYCOMMAND|MF_UNCHECKED); hStatus = CreateWindowEx(0, STATUSCLASSNAME, NULL, WS_CHILD | WS_VISIBLE, 0, 0, 0, 0, hWnd, (HMENU)ID_STATUS, GetModuleHandle(NULL), NULL); // Split the status bar in two parts, 100 pixels and the rest. SendMessage(hStatus, SB_SETPARTS, 2, (LPARAM)nStatBars); SendMessage(hStatus, SB_SETTEXT, 1, (LPARAM)"Application loaded."); ResizeWin(hWnd, 240,0); return 0; // The window gets resized when a video is loaded. When this // happens, refresh the status bar by sending a WM_SIZE. case WM_SIZE: if(emu) emu->resize(lParam); SendMessage(hStatus, WM_SIZE, 0, 0); return 0; // If we get a CLOSE, signal a DESTROY. case WM_CLOSE: if(emu) emu->running=0; DestroyWindow(hWnd); hWndMain=NULL; return 0; // If we get a DESTROY, stop the video and QUIT. case WM_DESTROY: if(emu) emu->running=0; logvt->append("WND: Shutdown."); PostQuitMessage(0); return 0; case WM_PAINT: BeginPaint(hWnd, &ps); if(emu) emu->refresh(); EndPaint(hWnd, &ps); return 0; case WM_TIMER: if(emu && !emu->running) { switch(emu->animate) { case EMU_ANIM_STEP: emu->step(); break; case EMU_ANIM_LINE: /* if(emuLineDbg()==-2) { KillTimer(hWnd, timerID); sprintf(str, "DSEmu v0.0.1a - %s (Paused)", filename); SetWindowText(hWnd, str); MITEMS_PAUSE(); emuRunning=0; emuAnim=0; } */ emu->line(); break; } } return 0; case WM_STATUSFPS: sprintf(str,"10 frames in %dms = %.1f fps.",wParam,(float)10000/wParam); SendMessage(hStatus, SB_SETTEXT, 1, (LPARAM)str); return 0; case WM_KEYDOWN: if(emu) emu->keyin(wParam, 1); return DefWindowProc(hWnd, msg, wParam, lParam); case WM_KEYUP: if(emu) emu->keyin(wParam, 0); return DefWindowProc(hWnd, msg, wParam, lParam); case WM_LBUTTONDOWN: if(LoadDS) if(emu) if(emu->running || emu->animate) emu->keyin(VK_LBUTTON,lParam|0x80000000); return 0; case WM_LBUTTONUP: if(LoadDS) if(emu) if(emu->running || emu->animate) emu->keyin(VK_LBUTTON,lParam); return 0; case WM_MOUSEMOVE: if(LoadDS) if(emu) if(emu->running || emu->animate) emu->keyin(VK_LBUTTON,lParam|((wParam&MK_LBUTTON)?0x80000000:0)); return 0; case WM_DROPFILES: DragQueryFile((HDROP)wParam, 0, str, MAX_PATH); #ifdef WNDDEBUG sprintf(strout, "WND: File dropped: %s", str); logvt->append(strout); #endif DragFinish((HDROP)wParam); if(!strncmp((str+strlen(str)-3),"nds",3)) SendMessage(hWnd, WM_COMMAND, ID_MENU_FILE_OPENDS, (LPARAM)str); else SendMessage(hWnd, WM_COMMAND, ID_MENU_FILE_OPENGBA, (LPARAM)str); return 0; // If we get a COMMAND, it's a menu command; process it. case WM_COMMAND: switch(LOWORD(wParam)) { // If we're told to exit, close up the window. case ID_MENU_FILE_EXIT: #ifdef WNDDEBUG logvt->append("WND: Menu option: File/Exit."); #endif PostMessage(hWnd, WM_CLOSE, 0, 0); return 0; case ID_MENU_FILE_CLOSE: #ifdef WNDDEBUG logvt->append("WND: Menu option: File/Close."); #endif if(emu) { emu->running=0; emu->fini(); if(LoadDS) pluginUnload("ds"); else pluginUnload("gba"); emu=NULL; MITEMS_STOP(); KillTimer(hWnd, timerID); SetWindowText(hWnd, DSEMU_VERSION_STR); } return 0; // Open up an OpenFile dialog with a 'video files' filter, // and get the filename into our local array. case ID_MENU_FILE_OPENGBA: #ifdef WNDDEBUG logvt->append("WND: Menu option: File/Open."); #endif if(lParam) { if(*((char*)lParam)=='\\') sprintf(filename,"%s",lParam); else if(strstr((char*)lParam,":")) { if(*((char*)lParam)=='\"') { strcpy((char*)lParam, ((char*)lParam)+1); ((char*)lParam)[strlen(((char*)lParam))-1]=0; } sprintf(filename,"%s",lParam); } else { GetCurrentDirectory(MAX_PATH, filename); sprintf(filename,"%s\\%s",filename,lParam); } } else { ZeroMemory(&ofn, sizeof(ofn)); ofn.lStructSize = sizeof(ofn); ofn.hwndOwner = hWnd; ofn.lpstrFilter = "GBA ROMs and Binaries (gba, agb, zip, bin)\0*.gba;*.agb;*.zip;*.bin\0All files (*.*)\0*.*\0"; ofn.lpstrFile = filename; ofn.nMaxFile = 4096; ofn.Flags = OFN_PATHMUSTEXIST | OFN_FILEMUSTEXIST; ofn.lpstrDefExt = "gba"; if(!GetOpenFileName(&ofn)) return 0; } if(emu) { emu->fini(); if(LoadDS) pluginUnload("ds"); else pluginUnload("gba"); emu=NULL; MITEMS_STOP(); SetWindowText(hWnd, DSEMU_VERSION_STR); SendMessage(hStatus, SB_SETTEXT, 1, (LPARAM)"ROM closed."); } SendMessage(hStatus, SB_SETTEXT, 1, (LPARAM)"Loading GBA ROM..."); LoadDS=0; emu=(EMUVTBL*)pluginLoad("gba"); // logvt->append(filename); if(emu->init(filename,logvt,hWnd)) { emu->fini(); pluginUnload("gba"); emu=NULL; SendMessage(hStatus, SB_SETTEXT, 1, (LPARAM)"GBA Load failed."); MessageBox(NULL, "DSemu was unable to initialise the emulator. Please check log.txt for more details.", "DSemu initialisation error", MB_OK|MB_ICONEXCLAMATION); return 0; } CheckMenuItem(hMenu, ID_MENU_VIEW_GPU, MF_BYCOMMAND|MF_CHECKED); CheckMenuItem(hMenu, ID_MENU_VIEW_FPS, MF_BYCOMMAND|((emu->fixfps)?MF_CHECKED:MF_UNCHECKED)); SetForegroundWindow(hWnd); MITEMS_START(); sprintf(str, "%s - %s", strrchr(filename,'\\')+1, DSEMU_VERSION_STR); SetWindowText(hWnd, str); SendMessage(hStatus, SB_SETTEXT, 1, (LPARAM)"New GBA ROM loaded."); if(GetPrivateProfileInt("General","LoadAndRun",0,INIfile)) { SendMessage(hWnd, WM_COMMAND, ID_MENU_DBG_RUN, 0); } else { SendMessage(hWnd, WM_COMMAND, ID_MENU_DBG_PAUSE, 0); SendMessage(hStatus, SB_SETTEXT, 0, (LPARAM)"Paused"); } return 0; case ID_MENU_FILE_OPENDS: #ifdef WNDDEBUG logvt->append("WND: Menu option: File/Open."); #endif if(lParam) { if(*((char*)lParam)=='\\') sprintf(filename,"%s",lParam); else if(strstr((char*)lParam,":")) { if(*((char*)lParam)=='\"') { strcpy((char*)lParam, ((char*)lParam)+1); ((char*)lParam)[strlen(((char*)lParam))-1]=0; } sprintf(filename,"%s",lParam); } else { GetCurrentDirectory(MAX_PATH, filename); sprintf(filename,"%s\\%s",filename,lParam); } } else { ZeroMemory(&ofn, sizeof(ofn)); ofn.lStructSize = sizeof(ofn); ofn.hwndOwner = hWnd; ofn.lpstrFilter = "DS ROMs and Binaries (nds, bin, zip)\0*.nds;*.bin;*.zip\0All files (*.*)\0*.*\0"; ofn.lpstrFile = filename; ofn.nMaxFile = 4096; ofn.Flags = OFN_PATHMUSTEXIST | OFN_FILEMUSTEXIST; ofn.lpstrDefExt = "bin"; if(!GetOpenFileName(&ofn)) return 0; } if(emu) { emu->fini(); if(LoadDS) pluginUnload("ds"); else pluginUnload("gba"); emu=NULL; MITEMS_STOP(); SetWindowText(hWnd, DSEMU_VERSION_STR); SendMessage(hStatus, SB_SETTEXT, 1, (LPARAM)"ROM closed."); } SendMessage(hStatus, SB_SETTEXT, 1, (LPARAM)"Loading DS ROM..."); LoadDS=1; emu=(EMUVTBL*)pluginLoad("ds"); // logvt->append(filename); if(emu->init(filename,logvt,hWnd)) { emu->fini(); pluginUnload("ds"); emu=NULL; SendMessage(hStatus, SB_SETTEXT, 1, (LPARAM)"DS Load failed."); MessageBox(NULL, "DSemu was unable to initialise the emulator. Please check log.txt for more details.", "DSemu initialisation error", MB_OK|MB_ICONEXCLAMATION); return 0; } CheckMenuItem(hMenu, ID_MENU_VIEW_GPU, MF_BYCOMMAND|MF_CHECKED); CheckMenuItem(hMenu, ID_MENU_VIEW_FPS, MF_BYCOMMAND|((emu->fixfps)?MF_CHECKED:MF_UNCHECKED)); SetForegroundWindow(hWnd); MITEMS_START(); sprintf(str, "%s - %s", strrchr(filename,'\\')+1, DSEMU_VERSION_STR); SetWindowText(hWnd, str); SendMessage(hStatus, SB_SETTEXT, 1, (LPARAM)"New DS ROM loaded."); if(GetPrivateProfileInt("General","LoadAndRun",0,INIfile)) { SendMessage(hWnd, WM_COMMAND, ID_MENU_DBG_RUN, 0); } else { SendMessage(hWnd, WM_COMMAND, ID_MENU_DBG_PAUSE, 0); SendMessage(hStatus, SB_SETTEXT, 0, (LPARAM)"Paused"); } return 0; case ID_MENU_DBG_RUN: #ifdef WNDDEBUG logvt->append("WND: Menu option: Debug/Run."); #endif if(emu && !emu->running) { KillTimer(hWnd, timerID); SendMessage(hStatus, SB_SETTEXT, 0, (LPARAM)"Running"); MITEMS_RUN(); emu->running=1; emu->animate=0; } return 0; case ID_MENU_DBG_PAUSE: #ifdef WNDDEBUG logvt->append("WND: Menu option: Debug/Pause."); #endif if(emu) { emu->refresh(); KillTimer(hWnd, timerID); SendMessage(hStatus, SB_SETTEXT, 0, (LPARAM)"Paused"); MITEMS_PAUSE(); emu->running=0; emu->animate=0; } return 0; case ID_MENU_DBG_RESET: #ifdef WNDDEBUG logvt->append("WND: Menu option: Debug/Reset."); #endif if(emu) { KillTimer(hWnd, timerID); emu->reset(); emu->refresh(); SendMessage(hStatus, SB_SETTEXT, 0, (LPARAM)"Reset"); MITEMS_START(); emu->running=0; emu->animate=0; } return 0; case ID_MENU_DBG_STEP: #ifdef WNDDEBUG logvt->append("WND: Menu option: Debug/Step."); #endif if(emu && !emu->running) { KillTimer(hWnd, timerID); emu->step(); MITEMS_PAUSE(); emu->running=0; emu->animate=0; } return 0; case ID_MENU_DBG_ASTEP: #ifdef WNDDEBUG logvt->append("WND: Menu option: Debug/Animate Step."); #endif if(emu && !emu->running) { emu->step(); MITEMS_RUN(); SendMessage(hStatus, SB_SETTEXT, 0, (LPARAM)"Stepping"); timerID = SetTimer(hWnd, 1, 1, NULL); emu->running=0; emu->animate=EMU_ANIM_STEP; } return 0; case ID_MENU_DBG_LINE: #ifdef WNDDEBUG logvt->append("WND: Menu option: Debug/Scanline."); #endif if(emu && !emu->running) { KillTimer(hWnd, timerID); emu->line(); MITEMS_PAUSE(); emu->running=0; } return 0; case ID_MENU_DBG_ALINE: #ifdef WNDDEBUG logvt->append("WND: Menu option: Debug/Animate Scanline."); #endif if(emu && !emu->running) { emu->line(); MITEMS_RUN(); SendMessage(hStatus, SB_SETTEXT, 0, (LPARAM)"Scanline"); timerID = SetTimer(hWnd, 1, 1, NULL); emu->running=0; emu->animate=EMU_ANIM_LINE; } return 0; case ID_MENU_VIEW_GPU: #ifdef WNDDEBUG logvt->append("WND: Menu option: View/GPU Active."); #endif if(emu->gpuon) { CheckMenuItem(hMenu, ID_MENU_VIEW_GPU, MF_BYCOMMAND|MF_UNCHECKED); emu->gpuon=0; } else { CheckMenuItem(hMenu, ID_MENU_VIEW_GPU, MF_BYCOMMAND|MF_CHECKED); emu->gpuon=1; } return 0; case ID_MENU_VIEW_FPS: #ifdef WNDDEBUG logvt->append("WND: Menu option: View/Limit FPS."); #endif if(emu->fixfps) { CheckMenuItem(hMenu, ID_MENU_VIEW_FPS, MF_BYCOMMAND|MF_UNCHECKED); emu->fixfps=0; } else { CheckMenuItem(hMenu, ID_MENU_VIEW_FPS, MF_BYCOMMAND|MF_CHECKED); emu->fixfps=1; } return 0; case ID_MENU_VIEW_PAL: #ifdef WNDDEBUG logvt->append("WND: Menu option: View/Palette."); #endif if(emu) CheckMenuItem(hMenu, ID_MENU_VIEW_PAL, MF_BYCOMMAND|emu->kidwin(1)); return 0; case ID_MENU_VIEW_DBG: #ifdef WNDDEBUG logvt->append("WND: Menu option: View/Debugger."); #endif if(emu) CheckMenuItem(hMenu, ID_MENU_VIEW_DBG, MF_BYCOMMAND|emu->kidwin(2)); return 0; case ID_MENU_VIEW_MEM: #ifdef WNDDEBUG logvt->append("WND: Menu option: View/Memory."); #endif if(emu) CheckMenuItem(hMenu, ID_MENU_VIEW_MEM, MF_BYCOMMAND|emu->kidwin(4)); return 0; case ID_MENU_OPT_CONF: #ifdef WNDDEBUG logvt->append("WND: Menu option: Options/Config."); #endif if(DialogBox(GetModuleHandle(NULL), MAKEINTRESOURCE(ID_CONFBOX), hWnd, WinConfProc)==ID_OK) { SendMessage(hStatus, SB_SETTEXT, 1, (LPARAM)"Configuration saved."); } else SendMessage(hStatus, SB_SETTEXT, 1, (LPARAM)"Configuration not saved."); return 0; // If we received notification to show the About, do it. case ID_MENU_HELP_ABOUT: #ifdef WNDDEBUG logvt->append("WND: Menu option: Help/About."); #endif DialogBox(GetModuleHandle(NULL), MAKEINTRESOURCE(ID_ABOUTBOX), hWnd, WinAboutProc); return 0; } // Otherwise, let Windows handle it. default: return DefWindowProc(hWnd, msg, wParam, lParam); } } //------------------------------------------------------------------------- // Function: WinAboutProc(HWND, UINT, WPARAM, LPARAM) // Purpose: Process messages for the About dialog box. // Comments: The About dialog is a window like any other, so needs a // message service routine. BOOL CALLBACK WinAboutProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam) { HDC hDC; switch(message) { // We don't actually care about initialisation, so say 'Nice'. case WM_INITDIALOG: return TRUE; case WM_CTLCOLORSTATIC: hDC=(HDC)wParam; SetTextColor(hDC,RGB(0,0,0)); SetBkMode(hDC,TRANSPARENT); return (LONG)GetStockObject(HOLLOW_BRUSH); case WM_CLOSE: EndDialog(hWnd, ID_OK); return TRUE; // If we receive a press of OK, close the box. case WM_COMMAND: switch(LOWORD(wParam)) { case ID_OK: EndDialog(hWnd, ID_OK); break; } break; // Otherwise, let Windows handle it. default: return FALSE; } return TRUE; } BOOL CALLBACK WinConfProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam) { HDC hDC; int inipathlen; char str[256], biosfile[MAX_PATH*2]; int loadrun, fpslimit, keys[10], a; switch(message) { case WM_INITDIALOG: CheckDlgButton(hWnd, ID_CONF_CHK_RUN, (GetPrivateProfileInt("General","LoadAndRun",0,INIfile)) ?BST_CHECKED:BST_UNCHECKED); CheckDlgButton(hWnd, ID_CONF_CHK_FPS, (GetPrivateProfileInt("General","FixFPS",0,INIfile)) ?BST_CHECKED:BST_UNCHECKED); GetPrivateProfileString("General","BIOS","bioshack.bin",biosfile,16,INIfile); SetDlgItemText(hWnd, ID_CONF_EDIT_BIOS, biosfile); for(a=0;a<10;a++) { KeyEdits[a].hWnd=GetDlgItem(hWnd,a+ID_CONF_EDIT_UP); KeyEdits[a].OldEditProc=SetWindowLong(KeyEdits[a].hWnd, GWL_WNDPROC,(LONG)&WinEditProc); } GetPrivateProfileString("Keys","UP","26",str,4,INIfile); SendMessage(KeyEdits[0].hWnd,WM_USER+15,strtol(str,NULL,16)&255,0); GetPrivateProfileString("Keys","DOWN","28",str,4,INIfile); SendMessage(KeyEdits[1].hWnd,WM_USER+15,strtol(str,NULL,16)&255,0); GetPrivateProfileString("Keys","LEFT","25",str,4,INIfile); SendMessage(KeyEdits[2].hWnd,WM_USER+15,strtol(str,NULL,16)&255,0); GetPrivateProfileString("Keys","RIGHT","27",str,4,INIfile); SendMessage(KeyEdits[3].hWnd,WM_USER+15,strtol(str,NULL,16)&255,0); GetPrivateProfileString("Keys","A","5A",str,4,INIfile); SendMessage(KeyEdits[4].hWnd,WM_USER+15,strtol(str,NULL,16)&255,0); GetPrivateProfileString("Keys","B","58",str,4,INIfile); SendMessage(KeyEdits[5].hWnd,WM_USER+15,strtol(str,NULL,16)&255,0); GetPrivateProfileString("Keys","L","41",str,4,INIfile); SendMessage(KeyEdits[6].hWnd,WM_USER+15,strtol(str,NULL,16)&255,0); GetPrivateProfileString("Keys","R","53",str,4,INIfile); SendMessage(KeyEdits[7].hWnd,WM_USER+15,strtol(str,NULL,16)&255,0); GetPrivateProfileString("Keys","START","0D",str,4,INIfile); SendMessage(KeyEdits[8].hWnd,WM_USER+15,strtol(str,NULL,16)&255,0); GetPrivateProfileString("Keys","SELECT","08",str,4,INIfile); SendMessage(KeyEdits[9].hWnd,WM_USER+15,strtol(str,NULL,16)&255,0); return TRUE; /* case WM_CTLCOLORSTATIC: hDC=(HDC)wParam; SetTextColor(hDC,RGB(0,0,0)); SetBkMode(hDC,TRANSPARENT); return (LONG)GetStockObject(HOLLOW_BRUSH); */ case WM_CLOSE: SendMessage(hWnd, WM_COMMAND, ID_CANCEL, 0); return TRUE; // If we receive a press of OK, close the box. case WM_COMMAND: switch(LOWORD(wParam)) { case ID_OK: sprintf(str,"%1d",IsDlgButtonChecked(hWnd,ID_CONF_CHK_RUN)?1:0); WritePrivateProfileString("General","LoadAndRun",str,INIfile); sprintf(str,"%1d",IsDlgButtonChecked(hWnd,ID_CONF_CHK_FPS)?1:0); WritePrivateProfileString("General","FixFPS",str,INIfile); GetDlgItemText(hWnd,ID_CONF_EDIT_BIOS,str,MAX_PATH); WritePrivateProfileString("General","BIOS",str,INIfile); sprintf(str,"%02X",KeyEdits[0].key); WritePrivateProfileString("Keys","UP",str,INIfile); sprintf(str,"%02X",KeyEdits[1].key); WritePrivateProfileString("Keys","DOWN",str,INIfile); sprintf(str,"%02X",KeyEdits[2].key); WritePrivateProfileString("Keys","LEFT",str,INIfile); sprintf(str,"%02X",KeyEdits[3].key); WritePrivateProfileString("Keys","RIGHT",str,INIfile); sprintf(str,"%02X",KeyEdits[4].key); WritePrivateProfileString("Keys","A",str,INIfile); sprintf(str,"%02X",KeyEdits[5].key); WritePrivateProfileString("Keys","B",str,INIfile); sprintf(str,"%02X",KeyEdits[6].key); WritePrivateProfileString("Keys","L",str,INIfile); sprintf(str,"%02X",KeyEdits[7].key); WritePrivateProfileString("Keys","R",str,INIfile); sprintf(str,"%02X",KeyEdits[8].key); WritePrivateProfileString("Keys","START",str,INIfile); sprintf(str,"%02X",KeyEdits[9].key); WritePrivateProfileString("Keys","SELECT",str,INIfile); EndDialog(hWnd, ID_OK); break; case ID_CANCEL: EndDialog(hWnd, ID_CANCEL); break; case ID_CONF_CHK_RUN: loadrun=IsDlgButtonChecked(hWnd, ID_CONF_CHK_RUN); CheckDlgButton(hWnd, ID_CONF_CHK_RUN, (loadrun==BST_UNCHECKED)?BST_CHECKED:BST_UNCHECKED); break; case ID_CONF_CHK_FPS: fpslimit=IsDlgButtonChecked(hWnd, ID_CONF_CHK_FPS); CheckDlgButton(hWnd, ID_CONF_CHK_FPS, (fpslimit==BST_UNCHECKED)?BST_CHECKED:BST_UNCHECKED); break; } break; // Otherwise, let Windows handle it. default: return FALSE; } return TRUE; } LRESULT CALLBACK WinEditProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam) { int a, ctl, curkey=-1; char str[80]; switch(msg) { case WM_SETFOCUS: SendMessage(hWnd, WM_SETTEXT, 0, (LPARAM)"Press a key"); for(a=0;a<10;a++) if(KeyEdits[a].hWnd==hWnd) ctl=a; return CallWindowProc(KeyEdits[ctl].OldEditProc,hWnd,msg,wParam,lParam); case WM_USER+15: LoadString(GetModuleHandle(NULL),wParam+1024,str,80); SendMessage(hWnd, WM_SETTEXT, 0, (LPARAM)str); for(a=0;a<10;a++) if(KeyEdits[a].hWnd==hWnd) ctl=a; KeyEdits[ctl].key=wParam; return CallWindowProc(KeyEdits[ctl].OldEditProc,hWnd,msg,wParam,lParam); case WM_KEYUP: LoadString(GetModuleHandle(NULL),wParam+1024,str,80); SendMessage(hWnd, WM_SETTEXT, 0, (LPARAM)str); for(a=0;a<10;a++) if(KeyEdits[a].hWnd==hWnd) ctl=a; for(a=0;a<10;a++) if(a!=ctl && KeyEdits[a].key==wParam) curkey=a; if(curkey>=0) SendMessage(hWnd, WM_SETTEXT, 0, (LPARAM)"Already used"); else KeyEdits[ctl].key=wParam; return CallWindowProc(KeyEdits[ctl].OldEditProc,hWnd,msg,wParam,lParam); case WM_GETDLGCODE: return DLGC_WANTALLKEYS; default: for(a=0;a<10;a++) if(KeyEdits[a].hWnd==hWnd) ctl=a; return CallWindowProc(KeyEdits[ctl].OldEditProc,hWnd,msg,wParam,lParam); } } void ResizeWin(HWND wnd, int x, int y) { RECT rWnd, rCli, rDiff, rStat; HWND hStatus; int neww, newh; char str[80]; GetWindowRect(wnd, &rWnd); GetClientRect(wnd, &rCli); SetRect(&rDiff, 0, 0, (rWnd.right - rWnd.left) - rCli.right, (rWnd.bottom - rWnd.top) - rCli.bottom); hStatus = GetDlgItem(wnd, ID_STATUS); if(hStatus) { SendMessage(hStatus, WM_SIZE, 0, 0); GetWindowRect(hStatus, &rStat); } else SetRect(&rStat,0,0,0,0); neww = x + rDiff.right; newh = y + rDiff.bottom + (rStat.bottom - rStat.top); SetWindowPos(wnd, HWND_TOP, 0, 0, neww, newh, SWP_NOMOVE|SWP_NOZORDER); } /*** EOF:win.c ***********************************************************/