PhysTest.cpp 10 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423
  1. /*
  2. ** Command & Conquer Renegade(tm)
  3. ** Copyright 2025 Electronic Arts Inc.
  4. **
  5. ** This program is free software: you can redistribute it and/or modify
  6. ** it under the terms of the GNU General Public License as published by
  7. ** the Free Software Foundation, either version 3 of the License, or
  8. ** (at your option) any later version.
  9. **
  10. ** This program is distributed in the hope that it will be useful,
  11. ** but WITHOUT ANY WARRANTY; without even the implied warranty of
  12. ** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  13. ** GNU General Public License for more details.
  14. **
  15. ** You should have received a copy of the GNU General Public License
  16. ** along with this program. If not, see <http://www.gnu.org/licenses/>.
  17. */
  18. // PhysTest.cpp : Defines the class behaviors for the application.
  19. //
  20. #include "stdafx.h"
  21. #include "PhysTest.h"
  22. #include "MainFrm.h"
  23. #include "PhysTestDoc.h"
  24. #include "GraphicView.h"
  25. #include "ww3d.h"
  26. #include "assetmgr.h"
  27. #include "refcount.h"
  28. #include "wwdebug.h"
  29. #include "wwphystrig.h"
  30. #include "srRuntimeClass.hpp"
  31. #ifdef _DEBUG
  32. #define new DEBUG_NEW
  33. #undef THIS_FILE
  34. static char THIS_FILE[] = __FILE__;
  35. #endif
  36. const char * LOGFILE_NAME = "_logfile";
  37. const char * LOGFILE_EXTENSION = "txt";
  38. /////////////////////////////////////////////////////////////////////////////
  39. //
  40. // Local prototypes
  41. //
  42. BOOL CALLBACK fnTopLevelWindowSearch (HWND hwnd, LPARAM lParam);
  43. void Debug_Refs(void);
  44. void init_logfile(void);
  45. void write_to_logfile(const char * string);
  46. void wwdebug_message_handler(DebugType type,const char * message);
  47. void wwdebug_assert_handler(const char * message);
  48. bool wwdebug_trigger_handler(int trigger_num);
  49. /////////////////////////////////////////////////////////////////////////////
  50. // CPhysTestApp
  51. BEGIN_MESSAGE_MAP(CPhysTestApp, CWinApp)
  52. //{{AFX_MSG_MAP(CPhysTestApp)
  53. ON_COMMAND(ID_APP_ABOUT, OnAppAbout)
  54. //}}AFX_MSG_MAP
  55. // Standard file based document commands
  56. ON_COMMAND(ID_FILE_NEW, CWinApp::OnFileNew)
  57. ON_COMMAND(ID_FILE_OPEN, CWinApp::OnFileOpen)
  58. END_MESSAGE_MAP()
  59. /////////////////////////////////////////////////////////////////////////////
  60. // CPhysTestApp construction
  61. CPhysTestApp::CPhysTestApp()
  62. {
  63. // TODO: add construction code here,
  64. // Place all significant initialization in InitInstance
  65. }
  66. /////////////////////////////////////////////////////////////////////////////
  67. // The one and only CPhysTestApp object
  68. CPhysTestApp theApp;
  69. /////////////////////////////////////////////////////////////////////////////
  70. // CAboutDlg dialog used for App About
  71. class CAboutDlg : public CDialog
  72. {
  73. public:
  74. CAboutDlg();
  75. // Dialog Data
  76. //{{AFX_DATA(CAboutDlg)
  77. enum { IDD = IDD_ABOUTBOX };
  78. //}}AFX_DATA
  79. // ClassWizard generated virtual function overrides
  80. //{{AFX_VIRTUAL(CAboutDlg)
  81. protected:
  82. virtual void DoDataExchange(CDataExchange* pDX); // DDX/DDV support
  83. //}}AFX_VIRTUAL
  84. // Implementation
  85. protected:
  86. //{{AFX_MSG(CAboutDlg)
  87. virtual BOOL OnInitDialog();
  88. //}}AFX_MSG
  89. DECLARE_MESSAGE_MAP()
  90. };
  91. CAboutDlg::CAboutDlg() : CDialog(CAboutDlg::IDD)
  92. {
  93. //{{AFX_DATA_INIT(CAboutDlg)
  94. //}}AFX_DATA_INIT
  95. }
  96. void CAboutDlg::DoDataExchange(CDataExchange* pDX)
  97. {
  98. CDialog::DoDataExchange(pDX);
  99. //{{AFX_DATA_MAP(CAboutDlg)
  100. //}}AFX_DATA_MAP
  101. }
  102. BEGIN_MESSAGE_MAP(CAboutDlg, CDialog)
  103. //{{AFX_MSG_MAP(CAboutDlg)
  104. //}}AFX_MSG_MAP
  105. END_MESSAGE_MAP()
  106. BOOL CAboutDlg::OnInitDialog()
  107. {
  108. CDialog::OnInitDialog();
  109. // TODO: Add extra initialization here
  110. return TRUE; // return TRUE unless you set the focus to a control
  111. // EXCEPTION: OCX Property Pages should return FALSE
  112. }
  113. // App command to run the dialog
  114. void CPhysTestApp::OnAppAbout()
  115. {
  116. CAboutDlg aboutDlg;
  117. aboutDlg.DoModal();
  118. }
  119. /////////////////////////////////////////////////////////////////////////////
  120. // CPhysTestApp initialization
  121. BOOL CPhysTestApp::InitInstance()
  122. {
  123. AfxEnableControlContainer();
  124. // Standard initialization
  125. // If you are not using these features and wish to reduce the size
  126. // of your final executable, you should remove from the following
  127. // the specific initialization routines you do not need.
  128. #ifdef _AFXDLL
  129. Enable3dControls(); // Call this when using MFC in a shared DLL
  130. #else
  131. Enable3dControlsStatic(); // Call this when linking to MFC statically
  132. #endif
  133. // Is there already an instance of the viewer running?
  134. HWND hprev_instance = NULL;
  135. ::EnumWindows (fnTopLevelWindowSearch, (LPARAM)&hprev_instance);
  136. if (hprev_instance == NULL) {
  137. // Change the registry key under which our settings are stored.
  138. // You should modify this string to be something appropriate
  139. // such as the name of your company or organization.
  140. SetRegistryKey(_T("Westwood Studios"));
  141. LoadStdProfileSettings(); // Load standard INI file options (including MRU)
  142. // Register the application's document templates. Document templates
  143. // serve as the connection between documents, frame windows and views.
  144. CSingleDocTemplate* pDocTemplate;
  145. pDocTemplate = new CSingleDocTemplate(
  146. IDR_MAINFRAME,
  147. RUNTIME_CLASS(CPhysTestDoc),
  148. RUNTIME_CLASS(CMainFrame), // main SDI frame window
  149. RUNTIME_CLASS(CGraphicView));
  150. AddDocTemplate(pDocTemplate);
  151. // Parse command line for standard shell commands, DDE, file open
  152. CCommandLineInfo cmdInfo;
  153. ParseCommandLine(cmdInfo);
  154. // Dispatch commands specified on the command line
  155. if (!ProcessShellCommand(cmdInfo))
  156. return FALSE;
  157. // The one and only window has been initialized, so show and update it.
  158. m_pMainWnd->ShowWindow(SW_SHOW);
  159. m_pMainWnd->UpdateWindow();
  160. } else {
  161. // Make the previous instance in the foreground
  162. ::ShowWindow (hprev_instance, SW_NORMAL);
  163. ::BringWindowToTop (hprev_instance);
  164. ::SetForegroundWindow (hprev_instance);
  165. }
  166. // Create the log file
  167. init_logfile();
  168. // Install message handler functions for the WWDebug messages
  169. // and assertion failures.
  170. WWDebug_Install_Message_Handler(wwdebug_message_handler);
  171. WWDebug_Install_Assert_Handler(wwdebug_assert_handler);
  172. //WWDebug_Install_Trigger_Handler(wwdebug_trigger_handler);
  173. WWDEBUG_SAY(("Logging Begin:\r\n"));
  174. return (hprev_instance == NULL);
  175. }
  176. /////////////////////////////////////////////////////////////////////////////
  177. // CPhysTestApp message handlers
  178. int CPhysTestApp::ExitInstance()
  179. {
  180. // Free any resources the WW3D engine allocated
  181. WW3DAssetManager::Get_Instance()->Free_Assets();
  182. if (WW3D::Is_Initted()) {
  183. WW3D::Shutdown();
  184. }
  185. // Remove message handler functions for the WWDebug messages
  186. // and assertion failures.
  187. WWDebug_Install_Message_Handler(NULL);
  188. WWDebug_Install_Assert_Handler(NULL);
  189. //WWDebug_Install_Trigger_Handler(NULL);
  190. // Check Active Refs
  191. Debug_Refs();
  192. return CWinApp::ExitInstance();
  193. }
  194. //////////////////////////////////////////////////////////////////////////////
  195. //
  196. // fnTopLevelWindowSearch
  197. //
  198. BOOL CALLBACK
  199. fnTopLevelWindowSearch
  200. (
  201. HWND hwnd,
  202. LPARAM lParam
  203. )
  204. {
  205. BOOL bcontinue = TRUE;
  206. // Is this a viewer window?
  207. if (::GetProp (hwnd, "WW3DVIEWER") != 0) {
  208. bcontinue = false;
  209. (*((HWND *)lParam)) = hwnd;
  210. }
  211. // Return the TRUE/FALSE result code
  212. return bcontinue;
  213. }
  214. //////////////////////////////////////////////////////////////////////////////
  215. //
  216. // Debug_Refs()
  217. //
  218. void Debug_Refs(void)
  219. {
  220. #ifndef NDEBUG
  221. RefBaseNodeClass * first = RefBaseClass::ActiveRefList.First();
  222. RefBaseNodeClass * node = first;
  223. while (node->Is_Valid())
  224. {
  225. RefBaseClass * obj = node->Get();
  226. ActiveRefStruct * ref = &(obj->ActiveRefInfo);
  227. bool display = true;
  228. int count = 0;
  229. RefBaseNodeClass * search = first;
  230. while (search->Is_Valid()) {
  231. if (search == node) { // if this is not the first one
  232. if (count != 0) {
  233. display = false;
  234. break;
  235. }
  236. }
  237. RefBaseClass * search_obj = search->Get();
  238. ActiveRefStruct * search_ref = &(search_obj->ActiveRefInfo);
  239. if ( ref->File && search_ref->File &&
  240. !strcmp(search_ref->File, ref->File) &&
  241. (search_ref->Line == ref->Line) ) {
  242. count++;
  243. } else if ( (ref->File == NULL) && (search_ref->File == NULL) ) {
  244. count++;
  245. }
  246. search = search->Next();
  247. }
  248. if ( display ) {
  249. char buf[256];
  250. sprintf(buf,"%d Active Ref: %s %d %p\n",count, ref->File,ref->Line,obj);
  251. ::MessageBox(NULL,buf,"Unreleased Object!",MB_OK);
  252. static int num_printed = 0;
  253. if (++num_printed > 20) {
  254. ::MessageBox(NULL,"And Many More......\n",NULL,MB_OK);
  255. break;
  256. }
  257. }
  258. node = node->Next();
  259. }
  260. #endif
  261. }
  262. //////////////////////////////////////////////////////////////////////////////
  263. //
  264. // get_log_filename
  265. //
  266. const char * get_log_filename(void)
  267. {
  268. static char log_name[_MAX_PATH];
  269. char exe_name[_MAX_PATH];
  270. ::GetModuleFileName(::AfxGetInstanceHandle(),exe_name,sizeof(exe_name));
  271. char drive[_MAX_DRIVE];
  272. char dir[_MAX_DIR];
  273. _splitpath(exe_name,drive,dir,NULL,NULL);
  274. _makepath(log_name,drive,dir,LOGFILE_NAME,LOGFILE_EXTENSION);
  275. return log_name;
  276. }
  277. //////////////////////////////////////////////////////////////////////////////
  278. //
  279. // init_logfile
  280. //
  281. void init_logfile(void)
  282. {
  283. // Destroy contents
  284. FILE * file = fopen(get_log_filename(), "w");
  285. fclose(file);
  286. }
  287. //////////////////////////////////////////////////////////////////////////////
  288. //
  289. // write_to_logfile
  290. //
  291. void write_to_logfile(const char * string)
  292. {
  293. // open/close for each write so as to maximize integrity of this file.
  294. FILE * file = fopen(get_log_filename(), "a");
  295. if (file != NULL) {
  296. fwrite(string, 1, strlen(string), file);
  297. fclose(file);
  298. }
  299. }
  300. //////////////////////////////////////////////////////////////////////////////
  301. //
  302. // wwdebug_message_handler
  303. //
  304. void wwdebug_message_handler(DebugType type,const char * message)
  305. {
  306. /*
  307. ** dump the message into our log file
  308. */
  309. write_to_logfile(message);
  310. }
  311. //////////////////////////////////////////////////////////////////////////////
  312. //
  313. // wwdebug assert handler
  314. //
  315. void wwdebug_assert_handler(const char * message)
  316. {
  317. /*
  318. ** dump the assert into our log file
  319. */
  320. write_to_logfile(message);
  321. /*
  322. ** break into the debugger
  323. */
  324. _asm int 0x03;
  325. }
  326. //////////////////////////////////////////////////////////////////////////////
  327. //
  328. // wwdebug trigger handler
  329. // Disables VIS!
  330. //
  331. bool wwdebug_trigger_handler(int trigger_num)
  332. {
  333. switch( trigger_num )
  334. {
  335. case WWPHYS_TRIGGER_DISABLE_VIS: return true;
  336. }
  337. return false;
  338. }