// ****************************************************************** // * // * .,-::::: .,:: .::::::::. .,:: .: // * ,;;;'````' `;;;, .,;; ;;;'';;' `;;;, .,;; // * [[[ '[[,,[[' [[[__[[\. '[[,,[[' // * $$$ Y$$$P $$""""Y$$ Y$$$P // * `88bo,__,o, oP"``"Yo, _88o,,od8P oP"``"Yo, // * "YUMMMMMP",m" "Mm,""YUMMMP" ,m" "Mm, // * // * Cxbx->Win32->Cxbx->WndMain.cpp // * // * This file is part of the Cxbx project. // * // * Cxbx and Cxbe are free software; you can redistribute them // * and/or modify them under the terms of the GNU General Public // * License as published by the Free Software Foundation; either // * version 2 of the license, or (at your option) any later version. // * // * This program is distributed in the hope that it will be useful, // * but WITHOUT ANY WARRANTY; without even the implied warranty of // * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // * GNU General Public License for more details. // * // * You should have recieved a copy of the GNU General Public License // * along with this program; see the file COPYING. // * If not, write to the Free Software Foundation, Inc., // * 59 Temple Place - Suite 330, Bostom, MA 02111-1307, USA. // * // * (c) 2002-2003 Aaron Robinson // * // * All rights reserved // * // ****************************************************************** #include "Cxbx.h" #include "EmuExe.h" #include "WndMain.h" #include "WndAbout.h" #include "ResCxbx.h" #include #include // ****************************************************************** // * constructor // ****************************************************************** WndMain::WndMain(HINSTANCE x_hInstance) : Wnd(x_hInstance), m_bCreated(false), m_Xbe(0), m_Exe(0), m_bExeChanged(false), m_bXbeChanged(false), m_KrnlDebug(DM_NONE), m_CxbxDebug(DM_NONE) { m_classname = "WndMain"; m_wndname = "Cxbx : Xbox Emulator"; m_w = 327; m_h = 253; // ****************************************************************** // * Center to desktop // ****************************************************************** { RECT rect; GetWindowRect(GetDesktopWindow(), &rect); m_x = rect.left + (rect.right - rect.left)/2 - m_w/2; m_y = rect.top + (rect.bottom - rect.top)/2 - m_h/2; } m_ExeFilename = (char*)calloc(1, 260); m_XbeFilename = (char*)calloc(1, 260); m_CxbxDebugFilename = (char*)calloc(1, 260); m_KrnlDebugFilename = (char*)calloc(1, 260); // ****************************************************************** // * Load configuration from registry // ****************************************************************** { DWORD dwDisposition, dwType, dwSize; HKEY hKey; if(RegCreateKeyEx(HKEY_CURRENT_USER, "Software\\Cxbx", 0, NULL, REG_OPTION_NON_VOLATILE, KEY_QUERY_VALUE, NULL, &hKey, &dwDisposition) == ERROR_SUCCESS) { dwType = REG_DWORD; dwSize = sizeof(DWORD); RegQueryValueEx(hKey, "CxbxDebug", NULL, &dwType, (PBYTE)&m_CxbxDebug, &dwSize); RegQueryValueEx(hKey, "KrnlDebug", NULL, &dwType, (PBYTE)&m_KrnlDebug, &dwSize); dwType = REG_SZ; dwSize = 260; RegQueryValueEx(hKey, "CxbxDebugFilename", NULL, &dwType, (PBYTE)m_CxbxDebugFilename, &dwSize); RegQueryValueEx(hKey, "KrnlDebugFilename", NULL, &dwType, (PBYTE)m_KrnlDebugFilename, &dwSize); RegCloseKey(hKey); } } return; } // ****************************************************************** // * deconstructor // ****************************************************************** WndMain::~WndMain() { // ****************************************************************** // * Save configuration to registry // ****************************************************************** { DWORD dwDisposition, dwType, dwSize; HKEY hKey; if(RegCreateKeyEx(HKEY_CURRENT_USER, "Software\\Cxbx", 0, NULL, REG_OPTION_NON_VOLATILE, KEY_SET_VALUE, NULL, &hKey, &dwDisposition) == ERROR_SUCCESS) { dwType = REG_DWORD; dwSize = sizeof(DWORD); RegSetValueEx(hKey, "CxbxDebug", 0, dwType, (PBYTE)&m_CxbxDebug, dwSize); RegSetValueEx(hKey, "KrnlDebug", 0, dwType, (PBYTE)&m_KrnlDebug, dwSize); dwType = REG_SZ; dwSize = 260; RegSetValueEx(hKey, "CxbxDebugFilename", 0, dwType, (PBYTE)m_CxbxDebugFilename, dwSize); RegSetValueEx(hKey, "KrnlDebugFilename", 0, dwType, (PBYTE)m_KrnlDebugFilename, dwSize); RegCloseKey(hKey); } } delete m_Xbe; delete m_Exe; delete[] m_XbeFilename; delete[] m_ExeFilename; delete[] m_CxbxDebugFilename; delete[] m_KrnlDebugFilename; } // ****************************************************************** // * WndProc // ****************************************************************** LRESULT CALLBACK WndMain::WndProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam) { switch(uMsg) { case WM_CREATE: { // ****************************************************************** // * resize window so that client area == 321x201 // ****************************************************************** { RECT cRect; RECT wRect; GetClientRect(hwnd, &cRect); GetWindowRect(hwnd, &wRect); uint32 difW = (wRect.right - wRect.left) - (cRect.right); uint32 difH = (wRect.bottom - wRect.top) - (cRect.bottom); MoveWindow(hwnd, wRect.left, wRect.top, difW + 321, difH + 221, TRUE); } // ****************************************************************** // * initialize menu // ****************************************************************** { HMENU hMenu = LoadMenu(m_hInstance, MAKEINTRESOURCE(IDR_MAINMENU)); SetMenu(hwnd, hMenu); } // ****************************************************************** // * initialize back buffer // ****************************************************************** { HDC hDC = GetDC(hwnd); m_BackBmp = (HBITMAP)LoadImage(m_hInstance, MAKEINTRESOURCE(IDB_SPLASH), IMAGE_BITMAP, 0, 0, 0); m_LogoBmp = (HBITMAP)LoadImage(m_hInstance, MAKEINTRESOURCE(IDB_LOGO), IMAGE_BITMAP, 0, 0, 0); m_BackDC = CreateCompatibleDC(hDC); m_LogoDC = CreateCompatibleDC(hDC); m_OrigBmp = (HBITMAP)SelectObject(m_BackDC, m_BackBmp); m_OrigLogo = (HBITMAP)SelectObject(m_LogoDC, m_LogoBmp); if(hDC != NULL) ReleaseDC(hwnd, hDC); } m_bCreated = true; } break; case WM_PAINT: { static bool s_bInitMenu = true; if(s_bInitMenu) { UpdateDebugConsoles(); s_bInitMenu = false; } PAINTSTRUCT ps; BeginPaint(hwnd, &ps); HDC hDC = GetDC(hwnd); // ****************************************************************** // * draw splash/logo/status // ****************************************************************** { BitBlt(hDC, 0, (m_Xbe == 0) ? 0 : 10, 320, 160, m_BackDC, 0, 0, SRCCOPY); BitBlt(hDC, 220, 168, 100, 17, m_LogoDC, 0, 0, SRCCOPY); int nHeight = -MulDiv(8, GetDeviceCaps(hDC, LOGPIXELSY), 72); HFONT hFont = CreateFont(nHeight, 0, 0, 0, FW_NORMAL, FALSE, FALSE, FALSE, DEFAULT_CHARSET, OUT_DEFAULT_PRECIS, CLIP_DEFAULT_PRECIS, PROOF_QUALITY, FF_ROMAN, "Verdana"); HGDIOBJ tmpObj = SelectObject(hDC, hFont); SetBkColor(hDC, GetSysColor(COLOR_HIGHLIGHT)); SetTextColor(hDC, GetSysColor(COLOR_HIGHLIGHTTEXT)); char buffer[255]; if(m_Xbe != 0 && m_Xbe->GetError() == 0) sprintf(buffer, "%s Loaded!", m_Xbe->m_szAsciiTitle); else sprintf(buffer, "%s", "Disclaimer: Cxbx has no affiliation with Microsoft"); RECT rect = {0, 187, 321, 201}; ExtTextOut(hDC, 5, 187, ETO_OPAQUE, &rect, buffer, strlen(buffer), 0); SelectObject(hDC, tmpObj); DeleteObject(hFont); } if(hDC != NULL) ReleaseDC(hwnd, hDC); EndPaint(hwnd, &ps); } break; case WM_COMMAND: { switch(LOWORD(wParam)) { case ID_FILE_OPEN_XBE: { OPENFILENAME ofn = {0}; char filename[260] = {0}; ofn.lStructSize = sizeof(OPENFILENAME); ofn.hwndOwner = m_hwnd; ofn.lpstrFilter = "Xbox Executables (*.xbe)\0*.xbe\0"; ofn.lpstrFile = filename; ofn.nMaxFile = 260; ofn.nFilterIndex = 1; ofn.lpstrFileTitle = NULL; ofn.nMaxFileTitle = 0; ofn.lpstrInitialDir = NULL; ofn.Flags = OFN_PATHMUSTEXIST | OFN_FILEMUSTEXIST; if(GetOpenFileName(&ofn) == TRUE) OpenXbe(ofn.lpstrFile); } break; case ID_FILE_CLOSE_XBE: CloseXbe(); break; case ID_FILE_SAVEXBEFILE: { if(m_XbeFilename[0] == '\0') SaveXbeAs(); else SaveXbe(m_XbeFilename); } break; case ID_FILE_SAVEXBEFILEAS: SaveXbeAs(); break; case ID_FILE_IMPORTFROMEXE: { m_ExeFilename[0] = '\0'; OPENFILENAME ofn = {0}; char filename[260] = {0}; ofn.lStructSize = sizeof(OPENFILENAME); ofn.hwndOwner = m_hwnd; ofn.lpstrFilter = "Windows Executables (*.exe)\0*.exe\0"; ofn.lpstrFile = filename; ofn.nMaxFile = 260; ofn.nFilterIndex = 1; ofn.lpstrFileTitle = NULL; ofn.nMaxFileTitle = 0; ofn.lpstrInitialDir = NULL; ofn.Flags = OFN_PATHMUSTEXIST | OFN_FILEMUSTEXIST; if(GetOpenFileName(&ofn) == TRUE) { m_XbeFilename[0] = '\0'; Exe *i_exe = new Exe(ofn.lpstrFile); if(i_exe->GetError() != 0) { MessageBox(m_hwnd, i_exe->GetError(), "Cxbx", MB_ICONSTOP | MB_OK); delete i_exe; break; } m_Xbe = new Xbe(i_exe, "Untitled", true); if(m_Xbe->GetError() != 0) { MessageBox(m_hwnd, m_Xbe->GetError(), "Cxbx", MB_ICONSTOP | MB_OK); delete m_Xbe; m_Xbe = 0; break; } XbeLoaded(); m_bExeChanged = true; } } break; case ID_FILE_EXPORTTOEXE: ConvertToExe(NULL, true); break; case ID_FILE_EXIT: SendMessage(hwnd, WM_CLOSE, 0, 0); break; case ID_EDIT_LOGOBITMAP_EXPORT: { OPENFILENAME ofn = {0}; char filename[260] = "logo.bmp"; ofn.lStructSize = sizeof(OPENFILENAME); ofn.hwndOwner = m_hwnd; ofn.lpstrFilter = "Bitmap Image Files (*.bmp)\0*.bmp\0"; ofn.lpstrFile = filename; ofn.nMaxFile = 260; ofn.nFilterIndex = 1; ofn.lpstrFileTitle = NULL; ofn.nMaxFileTitle = 0; ofn.lpstrInitialDir = NULL; ofn.lpstrDefExt = "bmp"; ofn.lpstrTitle = "Export Logo Bitmap"; ofn.Flags = OFN_PATHMUSTEXIST; if(GetSaveFileName(&ofn) == TRUE) { // ****************************************************************** // * ask permission to overwrite if file exists // ****************************************************************** if(_access(ofn.lpstrFile, 0) != -1) { if(MessageBox(m_hwnd, "Overwrite existing file?", "Cxbx", MB_ICONQUESTION | MB_YESNO) != IDYES) return TRUE; } // ****************************************************************** // * export logo bitmap // ****************************************************************** { uint08 i_gray[100*17]; m_Xbe->ExportLogoBitmap(i_gray); if(m_Xbe->GetError() == 0) { FILE *LogoBitmap = fopen(ofn.lpstrFile, "wb"); // ****************************************************************** // * write bitmap header // ****************************************************************** { BITMAPFILEHEADER bmfh; bmfh.bfType = *(uint16*)"BM"; bmfh.bfSize = sizeof(BITMAPFILEHEADER) + sizeof(BITMAPINFO) - sizeof(RGBQUAD) + (100*17)*sizeof(RGBTRIPLE) + 2; bmfh.bfReserved1 = 0; bmfh.bfReserved2 = 0; bmfh.bfOffBits = sizeof(BITMAPFILEHEADER) + sizeof(BITMAPINFO) - sizeof(RGBQUAD); fwrite(&bmfh, sizeof(bmfh), 1, LogoBitmap); } // ****************************************************************** // * write bitmap info // ****************************************************************** { BITMAPINFO bmi; bmi.bmiHeader.biSize = sizeof(BITMAPINFO) - sizeof(RGBQUAD); bmi.bmiHeader.biWidth = 100; bmi.bmiHeader.biHeight = -17; bmi.bmiHeader.biPlanes = 1; bmi.bmiHeader.biBitCount = 24; bmi.bmiHeader.biCompression = BI_RGB; bmi.bmiHeader.biSizeImage = 0; bmi.bmiHeader.biXPelsPerMeter = 0; bmi.bmiHeader.biYPelsPerMeter = 0; bmi.bmiHeader.biClrUsed = 0; bmi.bmiHeader.biClrImportant = 0; fwrite(&bmi, sizeof(bmi) - 4, 1, LogoBitmap); } // ****************************************************************** // * write bitmap data // ****************************************************************** { RGBTRIPLE bmp_data[100*17]; for(uint32 v=0;v<100*17;v++) { bmp_data[v].rgbtRed = i_gray[v]; bmp_data[v].rgbtGreen = i_gray[v]; bmp_data[v].rgbtBlue = i_gray[v]; } fwrite(bmp_data, 100*17*sizeof(RGBTRIPLE), 1, LogoBitmap); } // ****************************************************************** // * write bitmap padding // ****************************************************************** { uint16 pad = 0; fwrite(&pad, 2, 1, LogoBitmap); } fclose(LogoBitmap); } if(m_Xbe->GetError() != 0) MessageBox(m_hwnd, m_Xbe->GetError(), "Cxbx", MB_ICONSTOP | MB_OK); else { char buffer[255]; sprintf(buffer, "%s's logo bitmap was successfully exported.", m_Xbe->m_szAsciiTitle); MessageBox(m_hwnd, buffer, "Cxbx", MB_ICONINFORMATION | MB_OK); printf("WndMain: %s\n", buffer); } } } } break; case ID_EDIT_LOGOBITMAP_IMPORT: { OPENFILENAME ofn = {0}; char filename[260] = "*.bmp"; ofn.lStructSize = sizeof(OPENFILENAME); ofn.hwndOwner = m_hwnd; ofn.lpstrFilter = "Bitmap Image Files (*.bmp)\0*.bmp\0"; ofn.lpstrFile = filename; ofn.nMaxFile = 260; ofn.nFilterIndex = 1; ofn.lpstrFileTitle = NULL; ofn.nMaxFileTitle = 0; ofn.lpstrInitialDir = NULL; ofn.lpstrDefExt = "bmp"; ofn.lpstrTitle = "Import Logo Bitmap"; ofn.Flags = OFN_PATHMUSTEXIST; if(GetOpenFileName(&ofn) == TRUE) { // ****************************************************************** // * import logo bitmap // ****************************************************************** { uint08 i_gray[100*17]; // ****************************************************************** // * read bitmap file // ****************************************************************** { FILE *logo = fopen(ofn.lpstrFile, "rb"); char *bmp_err = 0; // ****************************************************************** // * read bitmap header // ****************************************************************** if(!bmp_err) { BITMAPFILEHEADER bmfh; fread(&bmfh, sizeof(bmfh), 1, logo); if(bmfh.bfType != *(uint16*)"BM") bmp_err = "Invalid bitmap file...\n\nonly allows 24 bit bitmaps (100 by 17 pixels) with row order swapped"; else if(bmfh.bfSize != sizeof(BITMAPFILEHEADER) + sizeof(BITMAPINFO) - sizeof(RGBQUAD) + (100*17)*sizeof(RGBTRIPLE) + 2) bmp_err = "Invalid bitmap file...\n\nonly allows 24 bit bitmaps (100 by 17 pixels) with row order swapped"; } // ****************************************************************** // * read bitmap info // ****************************************************************** if(!bmp_err) { BITMAPINFO bmi; fread(&bmi, sizeof(bmi) - 4, 1, logo); if(bmi.bmiHeader.biWidth != 100 || bmi.bmiHeader.biHeight != -17) bmp_err = "Invalid bitmap file...\n\nonly allows 24 bit bitmaps (100 by 17 pixels) with row order swapped"; } // ****************************************************************** // * read bitmap data // ****************************************************************** if(!bmp_err) { RGBTRIPLE bmp_data[100*17]; fread(bmp_data, 100*17*sizeof(RGBTRIPLE), 1, logo); for(uint32 c=0;c<100*17;c++) i_gray[c] = (char)(((float)bmp_data[c].rgbtRed + (float)bmp_data[c].rgbtGreen + (float)bmp_data[c].rgbtBlue) / 3.0); } fclose(logo); if(bmp_err != 0) { MessageBox(m_hwnd, bmp_err, "Cxbx", MB_OK | MB_ICONEXCLAMATION); break; } } m_Xbe->ImportLogoBitmap(i_gray); if(m_Xbe->GetError() != 0) { MessageBox(m_hwnd, m_Xbe->GetError(), "Cxbx", MB_ICONSTOP | MB_OK); if(m_Xbe->IsFatal()) CloseXbe(); else m_Xbe->ClearError(); } else { m_bExeChanged = true; m_bXbeChanged = true; LoadLogo(); char buffer[255]; sprintf(buffer, "%s's logo bitmap was successfully updated.", m_Xbe->m_szAsciiTitle); printf("WndMain: %s\n", buffer); MessageBox(m_hwnd, buffer, "Cxbx", MB_ICONINFORMATION | MB_OK); } } } } break; case ID_EDIT_PATCH_ALLOW64MB: { m_bExeChanged = true; m_bXbeChanged = true; m_Xbe->m_Header.dwInitFlags.bLimit64MB = !m_Xbe->m_Header.dwInitFlags.bLimit64MB; HMENU menu = GetMenu(m_hwnd); HMENU edit_menu = GetSubMenu(menu, 1); HMENU pach_menu = GetSubMenu(edit_menu, 1); // ****************************************************************** // * check "allow >64MB" if appropriate // ****************************************************************** { bool res = m_Xbe->m_Header.dwInitFlags.bLimit64MB; UINT chk_flag = (res) ? MF_UNCHECKED : MF_CHECKED; if(res) printf("WndMain: %s was patched to limit to 64MB of memory usage.\n", m_Xbe->m_szAsciiTitle); else printf("WndMain: %s was patched to allow >64MB of memory usage.\n", m_Xbe->m_szAsciiTitle); CheckMenuItem(pach_menu, ID_EDIT_PATCH_ALLOW64MB, chk_flag); } } break; case ID_EDIT_PATCH_DEBUGMODE: { m_bExeChanged = true; m_bXbeChanged = true; // ****************************************************************** // * patch to/from debug mode // ****************************************************************** if((m_Xbe->m_Header.dwEntryAddr ^ XOR_EP_RETAIL) > 0x01000000) { // we're in debug mode, so switch over to retail uint32 ep = m_Xbe->m_Header.dwEntryAddr ^ XOR_EP_RETAIL; // decode from debug mode uint32 kt = m_Xbe->m_Header.dwKernelImageThunkAddr ^ XOR_KT_DEBUG; // decode from debug mode m_Xbe->m_Header.dwEntryAddr = ep ^ XOR_EP_DEBUG; // encode to retail mode m_Xbe->m_Header.dwKernelImageThunkAddr = kt ^ XOR_KT_RETAIL; // encode to retail mode } else { // we're in retail mode, so switch to debug uint32 ep = m_Xbe->m_Header.dwEntryAddr ^ XOR_EP_DEBUG; // decode from retail mode uint32 kt = m_Xbe->m_Header.dwKernelImageThunkAddr ^ XOR_KT_RETAIL; // decode from retail mode m_Xbe->m_Header.dwEntryAddr = ep ^ XOR_EP_RETAIL; // encode to debug mode m_Xbe->m_Header.dwKernelImageThunkAddr = kt ^ XOR_KT_DEBUG; // encode to debug mode } HMENU menu = GetMenu(m_hwnd); HMENU edit_menu = GetSubMenu(menu, 1); HMENU pach_menu = GetSubMenu(edit_menu, 1); // ****************************************************************** // * check "debug mode" if appropriate // ****************************************************************** { bool res = (m_Xbe->m_Header.dwEntryAddr ^ XOR_EP_RETAIL) > 0x01000000; UINT chk_flag = (res) ? MF_CHECKED : MF_UNCHECKED; if(res) printf("WndMain: %s was converted to debug mode.\n", m_Xbe->m_szAsciiTitle); else printf("WndMain: %s was converted to retail mode.\n", m_Xbe->m_szAsciiTitle); CheckMenuItem(pach_menu, ID_EDIT_PATCH_DEBUGMODE, chk_flag); } } break; case ID_EDIT_EXTRACTXBEINFO: { OPENFILENAME ofn = {0}; char filename[260] = "Xbe.txt"; ofn.lStructSize = sizeof(OPENFILENAME); ofn.hwndOwner = m_hwnd; ofn.lpstrFilter = "Text Documents (*.txt)\0*.txt\0"; ofn.lpstrFile = filename; ofn.nMaxFile = 260; ofn.nFilterIndex = 1; ofn.lpstrFileTitle = NULL; ofn.nMaxFileTitle = 0; ofn.lpstrInitialDir = NULL; ofn.lpstrDefExt = "txt"; ofn.Flags = OFN_PATHMUSTEXIST; if(GetSaveFileName(&ofn) == TRUE) { // ****************************************************************** // * ask permission to overwrite if file exists // ****************************************************************** if(_access(ofn.lpstrFile, 0) != -1) { if(MessageBox(m_hwnd, "Overwrite existing file?", "Cxbx", MB_ICONQUESTION | MB_YESNO) != IDYES) return TRUE; } // ****************************************************************** // * dump xbe information // ****************************************************************** { m_Xbe->DumpInformation(ofn.lpstrFile); if(m_Xbe->GetError() != 0) MessageBox(m_hwnd, m_Xbe->GetError(), "Cxbx", MB_ICONSTOP | MB_OK); else { char buffer[255]; sprintf(buffer, "%s's .xbe info was successfully exported.", m_Xbe->m_szAsciiTitle); printf("WndMain: %s\n", buffer); MessageBox(m_hwnd, buffer, "Cxbx", MB_ICONINFORMATION | MB_OK); } } } } break; case ID_VIEW_DEBUGOUTPUTKERNEL_CONSOLE: { if(m_KrnlDebug == DM_NONE || m_KrnlDebug == DM_FILE) m_KrnlDebug = DM_CONSOLE; else m_KrnlDebug = DM_NONE; MessageBox(m_hwnd, "This will not take effect until emulation is (re)started.\n", "Cxbx", MB_OK); m_bExeChanged = true; UpdateDebugConsoles(); } break; case ID_VIEW_DEBUGOUTPUTKERNEL_FILE: { if(m_KrnlDebug == DM_FILE) { m_KrnlDebug = DM_NONE; UpdateDebugConsoles(); } else { OPENFILENAME ofn = {0}; char filename[260] = "KrnlDebug.txt"; ofn.lStructSize = sizeof(OPENFILENAME); ofn.hwndOwner = m_hwnd; ofn.lpstrFilter = "Text Documents (*.txt)\0*.txt\0"; ofn.lpstrFile = filename; ofn.nMaxFile = 260; ofn.nFilterIndex = 1; ofn.lpstrFileTitle = NULL; ofn.nMaxFileTitle = 0; ofn.lpstrInitialDir = NULL; ofn.lpstrDefExt = "txt"; ofn.Flags = OFN_PATHMUSTEXIST; if(GetSaveFileName(&ofn) != FALSE) { MessageBox(m_hwnd, "This will not take effect until emulation is (re)started.\n", "Cxbx", MB_OK); strncpy(m_KrnlDebugFilename, ofn.lpstrFile, 259); m_bExeChanged = true; m_KrnlDebug = DM_FILE; UpdateDebugConsoles(); } } } break; case ID_VIEW_DEBUGOUTPUTGUI_CONSOLE: { if(m_CxbxDebug == DM_NONE || m_CxbxDebug == DM_FILE) m_CxbxDebug = DM_CONSOLE; else m_CxbxDebug = DM_NONE; UpdateDebugConsoles(); } break; case ID_VIEW_DEBUGOUTPUTGUI_FILE: { if(m_CxbxDebug == DM_FILE) { m_CxbxDebug = DM_NONE; UpdateDebugConsoles(); } else { OPENFILENAME ofn = {0}; char filename[260] = "CxbxDebug.txt"; ofn.lStructSize = sizeof(OPENFILENAME); ofn.hwndOwner = m_hwnd; ofn.lpstrFilter = "Text Documents (*.txt)\0*.txt\0"; ofn.lpstrFile = filename; ofn.nMaxFile = 260; ofn.nFilterIndex = 1; ofn.lpstrFileTitle = NULL; ofn.nMaxFileTitle = 0; ofn.lpstrInitialDir = NULL; ofn.lpstrDefExt = "txt"; ofn.Flags = OFN_PATHMUSTEXIST; if(GetSaveFileName(&ofn) != FALSE) { strncpy(m_CxbxDebugFilename, ofn.lpstrFile, 259); m_CxbxDebug = DM_FILE; UpdateDebugConsoles(); } } } break; case ID_EMULATION_START: StartEmulation(false); break; case ID_HELP_ABOUT: { WndAbout *AboutWnd = new WndAbout(m_hInstance, m_hwnd); while(AboutWnd->GetError() == 0 && AboutWnd->ProcessMessages()) Sleep(10); if(AboutWnd->GetError() != 0) MessageBox(m_hwnd, AboutWnd->GetError(), "Cxbx", MB_ICONSTOP | MB_OK); delete AboutWnd; } break; case ID_HELP_HOMEPAGE: ShellExecute(NULL, "open", "http://www.caustik.com/xbox/", NULL, NULL, SW_SHOWNORMAL); break; } break; } case WM_CLOSE: if(m_bXbeChanged) { int ret = MessageBox(m_hwnd, "Changes have been made, do you wish to save?", "Cxbx", MB_ICONQUESTION | MB_YESNOCANCEL); switch(ret) { case IDYES: SaveXbeAs(); break; case IDCANCEL: break; } } DestroyWindow(hwnd); break; case WM_DESTROY: { FreeConsole(); HDC hDC = GetDC(hwnd); SelectObject(m_LogoDC, m_OrigLogo); SelectObject(m_BackDC, m_OrigBmp); DeleteObject(m_LogoDC); DeleteObject(m_BackDC); DeleteObject(m_LogoBmp); DeleteObject(m_BackBmp); ReleaseDC(hwnd, hDC); delete m_Xbe; m_Xbe = 0; PostQuitMessage(0); } break; default: return DefWindowProc(hwnd, uMsg, wParam, lParam); } return 0; } // ****************************************************************** // * SuggestFilename // ****************************************************************** void WndMain::SuggestFilename(const char *x_orig_filename, char *x_filename, char x_extension[4]) { uint32 found = 0; uint32 v = 0; while(x_orig_filename[v] != '\0') { if(x_orig_filename[v] == '\\') found = v; v++; } if(found != 0) { strcpy(x_filename, x_orig_filename); uint32 loc = 0; uint32 c = 0; while(x_filename[c] != '\0') { if(x_filename[c] == '.') loc = c; c++; } if(loc != 0) *(uint32*)&x_filename[loc] = *(uint32*)x_extension; } } // ****************************************************************** // * XbeLoaded // ****************************************************************** void WndMain::XbeLoaded() { LoadLogo(); // ****************************************************************** // * disable/enable appropriate menus // ****************************************************************** { HMENU menu = GetMenu(m_hwnd); // ****************************************************************** // * file menu // ****************************************************************** { HMENU file_menu = GetSubMenu(menu, 0); // disable open .xbe file EnableMenuItem(file_menu, ID_FILE_OPEN_XBE, MF_BYCOMMAND | MF_GRAYED); // enable close .xbe file EnableMenuItem(file_menu, ID_FILE_CLOSE_XBE, MF_BYCOMMAND | MF_ENABLED); // enable save .xbe file EnableMenuItem(file_menu, ID_FILE_SAVEXBEFILE, MF_BYCOMMAND | MF_ENABLED); // enable save .xbe file as EnableMenuItem(file_menu, ID_FILE_SAVEXBEFILEAS, MF_BYCOMMAND | MF_ENABLED); // disable import from .exe EnableMenuItem(file_menu, ID_FILE_IMPORTFROMEXE, MF_BYCOMMAND | MF_GRAYED); // enable export to .exe EnableMenuItem(file_menu, ID_FILE_EXPORTTOEXE, MF_BYCOMMAND | MF_ENABLED); } // ****************************************************************** // * edit menu // ****************************************************************** { HMENU edit_menu = GetSubMenu(menu, 1); HMENU logo_menu = GetSubMenu(edit_menu, 0); HMENU pach_menu = GetSubMenu(edit_menu, 1); // enable export .xbe info EnableMenuItem(edit_menu, ID_EDIT_EXTRACTXBEINFO, MF_BYCOMMAND | MF_ENABLED); // enable logo bitmap menu EnableMenuItem(edit_menu, 0, MF_BYPOSITION | MF_ENABLED); // enable patch menu EnableMenuItem(edit_menu, 1, MF_BYPOSITION | MF_ENABLED); // ****************************************************************** // * patch menu // ****************************************************************** { // check "allow >64 MB" if appropriate { UINT chk_flag = (m_Xbe->m_Header.dwInitFlags.bLimit64MB) ? MF_UNCHECKED : MF_CHECKED; CheckMenuItem(pach_menu, ID_EDIT_PATCH_ALLOW64MB, chk_flag); } // check "debug mode" if appropriate { UINT chk_flag = ((m_Xbe->m_Header.dwEntryAddr ^ XOR_EP_RETAIL) > 0x01000000) ? MF_CHECKED : MF_UNCHECKED; CheckMenuItem(pach_menu, ID_EDIT_PATCH_DEBUGMODE, chk_flag); } } } // ****************************************************************** // * view menu // ****************************************************************** { HMENU view_menu = GetSubMenu(menu, 2); } // ****************************************************************** // * emulation menu // ****************************************************************** { HMENU emul_menu = GetSubMenu(menu, 3); // enable emulation start EnableMenuItem(emul_menu, ID_EMULATION_START, MF_BYCOMMAND | MF_ENABLED); } } InvalidateRgn(m_hwnd, NULL, TRUE); printf("WndMain: %s loaded.\n", m_Xbe->m_szAsciiTitle); } // ****************************************************************** // * LoadLogo // ****************************************************************** void WndMain::LoadLogo() { uint08 i_gray[100*17]; m_Xbe->ExportLogoBitmap(i_gray); if(m_Xbe->GetError() != 0) { MessageBox(m_hwnd, m_Xbe->GetError(), "Cxbx", MB_ICONEXCLAMATION | MB_OK); if(m_Xbe->IsFatal()) CloseXbe(); return; } uint32 v=0; for(uint32 y=0;y<17;y++) { for(uint32 x=0;x<100;x++) { SetPixel(m_LogoDC, x, y, RGB(i_gray[v], i_gray[v], i_gray[v])); v++; } } RedrawWindow(m_hwnd, NULL, NULL, RDW_INVALIDATE); } // ****************************************************************** // * UpdateDebugConsoles // ****************************************************************** void WndMain::UpdateDebugConsoles() { HMENU menu = GetMenu(m_hwnd); HMENU view_menu = GetSubMenu(menu, 2); HMENU view_debg = GetSubMenu(view_menu, 0); HMENU view_krnl = GetSubMenu(view_menu, 1); if(m_KrnlDebug == DM_CONSOLE) { CheckMenuItem(view_krnl, ID_VIEW_DEBUGOUTPUTKERNEL_CONSOLE, MF_CHECKED); CheckMenuItem(view_krnl, ID_VIEW_DEBUGOUTPUTKERNEL_FILE, MF_UNCHECKED); } else if(m_KrnlDebug == DM_FILE) { CheckMenuItem(view_krnl, ID_VIEW_DEBUGOUTPUTKERNEL_CONSOLE, MF_UNCHECKED); CheckMenuItem(view_krnl, ID_VIEW_DEBUGOUTPUTKERNEL_FILE, MF_CHECKED); } else { CheckMenuItem(view_krnl, ID_VIEW_DEBUGOUTPUTKERNEL_CONSOLE, MF_UNCHECKED); CheckMenuItem(view_krnl, ID_VIEW_DEBUGOUTPUTKERNEL_FILE, MF_UNCHECKED); } if(m_CxbxDebug == DM_CONSOLE) { if(AllocConsole()) { freopen("CONOUT$", "wt", stdout); SetConsoleTitle("Cxbx : Debug Console"); SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE), FOREGROUND_GREEN | FOREGROUND_BLUE | FOREGROUND_RED); printf("%s", "WndMain: Debug console allocated.\n"); CheckMenuItem(view_debg, ID_VIEW_DEBUGOUTPUTGUI_CONSOLE, MF_CHECKED); CheckMenuItem(view_debg, ID_VIEW_DEBUGOUTPUTGUI_FILE, MF_UNCHECKED); SetForegroundWindow(m_hwnd); } } else if(m_CxbxDebug == DM_FILE) { FreeConsole(); freopen(m_CxbxDebugFilename, "wt", stdout); printf("%s", "WndMain: Debug console allocated.\n"); CheckMenuItem(view_debg, ID_VIEW_DEBUGOUTPUTGUI_CONSOLE, MF_UNCHECKED); CheckMenuItem(view_debg, ID_VIEW_DEBUGOUTPUTGUI_FILE, MF_CHECKED); } else { FreeConsole(); CheckMenuItem(view_debg, ID_VIEW_DEBUGOUTPUTGUI_CONSOLE, MF_UNCHECKED); CheckMenuItem(view_debg, ID_VIEW_DEBUGOUTPUTGUI_FILE, MF_UNCHECKED); } } // ****************************************************************** // * ConvertToExe // ****************************************************************** bool WndMain::ConvertToExe(const char *x_filename, bool x_bVerifyIfExists) { char filename[260] = "default.exe"; if(x_filename == NULL) { OPENFILENAME ofn = {0}; SuggestFilename(m_XbeFilename, filename, ".exe"); ofn.lStructSize = sizeof(OPENFILENAME); ofn.hwndOwner = m_hwnd; ofn.lpstrFilter = "Windows Executables (*.exe)\0*.exe\0"; ofn.lpstrFile = filename; ofn.nMaxFile = 260; ofn.nFilterIndex = 1; ofn.lpstrFileTitle = NULL; ofn.nMaxFileTitle = 0; ofn.lpstrInitialDir = NULL; ofn.lpstrDefExt = "exe"; ofn.Flags = OFN_PATHMUSTEXIST; if(GetSaveFileName(&ofn) == FALSE) return false; strcpy(filename, ofn.lpstrFile); } else { strcpy(filename, x_filename); } // ****************************************************************** // * ask permission to overwrite if file exists // ****************************************************************** if(x_bVerifyIfExists) { if(_access(filename, 0) != -1) { if(MessageBox(m_hwnd, "Overwrite existing file?", "Cxbx", MB_ICONQUESTION | MB_YESNO) != IDYES) return false; } } // ****************************************************************** // * convert file // ****************************************************************** { EmuExe i_EmuExe(m_Xbe, m_KrnlDebug, m_KrnlDebugFilename); i_EmuExe.Export(filename); if(i_EmuExe.GetError() != 0) { MessageBox(m_hwnd, i_EmuExe.GetError(), "Cxbx", MB_ICONSTOP | MB_OK); return false; } else { strcpy(m_ExeFilename, filename); printf("WndMain: %s was converted to .exe.\n", m_Xbe->m_szAsciiTitle); m_bExeChanged = false; } } return true; } // ****************************************************************** // * OpenXbe // ****************************************************************** void WndMain::OpenXbe(const char *x_filename) { if(m_Xbe != 0) return; m_ExeFilename[0] = '\0'; strcpy(m_XbeFilename, x_filename); m_Xbe = new Xbe(m_XbeFilename); if(m_Xbe->GetError() != 0) { MessageBox(m_hwnd, m_Xbe->GetError(), "Cxbx", MB_ICONSTOP | MB_OK); delete m_Xbe; m_Xbe = 0; return; } XbeLoaded(); } // ****************************************************************** // * CloseXbe // ****************************************************************** void WndMain::CloseXbe() { if(m_bXbeChanged) { int ret = MessageBox(m_hwnd, "Changes have been made, do you wish to save?", "Cxbx", MB_ICONQUESTION | MB_YESNOCANCEL); if(ret == IDYES) SaveXbeAs(); else if(ret == IDCANCEL) return; } printf("WndMain: %s unloaded.\n", m_Xbe->m_szAsciiTitle); m_bXbeChanged = false; delete m_Xbe; m_Xbe = 0; // ****************************************************************** // * disable/enable appropriate menus // ****************************************************************** { HMENU menu = GetMenu(m_hwnd); // ****************************************************************** // * file menu // ****************************************************************** { HMENU file_menu = GetSubMenu(menu, 0); // enable open .xbe file EnableMenuItem(file_menu, ID_FILE_OPEN_XBE, MF_BYCOMMAND | MF_ENABLED); // disable close .xbe file EnableMenuItem(file_menu, ID_FILE_CLOSE_XBE, MF_BYCOMMAND | MF_GRAYED); // disable save .xbe file EnableMenuItem(file_menu, ID_FILE_SAVEXBEFILE, MF_BYCOMMAND | MF_GRAYED); // disable save .xbe file as EnableMenuItem(file_menu, ID_FILE_SAVEXBEFILEAS, MF_BYCOMMAND | MF_GRAYED); // enable import from .exe EnableMenuItem(file_menu, ID_FILE_IMPORTFROMEXE, MF_BYCOMMAND | MF_ENABLED); // disable convert to .exe EnableMenuItem(file_menu, ID_FILE_EXPORTTOEXE, MF_BYCOMMAND | MF_GRAYED); } // ****************************************************************** // * edit menu // ****************************************************************** { HMENU edit_menu = GetSubMenu(menu, 1); // disable export .xbe info EnableMenuItem(edit_menu, ID_EDIT_EXTRACTXBEINFO, MF_BYCOMMAND | MF_GRAYED); // disable logo bitmap menu EnableMenuItem(edit_menu, 0, MF_BYPOSITION | MF_GRAYED); // disable patch menu EnableMenuItem(edit_menu, 1, MF_BYPOSITION | MF_GRAYED); } // ****************************************************************** // * view menu // ****************************************************************** { HMENU view_menu = GetSubMenu(menu, 2); } // ****************************************************************** // * emulation menu // ****************************************************************** { HMENU emul_menu = GetSubMenu(menu, 3); // disable emulation start EnableMenuItem(emul_menu, ID_EMULATION_START, MF_BYCOMMAND | MF_GRAYED); } } // ****************************************************************** // * clear logo bitmap // ****************************************************************** { uint32 v=0; for(uint32 y=0;y<17;y++) { for(uint32 x=0;x<100;x++) { SetPixel(m_LogoDC, x, y, RGB(0, 0, 0)); v++; } } } RedrawWindow(m_hwnd, NULL, NULL, RDW_INVALIDATE); } // ****************************************************************** // * SaveXbe // ****************************************************************** void WndMain::SaveXbe(const char *x_filename) { // ****************************************************************** // * ask permission to overwrite if file exists // ****************************************************************** if(_access(x_filename, 0) != -1) { if(MessageBox(m_hwnd, "Overwrite existing file?", "Cxbx", MB_ICONQUESTION | MB_YESNO) != IDYES) return; } // ****************************************************************** // * export xbe file // ****************************************************************** { m_Xbe->Export(x_filename); if(m_Xbe->GetError() != 0) MessageBox(m_hwnd, m_Xbe->GetError(), "Cxbx", MB_ICONSTOP | MB_OK); else { char buffer[255]; sprintf(buffer, "%s was successfully saved.", m_Xbe->m_szAsciiTitle); printf("WndMain: %s was successfully saved.\n", m_Xbe->m_szAsciiTitle); MessageBox(m_hwnd, buffer, "Cxbx", MB_ICONINFORMATION | MB_OK); m_bXbeChanged = false; } } } // ****************************************************************** // * SaveXbeAs // ****************************************************************** void WndMain::SaveXbeAs() { OPENFILENAME ofn = {0}; char filename[260] = "default.xbe"; SuggestFilename(m_XbeFilename, filename, ".xbe"); ofn.lStructSize = sizeof(OPENFILENAME); ofn.hwndOwner = m_hwnd; ofn.lpstrFilter = "Xbox Executables (*.xbe)\0*.xbe\0"; ofn.lpstrFile = filename; ofn.nMaxFile = 260; ofn.nFilterIndex = 1; ofn.lpstrFileTitle = NULL; ofn.nMaxFileTitle = 0; ofn.lpstrInitialDir = NULL; ofn.lpstrDefExt = "xbe"; ofn.Flags = OFN_PATHMUSTEXIST; if(GetSaveFileName(&ofn) == TRUE) SaveXbe(ofn.lpstrFile); } // ****************************************************************** // * StartEmulation // ****************************************************************** void WndMain::StartEmulation(bool x_bAutoConvert) { if(m_ExeFilename[0] == '\0' || m_bExeChanged) { if(x_bAutoConvert) { char filename[260]; SuggestFilename(m_XbeFilename, filename, ".exe"); ConvertToExe(filename, false); } else { if(!ConvertToExe(NULL, true)) return; } } // ****************************************************************** // * shell exe // ****************************************************************** { char dir[260]; GetModuleFileName(NULL, dir, 260); sint32 spot=-1; for(int v=0;v<260;v++) { if(dir[v] == '\\') spot = v; else if(dir[v] == '\0') break; } if(spot != -1) dir[spot] = '\0'; if((int)ShellExecute(NULL, "open", m_ExeFilename, NULL, dir, SW_SHOWDEFAULT) <= 32) { MessageBox(m_hwnd, "Shell failed. (try converting .exe again)", "Cxbx", MB_ICONSTOP | MB_OK); printf("WndMain: %s shell failed.\n", m_Xbe->m_szAsciiTitle); } else { printf("WndMain: %s emulation started.\n", m_Xbe->m_szAsciiTitle); } } }