Cxbx-Reloaded/Source/Win32/Cxbx/WndMain.cpp

1839 lines
60 KiB
C++

// ******************************************************************
// *
// * .,-::::: .,:: .::::::::. .,:: .:
// * ,;;;'````' `;;;, .,;; ;;;'';;' `;;;, .,;;
// * [[[ '[[,,[[' [[[__[[\. '[[,,[['
// * $$$ 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 <caustik@caustik.com>
// *
// * All rights reserved
// *
// ******************************************************************
#include "WndMain.h"
#include "WndAbout.h"
#include "DlgControllerConfig.h"
#include "EmuShared.h"
#include "ResCxbx.h"
#include "EmuExe.h"
#include <io.h>
// ******************************************************************
// * 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_bAutoConvertToExe(TRUE), m_KrnlDebug(DM_NONE), m_CxbxDebug(DM_NONE), m_dwRecentXbe(0), m_dwRecentExe(0)
{
// ******************************************************************
// * Initialize members
// ******************************************************************
{
m_classname = "WndMain";
m_wndname = "Cxbx : Xbox Emulator";
m_w = 327;
m_h = 253;
m_ExeFilename = (char*)calloc(1, 260);
m_XbeFilename = (char*)calloc(1, 260);
m_CxbxDebugFilename = (char*)calloc(1, 260);
m_KrnlDebugFilename = (char*)calloc(1, 260);
int v=0;
for(v=0;v<RECENT_XBE_SIZE;v++)
m_szRecentXbe[v] = 0;
for(v=0;v<RECENT_EXE_SIZE;v++)
m_szRecentExe[v] = 0;
}
// ******************************************************************
// * 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;
}
// ******************************************************************
// * 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);
dwType = REG_DWORD; dwSize = sizeof(DWORD);
RegQueryValueEx(hKey, "KrnlDebug", NULL, &dwType, (PBYTE)&m_KrnlDebug, &dwSize);
dwType = REG_DWORD; dwSize = sizeof(DWORD);
RegQueryValueEx(hKey, "RecentXbe", NULL, &dwType, (PBYTE)&m_dwRecentXbe, &dwSize);
dwType = REG_DWORD; dwSize = sizeof(DWORD);
RegQueryValueEx(hKey, "RecentExe", NULL, &dwType, (PBYTE)&m_dwRecentExe, &dwSize);
dwType = REG_DWORD; dwSize = sizeof(DWORD);
RegQueryValueEx(hKey, "AutoConvertToExe", NULL, &dwType, (PBYTE)&m_bAutoConvertToExe, &dwSize);
dwType = REG_SZ; dwSize = 260;
RegQueryValueEx(hKey, "CxbxDebugFilename", NULL, &dwType, (PBYTE)m_CxbxDebugFilename, &dwSize);
dwType = REG_SZ; dwSize = 260;
RegQueryValueEx(hKey, "KrnlDebugFilename", NULL, &dwType, (PBYTE)m_KrnlDebugFilename, &dwSize);
int v=0;
for(v=0;v<m_dwRecentXbe;v++)
{
char buffer[32];
sprintf(buffer, "RecentXbe%d", v);
m_szRecentXbe[v] = (char*)calloc(1, 260);
dwType = REG_SZ; dwSize = 260;
RegQueryValueEx(hKey, buffer, NULL, &dwType, (PBYTE)m_szRecentXbe[v], &dwSize);
}
for(v=0;v<m_dwRecentExe;v++)
{
char buffer[32];
sprintf(buffer, "RecentExe%d", v);
m_szRecentExe[v] = (char*)calloc(1, 260);
dwType = REG_SZ; dwSize = 260;
RegQueryValueEx(hKey, buffer, NULL, &dwType, (PBYTE)m_szRecentExe[v], &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);
dwType = REG_DWORD; dwSize = sizeof(DWORD);
RegSetValueEx(hKey, "KrnlDebug", 0, dwType, (PBYTE)&m_KrnlDebug, dwSize);
dwType = REG_DWORD; dwSize = sizeof(DWORD);
RegSetValueEx(hKey, "RecentXbe", 0, dwType, (PBYTE)&m_dwRecentXbe, dwSize);
dwType = REG_DWORD; dwSize = sizeof(DWORD);
RegSetValueEx(hKey, "RecentExe", 0, dwType, (PBYTE)&m_dwRecentExe, dwSize);
dwType = REG_DWORD; dwSize = sizeof(DWORD);
RegSetValueEx(hKey, "AutoConvertToExe", 0, dwType, (PBYTE)&m_bAutoConvertToExe, dwSize);
dwType = REG_SZ; dwSize = 260;
RegSetValueEx(hKey, "CxbxDebugFilename", 0, dwType, (PBYTE)m_CxbxDebugFilename, dwSize);
dwType = REG_SZ; dwSize = 260;
RegSetValueEx(hKey, "KrnlDebugFilename", 0, dwType, (PBYTE)m_KrnlDebugFilename, dwSize);
int v=0;
for(v=0;v<m_dwRecentXbe;v++)
{
char buffer[32];
sprintf(buffer, "RecentXbe%d", v);
dwType = REG_SZ; dwSize = 260;
RegSetValueEx(hKey, buffer, 0, dwType, (PBYTE)m_szRecentXbe[v], dwSize);
free(m_szRecentXbe[v]);
}
for(v=0;v<m_dwRecentExe;v++)
{
char buffer[32];
sprintf(buffer, "RecentExe%d", v);
dwType = REG_SZ; dwSize = 260;
RegSetValueEx(hKey, buffer, 0, dwType, (PBYTE)m_szRecentExe[v], dwSize);
free(m_szRecentExe[v]);
}
RegCloseKey(hKey);
}
}
// ******************************************************************
// * Cleanup allocations
// ******************************************************************
{
delete m_Xbe;
delete m_Exe;
free(m_XbeFilename);
free(m_ExeFilename);
free(m_CxbxDebugFilename);
free(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);
}
SetClassLong(hwnd, GCL_HICON, (LONG)LoadIcon(GetModuleHandle(NULL), MAKEINTRESOURCE(IDI_CXBX)));
m_bCreated = true;
}
break;
case WM_PAINT:
{
static bool s_bInitMenu = true;
// ******************************************************************
// * initialize menu's if they haven't been yet
// ******************************************************************
if(s_bInitMenu)
{
UpdateRecentFiles();
RefreshMenus();
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_3DFACE));
SetTextColor(hDC, GetSysColor(COLOR_BTNTEXT));
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_KEYDOWN:
{
switch(wParam)
{
case VK_F5:
{
if(m_Xbe != 0)
StartEmulation(m_bAutoConvertToExe == TRUE);
}
break;
}
}
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)
ImportExe(ofn.lpstrFile);
}
break;
case ID_FILE_EXPORTTOEXE:
ConvertToExe(NULL, true);
break;
case ID_FILE_RXBE_0:
case ID_FILE_RXBE_1:
case ID_FILE_RXBE_2:
case ID_FILE_RXBE_3:
case ID_FILE_RXBE_4:
case ID_FILE_RXBE_5:
case ID_FILE_RXBE_6:
case ID_FILE_RXBE_7:
case ID_FILE_RXBE_8:
case ID_FILE_RXBE_9:
{
if(m_Xbe != 0)
CloseXbe();
if(m_Xbe != 0)
break;
HMENU menu = GetMenu(m_hwnd);
HMENU file_menu = GetSubMenu(menu, 0);
HMENU rxbe_menu = GetSubMenu(file_menu, 9);
char szBuffer[270];
GetMenuString(rxbe_menu, LOWORD(wParam), szBuffer, 269, MF_BYCOMMAND);
char *szFilename = (char*)((uint32)szBuffer + 5);
OpenXbe(szFilename);
}
break;
case ID_FILE_REXE_0:
case ID_FILE_REXE_1:
case ID_FILE_REXE_2:
case ID_FILE_REXE_3:
case ID_FILE_REXE_4:
case ID_FILE_REXE_5:
case ID_FILE_REXE_6:
case ID_FILE_REXE_7:
case ID_FILE_REXE_8:
case ID_FILE_REXE_9:
{
if(m_Xbe != 0)
CloseXbe();
if(m_Xbe != 0)
break;
HMENU menu = GetMenu(m_hwnd);
HMENU file_menu = GetSubMenu(menu, 0);
HMENU rexe_menu = GetSubMenu(file_menu, 10);
char szBuffer[270];
GetMenuString(rexe_menu, LOWORD(wParam), szBuffer, 269, MF_BYCOMMAND);
char *szFilename = (char*)((uint32)szBuffer + 5);
ImportExe(szFilename);
}
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;
RefreshMenus();
if(m_Xbe->m_Header.dwInitFlags.bLimit64MB)
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);
}
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
}
RefreshMenus();
bool res = (m_Xbe->m_Header.dwEntryAddr ^ XOR_EP_RETAIL) > 0x01000000;
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);
}
break;
case ID_EDIT_DUMPXBEINFOTO_FILE:
{
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 to file
{
FILE *TxtFile = fopen(ofn.lpstrFile, "wt");
// verify file was opened
if(TxtFile == 0)
MessageBox(m_hwnd, "Could not open text file.", "Cxbx", MB_ICONSTOP | MB_OK);
else
{
m_Xbe->DumpInformation(TxtFile);
fclose(TxtFile);
if(m_Xbe->GetError())
{
MessageBox(m_hwnd, m_Xbe->GetError(), "Cxbx", MB_ICONSTOP | MB_OK);
}
else
{
char buffer[255];
sprintf(buffer, "%s's .xbe info was successfully dumped.", m_Xbe->m_szAsciiTitle);
printf("WndMain: %s\n", buffer);
MessageBox(m_hwnd, buffer, "Cxbx", MB_ICONINFORMATION | MB_OK);
}
}
}
}
}
break;
case ID_EDIT_DUMPXBEINFOTO_DEBUGCONSOLE:
{
// dump xbe information to debug console
m_Xbe->DumpInformation(stdout);
if(m_Xbe->GetError())
{
MessageBox(m_hwnd, m_Xbe->GetError(), "Cxbx", MB_ICONSTOP | MB_OK);
}
else
{
char buffer[255];
sprintf(buffer, "%s's .xbe info was successfully dumped.", m_Xbe->m_szAsciiTitle);
printf("WndMain: %s\n", buffer);
}
}
break;
case ID_SETTINGS_CONFIG_CONTROLLER:
ShowControllerConfig(hwnd);
break;
case ID_EMULATION_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 the next time emulation is started.\n", "Cxbx", MB_OK);
m_bExeChanged = true;
RefreshMenus();
UpdateDebugConsoles();
}
break;
case ID_EMULATION_DEBUGOUTPUTKERNEL_FILE:
{
if(m_KrnlDebug == DM_FILE)
{
m_KrnlDebug = DM_NONE;
RefreshMenus();
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;
RefreshMenus();
UpdateDebugConsoles();
}
}
}
break;
case ID_EMULATION_DEBUGOUTPUTGUI_CONSOLE:
{
if(m_CxbxDebug == DM_NONE || m_CxbxDebug == DM_FILE)
m_CxbxDebug = DM_CONSOLE;
else
m_CxbxDebug = DM_NONE;
RefreshMenus();
UpdateDebugConsoles();
}
break;
case ID_EMULATION_DEBUGOUTPUTGUI_FILE:
{
if(m_CxbxDebug == DM_FILE)
{
m_CxbxDebug = DM_NONE;
RefreshMenus();
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;
RefreshMenus();
UpdateDebugConsoles();
}
}
}
break;
case ID_EMULATION_START:
StartEmulation(m_bAutoConvertToExe == TRUE);
break;
case ID_SETTINGS_AUTOGEN:
{
m_bAutoConvertToExe = !m_bAutoConvertToExe;
RefreshMenus();
}
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;
}
}
if(m_Xbe != 0)
CloseXbe();
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();
RefreshMenus();
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);
}
// ******************************************************************
// * RefreshMenus
// ******************************************************************
void WndMain::RefreshMenus()
{
// ******************************************************************
// * disable/enable appropriate menus
// ******************************************************************
{
HMENU menu = GetMenu(m_hwnd);
// ******************************************************************
// * file menu
// ******************************************************************
{
HMENU file_menu = GetSubMenu(menu, 0);
// enable/disable open .xbe file
EnableMenuItem(file_menu, ID_FILE_OPEN_XBE, MF_BYCOMMAND | (m_Xbe != 0) ? MF_GRAYED : MF_ENABLED);
// enable/disable close .xbe file
EnableMenuItem(file_menu, ID_FILE_CLOSE_XBE, MF_BYCOMMAND | (m_Xbe == 0) ? MF_GRAYED : MF_ENABLED);
// enable/disable save .xbe file
EnableMenuItem(file_menu, ID_FILE_SAVEXBEFILE, MF_BYCOMMAND | (m_Xbe == 0) ? MF_GRAYED : MF_ENABLED);
// enable/disable save .xbe file as
EnableMenuItem(file_menu, ID_FILE_SAVEXBEFILEAS, MF_BYCOMMAND | (m_Xbe == 0) ? MF_GRAYED : MF_ENABLED);
// enable/disable import from .exe
EnableMenuItem(file_menu, ID_FILE_IMPORTFROMEXE, MF_BYCOMMAND | (m_Xbe != 0) ? MF_GRAYED : MF_ENABLED);
// enable/disable export to .exe
EnableMenuItem(file_menu, ID_FILE_EXPORTTOEXE, MF_BYCOMMAND | (m_Xbe == 0) ? MF_GRAYED : MF_ENABLED);
// ******************************************************************
// * recent xbe files menu
// ******************************************************************
{
HMENU rxbe_menu = GetSubMenu(file_menu, 9);
int max = m_dwRecentXbe;
for(int v=0;v<max;v++)
EnableMenuItem(rxbe_menu, ID_FILE_RXBE_0 + v, MF_BYCOMMAND | MF_ENABLED);
}
// ******************************************************************
// * recent xbe files menu
// ******************************************************************
{
HMENU rexe_menu = GetSubMenu(file_menu, 10);
int max = m_dwRecentExe;
for(int v=0;v<max;v++)
EnableMenuItem(rexe_menu, ID_FILE_REXE_0 + v, 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_DUMPXBEINFOTO_FILE, MF_BYCOMMAND | (m_Xbe == 0) ? MF_GRAYED : MF_ENABLED);
EnableMenuItem(edit_menu, ID_EDIT_DUMPXBEINFOTO_DEBUGCONSOLE, MF_BYCOMMAND | (m_Xbe == 0) ? MF_GRAYED : MF_ENABLED);
// enable logo bitmap menu
EnableMenuItem(edit_menu, 0, MF_BYPOSITION | ((m_Xbe == 0) ? MF_GRAYED : MF_ENABLED));
// enable patch menu
EnableMenuItem(edit_menu, 1, MF_BYPOSITION | ((m_Xbe == 0) ? MF_GRAYED : MF_ENABLED));
// ******************************************************************
// * patch menu
// ******************************************************************
{
// check "allow >64 MB" if appropriate
if(m_Xbe != 0)
{
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
if(m_Xbe != 0)
{
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);
HMENU emul_debg = GetSubMenu(view_menu, 0);
HMENU emul_krnl = GetSubMenu(view_menu, 1);
if(m_KrnlDebug == DM_CONSOLE)
{
CheckMenuItem(emul_krnl, ID_EMULATION_DEBUGOUTPUTKERNEL_CONSOLE, MF_CHECKED);
CheckMenuItem(emul_krnl, ID_EMULATION_DEBUGOUTPUTKERNEL_FILE, MF_UNCHECKED);
}
else if(m_KrnlDebug == DM_FILE)
{
CheckMenuItem(emul_krnl, ID_EMULATION_DEBUGOUTPUTKERNEL_CONSOLE, MF_UNCHECKED);
CheckMenuItem(emul_krnl, ID_EMULATION_DEBUGOUTPUTKERNEL_FILE, MF_CHECKED);
}
else
{
CheckMenuItem(emul_krnl, ID_EMULATION_DEBUGOUTPUTKERNEL_CONSOLE, MF_UNCHECKED);
CheckMenuItem(emul_krnl, ID_EMULATION_DEBUGOUTPUTKERNEL_FILE, MF_UNCHECKED);
}
if(m_CxbxDebug == DM_CONSOLE)
{
CheckMenuItem(emul_debg, ID_EMULATION_DEBUGOUTPUTGUI_CONSOLE, MF_CHECKED);
CheckMenuItem(emul_debg, ID_EMULATION_DEBUGOUTPUTGUI_FILE, MF_UNCHECKED);
}
else if(m_CxbxDebug == DM_FILE)
{
CheckMenuItem(emul_debg, ID_EMULATION_DEBUGOUTPUTGUI_CONSOLE, MF_UNCHECKED);
CheckMenuItem(emul_debg, ID_EMULATION_DEBUGOUTPUTGUI_FILE, MF_CHECKED);
}
else
{
CheckMenuItem(emul_debg, ID_EMULATION_DEBUGOUTPUTGUI_CONSOLE, MF_UNCHECKED);
CheckMenuItem(emul_debg, ID_EMULATION_DEBUGOUTPUTGUI_FILE, MF_UNCHECKED);
}
}
// ******************************************************************
// * settings menu
// ******************************************************************
{
HMENU sett_menu = GetSubMenu(menu, 3);
// check "Generate Exe Automatically" if appropriate
CheckMenuItem(sett_menu, ID_SETTINGS_AUTOGEN, MF_BYCOMMAND | ((m_bAutoConvertToExe == TRUE) ? MF_CHECKED : MF_UNCHECKED) );
}
// ******************************************************************
// * emulation menu
// ******************************************************************
{
HMENU emul_menu = GetSubMenu(menu, 4);
// enable emulation start
EnableMenuItem(emul_menu, ID_EMULATION_START, MF_BYCOMMAND | (m_Xbe == 0) ? MF_GRAYED : MF_ENABLED);
}
}
}
// ******************************************************************
// * UpdateDebugConsoles
// ******************************************************************
void WndMain::UpdateDebugConsoles()
{
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");
SetForegroundWindow(m_hwnd);
}
}
else if(m_CxbxDebug == DM_FILE)
{
FreeConsole();
freopen(m_CxbxDebugFilename, "wt", stdout);
printf("%s", "WndMain: Debug console allocated.\n");
}
else
{
FreeConsole();
char buffer[16];
if(GetConsoleTitle(buffer, 16) != NULL)
freopen("nul", "w", stdout);
}
}
// ******************************************************************
// * UpdateRecentFiles
// ******************************************************************
void WndMain::UpdateRecentFiles()
{
HMENU FileMenu = GetSubMenu(GetMenu(m_hwnd), 0);
HMENU RXbeMenu = GetSubMenu(FileMenu, 9);
HMENU RExeMenu = GetSubMenu(FileMenu, 10);
// clear existing menu items
{
int v, max;
max = GetMenuItemCount(RXbeMenu);
for(v=0;v<max;v++)
RemoveMenu(RXbeMenu, 0, MF_BYPOSITION);
max = GetMenuItemCount(RExeMenu);
for(v=0;v<max;v++)
RemoveMenu(RExeMenu, 0, MF_BYPOSITION);
}
// insert recent xbe files
{
char szBuffer[270];
int max = m_dwRecentXbe;
// if there are no recent files, throw in a disabled "(none)"
if(max == 0)
{
AppendMenu(RXbeMenu, MF_STRING, ID_FILE_RXBE_0, "(none)");
EnableMenuItem(RXbeMenu, ID_FILE_RXBE_0, MF_BYCOMMAND | MF_GRAYED);
}
// NOTE: Resource defines ID_FILE_RXBE_0 through ID_FILE_RXBE_9 must be in order
for(int v=0;v<max;v++)
{
sprintf(szBuffer, "&%d : %s", v, m_szRecentXbe[v]);
AppendMenu(RXbeMenu, MF_STRING, ID_FILE_RXBE_0 + v, szBuffer);
}
}
// insert recent exe files
{
char szBuffer[270];
int max = m_dwRecentExe;
// if there are no recent files, throw in a disabled "(none)"
if(max == 0)
{
AppendMenu(RExeMenu, MF_STRING, ID_FILE_REXE_0, "(none)");
EnableMenuItem(RExeMenu, ID_FILE_REXE_0, MF_BYCOMMAND | MF_GRAYED);
}
// NOTE: Resource defines ID_FILE_REXE_0 through ID_FILE_REXE_9 must be in order
for(int v=0;v<max;v++)
{
sprintf(szBuffer, "&%d : %s", v, m_szRecentExe[v]);
AppendMenu(RExeMenu, MF_STRING, ID_FILE_REXE_0 + v, szBuffer);
}
}
}
// ******************************************************************
// * 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;
}
// ******************************************************************
// * save this Xbe to the list of recent files
// ******************************************************************
if(m_XbeFilename[0] != '\0')
{
bool found = false;
// if this filename already exists, temporarily remove it
for(int c=0, r=0;c<m_dwRecentXbe;c++, r++)
{
if(strcmp(m_szRecentXbe[c], m_XbeFilename) == 0)
{
found = true;
r++;
}
if(r != c)
{
if(m_szRecentXbe[r] == 0 || r > m_dwRecentXbe - 1)
m_szRecentXbe[c] = 0;
else
strncpy(m_szRecentXbe[c], m_szRecentXbe[r], 259);
}
}
if(found)
m_dwRecentXbe--;
// move all items down one, removing the last one if necessary
for(int v=RECENT_XBE_SIZE-1;v>0;v--)
{
if(m_szRecentXbe[v-1] == 0)
m_szRecentXbe[v] = 0;
else
{
if(m_szRecentXbe[v] == 0)
m_szRecentXbe[v] = (char*)calloc(1, 260);
strncpy(m_szRecentXbe[v], m_szRecentXbe[v-1], 259);
}
}
// add new item as first index
{
if(m_szRecentXbe[0] == 0)
m_szRecentXbe[0] = (char*)calloc(1, 260);
strcpy(m_szRecentXbe[0], m_XbeFilename);
}
if(m_dwRecentXbe < RECENT_XBE_SIZE)
m_dwRecentXbe++;
}
UpdateRecentFiles();
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;
RefreshMenus();
// ******************************************************************
// * 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);
}
// ******************************************************************
// * ImportExe
// ******************************************************************
void WndMain::ImportExe(const char *x_filename)
{
m_XbeFilename[0] = '\0';
Exe *i_exe = new Exe(x_filename);
if(i_exe->GetError() != 0)
{
MessageBox(m_hwnd, i_exe->GetError(), "Cxbx", MB_ICONSTOP | MB_OK);
delete i_exe;
return;
}
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;
return;
}
// ******************************************************************
// * save this Exe to the list of recent files
// ******************************************************************
if(m_ExeFilename[0] != '\0')
{
bool found = false;
// if this filename already exists, temporarily remove it
for(int c=0, r=0;c<m_dwRecentExe;c++, r++)
{
if(strcmp(m_szRecentExe[c], m_ExeFilename) == 0)
{
found = true;
r++;
}
if(r != c)
{
if(m_szRecentExe[r] == 0 || r > m_dwRecentExe - 1)
m_szRecentExe[c] = 0;
else
strncpy(m_szRecentExe[c], m_szRecentExe[r], 259);
}
}
if(found)
m_dwRecentExe--;
// move all items down one, removing the last one if necessary
for(int v=RECENT_EXE_SIZE-1;v>0;v--)
{
if(m_szRecentExe[v-1] == 0)
m_szRecentExe[v] = 0;
else
{
if(m_szRecentExe[v] == 0)
m_szRecentExe[v] = (char*)calloc(1, 260);
strncpy(m_szRecentExe[v], m_szRecentExe[v-1], 259);
}
}
// add new item as first index
{
if(m_szRecentExe[0] == 0)
m_szRecentExe[0] = (char*)calloc(1, 260);
strcpy(m_szRecentExe[0], m_ExeFilename);
}
if(m_dwRecentExe < RECENT_EXE_SIZE)
m_dwRecentExe++;
}
UpdateRecentFiles();
XbeLoaded();
m_bExeChanged = true;
}
// ******************************************************************
// * 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;
}
// ******************************************************************
// * StartEmulation
// ******************************************************************
void WndMain::StartEmulation(bool x_bAutoConvert)
{
char szBuffer[260];
// ******************************************************************
// * convert Xbe to Exe, if necessary
// ******************************************************************
if(m_ExeFilename[0] == '\0' || m_bExeChanged)
{
if(x_bAutoConvert)
{
SuggestFilename(m_XbeFilename, szBuffer, ".exe");
if(!ConvertToExe(szBuffer, false))
return;
}
else
{
if(!ConvertToExe(NULL, true))
return;
}
}
// ******************************************************************
// * shell exe
// ******************************************************************
{
GetModuleFileName(NULL, szBuffer, 260);
sint32 spot=-1;
for(int v=0;v<260;v++)
{
if(szBuffer[v] == '\\')
spot = v;
else if(szBuffer[v] == '\0')
break;
}
if(spot != -1)
szBuffer[spot] = '\0';
if((int)ShellExecute(NULL, "open", m_ExeFilename, NULL, szBuffer, SW_SHOWDEFAULT) <= 32)
{
MessageBox(m_hwnd, "Emulation failed.\n\nTry converting again. If this message repeats, the Xbe is not supported.", "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);
}
}
}