1 /*
2 ===========================================================================
3 
4 Doom 3 GPL Source Code
5 Copyright (C) 1999-2011 id Software LLC, a ZeniMax Media company.
6 
7 This file is part of the Doom 3 GPL Source Code ("Doom 3 Source Code").
8 
9 Doom 3 Source Code is free software: you can redistribute it and/or modify
10 it under the terms of the GNU General Public License as published by
11 the Free Software Foundation, either version 3 of the License, or
12 (at your option) any later version.
13 
14 Doom 3 Source Code is distributed in the hope that it will be useful,
15 but WITHOUT ANY WARRANTY; without even the implied warranty of
16 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
17 GNU General Public License for more details.
18 
19 You should have received a copy of the GNU General Public License
20 along with Doom 3 Source Code.  If not, see <http://www.gnu.org/licenses/>.
21 
22 In addition, the Doom 3 Source Code is also subject to certain additional terms. You should have received a copy of these additional terms immediately following the terms and conditions of the GNU General Public License which accompanied the Doom 3 Source Code.  If not, please request a copy in writing from id Software at the address below.
23 
24 If you have questions concerning this license or the applicable additional terms, you may contact in writing id Software LLC, c/o ZeniMax Media Inc., Suite 120, Rockville, Maryland 20850 USA.
25 
26 ===========================================================================
27 */
28 
29 #include "tools/edit_gui_common.h"
30 
31 
32 #include "../../sys/win32/rc/debugger_resource.h"
33 #include "DebuggerApp.h"
34 #include "DebuggerServer.h"
35 
36 DWORD CALLBACK DebuggerThread ( LPVOID param );
37 
38 rvDebuggerApp					gDebuggerApp;
39 HWND							gDebuggerWindow = NULL;
40 bool							gDebuggerSuspend = false;
41 bool							gDebuggerConnnected = false;
42 HANDLE							gDebuggerGameThread = NULL;
43 
44 rvDebuggerServer*				gDebuggerServer			= NULL;
45 HANDLE							gDebuggerServerThread   = NULL;
46 DWORD							gDebuggerServerThreadID = 0;
47 bool							gDebuggerServerQuit     = false;
48 
49 /*
50 ================
51 DebuggerMain
52 
53 Main entry point for the debugger application
54 ================
55 */
DebuggerClientInit(const char * cmdline)56 void DebuggerClientInit( const char *cmdline )
57 {
58 	// See if the debugger is already running
59 	if ( rvDebuggerWindow::Activate ( ) )
60 	{
61 		goto DebuggerClientInitDone;
62 	}
63 
64 	if ( !gDebuggerApp.Initialize ( win32.hInstance ) )
65 	{
66 		goto DebuggerClientInitDone;
67 	}
68 
69 	gDebuggerApp.Run ( );
70 
71 DebuggerClientInitDone:
72 
73 	common->Quit();
74 }
75 
76 /*
77 ================
78 DebuggerLaunch
79 
80 Launches another instance of the running executable with +debugger appended
81 to the end to indicate that the debugger should start up.
82 ================
83 */
DebuggerClientLaunch(void)84 void DebuggerClientLaunch ( void )
85 {
86 	if ( renderSystem->IsFullScreen() ) {
87 		common->Printf( "Cannot run the script debugger in fullscreen mode.\n"
88 					"Set r_fullscreen to 0 and vid_restart.\n" );
89 		return;
90 	}
91 
92 	// See if the debugger is already running
93 	if ( rvDebuggerWindow::Activate ( ) ) {
94 		return;
95 	}
96 
97 	char exeFile[MAX_PATH];
98 	char curDir[MAX_PATH];
99 
100 	STARTUPINFO			startup;
101 	PROCESS_INFORMATION	process;
102 
103 	ZeroMemory ( &startup, sizeof(startup) );
104 	startup.cb = sizeof(startup);
105 
106 	GetCurrentDirectory ( MAX_PATH, curDir );
107 
108 	GetModuleFileName ( NULL, exeFile, MAX_PATH );
109 	const char* s = va("%s +set fs_game %s +set fs_cdpath %s +debugger", exeFile, cvarSystem->GetCVarString( "fs_game" ), cvarSystem->GetCVarString( "fs_cdpath" ) );
110 	CreateProcess ( NULL, (LPSTR)s,
111 					NULL, NULL, FALSE, 0, NULL, curDir, &startup, &process );
112 
113 	CloseHandle ( process.hThread );
114 	CloseHandle ( process.hProcess );
115 }
116 
117 /*
118 ================
119 DebuggerServerThread
120 
121 Thread proc for the debugger server
122 ================
123 */
DebuggerServerThread(LPVOID param)124 DWORD CALLBACK DebuggerServerThread ( LPVOID param )
125 {
126 	assert ( gDebuggerServer );
127 
128 	while ( !gDebuggerServerQuit )
129 	{
130 		gDebuggerServer->ProcessMessages ( );
131 		Sleep ( 1 );
132 	}
133 
134 	return 0;
135 }
136 
137 /*
138 ================
139 DebuggerServerInit
140 
141 Starts up the debugger server
142 ================
143 */
DebuggerServerInit(void)144 bool DebuggerServerInit ( void )
145 {
146 	// Dont do this if we are in the debugger already
147 	if ( com_editors & EDITOR_DEBUGGER )
148 	{
149 		return false;
150 	}
151 
152 	// Allocate the new debugger server
153 	gDebuggerServer = new rvDebuggerServer;
154 	if ( !gDebuggerServer )
155 	{
156 		return false;
157 	}
158 
159 	// Initialize the debugger server
160 	if ( !gDebuggerServer->Initialize ( ) )
161 	{
162 		delete gDebuggerServer;
163 		gDebuggerServer = NULL;
164 		return false;
165 	}
166 
167 	// Start the debugger server thread
168 	gDebuggerServerThread = CreateThread ( NULL, 0, DebuggerServerThread, 0, 0, &gDebuggerServerThreadID );
169 
170 	return true;
171 }
172 
173 /*
174 ================
175 DebuggerServerShutdown
176 
177 Shuts down the debugger server
178 ================
179 */
DebuggerServerShutdown(void)180 void DebuggerServerShutdown ( void )
181 {
182 	if ( gDebuggerServerThread )
183 	{
184 		// Signal the debugger server to quit
185 		gDebuggerServerQuit = true;
186 
187 		// Wait for the thread to finish
188 		WaitForSingleObject ( gDebuggerServerThread, INFINITE );
189 
190 		// Shutdown the server now
191 		gDebuggerServer->Shutdown();
192 
193 		delete gDebuggerServer;
194 		gDebuggerServer = NULL;
195 
196 		// Cleanup the thread handle
197 		CloseHandle ( gDebuggerServerThread );
198 		gDebuggerServerThread = NULL;
199 	}
200 }
201 
202 /*
203 ================
204 DebuggerServerCheckBreakpoint
205 
206 Check to see if there is a breakpoint associtated with this statement
207 ================
208 */
DebuggerServerCheckBreakpoint(idInterpreter * interpreter,idProgram * program,int instructionPointer)209 void DebuggerServerCheckBreakpoint ( idInterpreter* interpreter, idProgram* program, int instructionPointer )
210 {
211 	if ( !gDebuggerServer )
212 	{
213 		return;
214 	}
215 
216 	gDebuggerServer->CheckBreakpoints ( interpreter, program, instructionPointer );
217 }
218 
219 /*
220 ================
221 DebuggerServerPrint
222 
223 Sends a print message to the debugger client
224 ================
225 */
DebuggerServerPrint(const char * text)226 void DebuggerServerPrint ( const char* text )
227 {
228 	if ( !gDebuggerServer )
229 	{
230 		return;
231 	}
232 
233 	gDebuggerServer->Print ( text );
234 }
235