diff --git a/Lang/English.pj.Lang b/Lang/English.pj.Lang
index 30dd81bdf..8355a7d3e 100644
--- a/Lang/English.pj.Lang
+++ b/Lang/English.pj.Lang
@@ -455,17 +455,20 @@
* Support Window *
*********************************************************************************/
#1200# "Support Project64"
-#1201# "Project64 is a software package designed to emulate a Nintendo64 video game system on a Microsoft Windows based PC. This allows you to play real N64 software in much the same way as it would be on the original hardware system.\n\nIf you like Project64 and have gotten some value out of it then please support project64 as either a thank you, or your desire to see it continually improved.\n\nIf you have supported project64:"
-#1202# "Enter notification code"
+#1201# "Project64 is a free and open source Nintendo64 emulator. This allows you to play real N64 software in much the same way as it would be on the original hardware system.\n\nI am sorry about the inconvenience of this prompt, but you are being asked to wait for a few seconds in order to enjoy the result of hundreds of hours of work.\n\nIf you can and would like to support Project64 or you have gotten some value out of it then please support project64 as either a thank you, or your a desire to see removal of this prompt.\n\nIf you have supported Project64:"
+#1202# "Enter/Request Notification Code"
#1203# "Support Project64"
#1204# "Continue"
#1205# "Please enter the support code"
-#1206# "Incorrect support code"
+#1206# "Failed to validate the code\n\nMake sure the code matches in email based on your machine"
#1207# "Thank you"
-#1208# "Enter code"
-#1209# "Please enter the code in the email"
+#1208# "Please enter your support code"
+#1209# "Please enter the code you recieved in the email.\n\nThis email will be sent to the email address used to support project64.\n\nPlease note that the code is will only work for a unique machine. This computer id is:"
#1210# "OK"
#1211# "Cancel"
+#1212# "Request Code"
+#1213# "Code has been sent to your email"
+#1214# "Failed to send code, please make sure it is the email you supported with"
/*********************************************************************************
* Messages *
diff --git a/Source/Project64-core/Multilanguage.h b/Source/Project64-core/Multilanguage.h
index ec52a0945..2fefe9dfe 100644
--- a/Source/Project64-core/Multilanguage.h
+++ b/Source/Project64-core/Multilanguage.h
@@ -107,6 +107,7 @@ enum LanguageStringID
MENU_ABOUT_PJ64 = 182,
MENU_FORUM = 183,
MENU_HOMEPAGE = 184,
+ MENU_SUPPORT_PROJECT64 = 185,
//Current Save Slot menu
MENU_SLOT_DEFAULT = 190,
@@ -506,6 +507,9 @@ enum LanguageStringID
MSG_SUPPORT_ENTER_CODE_DESC = 1209,
MSG_SUPPORT_OK = 1210,
MSG_SUPPORT_CANCEL = 1211,
+ MSG_SUPPORT_REQUESTCODE_TITLE = 1212,
+ MSG_SUPPORT_REQUESTCODE_SUCCESS = 1213,
+ MSG_SUPPORT_REQUESTCODE_FAIL = 1214,
/*********************************************************************************
* Messages *
diff --git a/Source/Project64-core/Multilanguage/LanguageClass.cpp b/Source/Project64-core/Multilanguage/LanguageClass.cpp
index 096469b3c..117bd705e 100644
--- a/Source/Project64-core/Multilanguage/LanguageClass.cpp
+++ b/Source/Project64-core/Multilanguage/LanguageClass.cpp
@@ -114,6 +114,7 @@ void CLanguage::LoadDefaultStrings(void)
DEF_STR(MENU_ABOUT_PJ64, "&About Project64");
DEF_STR(MENU_FORUM, "Support &Forum");
DEF_STR(MENU_HOMEPAGE, "&Homepage");
+ DEF_STR(MENU_SUPPORT_PROJECT64, "Support Project64");
//Current Save Slot menu
DEF_STR(MENU_SLOT_DEFAULT, "Default");
@@ -460,17 +461,20 @@ void CLanguage::LoadDefaultStrings(void)
* Support Window *
*********************************************************************************/
DEF_STR(MSG_SUPPORT_TITLE, "Support Project64");
- DEF_STR(MSG_SUPPORT_INFO, "Project64 is a software package designed to emulate a Nintendo64 video game system on a Microsoft Windows based PC. This allows you to play real N64 software in much the same way as it would be on the original hardware system.\n\nIf you like Project64 and have gotten some value out of it then please support project64 as either a thank you, or your desire to see it continually improved.\n\nIf you have supported project64:");
- DEF_STR(MSG_SUPPORT_ENTER_CODE, "Enter notification code");
+ DEF_STR(MSG_SUPPORT_INFO, "Project64 is a free and open source Nintendo64 emulator. This allows you to play real N64 software in much the same way as it would be on the original hardware system.\n\nI am sorry about the inconvenience of this prompt, but you are being asked to wait for a few seconds in order to enjoy the result of hundreds of hours of work.\n\nIf you can and would like to support Project64 or you have gotten some value out of it then please support project64 as either a thank you, or your a desire to see removal of this prompt.\n\nIf you have supported Project64:");
+ DEF_STR(MSG_SUPPORT_ENTER_CODE, "Enter/Request Notification Code");
DEF_STR(MSG_SUPPORT_PROJECT64, "Support Project64");
DEF_STR(MSG_SUPPORT_CONTINUE, "Continue");
DEF_STR(MSG_SUPPORT_ENTER_SUPPORT_CODE, "Please enter the support code");
- DEF_STR(MSG_SUPPORT_INCORRECT_CODE, "Incorrect support code");
+ DEF_STR(MSG_SUPPORT_INCORRECT_CODE, "Failed to validate the code\n\nMake sure the code matches in email based on your machine");
DEF_STR(MSG_SUPPORT_COMPLETE, "Thank you");
- DEF_STR(MSG_SUPPORT_ENTER_CODE_TITLE, "Enter code");
- DEF_STR(MSG_SUPPORT_ENTER_CODE_DESC, "Please enter the code in the email");
+ DEF_STR(MSG_SUPPORT_ENTER_CODE_TITLE, "Please enter your support code");
+ DEF_STR(MSG_SUPPORT_ENTER_CODE_DESC, "Please enter the code you recieved in the email.\n\nThis email will be sent to the email address used to support project64.\n\nPlease note that the code is will only work for a unique machine. This computer id is:");
DEF_STR(MSG_SUPPORT_OK, "OK");
DEF_STR(MSG_SUPPORT_CANCEL, "Cancel");
+ DEF_STR(MSG_SUPPORT_REQUESTCODE_TITLE, "Request Code");
+ DEF_STR(MSG_SUPPORT_REQUESTCODE_SUCCESS, "Code has been sent to your email");
+ DEF_STR(MSG_SUPPORT_REQUESTCODE_FAIL, "Failed to send code, please make sure it is the email you supported with");
/*********************************************************************************
* Messages *
diff --git a/Source/Project64/Project64.vcxproj b/Source/Project64/Project64.vcxproj
index cfaf32fad..531459599 100644
--- a/Source/Project64/Project64.vcxproj
+++ b/Source/Project64/Project64.vcxproj
@@ -91,6 +91,7 @@
+
@@ -166,6 +167,7 @@
+
diff --git a/Source/Project64/Project64.vcxproj.filters b/Source/Project64/Project64.vcxproj.filters
index d436f28fe..288a0a293 100644
--- a/Source/Project64/Project64.vcxproj.filters
+++ b/Source/Project64/Project64.vcxproj.filters
@@ -246,6 +246,9 @@
Source Files\User Interface Source\WTL Controls Source
+
+ Source Files\User Interface Source
+
@@ -485,6 +488,9 @@
Header Files\User Interface Headers\WTL Controls Headers
+
+ Header Files
+
diff --git a/Source/Project64/UserInterface/MainMenu.cpp b/Source/Project64/UserInterface/MainMenu.cpp
index b76e671fe..0f64697c5 100644
--- a/Source/Project64/UserInterface/MainMenu.cpp
+++ b/Source/Project64/UserInterface/MainMenu.cpp
@@ -271,7 +271,7 @@ void CMainMenu::OnLodState(HWND hWnd)
g_BaseSystem->ExternalEvent(SysEvent_ResumeCPU_LoadGame);
}
-void CMainMenu::OnCheats(HWND hWnd)
+void CMainMenu::OnCheats(HWND /*hWnd*/)
{
m_Gui->DisplayCheatsUI(false);
}
@@ -281,6 +281,11 @@ void CMainMenu::OnSettings(HWND hWnd)
CSettingConfig().Display(hWnd);
}
+void CMainMenu::OnSupportProject64(HWND hWnd)
+{
+ CSupportWindow(m_Gui->Support()).Show(hWnd, false);
+}
+
bool CMainMenu::ProcessMessage(HWND hWnd, DWORD /*FromAccelerator*/, DWORD MenuID)
{
switch (MenuID)
@@ -568,6 +573,7 @@ bool CMainMenu::ProcessMessage(HWND hWnd, DWORD /*FromAccelerator*/, DWORD MenuI
g_Notify->DisplayMessage(3, stdstr_f(GS(MENU_SLOT_SAVE), GetSaveSlotString((MenuID - ID_CURRENT_SAVE_1) + 1).c_str()).c_str());
g_Settings->SaveDword(Game_CurrentSaveState, (DWORD)((MenuID - ID_CURRENT_SAVE_1) + 1));
break;
+ case ID_HELP_SUPPORT_PROJECT64: OnSupportProject64(hWnd); break;
case ID_HELP_SUPPORTFORUM: ShellExecute(NULL, L"open", L"http://forum.pj64-emu.com/", NULL, NULL, SW_SHOWMAXIMIZED); break;
case ID_HELP_HOMEPAGE: ShellExecute(NULL, L"open", L"http://www.pj64-emu.com", NULL, NULL, SW_SHOWMAXIMIZED); break;
case ID_HELP_ABOUT: m_Gui->AboutBox(); break;
@@ -1284,7 +1290,7 @@ void CMainMenu::FillOutMenu(HMENU hMenu)
/* Help Menu
****************/
MenuItemList HelpMenu;
-
+ HelpMenu.push_back(MENU_ITEM(ID_HELP_SUPPORT_PROJECT64, MENU_SUPPORT_PROJECT64));
HelpMenu.push_back(MENU_ITEM(ID_HELP_SUPPORTFORUM, MENU_FORUM));
HelpMenu.push_back(MENU_ITEM(ID_HELP_HOMEPAGE, MENU_HOMEPAGE));
HelpMenu.push_back(MENU_ITEM(SPLITER));
diff --git a/Source/Project64/UserInterface/MainMenu.h b/Source/Project64/UserInterface/MainMenu.h
index 6fd4bb5fc..79c7eb319 100644
--- a/Source/Project64/UserInterface/MainMenu.h
+++ b/Source/Project64/UserInterface/MainMenu.h
@@ -53,7 +53,7 @@ enum MainMenuID
ID_PROFILE_PROFILE, ID_PROFILE_RESETCOUNTER, ID_PROFILE_GENERATELOG,
//Help Menu
- ID_HELP_SUPPORTFORUM, ID_HELP_HOMEPAGE, ID_HELP_ABOUTSETTINGFILES, ID_HELP_ABOUT,
+ ID_HELP_SUPPORT_PROJECT64, ID_HELP_SUPPORTFORUM, ID_HELP_HOMEPAGE, ID_HELP_ABOUTSETTINGFILES, ID_HELP_ABOUT,
};
class CMainMenu :
@@ -83,6 +83,7 @@ private:
void OnLodState(HWND hWnd);
void OnCheats(HWND hWnd);
void OnSettings(HWND hWnd);
+ void OnSupportProject64(HWND hWnd);
void FillOutMenu(HMENU hMenu);
std::wstring GetSaveSlotString(int Slot);
@@ -98,12 +99,12 @@ private:
typedef std::list SettingList;
typedef std::list UISettingList;
- CMainGui * m_Gui;
+ CMainGui * m_Gui;
- void * m_AccelTable;
- bool m_ResetAccelerators;
- CShortCuts m_ShortCuts;
- SettingList m_ChangeSettingList;
+ void * m_AccelTable;
+ bool m_ResetAccelerators;
+ CShortCuts m_ShortCuts;
+ SettingList m_ChangeSettingList;
UISettingList m_ChangeUISettingList;
CriticalSection m_CS;
};
diff --git a/Source/Project64/UserInterface/MainWindow.h b/Source/Project64/UserInterface/MainWindow.h
index c99b0d35d..479fc959b 100644
--- a/Source/Project64/UserInterface/MainWindow.h
+++ b/Source/Project64/UserInterface/MainWindow.h
@@ -14,6 +14,7 @@
#include
#include
#include
+#include
class CGfxPlugin; //Plugin that controls the rendering
class CAudioPlugin; //Plugin for audio, need the hwnd
@@ -95,10 +96,12 @@ public:
void * GetStatusBar(void) const { return m_hStatusWnd; }
void * GetModuleInstance(void) const;
+ inline CProjectSupport & Support(void) { return m_Support; }
+
private:
- CMainGui(void); // Disable default constructor
- CMainGui(const CMainGui&); // Disable copy constructor
- CMainGui& operator=(const CMainGui&); // Disable assignment
+ CMainGui(void);
+ CMainGui(const CMainGui&);
+ CMainGui& operator=(const CMainGui&);
friend class CGfxPlugin;
friend class CAudioPlugin;
@@ -126,26 +129,27 @@ private:
static void GamePaused(CMainGui * Gui);
static void GameCpuRunning(CMainGui * Gui);
- CBaseMenu * m_Menu;
+ CBaseMenu * m_Menu;
- HWND m_hMainWindow, m_hStatusWnd;
- DWORD m_ThreadId;
- CCheatsUI m_CheatsUI;
+ HWND m_hMainWindow, m_hStatusWnd;
+ DWORD m_ThreadId;
+ CCheatsUI m_CheatsUI;
+ CProjectSupport m_Support;
- const bool m_bMainWindow;
- bool m_Created;
- bool m_AttachingMenu;
- bool m_MakingVisible;
- bool m_ResetPlugins;
+ const bool m_bMainWindow;
+ bool m_Created;
+ bool m_AttachingMenu;
+ bool m_MakingVisible;
+ bool m_ResetPlugins;
RESET_PLUGIN * m_ResetInfo;
CriticalSection m_CS;
- bool m_SaveMainWindowPos;
- LONG m_SaveMainWindowTop;
- LONG m_SaveMainWindowLeft;
+ bool m_SaveMainWindowPos;
+ LONG m_SaveMainWindowTop;
+ LONG m_SaveMainWindowLeft;
- bool m_SaveRomBrowserPos;
- LONG m_SaveRomBrowserTop;
- LONG m_SaveRomBrowserLeft;
+ bool m_SaveRomBrowserPos;
+ LONG m_SaveRomBrowserTop;
+ LONG m_SaveRomBrowserLeft;
};
diff --git a/Source/Project64/UserInterface/ProjectSupport.cpp b/Source/Project64/UserInterface/ProjectSupport.cpp
new file mode 100644
index 000000000..5eff9b59f
--- /dev/null
+++ b/Source/Project64/UserInterface/ProjectSupport.cpp
@@ -0,0 +1,273 @@
+#include "stdafx.h"
+#include
+#include
+#include
+
+#pragma comment(lib, "Wininet.lib")
+
+CProjectSupport::CProjectSupport() :
+ m_SupportInfo({0})
+{
+ LoadSupportInfo();
+}
+
+bool CProjectSupport::RequestCode(const char * Email)
+{
+ stdstr_f PostData("task=RequestCode&email=%s&machine=%s", Email, MachineID());
+ std::vector Headers;
+ DWORD StatusCode;
+ if (!PerformRequest(L"/index.php?option=com_project64", PostData, StatusCode, Headers))
+ {
+ return false;
+ }
+ if (StatusCode == 200)
+ {
+ for (size_t i = 0, n = Headers.size(); i < n; i++)
+ {
+ if (strcmp(Headers[i].c_str(), "Email: Sent") == 0)
+ {
+ return true;
+ }
+ }
+ }
+ return false;
+}
+
+bool CProjectSupport::ValidateCode(const char * Code)
+{
+ stdstr_f PostData("task=ValidateCode&code=%s&machine=%s", Code, MachineID());
+ std::vector Headers;
+ DWORD StatusCode;
+ if (PerformRequest(L"/index.php?option=com_project64", PostData, StatusCode, Headers) && StatusCode == 200)
+ {
+ std::string Name, Email;
+ struct
+ {
+ const char * Key;
+ std::string & Value;
+ }
+ Test[] =
+ {
+ { "SupporterName: ", Name },
+ { "SupporterEmail: ", Email },
+ };
+
+ for (size_t i = 0, n = Headers.size(); i < n; i++)
+ {
+ for (size_t t = 0; t < sizeof(Test) / sizeof(Test[0]); t++)
+ {
+ size_t KeyLen = strlen(Test[t].Key);
+ if (strncmp(Headers[i].c_str(), Test[t].Key, KeyLen) == 0)
+ {
+ Test[t].Value = stdstr(&Headers[i][KeyLen]).Trim();
+ break;
+ }
+ }
+ }
+
+ if (Name.length() > 0 && Email.length() > 0)
+ {
+ strncpy(m_SupportInfo.Code, Code, sizeof(m_SupportInfo.Code));
+ strncpy(m_SupportInfo.Email, Email.c_str(), sizeof(m_SupportInfo.Email));
+ strncpy(m_SupportInfo.Name, Name.c_str(), sizeof(m_SupportInfo.Name));
+ m_SupportInfo.Validated = true;
+ SaveSupportInfo();
+ }
+ }
+ return m_SupportInfo.Validated;
+}
+
+std::string CProjectSupport::GenerateMachineID(void)
+{
+ wchar_t ComputerName[256];
+ DWORD Length = sizeof(ComputerName) / sizeof(ComputerName[0]);
+ GetComputerName(ComputerName, &Length);
+
+ wchar_t SysPath[MAX_PATH] = { 0 }, VolumePath[MAX_PATH] = { 0 };
+ GetSystemDirectory(SysPath, sizeof(SysPath) / sizeof(SysPath[0]));
+
+ GetVolumePathName(SysPath, VolumePath, sizeof(VolumePath) / sizeof(VolumePath[0]));
+
+ DWORD SerialNumber = 0;
+ GetVolumeInformation(VolumePath, NULL, NULL, &SerialNumber, NULL, NULL, NULL, NULL);
+
+ wchar_t MachineGuid[200] = { 0 };
+ HKEY hKey;
+ if (RegOpenKeyEx(HKEY_LOCAL_MACHINE, L"SOFTWARE\\Microsoft\\Cryptography", 0, KEY_QUERY_VALUE | KEY_WOW64_64KEY, &hKey) == ERROR_SUCCESS)
+ {
+ DWORD Type, dwDataSize = sizeof(MachineGuid);
+ RegQueryValueEx(hKey, L"MachineGuid", nullptr, &Type, (LPBYTE)MachineGuid, &dwDataSize);
+ RegCloseKey(hKey);
+ }
+
+ stdstr_f Machine("%s.%ud.%s", stdstr().FromUTF16(ComputerName).c_str(), SerialNumber, stdstr().FromUTF16(MachineGuid).c_str());
+ return std::string(MD5((const unsigned char *)Machine.c_str(), Machine.size()).hex_digest());
+}
+
+void CProjectSupport::IncrementRunCount()
+{
+ m_SupportInfo.RunCount += 1;
+ SaveSupportInfo();
+}
+
+bool CProjectSupport::PerformRequest(const wchar_t * Url, const std::string & PostData, DWORD & StatusCode, std::vector & Headers)
+{
+ StatusCode = 0;
+ Headers.clear();
+
+ HINTERNET hSession = InternetOpen(L"Project64", INTERNET_OPEN_TYPE_PRECONFIG, nullptr, nullptr, 0);
+ if (hSession == nullptr)
+ {
+ return false;
+ }
+
+ HINTERNET hConnect = InternetConnect(hSession, L"www.pj64-emu.com", INTERNET_DEFAULT_HTTPS_PORT, L"", L"", INTERNET_SERVICE_HTTP, 0, 0);
+ if (hConnect == nullptr)
+ {
+ return false;
+ }
+ LPCWSTR lpszAcceptTypes[] =
+ {
+ L"text/*",
+ nullptr
+ };
+ HINTERNET hRequest = HttpOpenRequest(hConnect, L"POST", Url, NULL, NULL, lpszAcceptTypes, INTERNET_FLAG_SECURE | INTERNET_FLAG_NO_AUTO_REDIRECT | INTERNET_FLAG_PRAGMA_NOCACHE | INTERNET_FLAG_NO_CACHE_WRITE, (LPARAM)0);
+ if (hRequest == nullptr)
+ {
+ InternetCloseHandle(hRequest);
+ return false;
+ }
+ wchar_t hdheaders[] = _T("Content-Type: application/x-www-form-urlencoded\r\n");
+ BOOL Success = HttpSendRequest(hRequest, hdheaders, _tcslen(hdheaders), (LPVOID)PostData.c_str(), PostData.length());
+ if (!Success)
+ {
+ InternetCloseHandle(hRequest);
+ return false;
+ }
+
+ DWORD StatusCodeSize = sizeof(StatusCode);
+ if (!HttpQueryInfo(hRequest, HTTP_QUERY_STATUS_CODE | HTTP_QUERY_FLAG_NUMBER, &StatusCode, &StatusCodeSize, NULL))
+ {
+ InternetCloseHandle(hRequest);
+ return false;
+ }
+
+ DWORD dwSize = 0;
+ if (!HttpQueryInfo(hRequest, HTTP_QUERY_RAW_HEADERS_CRLF, NULL, &dwSize, NULL) && GetLastError() == ERROR_INSUFFICIENT_BUFFER)
+ {
+ std::vector RawHeaderData(dwSize);
+ if (!HttpQueryInfo(hRequest, HTTP_QUERY_RAW_HEADERS_CRLF, RawHeaderData.data(), &dwSize, NULL))
+ {
+ InternetCloseHandle(hRequest);
+ return false;
+ }
+ strvector RawHeader = stdstr().FromUTF16((wchar_t *)RawHeaderData.data()).Tokenize("\n");
+ for (size_t i = 0, n = RawHeader.size(); i < n; i++)
+ {
+ RawHeader[i].Replace("\r", "");
+ RawHeader[i].Trim();
+ if (RawHeader[i].length() > 0)
+ {
+ Headers.push_back(RawHeader[i]);
+ }
+ }
+ }
+ return true;
+}
+
+void CProjectSupport::SaveSupportInfo(void)
+{
+ std::string hash = MD5((const unsigned char *)&m_SupportInfo, sizeof(m_SupportInfo)).hex_digest();
+
+ std::vector InData(sizeof(m_SupportInfo) + hash.length());
+ memcpy(InData.data(), (const unsigned char *)&m_SupportInfo, sizeof(m_SupportInfo));
+ memcpy(InData.data() + sizeof(m_SupportInfo), hash.data(), hash.length());
+ std::vector OutData(InData.size());
+
+ z_stream defstream;
+ defstream.zalloc = Z_NULL;
+ defstream.zfree = Z_NULL;
+ defstream.opaque = Z_NULL;
+ defstream.avail_in = (uInt)InData.size();
+ defstream.next_in = (Bytef *)InData.data();
+ defstream.avail_out = (uInt)OutData.size();
+ defstream.next_out = (Bytef *)OutData.data();
+
+ deflateInit(&defstream, Z_BEST_COMPRESSION);
+ deflate(&defstream, Z_FINISH);
+ deflateEnd(&defstream);
+
+ OutData.resize(defstream.total_out);
+
+ for (size_t i = 0, n = OutData.size(); i < n; i++)
+ {
+ OutData[i] ^= 0xAA;
+ }
+
+ HKEY hKeyResults = 0;
+ DWORD Disposition = 0;
+ long lResult = RegCreateKeyEx(HKEY_CURRENT_USER, L"SOFTWARE\\Project64", 0, L"", REG_OPTION_NON_VOLATILE, KEY_ALL_ACCESS, NULL, &hKeyResults, &Disposition);
+ if (lResult == ERROR_SUCCESS)
+ {
+ RegSetValueEx(hKeyResults, L"user", 0, REG_BINARY, (BYTE *)OutData.data(), OutData.size());
+ RegCloseKey(hKeyResults);
+ }
+}
+
+void CProjectSupport::LoadSupportInfo(void)
+{
+ std::string MachineID = GenerateMachineID();
+ std::vector InData;
+
+ HKEY hKeyResults = 0;
+ long lResult = RegOpenKeyEx(HKEY_CURRENT_USER, L"SOFTWARE\\Project64", 0, KEY_READ, &hKeyResults);
+ if (lResult == ERROR_SUCCESS)
+ {
+ DWORD DataSize = 0;
+ if (RegQueryValueEx(hKeyResults, L"user", NULL, NULL, NULL, &DataSize) == ERROR_SUCCESS)
+ {
+ InData.resize(DataSize);
+ if (RegQueryValueEx(hKeyResults, L"user", NULL, NULL, InData.data(), &DataSize) != ERROR_SUCCESS)
+ {
+ InData.clear();
+ }
+ }
+ }
+
+ if (hKeyResults != NULL)
+ {
+ RegCloseKey(hKeyResults);
+ NULL;
+ }
+
+ std::vector OutData;
+ if (InData.size() > 0)
+ {
+ for (size_t i = 0, n = InData.size(); i < n; i++)
+ {
+ InData[i] ^= 0xAA;
+ }
+ OutData.resize(sizeof(m_SupportInfo) + 100);
+ uLongf DestLen = OutData.size();
+ if (uncompress(OutData.data(), &DestLen, InData.data(), InData.size()) >= 0)
+ {
+ OutData.resize(DestLen);
+ }
+ else
+ {
+ OutData.clear();
+ }
+ }
+
+ if (OutData.size() > 0)
+ {
+ SupportInfo * Info = (SupportInfo *)OutData.data();
+ const char * CurrentHash = (const char *)(OutData.data() + sizeof(SupportInfo));
+ std::string hash = MD5((const unsigned char *)Info, sizeof(SupportInfo)).hex_digest();
+ if (strcmp(hash.c_str(), CurrentHash) == 0 && strcmp(Info->MachineID, MachineID.c_str()) == 0)
+ {
+ memcpy(&m_SupportInfo, Info, sizeof(SupportInfo));
+ }
+ }
+ strcpy(m_SupportInfo.MachineID, MachineID.c_str());
+}
\ No newline at end of file
diff --git a/Source/Project64/UserInterface/ProjectSupport.h b/Source/Project64/UserInterface/ProjectSupport.h
new file mode 100644
index 000000000..fd99cfe56
--- /dev/null
+++ b/Source/Project64/UserInterface/ProjectSupport.h
@@ -0,0 +1,39 @@
+#pragma once
+#include
+#include
+
+class CProjectSupport
+{
+ typedef struct
+ {
+ char Code[300];
+ char Email[300];
+ char Name[300];
+ char MachineID[300];
+ uint32_t RunCount;
+ bool Validated;
+ } SupportInfo;
+
+public:
+ CProjectSupport();
+
+ bool RequestCode(const char * Email);
+ bool ValidateCode(const char * Code);
+ void IncrementRunCount();
+
+ inline uint32_t RunCount() const { return m_SupportInfo.RunCount; }
+ inline const char * MachineID(void) const { return m_SupportInfo.MachineID; }
+ inline bool Validated(void) const { return m_SupportInfo.Validated; }
+
+private:
+ CProjectSupport(const CProjectSupport&);
+ CProjectSupport& operator=(const CProjectSupport&);
+
+ std::string GenerateMachineID();
+ bool PerformRequest(const wchar_t * Url, const std::string & PostData, DWORD & StatusCode, std::vector & Headers);
+
+ void SaveSupportInfo(void);
+ void LoadSupportInfo(void);
+
+ SupportInfo m_SupportInfo;
+};
\ No newline at end of file
diff --git a/Source/Project64/UserInterface/SupportEnterCode.cpp b/Source/Project64/UserInterface/SupportEnterCode.cpp
index b307b9681..7e29c7cc3 100644
--- a/Source/Project64/UserInterface/SupportEnterCode.cpp
+++ b/Source/Project64/UserInterface/SupportEnterCode.cpp
@@ -3,34 +3,137 @@
#include
#include "resource.h"
+class CRequestCode :
+ public CDialogImpl
+{
+public:
+ BEGIN_MSG_MAP_EX(CRequestCode)
+ MESSAGE_HANDLER(WM_INITDIALOG, OnInitDialog)
+ MESSAGE_HANDLER(WM_CTLCOLORSTATIC, OnColorStatic)
+ MESSAGE_HANDLER(WM_ERASEBKGND, OnEraseBackground)
+ COMMAND_ID_HANDLER(IDOK, OnOkCmd)
+ COMMAND_ID_HANDLER(IDCANCEL, OnCloseCmd)
+ END_MSG_MAP()
+
+ enum { IDD = IDD_Support_RequestCode };
+
+ CRequestCode(CProjectSupport & Support);
+
+private:
+ CRequestCode(void);
+ CRequestCode(const CRequestCode&);
+ CRequestCode& operator=(const CRequestCode&);
+
+ LRESULT OnInitDialog(UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM /*lParam*/, BOOL& /*bHandled*/);
+ LRESULT OnColorStatic(UINT /*uMsg*/, WPARAM wParam, LPARAM lParam, BOOL& bHandled);
+ LRESULT OnEraseBackground(UINT /*uMsg*/, WPARAM wParam, LPARAM /*lParam*/, BOOL& bHandled);
+ LRESULT OnOkCmd(WORD /*wNotifyCode*/, WORD wID, HWND /*hWndCtl*/, BOOL& /*bHandled*/);
+ LRESULT OnCloseCmd(WORD /*wNotifyCode*/, WORD wID, HWND /*hWndCtl*/, BOOL& /*bHandled*/);
+
+ CProjectSupport & m_Support;
+};
+
+CSupportEnterCode::CSupportEnterCode(CProjectSupport & Support) :
+ m_Support(Support)
+{
+}
+
LRESULT CSupportEnterCode::OnInitDialog(UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM /*lParam*/, BOOL& /*bHandled*/)
{
- ::SetWindowTextW(m_hWnd, wGS(MSG_SUPPORT_ENTER_CODE_TITLE).c_str());
- ::SetWindowTextW(GetDlgItem(IDOK), wGS(MSG_SUPPORT_OK).c_str());
- ::SetWindowTextW(GetDlgItem(IDCANCEL), wGS(MSG_SUPPORT_CANCEL).c_str());
- ::SetWindowTextW(GetDlgItem(IDC_DESCRIPTION), wGS(MSG_SUPPORT_ENTER_CODE_DESC).c_str());
+ SetWindowText(wGS(MSG_SUPPORT_ENTER_CODE_TITLE).c_str());
+ CWindow hDescription = GetDlgItem(IDC_DESCRIPTION);
+ CWindow MachineId = GetDlgItem(IDC_MACHINE_ID);
+ CWindow OkBtn = GetDlgItem(IDOK);
+ CWindow CancelBtn = GetDlgItem(IDCANCEL);
+
+ std::wstring DescriptionText = wGS(MSG_SUPPORT_ENTER_CODE_DESC);
+ hDescription.SetWindowText(DescriptionText.c_str());
+ MachineId.SetWindowText(stdstr(m_Support.MachineID()).ToUTF16().c_str());
+ OkBtn.SetWindowText(wGS(MSG_SUPPORT_OK).c_str());
+ CancelBtn.SetWindowText(wGS(MSG_SUPPORT_CANCEL).c_str());
+
+ m_RequestLink.SubclassWindow(GetDlgItem(IDC_REQUEST_LINK));
+ m_RequestLink.SetHyperLinkExtendedStyle(HLINK_COMMANDBUTTON, HLINK_COMMANDBUTTON);
+
+ CRect rcWin = { 0 };
+ hDescription.GetClientRect(&rcWin);
+
+ CDC hDC = hDescription.GetDC();
+ HFONT hFont = hDescription.GetFont();
+ if (hFont == nullptr)
+ {
+ hFont = (HFONT)::GetStockObject(SYSTEM_FONT);
+ }
+ hDC.SelectFont(hFont);
+ if (hDC.DrawText(DescriptionText.c_str(), DescriptionText.length(), &rcWin, DT_LEFT | DT_CALCRECT | DT_WORDBREAK | DT_NOCLIP) > 0)
+ {
+ hDescription.SetWindowPos(NULL, 0, 0, rcWin.right, rcWin.bottom, SWP_NOACTIVATE | SWP_NOMOVE | SWP_NOOWNERZORDER);
+ }
+ hDescription.GetWindowRect(&rcWin);
+ ::MapWindowPoints(NULL, m_hWnd, (LPPOINT)&rcWin, 2);
+
+ MachineId.SetWindowPos(NULL, rcWin.left, rcWin.bottom + 4, 0, 0, SWP_NOACTIVATE | SWP_NOSIZE | SWP_NOOWNERZORDER);
+ MachineId.GetWindowRect(&rcWin);
+ ::MapWindowPoints(NULL, m_hWnd, (LPPOINT)&rcWin, 2);
+
+ CWindow Code = GetDlgItem(IDC_CODE);
+ Code.SetWindowPos(NULL, rcWin.left, rcWin.bottom + 4, 0, 0, SWP_NOACTIVATE | SWP_NOSIZE | SWP_NOOWNERZORDER);
+ Code.GetWindowRect(&rcWin);
+ ::MapWindowPoints(NULL, m_hWnd, (LPPOINT)&rcWin, 2);
+
+ CWindow RequestDescption = GetDlgItem(IDC_REQUEST_DESCPTION);
+ RequestDescption.ShowWindow(SWP_HIDEWINDOW);
+ RequestDescption.SetWindowPos(NULL, rcWin.left, rcWin.bottom + 10, 0, 0, SWP_NOACTIVATE | SWP_NOSIZE | SWP_NOOWNERZORDER);
+ RequestDescption.GetWindowRect(&rcWin);
+ ::MapWindowPoints(NULL, m_hWnd, (LPPOINT)&rcWin, 2);
+
+ CWindow RequestLink = GetDlgItem(IDC_REQUEST_LINK);
+ RequestLink.ShowWindow(SWP_HIDEWINDOW);
+ RequestLink.SetWindowPos(NULL, rcWin.left, rcWin.bottom + 4, 0, 0, SWP_NOACTIVATE | SWP_NOSIZE | SWP_NOOWNERZORDER);
+ RequestLink.GetWindowRect(&rcWin);
+ ::MapWindowPoints(NULL, m_hWnd, (LPPOINT)&rcWin, 2);
+
+ RECT CancelBtnWin = { 0 };
+ CancelBtn.GetWindowRect(&CancelBtnWin);
+ ::MapWindowPoints(NULL, m_hWnd, (LPPOINT)&CancelBtnWin, 2);
+ CancelBtn.SetWindowPos(NULL, CancelBtnWin.left, rcWin.bottom + 40, 0, 0, SWP_NOACTIVATE | SWP_NOSIZE | SWP_NOOWNERZORDER);
+
+ RECT OkBtnWin = { 0 };
+ OkBtn.GetWindowRect(&OkBtnWin);
+ ::MapWindowPoints(NULL, m_hWnd, (LPPOINT)&OkBtnWin, 2);
+ OkBtn.SetWindowPos(NULL, OkBtnWin.left, rcWin.bottom + 40, 0, 0, SWP_NOACTIVATE | SWP_NOSIZE | SWP_NOOWNERZORDER);
+ OkBtn.GetWindowRect(&OkBtnWin);
+ ::MapWindowPoints(NULL, m_hWnd, (LPPOINT)&OkBtnWin, 2);
+
+ GetWindowRect(&rcWin);
+ SetRect(&rcWin, 0, 0, rcWin.Width(), OkBtnWin.bottom + 30);
+ AdjustWindowRectEx(&rcWin, GetStyle(), GetMenu() != NULL, GetExStyle());
+ int32_t Left = (GetSystemMetrics(SM_CXSCREEN) - rcWin.Width()) / 2;
+ int32_t Top = (GetSystemMetrics(SM_CYSCREEN) - rcWin.Height()) / 2;
+ MoveWindow(Left, Top, rcWin.Width(), rcWin.Height(), TRUE);
return TRUE;
}
LRESULT CSupportEnterCode::OnColorStatic(UINT /*uMsg*/, WPARAM wParam, LPARAM /*lParam*/, BOOL& /*bHandled*/)
{
- HDC hdcStatic = (HDC)wParam;
- SetTextColor(hdcStatic, RGB(0, 0, 0));
- SetBkMode(hdcStatic, TRANSPARENT);
+ CDCHandle hdcStatic = (HDC)wParam;
+ hdcStatic.SetTextColor(RGB(0, 0, 0));
+ hdcStatic.SetBkMode(TRANSPARENT);
return (LONG)(LRESULT)((HBRUSH)GetStockObject(NULL_BRUSH));
}
LRESULT CSupportEnterCode::OnEraseBackground(UINT /*uMsg*/, WPARAM wParam, LPARAM /*lParam*/, BOOL& /*bHandled*/)
{
- static HPEN outline = CreatePen(PS_SOLID, 1, 0x00FFFFFF);
- static HBRUSH fill = CreateSolidBrush(0x00FFFFFF);
- SelectObject((HDC)wParam, outline);
- SelectObject((HDC)wParam, fill);
+ static HPEN Outline = CreatePen(PS_SOLID, 1, 0x00FFFFFF);
+ static HBRUSH Fill = CreateSolidBrush(0x00FFFFFF);
+
+ CDCHandle hdc = (HDC)wParam;
+ hdc.SelectPen(Outline);
+ hdc.SelectBrush(Fill);
RECT rect;
GetClientRect(&rect);
-
- Rectangle((HDC)wParam, rect.left, rect.top, rect.right, rect.bottom);
+ hdc.Rectangle(&rect);
return TRUE;
}
@@ -48,14 +151,99 @@ LRESULT CSupportEnterCode::OnOkCmd(WORD /*wNotifyCode*/, WORD wID, HWND /*hWndCt
MessageBox(wGS(MSG_SUPPORT_ENTER_SUPPORT_CODE).c_str(), wGS(MSG_SUPPORT_PROJECT64).c_str(), MB_OK);
return false;
}
- if (_wcsicmp(code,L"thank you from project64") != 0)
+ GetDlgItem(IDOK).EnableWindow(false);
+ GetDlgItem(IDCANCEL).EnableWindow(false);
+
+ bool ValidCode = false;
+ if (_wcsicmp(code,L"thank you from project64") == 0)
+ {
+ UISettingsSaveDword(SupportWindows_RunCount, (uint32_t)-1);
+ CSettingTypeApplication::Flush();
+ ValidCode = true;
+ }
+ else if (m_Support.ValidateCode(stdstr().FromUTF16(code).c_str()))
+ {
+ ValidCode = true;
+ }
+ if (ValidCode)
+ {
+ MessageBox(wGS(MSG_SUPPORT_COMPLETE).c_str(), wGS(MSG_SUPPORT_PROJECT64).c_str(), MB_OK);
+ EndDialog(wID);
+ }
+ else
{
MessageBox(wGS(MSG_SUPPORT_INCORRECT_CODE).c_str(), wGS(MSG_SUPPORT_PROJECT64).c_str(), MB_OK);
- return false;
+ GetDlgItem(IDOK).EnableWindow(TRUE);
+ GetDlgItem(IDCANCEL).EnableWindow(TRUE);
}
- UISettingsSaveDword(SupportWindows_RunCount, (uint32_t) -1);
- CSettingTypeApplication::Flush();
- MessageBox(wGS(MSG_SUPPORT_COMPLETE).c_str(), wGS(MSG_SUPPORT_PROJECT64).c_str(), MB_OK);
+ return TRUE;
+}
+
+CRequestCode::CRequestCode(CProjectSupport & Support) :
+ m_Support(Support)
+{
+}
+
+LRESULT CSupportEnterCode::OnRequestCode(WORD /*wNotifyCode*/, WORD /*wID*/, HWND /*hWndCtl*/, BOOL& /*bHandled*/)
+{
+ CRequestCode RequestWindow(m_Support);
+ RequestWindow.DoModal(m_hWnd);
+ return 0;
+}
+
+LRESULT CRequestCode::OnInitDialog(UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM /*lParam*/, BOOL& /*bHandled*/)
+{
+ return TRUE;
+}
+
+LRESULT CRequestCode::OnColorStatic(UINT /*uMsg*/, WPARAM wParam, LPARAM /*lParam*/, BOOL& /*bHandled*/)
+{
+ CDCHandle hdcStatic = (HDC)wParam;
+ hdcStatic.SetTextColor(RGB(0, 0, 0));
+ hdcStatic.SetBkMode(TRANSPARENT);
+ return (LONG)(LRESULT)((HBRUSH)GetStockObject(NULL_BRUSH));
+}
+
+LRESULT CRequestCode::OnEraseBackground(UINT /*uMsg*/, WPARAM wParam, LPARAM /*lParam*/, BOOL& /*bHandled*/)
+{
+ static HPEN Outline = CreatePen(PS_SOLID, 1, 0x00FFFFFF);
+ static HBRUSH Fill = CreateSolidBrush(0x00FFFFFF);
+
+ CDCHandle hdc = (HDC)wParam;
+ hdc.SelectPen(Outline);
+ hdc.SelectBrush(Fill);
+
+ RECT rect;
+ GetClientRect(&rect);
+ hdc.Rectangle(&rect);
+ return TRUE;
+}
+
+LRESULT CRequestCode::OnOkCmd(WORD /*wNotifyCode*/, WORD wID, HWND /*hWndCtl*/, BOOL& /*bHandled*/)
+{
+ CWindow EmailWnd(GetDlgItem(IDC_EMAIL));
+ int EmailLen = EmailWnd.GetWindowTextLength();
+ std::wstring Email;
+ Email.resize(EmailLen + 1);
+ EmailWnd.GetWindowText((wchar_t *)Email.c_str(), Email.length());
+ GetDlgItem(IDOK).EnableWindow(false);
+ GetDlgItem(IDCANCEL).EnableWindow(false);
+ if (m_Support.RequestCode(stdstr().FromUTF16(Email.c_str()).c_str()))
+ {
+ MessageBox(wGS(MSG_SUPPORT_REQUESTCODE_SUCCESS).c_str(), wGS(MSG_SUPPORT_REQUESTCODE_TITLE).c_str(), MB_OK);
+ EndDialog(wID);
+ }
+ else
+ {
+ MessageBox(wGS(MSG_SUPPORT_REQUESTCODE_FAIL).c_str(), wGS(MSG_SUPPORT_REQUESTCODE_TITLE).c_str(), MB_OK);
+ GetDlgItem(IDOK).EnableWindow(true);
+ GetDlgItem(IDCANCEL).EnableWindow(true);
+ }
+ return TRUE;
+}
+
+LRESULT CRequestCode::OnCloseCmd(WORD /*wNotifyCode*/, WORD wID, HWND /*hWndCtl*/, BOOL& /*bHandled*/)
+{
EndDialog(wID);
return TRUE;
-}
\ No newline at end of file
+}
diff --git a/Source/Project64/UserInterface/SupportEnterCode.h b/Source/Project64/UserInterface/SupportEnterCode.h
index c0bebfe68..6da93f3c0 100644
--- a/Source/Project64/UserInterface/SupportEnterCode.h
+++ b/Source/Project64/UserInterface/SupportEnterCode.h
@@ -1,4 +1,5 @@
#pragma once
+#include "resource.h"
class CSupportEnterCode :
public CDialogImpl
@@ -10,14 +11,25 @@ public:
MESSAGE_HANDLER(WM_ERASEBKGND, OnEraseBackground)
COMMAND_ID_HANDLER(IDOK, OnOkCmd)
COMMAND_ID_HANDLER(IDCANCEL, OnCloseCmd)
- END_MSG_MAP()
+ COMMAND_ID_HANDLER(IDC_REQUEST_LINK, OnRequestCode)
+ END_MSG_MAP()
- enum { IDD = IDD_Support_EnterCode };
+ enum { IDD = IDD_Support_EnterCode };
+
+ CSupportEnterCode(CProjectSupport & Support);
private:
+ CSupportEnterCode(void);
+ CSupportEnterCode(const CSupportEnterCode&);
+ CSupportEnterCode& operator=(const CSupportEnterCode&);
+
LRESULT OnInitDialog(UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM /*lParam*/, BOOL& /*bHandled*/);
LRESULT OnColorStatic(UINT /*uMsg*/, WPARAM wParam, LPARAM lParam, BOOL& bHandled);
LRESULT OnEraseBackground(UINT /*uMsg*/, WPARAM wParam, LPARAM /*lParam*/, BOOL& bHandled);
LRESULT OnOkCmd(WORD /*wNotifyCode*/, WORD wID, HWND /*hWndCtl*/, BOOL& /*bHandled*/);
LRESULT OnCloseCmd(WORD /*wNotifyCode*/, WORD wID, HWND /*hWndCtl*/, BOOL& /*bHandled*/);
+ LRESULT OnRequestCode(WORD /*wNotifyCode*/, WORD wID, HWND /*hWndCtl*/, BOOL& /*bHandled*/);
+
+ CHyperLink m_RequestLink;
+ CProjectSupport & m_Support;
};
\ No newline at end of file
diff --git a/Source/Project64/UserInterface/SupportWindow.cpp b/Source/Project64/UserInterface/SupportWindow.cpp
index a9c352a20..02a2acd25 100644
--- a/Source/Project64/UserInterface/SupportWindow.cpp
+++ b/Source/Project64/UserInterface/SupportWindow.cpp
@@ -2,12 +2,13 @@
#include "SupportEnterCode.h"
#include
-HWND CSupportWindow::m_hParent = NULL;
-CSupportWindow * CSupportWindow::m_this = NULL;
-uint32_t CSupportWindow::m_RunCount = 0;
-uint32_t CSupportWindow::m_TimeOutTime = 30;
+CSupportWindow * CSupportWindow::m_this = nullptr;
-CSupportWindow::CSupportWindow(void)
+CSupportWindow::CSupportWindow(CProjectSupport & Support) :
+ m_Support(Support),
+ m_TimeOutTime(30),
+ m_hParent(nullptr),
+ m_Delay(false)
{
}
@@ -18,27 +19,32 @@ CSupportWindow::~CSupportWindow(void)
void CALLBACK CSupportWindow::TimerProc(HWND, UINT, UINT_PTR idEvent, DWORD)
{
::KillTimer(NULL, idEvent);
- CSupportWindow SupportWindow;
- SupportWindow.DoModal(m_hParent);
+ m_this->DoModal(m_this->m_hParent);
}
-void CSupportWindow::Show(HWND hParent)
+void CSupportWindow::Show(HWND hParent, bool Delay)
{
- m_RunCount = UISettingsLoadDword(SupportWindows_RunCount);
- if (m_RunCount == -1)
+ m_Delay = Delay;
+ if (Delay)
{
- return;
- }
- UISettingsSaveDword(SupportWindows_RunCount, m_RunCount + 1);
+ if (UISettingsLoadDword(SupportWindows_RunCount) == -1 || m_Support.Validated())
+ {
+ return;
+ }
- if (m_RunCount < 3)
+ m_Support.IncrementRunCount();
+ if (m_Support.RunCount() < 7)
+ {
+ return;
+ }
+ m_hParent = hParent;
+ m_this = this;
+ ::SetTimer(nullptr, 0, 2500, TimerProc);
+ }
+ else
{
- return;
+ DoModal(hParent);
}
-
- m_hParent = hParent;
- m_this = this;
- ::SetTimer(NULL, 0, 2500, TimerProc);
}
void CSupportWindow::EnableContinue()
@@ -50,72 +56,101 @@ void CSupportWindow::EnableContinue()
LRESULT CSupportWindow::OnInitDialog(UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM /*lParam*/, BOOL& /*bHandled*/)
{
- ::SetWindowTextW(m_hWnd, wGS(MSG_SUPPORT_TITLE).c_str());
- ::SetWindowTextW(GetDlgItem(IDC_ENTER_CODE), wGS(MSG_SUPPORT_ENTER_CODE).c_str());
- ::SetWindowTextW(GetDlgItem(ID_SUPPORT_PJ64), wGS(MSG_SUPPORT_PROJECT64).c_str());
- ::SetWindowTextW(GetDlgItem(IDCANCEL), wGS(MSG_SUPPORT_CONTINUE).c_str());
+ m_Logo.SubclassWindow(GetDlgItem(IDC_BMP_LOGO));
+ m_Logo.SetBitmap(MAKEINTRESOURCE(IDB_ABOUT_LOGO));
+ std::wstring InfoText = wGS(MSG_SUPPORT_INFO);
+ SetWindowText(wGS(MSG_SUPPORT_TITLE).c_str());
+ GetDlgItem(IDC_ENTER_CODE).SetWindowText(wGS(MSG_SUPPORT_ENTER_CODE).c_str());
+ GetDlgItem(ID_SUPPORT_PJ64).SetWindowText(wGS(MSG_SUPPORT_PROJECT64).c_str());
+ GetDlgItem(IDCANCEL).SetWindowText(wGS(MSG_SUPPORT_CONTINUE).c_str());
+
+ m_EnterLink.SubclassWindow(GetDlgItem(IDC_ENTER_CODE));
+ m_EnterLink.SetHyperLinkExtendedStyle(HLINK_COMMANDBUTTON, HLINK_COMMANDBUTTON);
+ m_EnterLink.EnableWindow(!m_Support.Validated());
+
+ CWindow hInfo = GetDlgItem(IDC_INFO);
+ CRect rcWin = { 0 };
+ hInfo.GetClientRect(&rcWin);
+
+ CDC hDC = hInfo.GetDC();
+ HFONT hFont = hInfo.GetFont();
+ if(hFont == nullptr)
{
- HWND hInfo = GetDlgItem(IDC_INFO);
- std::wstring InfoText = wGS(MSG_SUPPORT_INFO);
- RECT rcWin = { 0 };
- ::GetClientRect(hInfo,&rcWin);
-
- HDC hDC = ::GetDC(hInfo);
- HFONT hFont = (HFONT)::SendMessage(hInfo, WM_GETFONT, 0, 0L);
- if(hFont == NULL)
- {
- hFont = (HFONT)::GetStockObject(SYSTEM_FONT);
- }
- SelectObject(hDC, hFont);
-
- if (DrawTextW(hDC,InfoText.c_str(),InfoText.length(),&rcWin,DT_LEFT | DT_CALCRECT | DT_WORDBREAK | DT_NOCLIP) > 0)
- {
- ::SetWindowPos(hInfo,NULL,0,0,rcWin.right, rcWin.bottom,SWP_NOACTIVATE|SWP_NOMOVE|SWP_NOOWNERZORDER);
- }
- ::SetWindowTextW(hInfo, InfoText.c_str());
-
- ::GetWindowRect(hInfo,&rcWin);
- ::MapWindowPoints(NULL, m_hWnd, (LPPOINT)&rcWin, 2);
- ::SetWindowPos(GetDlgItem(IDC_ENTER_CODE),NULL,rcWin.left,rcWin.bottom + 4,0,0,SWP_NOACTIVATE|SWP_NOSIZE|SWP_NOOWNERZORDER);
-
- m_EnterLink.SubclassWindow(GetDlgItem(IDC_ENTER_CODE));
- m_EnterLink.SetHyperLinkExtendedStyle(HLINK_COMMANDBUTTON,HLINK_COMMANDBUTTON);
+ hFont = (HFONT)::GetStockObject(SYSTEM_FONT);
}
- if (m_RunCount >= 10)
+ hDC.SelectFont(hFont);
+ if (hDC.DrawText(InfoText.c_str(),InfoText.length(),&rcWin,DT_LEFT | DT_CALCRECT | DT_WORDBREAK | DT_NOCLIP) > 0)
{
- HMENU menu = GetSystemMenu(false);
- RemoveMenu(menu, SC_CLOSE, MF_BYCOMMAND);
+ hInfo.SetWindowPos(NULL,0,0,rcWin.right, rcWin.bottom,SWP_NOACTIVATE|SWP_NOMOVE|SWP_NOOWNERZORDER);
+ }
+ hInfo.SetWindowText(InfoText.c_str());
+ hInfo.GetWindowRect(&rcWin);
+ ::MapWindowPoints(NULL, m_hWnd, (LPPOINT)&rcWin, 2);
+
+ CWindow EnterCode = GetDlgItem(IDC_ENTER_CODE);
+ EnterCode.SetWindowPos(NULL,rcWin.left,rcWin.bottom + 4,0,0,SWP_NOACTIVATE|SWP_NOSIZE|SWP_NOOWNERZORDER);
+ EnterCode.GetWindowRect(&rcWin);
+ ::MapWindowPoints(NULL, m_hWnd, (LPPOINT)&rcWin, 2);
+
+ CWindow SupportBtn = GetDlgItem(ID_SUPPORT_PJ64);
+ RECT SupportBtnWin = { 0 };
+ SupportBtn.GetWindowRect(&SupportBtnWin);
+ ::MapWindowPoints(NULL, m_hWnd, (LPPOINT)&SupportBtnWin, 2);
+ SupportBtn.SetWindowPos(NULL, SupportBtnWin.left, rcWin.bottom + 40, 0, 0, SWP_NOACTIVATE | SWP_NOSIZE | SWP_NOOWNERZORDER);
+
+ CWindow CancelBtn = GetDlgItem(IDCANCEL);
+ RECT CancelBtnWin = { 0 };
+ CancelBtn.GetWindowRect(&CancelBtnWin);
+ ::MapWindowPoints(NULL, m_hWnd, (LPPOINT)&CancelBtnWin, 2);
+ CancelBtn.SetWindowPos(NULL, CancelBtnWin.left, rcWin.bottom + 40, 0, 0, SWP_NOACTIVATE | SWP_NOSIZE | SWP_NOOWNERZORDER);
+
+ GetWindowRect(&rcWin);
+ SupportBtn.GetWindowRect(&SupportBtnWin);
+ ::MapWindowPoints(NULL, m_hWnd, (LPPOINT)&SupportBtnWin, 2);
+ SetRect(&rcWin, 0, 0, rcWin.Width(), SupportBtnWin.bottom + 30);
+ AdjustWindowRectEx(&rcWin, GetStyle(), GetMenu() != NULL, GetExStyle());
+
+ int32_t Left = (GetSystemMetrics(SM_CXSCREEN) - rcWin.Width()) / 2;
+ int32_t Top = (GetSystemMetrics(SM_CYSCREEN) - rcWin.Height()) / 2;
+
+ MoveWindow(Left, Top, rcWin.Width(), rcWin.Height(), TRUE);
+
+ /*if (m_Delay && m_RunCount >= 10)
+ {
+ CMenuHandle menu = GetSystemMenu(false);
+ menu.RemoveMenu(SC_CLOSE, MF_BYCOMMAND);
DWORD dwStyle = GetWindowLong(GWL_STYLE);
dwStyle |= CS_NOCLOSE;
SetWindowLong(GWL_STYLE, dwStyle);
- ::EnableWindow(GetDlgItem(IDCANCEL), false);
+ GetDlgItem(IDCANCEL).EnableWindow(false);
srand ((uint32_t)time(NULL));
SetTimer(0, 1000, NULL);
- }
+ }*/
return TRUE;
}
LRESULT CSupportWindow::OnColorStatic(UINT /*uMsg*/, WPARAM wParam, LPARAM /*lParam*/, BOOL& /*bHandled*/)
{
- HDC hdcStatic = (HDC)wParam;
- SetTextColor(hdcStatic, RGB(0, 0, 0));
- SetBkMode(hdcStatic, TRANSPARENT);
+ CDCHandle hdcStatic = (HDC)wParam;
+ hdcStatic.SetTextColor(RGB(0, 0, 0));
+ hdcStatic.SetBkMode(TRANSPARENT);
return (LONG)(LRESULT)((HBRUSH)GetStockObject(NULL_BRUSH));
}
LRESULT CSupportWindow::OnEraseBackground(UINT /*uMsg*/, WPARAM wParam, LPARAM /*lParam*/, BOOL& /*bHandled*/)
{
- static HPEN outline = CreatePen(PS_SOLID, 1, 0x00FFFFFF);
- static HBRUSH fill = CreateSolidBrush(0x00FFFFFF);
- SelectObject((HDC)wParam, outline);
- SelectObject((HDC)wParam, fill);
+ static HPEN Outline = CreatePen(PS_SOLID, 1, 0x00FFFFFF);
+ static HBRUSH Fill = CreateSolidBrush(0x00FFFFFF);
+
+ CDCHandle hdc = (HDC)wParam;
+ hdc.SelectPen(Outline);
+ hdc.SelectBrush(Fill);
RECT rect;
GetClientRect(&rect);
-
- Rectangle((HDC)wParam, rect.left, rect.top, rect.right, rect.bottom);
+ hdc.Rectangle(&rect);
return TRUE;
}
@@ -127,8 +162,8 @@ LRESULT CSupportWindow::OnTimer(UINT /*uMsg*/, WPARAM wParam, LPARAM /*lParam*/,
KillTimer(wParam);
EnableContinue();
}
- stdstr_f continue_txt(m_TimeOutTime > 0 ? "%s (%d)" : "%s", GS(MSG_SUPPORT_CONTINUE), m_TimeOutTime);
- ::SetWindowTextW(GetDlgItem(IDCANCEL), continue_txt.ToUTF16().c_str());
+ stdstr_f Continue_txt(m_TimeOutTime > 0 ? "%s (%d)" : "%s", GS(MSG_SUPPORT_CONTINUE), m_TimeOutTime);
+ GetDlgItem(IDCANCEL).SetWindowText(Continue_txt.ToUTF16().c_str());
return true;
}
@@ -140,18 +175,22 @@ LRESULT CSupportWindow::OnCloseCmd(WORD /*wNotifyCode*/, WORD wID, HWND /*hWndCt
LRESULT CSupportWindow::OnSupportProject64(WORD /*wNotifyCode*/, WORD /*wID*/, HWND /*hWndCtl*/, BOOL& /*bHandled*/)
{
- stdstr SupportURL = stdstr_f("http://www.pj64-emu.com/support-project64.html?ver=%s", VER_FILE_VERSION_STR);
+ stdstr SupportURL = stdstr_f("https://www.pj64-emu.com/support-project64.html?ver=%s&machine=%s", VER_FILE_VERSION_STR, m_Support.MachineID());
ShellExecute(NULL, L"open", SupportURL.ToUTF16().c_str(), NULL, NULL, SW_SHOWMAXIMIZED);
return TRUE;
}
LRESULT CSupportWindow::OnEnterCode(WORD /*wNotifyCode*/, WORD wID, HWND /*hWndCtl*/, BOOL& /*bHandled*/)
{
- CSupportEnterCode EnterCodeWindow;
+ CSupportEnterCode EnterCodeWindow(m_Support);
EnterCodeWindow.DoModal(m_hWnd);
if (UISettingsLoadDword(SupportWindows_RunCount) == -1)
{
EndDialog(wID);
}
+ if (m_Support.Validated())
+ {
+ EndDialog(wID);
+ }
return TRUE;
}
\ No newline at end of file
diff --git a/Source/Project64/UserInterface/SupportWindow.h b/Source/Project64/UserInterface/SupportWindow.h
index 0065ec8ad..c44ada8c7 100644
--- a/Source/Project64/UserInterface/SupportWindow.h
+++ b/Source/Project64/UserInterface/SupportWindow.h
@@ -1,4 +1,6 @@
#pragma once
+#include
+#include "resource.h"
class CSupportWindow :
public CDialogImpl
@@ -16,12 +18,16 @@ public:
enum { IDD = IDD_Support_Project64 };
- CSupportWindow(void);
+ CSupportWindow(CProjectSupport & Support);
~CSupportWindow(void);
- void Show(HWND hParent);
+ void Show(HWND hParent, bool Delay);
private:
+ CSupportWindow();
+ CSupportWindow(const CSupportWindow&);
+ CSupportWindow& operator=(const CSupportWindow&);
+
LRESULT OnInitDialog(UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM /*lParam*/, BOOL& /*bHandled*/);
LRESULT OnColorStatic(UINT /*uMsg*/, WPARAM wParam, LPARAM lParam, BOOL& bHandled);
LRESULT OnEraseBackground(UINT /*uMsg*/, WPARAM wParam, LPARAM /*lParam*/, BOOL& bHandled);
@@ -34,11 +40,12 @@ private:
CHyperLink m_EnterLink;
- static DWORD CALLBACK SupportWindowProc(HWND hWnd, DWORD uMsg, DWORD wParam, DWORD lParam);
static void CALLBACK TimerProc(HWND, UINT, UINT_PTR idEvent, DWORD);
- static HWND m_hParent;
+ CProjectSupport & m_Support;
+ CBitmapPicture m_Logo;
+ bool m_Delay;
+ uint32_t m_TimeOutTime;
+ HWND m_hParent;
static CSupportWindow * m_this;
- static uint32_t m_RunCount;
- static uint32_t m_TimeOutTime;
};
\ No newline at end of file
diff --git a/Source/Project64/UserInterface/UIResources.rc b/Source/Project64/UserInterface/UIResources.rc
index c61ec3110..fe0b3c82a 100644
--- a/Source/Project64/UserInterface/UIResources.rc
+++ b/Source/Project64/UserInterface/UIResources.rc
@@ -650,22 +650,25 @@ STYLE DS_SETFONT | DS_MODALFRAME | DS_FIXEDSYS | DS_CENTER | WS_POPUP | WS_CAPTI
CAPTION "Support Project64"
FONT 8, "MS Shell Dlg", 0, 0, 0x1
BEGIN
- CONTROL IDD_About_Ini,IDC_STATIC,"Static",SS_BITMAP,0,0,233,74
+ CONTROL "",IDC_BMP_LOGO,"Static",SS_BLACKFRAME,1,0,232,74
DEFPUSHBUTTON "Support Project64",ID_SUPPORT_PJ64,19,186,71,14
PUSHBUTTON "Continue",IDCANCEL,139,186,71,14
LTEXT "Project64 is a software package",IDC_INFO,7,76,213,79
LTEXT "Enter notification code",IDC_ENTER_CODE,8,164,213,8
END
-IDD_Support_EnterCode DIALOGEX 0, 0, 161, 68
+IDD_Support_EnterCode DIALOGEX 0, 0, 174, 117
STYLE DS_SETFONT | DS_MODALFRAME | DS_FIXEDSYS | DS_CENTER | WS_POPUP | WS_CAPTION | WS_SYSMENU
CAPTION "Enter Code"
FONT 8, "MS Shell Dlg", 0, 0, 0x1
BEGIN
- DEFPUSHBUTTON "OK",IDOK,50,47,50,14
- PUSHBUTTON "Cancel",IDCANCEL,104,47,50,14
- LTEXT "Please enter the code in email",IDC_DESCRIPTION,7,7,147,15
- EDITTEXT IDC_CODE,7,25,147,12,ES_AUTOHSCROLL
+ DEFPUSHBUTTON "OK",IDOK,64,96,50,14
+ PUSHBUTTON "Cancel",IDCANCEL,117,96,50,14
+ LTEXT "Please enter the code in email",IDC_DESCRIPTION,7,8,160,8,SS_NOPREFIX
+ EDITTEXT IDC_CODE,7,38,160,12,ES_AUTOHSCROLL
+ LTEXT "Please enter the code in email",IDC_REQUEST_DESCPTION,7,57,160,10
+ LTEXT "Request Code",IDC_REQUEST_LINK,7,72,160,8
+ LTEXT "Machine ID",IDC_MACHINE_ID,7,24,160,10,SS_NOPREFIX
END
IDD_Debugger_Commands DIALOGEX 0, 0, 535, 327
@@ -1411,6 +1414,17 @@ BEGIN
COMBOBOX IDC_DISKSAVETYPE,95,104,115,30,CBS_DROPDOWNLIST | CBS_SORT | WS_VSCROLL | WS_TABSTOP
END
+IDD_Support_RequestCode DIALOGEX 0, 0, 165, 96
+STYLE DS_SETFONT | DS_MODALFRAME | DS_FIXEDSYS | DS_CENTER | WS_POPUP | WS_CAPTION | WS_SYSMENU
+CAPTION "Request Code"
+FONT 8, "MS Shell Dlg", 0, 0, 0x1
+BEGIN
+ LTEXT "Please enter the email used to support Project64",IDC_DESCRIPTION,8,8,148,15
+ EDITTEXT IDC_EMAIL,8,34,148,12,ES_AUTOHSCROLL
+ DEFPUSHBUTTON "OK",IDOK,55,75,50,14
+ PUSHBUTTON "Cancel",IDCANCEL,108,75,50,14
+END
+
/////////////////////////////////////////////////////////////////////////////
//
@@ -1646,8 +1660,6 @@ BEGIN
IDD_Support_Project64, DIALOG
BEGIN
- LEFTMARGIN, 7
- RIGHTMARGIN, 170
TOPMARGIN, 7
BOTTOMMARGIN, 200
END
@@ -1655,9 +1667,9 @@ BEGIN
IDD_Support_EnterCode, DIALOG
BEGIN
LEFTMARGIN, 7
- RIGHTMARGIN, 154
+ RIGHTMARGIN, 167
TOPMARGIN, 7
- BOTTOMMARGIN, 61
+ BOTTOMMARGIN, 110
END
IDD_Debugger_Commands, DIALOG
@@ -1882,6 +1894,13 @@ BEGIN
TOPMARGIN, 7
BOTTOMMARGIN, 148
END
+
+ IDD_Support_RequestCode, DIALOG
+ BEGIN
+ RIGHTMARGIN, 155
+ TOPMARGIN, 7
+ BOTTOMMARGIN, 89
+ END
END
#endif // APSTUDIO_INVOKED
@@ -2231,6 +2250,21 @@ BEGIN
0
END
+IDD_Support_Project64 AFX_DIALOG_LAYOUT
+BEGIN
+ 0
+END
+
+IDD_Support_EnterCode AFX_DIALOG_LAYOUT
+BEGIN
+ 0
+END
+
+IDD_Support_RequestCode AFX_DIALOG_LAYOUT
+BEGIN
+ 0
+END
+
/////////////////////////////////////////////////////////////////////////////
//
diff --git a/Source/Project64/UserInterface/resource.h b/Source/Project64/UserInterface/resource.h
index 97784ab82..24aeac452 100644
--- a/Source/Project64/UserInterface/resource.h
+++ b/Source/Project64/UserInterface/resource.h
@@ -83,6 +83,7 @@
#define IDD_Debugger_ExceptionBP 207
#define IDD_Debugger_Search_SetValue 210
#define IDD_Settings_DiskDrive 215
+#define IDD_Support_RequestCode 216
#define IDC_MENU_ITEM_TEXT 1000
#define IDC_CLOSE_BUTTON 1001
#define IDC_LIST2 1003
@@ -276,8 +277,11 @@
#define IDC_DESCRIPTION 1102
#define IDC_DIR_FRAME3 1103
#define IDC_OVER_CLOCK_MODIFIER 1103
+#define IDC_REQUEST_DESCPTION 1103
#define IDC_DIR_FRAME4 1104
+#define IDC_REQUEST_LINK 1104
#define IDC_DIR_FRAME5 1105
+#define IDC_MACHINE_ID 1105
#define IDC_MAXROMS_TXT 1111
#define IDC_ROMSEL_TEXT2 1112
#define IDC_R0_EDIT 1112
@@ -722,6 +726,7 @@
#define IDC_F1_LBL 1576
#define IDC_SELECT_GAME_DIR 1576
#define IDC_F2_LBL 1577
+#define IDC_EMAIL 1577
#define IDC_F3_LBL 1578
#define IDC_F4_LBL 1579
#define IDC_F5_LBL 1580
@@ -938,9 +943,9 @@
//
#ifdef APSTUDIO_INVOKED
#ifndef APSTUDIO_READONLY_SYMBOLS
-#define _APS_NEXT_RESOURCE_VALUE 220
+#define _APS_NEXT_RESOURCE_VALUE 221
#define _APS_NEXT_COMMAND_VALUE 40121
-#define _APS_NEXT_CONTROL_VALUE 1577
+#define _APS_NEXT_CONTROL_VALUE 1578
#define _APS_NEXT_SYMED_VALUE 102
#endif
#endif
diff --git a/Source/Project64/main.cpp b/Source/Project64/main.cpp
index 9e3861d04..0f69c8c20 100644
--- a/Source/Project64/main.cpp
+++ b/Source/Project64/main.cpp
@@ -22,7 +22,6 @@ int WINAPI WinMain(HINSTANCE /*hInstance*/, HINSTANCE /*hPrevInstance*/, LPSTR /
g_Debugger = &Debugger;
g_Plugins->SetRenderWindows(&MainWindow, &HiddenWindow);
Notify().SetMainWindow(&MainWindow);
- CSupportWindow SupportWindow;
bool isROMLoaded = false;
if (g_Settings->LoadStringVal(Cmd_RomFile).length() > 0 && g_Settings->LoadStringVal(Cmd_ComboDiskFile).length() > 0)
@@ -64,26 +63,23 @@ int WINAPI WinMain(HINSTANCE /*hInstance*/, HINSTANCE /*hPrevInstance*/, LPSTR /
}
}
- //Handle Main Window if ROM is not loaded and running
if (!isROMLoaded)
{
- SupportWindow.Show(reinterpret_cast(MainWindow.GetWindowHandle()));
+ CSupportWindow(MainWindow.Support()).Show((HWND)MainWindow.GetWindowHandle(), true);
if (UISettingsLoadBool(RomBrowser_Enabled))
{
WriteTrace(TraceUserInterface, TraceDebug, "Show Rom Browser");
- //Display the rom browser
MainWindow.ShowRomList();
- MainWindow.Show(true); //Show the main window
+ MainWindow.Show(true);
MainWindow.HighLightLastRom();
}
else
{
WriteTrace(TraceUserInterface, TraceDebug, "Show Main Window");
- MainWindow.Show(true); //Show the main window
+ MainWindow.Show(true);
}
}
- //Process Messages till program is closed
WriteTrace(TraceUserInterface, TraceDebug, "Entering Message Loop");
MainWindow.ProcessAllMessages();
WriteTrace(TraceUserInterface, TraceDebug, "Message Loop Finished");