OSDN Git Service

[VM][General] Merge Upstream 20180530.
[csp-qt/common_source_project-fm7.git] / source / src / debugger.cpp
1 /*
2         Skelton for retropc emulator
3
4         Author : Takeda.Toshiya
5         Date   : 2006.08.18 -
6
7         [ debugger console ]
8 */
9
10 #if !defined(_MSC_VER)
11 #include <SDL.h>
12 #endif
13 #include <stdlib.h>
14 #include <io.h>
15 #include <fcntl.h>
16 #include "vm/device.h"
17 #include "vm/debugger.h"
18 #include "vm/vm.h"
19 #include "fileio.h"
20 #include <pthread.h>
21
22 #ifdef USE_DEBUGGER
23
24 #ifndef FOREGROUND_BLUE
25 #define FOREGROUND_BLUE      0x0001 // text color contains blue.
26 #endif
27 #ifndef FOREGROUND_GREEN
28 #define FOREGROUND_GREEN     0x0002 // text color contains green.
29 #endif
30 #ifndef FOREGROUND_RED
31 #define FOREGROUND_RED       0x0004 // text color contains red.
32 #endif
33 #ifndef FOREGROUND_INTENSITY
34 #define FOREGROUND_INTENSITY 0x0008 // text color is intensified.
35 #endif
36
37 static FILEIO* logfile = NULL;
38 static FILEIO* cmdfile = NULL;
39
40 const _TCHAR *my_absolute_path(const _TCHAR *file_name)
41 {
42         static _TCHAR file_path[_MAX_PATH];
43         
44         if(is_absolute_path(file_name)) {
45                 my_tcscpy_s(file_path, _MAX_PATH, file_name);
46         } else {
47                 my_stprintf_s(file_path, _MAX_PATH, _T("%s%s"), get_initial_current_path(), file_name);
48         }
49         return (const _TCHAR *)file_path;
50 }
51
52 void my_printf(OSD *osd, const _TCHAR *format, ...)
53 {
54         _TCHAR buffer[1024];
55         va_list ap;
56         
57         va_start(ap, format);
58         my_vstprintf_s(buffer, 1024, format, ap);
59         va_end(ap);
60         
61         if(logfile != NULL && logfile->IsOpened()) {
62                 logfile->Fwrite(buffer, _tcslen(buffer) * sizeof(_TCHAR), 1);
63         }
64         osd->write_console(buffer, _tcslen(buffer));
65 }
66
67 void my_putch(OSD *osd, _TCHAR c)
68 {
69         if(logfile != NULL && logfile->IsOpened()) {
70                 logfile->Fwrite(&c, sizeof(_TCHAR), 1);
71         }
72         osd->write_console(&c, 1);
73 }
74
75 uint32_t my_hexatoi(DEVICE *target, const _TCHAR *str)
76 {
77         _TCHAR tmp[1024], *s;
78         symbol_t *first_symbol = NULL;
79         
80         if(str == NULL || _tcslen(str) == 0) {
81                 return 0;
82         }
83         my_tcscpy_s(tmp, 1024, str);
84         
85         if(target) {
86                 DEBUGGER *debugger = (DEBUGGER *)target->get_debugger();
87                 if(debugger) {
88                         first_symbol = debugger->first_symbol;
89                 }
90         }
91         for(symbol_t* symbol = first_symbol; symbol; symbol = symbol->next_symbol) {
92                 if(_tcsicmp(symbol->name, str) == 0) {
93                         return symbol->addr;
94                 }
95         }
96         if(_tcslen(tmp) == 3 && tmp[0] == _T('\'') && tmp[2] == _T('\'')) {
97                 // ank
98                 return tmp[1] & 0xff;
99         } else if((s = _tcsstr(tmp, _T(":"))) != NULL) {
100                 // 0000:0000
101                 s[0] = _T('\0');
102                 return (my_hexatoi(target, tmp) << 4) + my_hexatoi(target, s + 1);
103         } else if(tmp[0] == _T('%')) {
104                 // decimal
105 #if defined(__MINGW32__)
106                 return atoi(tmp + 1);
107 #else
108                 return _tstoi(tmp + 1);
109 #endif
110         }
111         return _tcstoul(tmp, NULL, 16);
112 }
113
114 uint8_t my_hexatob(char *value)
115 {
116         char tmp[3];
117         tmp[0] = value[0];
118         tmp[1] = value[1];
119         tmp[2] = '\0';
120         return (uint8_t)strtoul(tmp, NULL, 16);
121 }
122
123 uint16_t my_hexatow(char *value)
124 {
125         char tmp[5];
126         tmp[0] = value[0];
127         tmp[1] = value[1];
128         tmp[2] = value[2];
129         tmp[3] = value[3];
130         tmp[4] = '\0';
131         return (uint16_t)strtoul(tmp, NULL, 16);
132 }
133
134 const _TCHAR *my_get_symbol(DEVICE *target, uint32_t addr)
135 {
136         symbol_t *first_symbol = NULL;
137         
138         if(target) {
139                 DEBUGGER *debugger = (DEBUGGER *)target->get_debugger();
140                 if(debugger) {
141                         first_symbol = debugger->first_symbol;
142                 }
143         }
144         return get_symbol(first_symbol, addr);
145 }
146
147 const _TCHAR *my_get_value_or_symbol(DEVICE *target, const _TCHAR *format, uint32_t addr)
148 {
149         symbol_t *first_symbol = NULL;
150         
151         if(target) {
152                 DEBUGGER *debugger = (DEBUGGER *)target->get_debugger();
153                 if(debugger) {
154                         first_symbol = debugger->first_symbol;
155                 }
156         }
157         return get_value_or_symbol(first_symbol, format, addr);
158 }
159
160 const _TCHAR *my_get_value_and_symbol(DEVICE *target, const _TCHAR *format, uint32_t addr)
161 {
162         symbol_t *first_symbol = NULL;
163         
164         if(target) {
165                 DEBUGGER *debugger = (DEBUGGER *)target->get_debugger();
166                 if(debugger) {
167                         first_symbol = debugger->first_symbol;
168                 }
169         }
170         return get_value_and_symbol(first_symbol, format, addr);
171 }
172
173 break_point_t *get_break_point(DEBUGGER *debugger, const _TCHAR *command)
174 {
175         if(command[0] == _T('B') || command[0] == _T('b') || command[0] == _T('C') || command[0] == _T('c')) {
176                 return &debugger->bp;
177         } else if(command[0] == _T('R') || command[0] == _T('r')) {
178                 return &debugger->rbp;
179         } else if(command[0] == _T('W') || command[0] == _T('w')) {
180                 return &debugger->wbp;
181         } else if(command[0] == _T('I') || command[0] == _T('i')) {
182                 return &debugger->ibp;
183         } else if(command[0] == _T('O') || command[0] == _T('o')) {
184                 return &debugger->obp;
185         }
186         return NULL;
187 }
188 #ifdef _MSC_VER
189 unsigned __stdcall debugger_thread(void *lpx)
190 #else
191 void* debugger_thread(void *lpx)
192 #endif
193 {
194         volatile debugger_thread_t *p = (debugger_thread_t *)lpx;
195         p->running = true;
196         
197         // initialize console
198         _TCHAR buffer[1024];
199         bool cp932 = (p->osd->get_console_code_page() == 932);
200         
201         p->osd->open_console((_TCHAR *)create_string(_T("Debugger - %s"), _T(DEVICE_NAME)));
202         
203         // break cpu
204         DEVICE *cpu = p->vm->get_cpu(p->cpu_index);
205         DEBUGGER *debugger = (DEBUGGER *)cpu->get_debugger();
206         DEVICE *target = cpu;
207         DEBUGGER *target_debugger = debugger;
208         
209         debugger->now_going = false;
210         debugger->now_debugging = true;
211         int wait_count = 0;
212         while(!p->request_terminate && !(debugger->now_suspended && debugger->now_waiting)) {
213                 if((wait_count++) == 100) {
214                         p->osd->set_console_text_attribute(FOREGROUND_RED | FOREGROUND_INTENSITY);
215                         my_printf(p->osd, _T("waiting until cpu is suspended...\n"));
216                 }
217                 p->osd->sleep(10);
218         }
219         
220         uint32_t dump_addr = 0;
221         uint32_t dasm_addr = cpu->get_next_pc();
222         
223         p->osd->set_console_text_attribute(FOREGROUND_RED | FOREGROUND_GREEN | FOREGROUND_BLUE | FOREGROUND_INTENSITY);
224         cpu->get_debug_regs_info(buffer, 1024);
225         my_printf(p->osd, _T("%s\n"), buffer);
226         
227         p->osd->set_console_text_attribute(FOREGROUND_RED | FOREGROUND_INTENSITY);
228         my_printf(p->osd, _T("breaked at %s\n"), my_get_value_and_symbol(cpu, _T("%08X"), cpu->get_next_pc()));
229         
230         p->osd->set_console_text_attribute(FOREGROUND_GREEN | FOREGROUND_BLUE | FOREGROUND_INTENSITY);
231         cpu->debug_dasm(cpu->get_next_pc(), buffer, 1024);
232         my_printf(p->osd, _T("next\t%s  %s\n"), my_get_value_and_symbol(cpu, _T("%08X"), cpu->get_next_pc()), buffer);
233         p->osd->set_console_text_attribute(FOREGROUND_RED | FOREGROUND_GREEN | FOREGROUND_BLUE | FOREGROUND_INTENSITY);
234         
235         // initialize files
236         logfile = NULL;
237         cmdfile = NULL;
238         
239         _TCHAR command[MAX_COMMAND_LENGTH + 1];
240         _TCHAR prev_command[MAX_COMMAND_LENGTH + 1];
241         
242         memset(prev_command, 0, sizeof(prev_command));
243         
244         while(!p->request_terminate) {
245                 my_printf(p->osd, _T("- "));
246                 
247                 // get command
248                 _TCHAR ir[16 + 2];
249                 int enter_ptr = 0;
250                 int history_ptr = 0;
251                 bool enter_done = false;
252                 
253                 while(!p->request_terminate && !enter_done) {
254                         if(cmdfile != NULL && cmdfile->IsOpened()) {
255                                 if(cmdfile->Fgetts(command, array_length(command)) != NULL) {
256                                         while(_tcslen(command) > 0 && (command[_tcslen(command) - 1] == 0x0d || command[_tcslen(command) - 1] == 0x0a)) {
257                                                 command[_tcslen(command) - 1] = _T('\0');
258                                         }
259                                         if(_tcslen(command) > 0) {
260                                                 my_printf(p->osd, _T("%s\n"), command);
261                                                 enter_done = true;
262                                         }
263                                 } else {
264                                         cmdfile->Fclose();
265                                         delete cmdfile;
266                                         cmdfile = NULL;
267                                 }
268                         } else {
269                                 memset(ir, 0, sizeof(ir));
270                                 int count = p->osd->read_console_input(ir, 16);
271                                 
272                                 for(int i = 0; i < count; i++) {
273                                         if(ir[i] == 0x08) {
274                                                 if(enter_ptr > 0) {
275                                                         enter_ptr--;
276                                                         my_putch(p->osd, 0x08);
277                                                         my_putch(p->osd, _T(' '));
278                                                         my_putch(p->osd, 0x08);
279                                                 }
280                                         } else if(ir[i] == 0x0d || ir[i] == 0x0a) {
281                                                 if(enter_ptr == 0 && prev_command[0] != _T('\0')) {
282                                                         memcpy(command, prev_command, sizeof(command));
283                                                         my_printf(p->osd, _T("%s\n"), command);
284                                                         enter_done = true;
285                                                         break;
286                                                 } else if(enter_ptr > 0) {
287                                                         command[enter_ptr] = _T('\0');
288                                                         memcpy(prev_command, command, sizeof(command));
289                                                         memcpy(debugger->history[debugger->history_ptr], command, sizeof(command));
290                                                         if (++debugger->history_ptr >= MAX_COMMAND_HISTORY) {
291                                                                 debugger->history_ptr = 0;
292                                                         }
293                                                         my_printf(p->osd, _T("\n"));
294                                                         enter_done = true;
295                                                         break;
296                                                 }
297                                         } else if(ir[i] == 0x1b && ir[i + 1] == 0x5b) {
298                                                 if(ir[i + 2] == _T('A') || ir[i + 2] == _T('B')) {
299                                                         int history_ptr_stored = history_ptr;
300                                                         if(ir[i + 2] == _T('A')) {
301                                                                 if(++history_ptr >= MAX_COMMAND_HISTORY) {
302                                                                         history_ptr = MAX_COMMAND_HISTORY;
303                                                                 }
304                                                         } else {
305                                                                 if(--history_ptr < 0) {
306                                                                         history_ptr = 0;
307                                                                 }
308                                                         }
309                                                         int index = debugger->history_ptr - history_ptr;
310                                                         while(index < 0) {
311                                                                 index += MAX_COMMAND_HISTORY;
312                                                         }
313                                                         while(index >= MAX_COMMAND_HISTORY) {
314                                                                 index -= MAX_COMMAND_HISTORY;
315                                                         }
316                                                         if(debugger->history[index][0] != _T('\0')) {
317                                                                 for(int i = 0; i < enter_ptr; i++) {
318                                                                         my_putch(p->osd, 0x08);
319                                                                         my_putch(p->osd, _T(' '));
320                                                                         my_putch(p->osd, 0x08);
321                                                                 }
322                                                                 memcpy(command, debugger->history[index], sizeof(command));
323                                                                 my_printf(p->osd, _T("%s"), command);
324                                                                 enter_ptr = _tcslen(command);
325                                                         } else {
326                                                                 history_ptr = history_ptr_stored;
327                                                         }
328                                                 }
329                                                 i += 2; // skip 2 characters
330                                         } else if(ir[i] >= 0x20 && ir[i] <= 0x7e && enter_ptr < MAX_COMMAND_LENGTH && !(ir[i] == 0x20 && enter_ptr == 0)) {
331                                                 command[enter_ptr++] = ir[i];
332                                                 my_putch(p->osd, ir[i]);
333                                         }
334                                 }
335                                 p->osd->sleep(10);
336                         }
337                 }
338                 
339                 // process command
340                 if(!p->request_terminate && enter_done) {
341                         _TCHAR *params[32], *token = NULL, *context = NULL;
342                         int num = 0;
343                         
344                         if((token = my_tcstok_s(command, _T(" "), &context)) != NULL) {
345                                 params[num++] = token;
346                                 while(num < 32 && (token = my_tcstok_s(NULL, _T(" "), &context)) != NULL) {
347                                         params[num++] = token;
348                                 }
349                         }
350                         if(_tcsicmp(params[0], _T("D")) == 0) {
351                                 if(num <= 3) {
352                                         uint32_t start_addr = dump_addr;
353                                         if(num >= 2) {
354                                                 start_addr = my_hexatoi(target, params[1]);
355                                         }
356                                         start_addr &= target->get_debug_data_addr_mask();
357                                         
358                                         uint32_t end_addr = start_addr + 8 * 16 - 1;
359                                         if(num == 3) {
360                                                 end_addr = my_hexatoi(target, params[2]);
361                                         }
362                                         end_addr &= target->get_debug_data_addr_mask();
363                                         
364                                         if(start_addr > end_addr) {
365                                                 end_addr = target->get_debug_data_addr_mask();
366                                         }
367                                         for(uint64_t addr = start_addr & ~0x0f; addr <= end_addr; addr++) {
368                                                 if(addr > target->get_debug_data_addr_mask()) {
369                                                         end_addr = target->get_debug_data_addr_mask();
370                                                         break;
371                                                 }
372                                                 if((addr & 0x0f) == 0) {
373                                                         my_printf(p->osd, _T("%08X "), addr & target->get_debug_data_addr_mask());
374                                                         memset(buffer, 0, sizeof(buffer));
375                                                 }
376                                                 if(addr < start_addr) {
377                                                         my_printf(p->osd, _T("   "));
378                                                         buffer[addr & 0x0f] = _T(' ');
379                                                 } else {
380                                                         uint32_t data = target->read_debug_data8(addr & target->get_debug_data_addr_mask());
381                                                         my_printf(p->osd, _T(" %02X"), data);
382                                                         buffer[addr & 0x0f] = ((data >= 0x20 && data <= 0x7e) || (cp932 && data >= 0xa1 && data <= 0xdf)) ? data : _T('.');
383                                                 }
384                                                 if((addr & 0x0f) == 0x0f) {
385                                                         my_printf(p->osd, _T("  %s\n"), buffer);
386                                                 }
387                                         }
388                                         if((end_addr & 0x0f) != 0x0f) {
389                                                 for(uint32_t addr = (end_addr & 0x0f) + 1; addr <= 0x0f; addr++) {
390                                                         my_printf(p->osd, _T("   "));
391                                                 }
392                                                 my_printf(p->osd, _T("  %s\n"), buffer);
393                                         }
394                                         dump_addr = (end_addr + 1) & target->get_debug_data_addr_mask();
395                                         prev_command[1] = _T('\0'); // remove parameters to dump continuously
396                                 } else {
397                                         my_printf(p->osd, _T("invalid parameter number\n"));
398                                 }
399                         } else if(_tcsicmp(params[0], _T("E")) == 0 || _tcsicmp(params[0], _T("EB")) == 0) {
400                                 if(num >= 3) {
401                                         uint32_t addr = my_hexatoi(target, params[1]) & target->get_debug_data_addr_mask();
402                                         for(int i = 2; i < num; i++) {
403                                                 target->write_debug_data8(addr, my_hexatoi(target, params[i]) & 0xff);
404                                                 addr = (addr + 1) & target->get_debug_data_addr_mask();
405                                         }
406                                 } else {
407                                         my_printf(p->osd, _T("invalid parameter number\n"));
408                                 }
409                         } else if(_tcsicmp(params[0], _T("EW")) == 0) {
410                                 if(num >= 3) {
411                                         uint32_t addr = my_hexatoi(target, params[1]) & target->get_debug_data_addr_mask();
412                                         for(int i = 2; i < num; i++) {
413                                                 target->write_debug_data16(addr, my_hexatoi(target, params[i]) & 0xffff);
414                                                 addr = (addr + 2) & target->get_debug_data_addr_mask();
415                                         }
416                                 } else {
417                                         my_printf(p->osd, _T("invalid parameter number\n"));
418                                 }
419                         } else if(_tcsicmp(params[0], _T("ED")) == 0) {
420                                 if(num >= 3) {
421                                         uint32_t addr = my_hexatoi(target, params[1]) & target->get_debug_data_addr_mask();
422                                         for(int i = 2; i < num; i++) {
423                                                 target->write_debug_data32(addr, my_hexatoi(target, params[i]));
424                                                 addr = (addr + 4) & target->get_debug_data_addr_mask();
425                                         }
426                                 } else {
427                                         my_printf(p->osd, _T("invalid parameter number\n"));
428                                 }
429                         } else if(_tcsicmp(params[0], _T("EA")) == 0) {
430                                 if(num >= 3) {
431                                         uint32_t addr = my_hexatoi(target, params[1]) & target->get_debug_data_addr_mask();
432                                         my_tcscpy_s(buffer, 1024, prev_command);
433                                         if((token = my_tcstok_s(buffer, _T("\""), &context)) != NULL && (token = my_tcstok_s(NULL, _T("\""), &context)) != NULL) {
434                                                 int len = _tcslen(token);
435                                                 for(int i = 0; i < len; i++) {
436                                                         target->write_debug_data8(addr, token[i] & 0xff);
437                                                         addr = (addr + 1) & target->get_debug_data_addr_mask();
438                                                 }
439                                         } else {
440                                                 my_printf(p->osd, _T("invalid parameter\n"));
441                                         }
442                                 } else {
443                                         my_printf(p->osd, _T("invalid parameter number\n"));
444                                 }
445                         } else if(_tcsicmp(params[0], _T("I")) == 0 || _tcsicmp(params[0], _T("IB")) == 0) {
446                                 if(num == 2) {
447                                         my_printf(p->osd, _T("%02X\n"), target->read_debug_io8(my_hexatoi(target, params[1])) & 0xff);
448                                 } else {
449                                         my_printf(p->osd, _T("invalid parameter number\n"));
450                                 }
451                         } else if(_tcsicmp(params[0], _T("IW")) == 0) {
452                                 if(num == 2) {
453                                         my_printf(p->osd, _T("%02X\n"), target->read_debug_io16(my_hexatoi(target, params[1])) & 0xffff);
454                                 } else {
455                                         my_printf(p->osd, _T("invalid parameter number\n"));
456                                 }
457                         } else if(_tcsicmp(params[0], _T("ID")) == 0) {
458                                 if(num == 2) {
459                                         my_printf(p->osd, _T("%02X\n"), target->read_debug_io32(my_hexatoi(target, params[1])));
460                                 } else {
461                                         my_printf(p->osd, _T("invalid parameter number\n"));
462                                 }
463                         } else if(_tcsicmp(params[0], _T("O")) == 0 || _tcsicmp(params[0], _T("OB")) == 0) {
464                                 if(num == 3) {
465                                         target->write_debug_io8(my_hexatoi(target, params[1]), my_hexatoi(target, params[2]) & 0xff);
466                                 } else {
467                                         my_printf(p->osd, _T("invalid parameter number\n"));
468                                 }
469                         } else if(_tcsicmp(params[0], _T("OW")) == 0) {
470                                 if(num == 3) {
471                                         target->write_debug_io16(my_hexatoi(target, params[1]), my_hexatoi(target, params[2]) & 0xffff);
472                                 } else {
473                                         my_printf(p->osd, _T("invalid parameter number\n"));
474                                 }
475                         } else if(_tcsicmp(params[0], _T("OD")) == 0) {
476                                 if(num == 3) {
477                                         target->write_debug_io32(my_hexatoi(target, params[1]), my_hexatoi(target, params[2]));
478                                 } else {
479                                         my_printf(p->osd, _T("invalid parameter number\n"));
480                                 }
481                         } else if(_tcsicmp(params[0], _T("R")) == 0) {
482                                 if(num == 1) {
483                                         target->get_debug_regs_info(buffer, 1024);
484                                         my_printf(p->osd, _T("%s\n"), buffer);
485                                 } else if(num == 3) {
486                                         if(!target->write_debug_reg(params[1], my_hexatoi(target, params[2]))) {
487                                                 my_printf(p->osd, _T("unknown register %s\n"), params[1]);
488                                         }
489                                 } else {
490                                         my_printf(p->osd, _T("invalid parameter number\n"));
491                                 }
492                         } else if(_tcsicmp(params[0], _T("S")) == 0) {
493                                 if(num >= 4) {
494                                         uint32_t start_addr = my_hexatoi(target, params[1]) & target->get_debug_data_addr_mask();
495                                         uint32_t end_addr = my_hexatoi(target, params[2]) & target->get_debug_data_addr_mask();
496                                         uint8_t list[32];
497                                         for(int i = 3, j = 0; i < num; i++, j++) {
498                                                 list[j] = my_hexatoi(target, params[i]);
499                                         }
500                                         for(uint64_t addr = start_addr; addr <= end_addr; addr++) {
501                                                 bool found = true;
502                                                 for(int i = 3, j = 0; i < num; i++, j++) {
503                                                         if(target->read_debug_data8((uint32_t)((addr + j) & target->get_debug_data_addr_mask())) != list[j]) {
504                                                                 found = false;
505                                                                 break;
506                                                         }
507                                                 }
508                                                 if(found) {
509                                                         my_printf(p->osd, _T("%s\n"), my_get_value_and_symbol(target, _T("%08X"), (uint32_t)addr));
510                                                 }
511                                         }
512                                 } else {
513                                         my_printf(p->osd, _T("invalid parameter number\n"));
514                                 }
515                         } else if(_tcsicmp(params[0], _T("U")) == 0) {
516                                 if(num <= 3) {
517                                         if(num >= 2) {
518                                                 dasm_addr = my_hexatoi(target, params[1]) & target->get_debug_prog_addr_mask();
519                                         }
520                                         if(num == 3) {
521                                                 uint32_t end_addr = my_hexatoi(target, params[2]) & target->get_debug_prog_addr_mask();
522                                                 while(dasm_addr <= end_addr) {
523                                                         const _TCHAR *name = my_get_symbol(target, dasm_addr & target->get_debug_prog_addr_mask());
524                                                         int len = target->debug_dasm(dasm_addr & target->get_debug_prog_addr_mask(), buffer, 1024);
525                                                         if(name != NULL) {
526                                                                 my_printf(p->osd, _T("%08X                  "), dasm_addr & target->get_debug_prog_addr_mask());
527                                                                 p->osd->set_console_text_attribute(FOREGROUND_GREEN | FOREGROUND_INTENSITY);
528                                                                 my_printf(p->osd, _T("%s:\n"), name);
529                                                                 p->osd->set_console_text_attribute(FOREGROUND_RED | FOREGROUND_GREEN | FOREGROUND_BLUE | FOREGROUND_INTENSITY);
530                                                         }
531                                                         my_printf(p->osd, _T("%08X  "), dasm_addr & target->get_debug_prog_addr_mask());
532                                                         for(int i = 0; i < len; i++) {
533                                                                 my_printf(p->osd, _T("%02X"), target->read_debug_data8((dasm_addr + i) & target->get_debug_prog_addr_mask()));
534                                                         }
535                                                         for(int i = len; i < 8; i++) {
536                                                                 my_printf(p->osd, _T("  "));
537                                                         }
538                                                         my_printf(p->osd, _T("  %s\n"), buffer);
539                                                         dasm_addr += len;
540                                                 }
541                                         } else {
542                                                 for(int i = 0; i < 16; i++) {
543                                                         const _TCHAR *name = my_get_symbol(target, dasm_addr & target->get_debug_prog_addr_mask());
544                                                         int len = target->debug_dasm(dasm_addr & target->get_debug_prog_addr_mask(), buffer, 1024);
545                                                         if(name != NULL) {
546                                                                 my_printf(p->osd, _T("%08X                  "), dasm_addr & target->get_debug_prog_addr_mask());
547                                                                 p->osd->set_console_text_attribute(FOREGROUND_GREEN | FOREGROUND_INTENSITY);
548                                                                 my_printf(p->osd, _T("%s:\n"), name);
549                                                                 p->osd->set_console_text_attribute(FOREGROUND_RED | FOREGROUND_GREEN | FOREGROUND_BLUE | FOREGROUND_INTENSITY);
550                                                         }
551                                                         my_printf(p->osd, _T("%08X  "), dasm_addr & target->get_debug_prog_addr_mask());
552                                                         for(int i = 0; i < len; i++) {
553                                                                 my_printf(p->osd, _T("%02X"), target->read_debug_data8((dasm_addr + i) & target->get_debug_prog_addr_mask()));
554                                                         }
555                                                         for(int i = len; i < 8; i++) {
556                                                                 my_printf(p->osd, _T("  "));
557                                                         }
558                                                         my_printf(p->osd, _T("  %s\n"), buffer);
559                                                         dasm_addr += len;
560                                                 }
561                                         }
562                                         prev_command[1] = _T('\0'); // remove parameters to disassemble continuously
563                                 } else {
564                                         my_printf(p->osd, _T("invalid parameter number\n"));
565                                 }
566                         } else if(_tcsicmp(params[0], _T("UT")) == 0) {
567                                 if(target_debugger == NULL) {
568                                         my_printf(p->osd, _T("debugger is not attached to target device %s\n"), target->this_device_name);
569                                 } else if(num <= 3) {
570                                         int steps = 128;
571                                         if(num >= 2) {
572                                                 steps = min((int)my_hexatoi(target, params[1]), MAX_CPU_TRACE);
573                                         }
574                                         for(int i = MAX_CPU_TRACE - steps; i < MAX_CPU_TRACE; i++) {
575                                                 int index = (target_debugger->cpu_trace_ptr + i) & (MAX_CPU_TRACE - 1);
576                                                 if(!(target_debugger->cpu_trace[index] & ~target->get_debug_prog_addr_mask())) {
577                                                         const _TCHAR *name = my_get_symbol(target, target_debugger->cpu_trace[index] & target->get_debug_prog_addr_mask());
578                                                         int len = target->debug_dasm(target_debugger->cpu_trace[index] & target->get_debug_prog_addr_mask(), buffer, 1024);
579                                                         if(name != NULL) {
580                                                                 my_printf(p->osd, _T("%08X                  "), target_debugger->cpu_trace[index] & target->get_debug_prog_addr_mask());
581                                                                 p->osd->set_console_text_attribute(FOREGROUND_GREEN | FOREGROUND_INTENSITY);
582                                                                 my_printf(p->osd, _T("%s:\n"), name);
583                                                                 p->osd->set_console_text_attribute(FOREGROUND_RED | FOREGROUND_GREEN | FOREGROUND_BLUE | FOREGROUND_INTENSITY);
584                                                         }
585                                                         my_printf(p->osd, _T("%08X  "), target_debugger->cpu_trace[index] & target->get_debug_prog_addr_mask());
586                                                         for(int i = 0; i < len; i++) {
587                                                                 my_printf(p->osd, _T("%02X"), target->read_debug_data8((target_debugger->cpu_trace[index] + i) & target->get_debug_prog_addr_mask()));
588                                                         }
589                                                         for(int i = len; i < 8; i++) {
590                                                                 my_printf(p->osd, _T("  "));
591                                                         }
592                                                         my_printf(p->osd, _T("  %s\n"), buffer);
593                                                 }
594                                         }
595                                 } else {
596                                         my_printf(p->osd, _T("invalid parameter number\n"));
597                                 }
598                         } else if(_tcsicmp(params[0], _T("H")) == 0) {
599                                 if(num == 3) {
600                                         uint32_t l = my_hexatoi(target, params[1]);
601                                         uint32_t r = my_hexatoi(target, params[2]);
602                                         my_printf(p->osd, _T("%08X  %08X\n"), l + r, l - r);
603                                 } else {
604                                         my_printf(p->osd, _T("invalid parameter number\n"));
605                                 }
606                         } else if(_tcsicmp(params[0], _T("N")) == 0) {
607                                 if(num >= 2 && params[1][0] == _T('\"')) {
608                                         my_tcscpy_s(buffer, 1024, prev_command);
609                                         if((token = my_tcstok_s(buffer, _T("\""), &context)) != NULL && (token = my_tcstok_s(NULL, _T("\""), &context)) != NULL) {
610                                                 my_tcscpy_s(debugger->file_path, _MAX_PATH, my_absolute_path(token));
611                                         } else {
612                                                 my_printf(p->osd, _T("invalid parameter\n"));
613                                         }
614                                 } else if(num == 2) {
615                                         my_tcscpy_s(debugger->file_path, _MAX_PATH, my_absolute_path(params[1]));
616                                 } else {
617                                         my_printf(p->osd, _T("invalid parameter number\n"));
618                                 }
619                         } else if(_tcsicmp(params[0], _T("L")) == 0) {
620                                 FILEIO* fio = new FILEIO();
621                                 if(check_file_extension(debugger->file_path, _T(".sym"))) {
622                                         if(target_debugger == NULL) {
623                                                 my_printf(p->osd, _T("debugger is not attached to target device %s\n"), target->this_device_name);
624                                         } else if(fio->Fopen(debugger->file_path, FILEIO_READ_ASCII)) {
625                                                 target_debugger->release_symbols();
626                                                 _TCHAR line[1024];
627                                                 while(fio->Fgetts(line, array_length(line)) != NULL) {
628                                                         _TCHAR *next = NULL;
629                                                         _TCHAR *addr = my_tcstok_s(line, _T("\t #$*,;"), &next);
630                                                         while(addr != NULL) {
631                                                                 if(_tcslen(addr) > 0) {
632                                                                         _TCHAR *name = my_tcstok_s(NULL, _T("\t #$*,;"), &next);
633                                                                         while(name != NULL) {
634                                                                                 while(_tcslen(name) > 0 && (name[_tcslen(name) - 1] == 0x0d || name[_tcslen(name) - 1] == 0x0a)) {
635                                                                                         name[_tcslen(name) - 1] = _T('\0');
636                                                                                 }
637                                                                                 if(_tcslen(name) > 0) {
638                                                                                         target_debugger->add_symbol(my_hexatoi(NULL, addr), name);
639                                                                                         break;
640                                                                                 }
641                                                                                 name = my_tcstok_s(NULL, _T("\t #$*,;"), &next);
642                                                                         }
643                                                                 }
644                                                                 addr = my_tcstok_s(NULL, _T("\t #$*,;"), &next);
645                                                         }
646                                                 }
647                                                 fio->Fclose();
648                                         } else {
649                                                 my_printf(p->osd, _T("can't open %s\n"), debugger->file_path);
650                                         }
651                                 } else if(check_file_extension(debugger->file_path, _T(".hex"))) {
652                                         if(fio->Fopen(debugger->file_path, FILEIO_READ_ASCII)) {
653                                                 uint32_t start_addr = 0, linear = 0, segment = 0;
654                                                 if(num >= 2) {
655                                                         start_addr = my_hexatoi(target, params[1]);
656                                                 }
657                                                 char line[1024];
658                                                 while(fio->Fgets(line, sizeof(line)) != NULL) {
659                                                         if(line[0] != ':') continue;
660                                                         int type = my_hexatob(line + 7);
661                                                         if(type == 0x00) {
662                                                                 uint32_t bytes = my_hexatob(line + 1);
663                                                                 uint32_t addr = my_hexatow(line + 3) + start_addr + linear + segment;
664                                                                 for(uint32_t i = 0; i < bytes; i++) {
665                                                                         target->write_debug_data8((addr + i) & target->get_debug_data_addr_mask(), my_hexatob(line + 9 + 2 * i));
666                                                                 }
667                                                         } else if(type == 0x01) {
668                                                                 break;
669                                                         } else if(type == 0x02) {
670                                                                 segment = my_hexatow(line + 9) << 4;
671                                                                 start_addr = 0;
672                                                         } else if(type == 0x04) {
673                                                                 linear = my_hexatow(line + 9) << 16;
674                                                                 start_addr = 0;
675                                                         }
676                                                 }
677                                                 fio->Fclose();
678                                         } else {
679                                                 my_printf(p->osd, _T("can't open %s\n"), debugger->file_path);
680                                         }
681                                 } else {
682                                         if(fio->Fopen(debugger->file_path, FILEIO_READ_BINARY)) {
683                                                 uint32_t start_addr = 0x100, end_addr = target->get_debug_data_addr_mask();
684                                                 if(num >= 2) {
685                                                         start_addr = my_hexatoi(target, params[1]) & target->get_debug_data_addr_mask();
686                                                 }
687                                                 if(num >= 3) {
688                                                         end_addr = my_hexatoi(target, params[2]) & target->get_debug_data_addr_mask();
689                                                 }
690                                                 for(uint32_t addr = start_addr; addr <= end_addr; addr++) {
691                                                         int data = fio->Fgetc();
692                                                         if(data == EOF) {
693                                                                 break;
694                                                         }
695                                                         target->write_debug_data8(addr & target->get_debug_data_addr_mask(), data);
696                                                 }
697                                                 fio->Fclose();
698                                         } else {
699                                                 my_printf(p->osd, _T("can't open %s\n"), debugger->file_path);
700                                         }
701                                 }
702                                 delete fio;
703                         } else if(_tcsicmp(params[0], _T("W")) == 0) {
704                                 if(num == 3) {
705                                         uint32_t start_addr = my_hexatoi(target, params[1]) & target->get_debug_data_addr_mask(), end_addr = my_hexatoi(target, params[2]) & target->get_debug_data_addr_mask();
706                                         FILEIO* fio = new FILEIO();
707                                         if(check_file_extension(debugger->file_path, _T(".hex"))) {
708                                                 // write intel hex format file
709                                                 if(fio->Fopen(debugger->file_path, FILEIO_WRITE_ASCII)) {
710                                                         uint32_t addr = start_addr;
711                                                         while(addr <= end_addr) {
712                                                                 uint32_t len = min(end_addr - addr + 1, (uint32_t)16);
713                                                                 uint32_t sum = len + ((addr >> 8) & 0xff) + (addr & 0xff) + 0x00;
714                                                                 fio->Fprintf(":%02X%04X%02X", len, addr & 0xffff, 0x00);
715                                                                 for(uint32_t i = 0; i < len; i++) {
716                                                                         uint8_t data = target->read_debug_data8((addr++) & target->get_debug_data_addr_mask());
717                                                                         sum += data;
718                                                                         fio->Fprintf("%02X", data);
719                                                                 }
720                                                                 fio->Fprintf("%02X\n", (0x100 - (sum & 0xff)) & 0xff);
721                                                         }
722                                                         fio->Fprintf(":00000001FF\n");
723                                                         fio->Fclose();
724                                                 } else {
725                                                         my_printf(p->osd, _T("can't open %s\n"), debugger->file_path);
726                                                 }
727                                         } else {
728                                                 if(fio->Fopen(debugger->file_path, FILEIO_WRITE_BINARY)) {
729                                                         for(uint32_t addr = start_addr; addr <= end_addr; addr++) {
730                                                                 fio->Fputc(target->read_debug_data8(addr & target->get_debug_data_addr_mask()));
731                                                         }
732                                                         fio->Fclose();
733                                                 } else {
734                                                         my_printf(p->osd, _T("can't open %s\n"), debugger->file_path);
735                                                 }
736                                         }
737                                         delete fio;
738                                 } else {
739                                         my_printf(p->osd, _T("invalid parameter number\n"));
740                                 }
741                         } else if(_tcsicmp(params[0], _T("SC")) == 0) {
742                                 if(target_debugger == NULL) {
743                                         my_printf(p->osd, _T("debugger is not attached to target device %s\n"), target->this_device_name);
744                                 } else if(num == 1) {
745                                         target_debugger->release_symbols();
746                                 } else {
747                                         my_printf(p->osd, _T("invalid parameter number\n"));
748                                 }
749                         } else if(_tcsicmp(params[0], _T("SL")) == 0) {
750                                 if(target_debugger == NULL) {
751                                         my_printf(p->osd, _T("debugger is not attached to target device %s\n"), target->this_device_name);
752                                 } else if(num == 1) {
753                                         for(symbol_t* symbol = debugger->first_symbol; symbol; symbol = symbol->next_symbol) {
754                                                 my_printf(p->osd, _T("%08X %s\n"), symbol->addr, symbol->name);
755                                         }
756                                 } else {
757                                         my_printf(p->osd, _T("invalid parameter number\n"));
758                                 }
759                         } else if(_tcsicmp(params[0], _T( "BP")) == 0 || _tcsicmp(params[0], _T("RBP")) == 0 || _tcsicmp(params[0], _T("WBP")) == 0 ||
760                                   _tcsicmp(params[0], _T( "CP")) == 0 || _tcsicmp(params[0], _T("RCP")) == 0 || _tcsicmp(params[0], _T("WCP")) == 0) {
761                                 break_point_t *bp = get_break_point(debugger, params[0]);
762                                 if(num == 2) {
763                                         uint32_t addr = my_hexatoi(cpu, params[1]);
764                                         bool found = false;
765                                         for(int i = 0; i < MAX_BREAK_POINTS && !found; i++) {
766                                                 if(bp->table[i].status == 0 || (bp->table[i].addr == addr && bp->table[i].mask == cpu->get_debug_prog_addr_mask())) {
767                                                         bp->table[i].addr = addr;
768                                                         bp->table[i].mask = cpu->get_debug_prog_addr_mask();
769                                                         bp->table[i].status = 1;
770                                                         bp->table[i].check_point = (params[0][0] == 'C' || params[0][0] == 'c' || params[0][1] == 'C' || params[0][1] == 'c');
771                                                         found = true;
772                                                 }
773                                         }
774                                         if(!found) {
775                                                 my_printf(p->osd, _T("too many break points\n"));
776                                         }
777                                 } else {
778                                         my_printf(p->osd, _T("invalid parameter number\n"));
779                                 }
780                         } else if(_tcsicmp(params[0], _T("IBP")) == 0 || _tcsicmp(params[0], _T("OBP")) == 0 ||
781                                   _tcsicmp(params[0], _T("ICP")) == 0 || _tcsicmp(params[0], _T("OCP")) == 0) {
782                                 break_point_t *bp = get_break_point(debugger, params[0]);
783                                 if(num == 2 || num == 3) {
784                                         uint32_t addr = my_hexatoi(cpu, params[1]), mask = 0xff;
785                                         if(num == 3) {
786                                                 mask = my_hexatoi(cpu, params[2]);
787                                         }
788                                         bool found = false;
789                                         for(int i = 0; i < MAX_BREAK_POINTS && !found; i++) {
790                                                 if(bp->table[i].status == 0 || (bp->table[i].addr == addr && bp->table[i].mask == mask)) {
791                                                         bp->table[i].addr = addr;
792                                                         bp->table[i].mask = mask;
793                                                         bp->table[i].status = 1;
794                                                         bp->table[i].check_point = (params[0][1] == 'C' || params[0][1] == 'c');
795                                                         found = true;
796                                                 }
797                                         }
798                                         if(!found) {
799                                                 my_printf(p->osd, _T("too many break points\n"));
800                                         }
801                                 } else {
802                                         my_printf(p->osd, _T("invalid parameter number\n"));
803                                 }
804                         } else if(_tcsicmp(params[0], _T("BC")) == 0 || _tcsicmp(params[0], _T("RBC")) == 0 || _tcsicmp(params[0], _T("WBC")) == 0 || _tcsicmp(params[0], _T("IBC")) == 0 || _tcsicmp(params[0], _T("OBC")) == 0) {
805                                 break_point_t *bp = get_break_point(debugger, params[0]);
806                                 if(num == 2 && (_tcsicmp(params[1], _T("*")) == 0 || _tcsicmp(params[1], _T("ALL")) == 0)) {
807                                         memset(bp->table, 0, sizeof(bp->table));
808                                 } else if(num >= 2) {
809                                         for(int i = 1; i < num; i++) {
810                                                 int index = my_hexatoi(cpu, params[i]);
811                                                 if(!(index >= 1 && index <= MAX_BREAK_POINTS)) {
812                                                         my_printf(p->osd, _T("invalid index %x\n"), index);
813                                                 } else {
814                                                         bp->table[index - 1].addr = bp->table[index - 1].mask = 0;
815                                                         bp->table[index - 1].status = 0;
816                                                 }
817                                         }
818                                 } else {
819                                         my_printf(p->osd, _T("invalid parameter number\n"));
820                                 }
821                         } else if(_tcsicmp(params[0], _T("BD")) == 0 || _tcsicmp(params[0], _T("RBD")) == 0 || _tcsicmp(params[0], _T("WBD")) == 0 || _tcsicmp(params[0], _T("IBD")) == 0 || _tcsicmp(params[0], _T("OBD")) == 0 ||
822                                   _tcsicmp(params[0], _T("BE")) == 0 || _tcsicmp(params[0], _T("RBE")) == 0 || _tcsicmp(params[0], _T("WBE")) == 0 || _tcsicmp(params[0], _T("IBE")) == 0 || _tcsicmp(params[0], _T("OBE")) == 0) {
823                                 break_point_t *bp = get_break_point(debugger, params[0]);
824                                 bool enabled = (params[0][1] == _T('E') || params[0][1] == _T('e') || params[0][2] == _T('E') || params[0][2] == _T('e'));
825                                 if(num == 2 && (_tcsicmp(params[1], _T("*")) == 0 || _tcsicmp(params[1], _T("ALL")) == 0)) {
826                                         for(int i = 0; i < MAX_BREAK_POINTS; i++) {
827                                                 if(bp->table[i].status != 0) {
828                                                         bp->table[i].status = enabled ? 1 : -1;
829                                                 }
830                                         }
831                                 } else if(num >= 2) {
832                                         for(int i = 1; i < num; i++) {
833                                                 int index = my_hexatoi(cpu, params[i]);
834                                                 if(!(index >= 1 && index <= MAX_BREAK_POINTS)) {
835                                                         my_printf(p->osd, _T("invalid index %x\n"), index);
836                                                 } else if(bp->table[index - 1].status == 0) {
837                                                         my_printf(p->osd, _T("break point %x is null\n"), index);
838                                                 } else {
839                                                         bp->table[index - 1].status = enabled ? 1 : -1;
840                                                 }
841                                         }
842                                 } else {
843                                         my_printf(p->osd, _T("invalid parameter number\n"));
844                                 }
845                         } else if(_tcsicmp(params[0], _T("BL")) == 0 || _tcsicmp(params[0], _T("RBL")) == 0 || _tcsicmp(params[0], _T("WBL")) == 0) {
846                                 if(num == 1) {
847                                         break_point_t *bp = get_break_point(debugger, params[0]);
848                                         for(int i = 0; i < MAX_BREAK_POINTS; i++) {
849                                                 if(bp->table[i].status) {
850                                                         my_printf(p->osd, _T("%d %c %s %s\n"), i + 1,
851                                                                 bp->table[i].status == 1 ? _T('e') : _T('d'),
852                                                                 my_get_value_and_symbol(cpu, _T("%08X"), bp->table[i].addr),
853                                                                 bp->table[i].check_point ? "checkpoint" : "");
854                                                 }
855                                         }
856                                 } else {
857                                         my_printf(p->osd, _T("invalid parameter number\n"));
858                                 }
859                         } else if(_tcsicmp(params[0], _T("IBL")) == 0 || _tcsicmp(params[0], _T("OBL")) == 0) {
860                                 if(num == 1) {
861                                         break_point_t *bp = get_break_point(debugger, params[0]);
862                                         for(int i = 0; i < MAX_BREAK_POINTS; i++) {
863                                                 if(bp->table[i].status) {
864                                                         my_printf(p->osd, _T("%d %c %s %08X %s\n"), i + 1,
865                                                                 bp->table[i].status == 1 ? _T('e') : _T('d'),
866                                                                 my_get_value_and_symbol(cpu, _T("%08X"), bp->table[i].addr),
867                                                                 bp->table[i].mask,
868                                                                 bp->table[i].check_point ? "checkpoint" : "");
869                                                 }
870                                         }
871                                 } else {
872                                         my_printf(p->osd, _T("invalid parameter number\n"));
873                                 }
874                         } else if(_tcsicmp(params[0], _T("G")) == 0 || _tcsicmp(params[0], _T("P")) == 0) {
875                                 if(num == 1 || num == 2) {
876                                         bool break_points_stored = false;
877                                         if(_tcsicmp(params[0], _T("P")) == 0) {
878                                                 debugger->store_break_points();
879                                                 debugger->bp.table[0].addr = (cpu->get_next_pc() + cpu->debug_dasm(cpu->get_next_pc(), buffer, 1024)) & cpu->get_debug_prog_addr_mask();
880                                                 debugger->bp.table[0].mask = cpu->get_debug_prog_addr_mask();
881                                                 debugger->bp.table[0].status = 1;
882                                                 debugger->bp.table[0].check_point = false;
883                                                 break_points_stored = true;
884                                         } else if(num >= 2) {
885                                                 debugger->store_break_points();
886                                                 debugger->bp.table[0].addr = my_hexatoi(cpu, params[1]) & cpu->get_debug_prog_addr_mask();
887                                                 debugger->bp.table[0].mask = cpu->get_debug_prog_addr_mask();
888                                                 debugger->bp.table[0].status = 1;
889                                                 debugger->bp.table[0].check_point = false;
890                                                 break_points_stored = true;
891                                         }
892 RESTART_GO:
893                                         debugger->now_going = true;
894                                         debugger->now_suspended = false;
895 #if defined(_MSC_VER)                                      
896                                         while(!p->request_terminate && !debugger->now_suspended) {
897                                                 if(p->osd->is_console_key_pressed(VK_ESCAPE) && p->osd->is_console_active()) {
898                                                         break;
899                                                 }
900                                                 p->osd->sleep(10);
901                                         }
902 #elif defined(OSD_QT)
903                                         while(!p->request_terminate && !debugger->now_suspended) {
904                                                 if(p->osd->console_input_string() != NULL && p->osd->is_console_active()) {
905                                                         p->osd->clear_console_input_string();
906                                                         break;
907                                                 }
908                                                 p->osd->sleep(10);
909                                         }
910 #endif                                     
911                                         // break cpu
912                                         debugger->now_going = false;
913                                         wait_count = 0;
914                                         while(!p->request_terminate && !(debugger->now_suspended && debugger->now_waiting)) {
915                                                 if((wait_count++) == 100) {
916                                                         p->osd->set_console_text_attribute(FOREGROUND_RED | FOREGROUND_INTENSITY);
917                                                         my_printf(p->osd, _T("waiting until cpu is suspended...\n"));
918                                                 }
919                                                 p->osd->sleep(10);
920                                         }
921                                         if(cpu == target) {
922                                                 dasm_addr = cpu->get_next_pc();
923                                         }
924                                         
925                                         p->osd->set_console_text_attribute(FOREGROUND_GREEN | FOREGROUND_BLUE | FOREGROUND_INTENSITY);
926                                         cpu->debug_dasm(cpu->get_pc(), buffer, 1024);
927                                         my_printf(p->osd, _T("done\t%s  %s\n"), my_get_value_and_symbol(cpu, _T("%08X"), cpu->get_pc()), buffer);
928                                         
929                                         p->osd->set_console_text_attribute(FOREGROUND_RED | FOREGROUND_GREEN | FOREGROUND_BLUE | FOREGROUND_INTENSITY);
930                                         cpu->get_debug_regs_info(buffer, 1024);
931                                         my_printf(p->osd, _T("%s\n"), buffer);
932                                         
933                                         if(cpu != target) {
934                                                 p->osd->set_console_text_attribute(FOREGROUND_GREEN | FOREGROUND_INTENSITY);
935                                                 if(target->debug_dasm(target->get_next_pc(), buffer, 1024) != 0) {
936                                                         my_printf(p->osd, _T("next\t%s  %s\n"), my_get_value_and_symbol(target, _T("%08X"), target->get_next_pc()), buffer);
937                                                 }
938                                                 target->get_debug_regs_info(buffer, 1024);
939                                                 my_printf(p->osd, _T("%s\n"), buffer);
940                                         }
941                                         
942                                         if(debugger->hit()) {
943                                                 p->osd->set_console_text_attribute(FOREGROUND_RED | FOREGROUND_INTENSITY);
944                                                 if(debugger->bp.hit) {
945                                                         if(_tcsicmp(params[0], _T("G")) == 0) {
946                                                                 my_printf(p->osd, _T("breaked at %s\n"), my_get_value_and_symbol(cpu, _T("%08X"), cpu->get_next_pc()));
947                                                         }
948                                                         debugger->bp.hit = false;
949                                                         if(debugger->bp.restart) goto RESTART_GO;
950                                                 } else if(debugger->rbp.hit) {
951                                                         my_printf(p->osd, _T("breaked at %s: memory %s was read at %s\n"), my_get_value_and_symbol(cpu, _T("%08X"), cpu->get_next_pc()),
952                                                                 my_get_value_and_symbol(cpu, _T("%08X"), debugger->rbp.hit_addr),
953                                                                 my_get_value_and_symbol(cpu, _T("%08X"), cpu->get_pc()));
954                                                         debugger->rbp.hit = false;
955                                                         if(debugger->rbp.restart) goto RESTART_GO;
956                                                 } else if(debugger->wbp.hit) {
957                                                         my_printf(p->osd, _T("breaked at %s: memory %s was written at %s\n"), my_get_value_and_symbol(cpu, _T("%08X"), cpu->get_next_pc()),
958                                                                 my_get_value_and_symbol(cpu, _T("%08X"), debugger->wbp.hit_addr),
959                                                                 my_get_value_and_symbol(cpu, _T("%08X"), cpu->get_pc()));
960                                                         debugger->wbp.hit = false;
961                                                         if(debugger->wbp.restart) goto RESTART_GO;
962                                                 } else if(debugger->ibp.hit) {
963                                                         my_printf(p->osd, _T("breaked at %s: port %s was read at %s\n"), my_get_value_and_symbol(cpu, _T("%08X"), cpu->get_next_pc()),
964                                                                 my_get_value_and_symbol(cpu, _T("%08X"), debugger->ibp.hit_addr),
965                                                                 my_get_value_and_symbol(cpu, _T("%08X"), cpu->get_pc()));
966                                                         debugger->ibp.hit = false;
967                                                         if(debugger->ibp.restart) goto RESTART_GO;
968                                                 } else if(debugger->obp.hit) {
969                                                         my_printf(p->osd, _T("breaked at %s: port %s was written at %s\n"), my_get_value_and_symbol(cpu, _T("%08X"), cpu->get_next_pc()),
970                                                                 my_get_value_and_symbol(cpu, _T("%08X"), debugger->obp.hit_addr),
971                                                                 my_get_value_and_symbol(cpu, _T("%08X"), cpu->get_pc()));
972                                                         debugger->obp.hit = false;
973                                                         if(debugger->obp.restart) goto RESTART_GO;
974                                                 }
975                                         } else {
976                                                 p->osd->set_console_text_attribute(FOREGROUND_RED | FOREGROUND_INTENSITY);
977                                                 my_printf(p->osd, _T("breaked at %s: esc key was pressed\n"), my_get_value_and_symbol(cpu, _T("%08X"), cpu->get_next_pc()));
978                                         }
979                                         if(break_points_stored) {
980                                                 debugger->restore_break_points();
981                                         }
982                                         p->osd->set_console_text_attribute(FOREGROUND_GREEN | FOREGROUND_BLUE | FOREGROUND_INTENSITY);
983                                         cpu->debug_dasm(cpu->get_next_pc(), buffer, 1024);
984                                         my_printf(p->osd, _T("next\t%s  %s\n"), my_get_value_and_symbol(cpu, _T("%08X"), cpu->get_next_pc()), buffer);
985                                         p->osd->set_console_text_attribute(FOREGROUND_RED | FOREGROUND_GREEN | FOREGROUND_BLUE | FOREGROUND_INTENSITY);
986                                 } else {
987                                         my_printf(p->osd, _T("invalid parameter number\n"));
988                                 }
989                         } else if(_tcsicmp(params[0], _T("T")) == 0) {
990                                 if(num == 1 || num == 2) {
991                                         int steps = 1;
992                                         if(num >= 2) {
993                                                 steps = my_hexatoi(cpu, params[1]);
994                                         }
995                                         for(int i = 0; i < steps; i++) {
996                                                 debugger->now_going = false;
997                                                 debugger->now_suspended = false;
998                                                 wait_count = 0;
999                                                 while(!p->request_terminate && !(debugger->now_suspended && debugger->now_waiting)) {
1000                                                         if((wait_count++) == 100) {
1001                                                                 p->osd->set_console_text_attribute(FOREGROUND_RED | FOREGROUND_INTENSITY);
1002                                                                 my_printf(p->osd, _T("waiting until cpu is suspended...\n"));
1003                                                         }
1004                                                         p->osd->sleep(10);
1005                                                 }
1006                                                 if(cpu == target) {
1007                                                         dasm_addr = cpu->get_next_pc();
1008                                                 }
1009                                                 
1010                                                 p->osd->set_console_text_attribute(FOREGROUND_GREEN | FOREGROUND_BLUE | FOREGROUND_INTENSITY);
1011                                                 cpu->debug_dasm(cpu->get_pc(), buffer, 1024);
1012                                                 my_printf(p->osd, _T("done\t%s  %s\n"), my_get_value_and_symbol(cpu, _T("%08X"), cpu->get_pc()), buffer);
1013                                                 
1014                                                 p->osd->set_console_text_attribute(FOREGROUND_RED | FOREGROUND_GREEN | FOREGROUND_BLUE | FOREGROUND_INTENSITY);
1015                                                 cpu->get_debug_regs_info(buffer, 1024);
1016                                                 my_printf(p->osd, _T("%s\n"), buffer);
1017                                                 
1018                                                 if(cpu != target) {
1019                                                         p->osd->set_console_text_attribute(FOREGROUND_GREEN | FOREGROUND_INTENSITY);
1020                                                         if(target->debug_dasm(target->get_next_pc(), buffer, 1024) != 0) {
1021                                                                 my_printf(p->osd, _T("next\t%s  %s\n"), my_get_value_and_symbol(target, _T("%08X"), target->get_next_pc()), buffer);
1022                                                         }
1023                                                         target->get_debug_regs_info(buffer, 1024);
1024                                                         my_printf(p->osd, _T("%s\n"), buffer);
1025                                                 }
1026                                                 
1027                                                 if(debugger->hit()) {
1028                                                         p->osd->set_console_text_attribute(FOREGROUND_RED | FOREGROUND_INTENSITY);
1029                                                         if(debugger->bp.hit) {
1030                                                                 my_printf(p->osd, _T("breaked at %s\n"), my_get_value_and_symbol(cpu, _T("%08X"), cpu->get_next_pc()));
1031                                                                 debugger->bp.hit = false;
1032                                                                 if(!debugger->bp.restart) break;
1033                                                         } else if(debugger->rbp.hit) {
1034                                                                 my_printf(p->osd, _T("breaked at %s: memory %s was read at %s\n"), my_get_value_and_symbol(cpu, _T("%08X"), cpu->get_next_pc()),
1035                                                                         my_get_value_and_symbol(cpu, _T("%08X"), debugger->rbp.hit_addr),
1036                                                                         my_get_value_and_symbol(cpu, _T("%08X"), cpu->get_pc()));
1037                                                                 debugger->rbp.hit = false;
1038                                                                 if(!debugger->rbp.restart) break;
1039                                                         } else if(debugger->wbp.hit) {
1040                                                                 my_printf(p->osd, _T("breaked at %s: memory %s was written at %s\n"), my_get_value_and_symbol(cpu, _T("%08X"), cpu->get_next_pc()),
1041                                                                         my_get_value_and_symbol(cpu, _T("%08X"), debugger->wbp.hit_addr),
1042                                                                         my_get_value_and_symbol(cpu, _T("%08X"), cpu->get_pc()));
1043                                                                 debugger->wbp.hit = false;
1044                                                                 if(!debugger->wbp.restart) break;
1045                                                         } else if(debugger->ibp.hit) {
1046                                                                 my_printf(p->osd, _T("breaked at %s: port %s was read at %s\n"), my_get_value_and_symbol(cpu, _T("%08X"), cpu->get_next_pc()),
1047                                                                         my_get_value_and_symbol(cpu, _T("%08X"), debugger->ibp.hit_addr),
1048                                                                         my_get_value_and_symbol(cpu, _T("%08X"), cpu->get_pc()));
1049                                                                 debugger->ibp.hit = false;
1050                                                                 if(!debugger->ibp.restart) break;
1051                                                         } else if(debugger->obp.hit) {
1052                                                                 my_printf(p->osd, _T("breaked at %s: port %s was written at %s\n"), my_get_value_and_symbol(cpu, _T("%08X"), cpu->get_next_pc()),
1053                                                                         my_get_value_and_symbol(cpu, _T("%08X"), debugger->obp.hit_addr),
1054                                                                         my_get_value_and_symbol(cpu, _T("%08X"), cpu->get_pc()));
1055                                                                 debugger->obp.hit = false;
1056                                                                 if(!debugger->obp.restart) break;
1057                                                         }
1058                                                 } else if(p->osd->is_console_key_pressed(VK_ESCAPE) && p->osd->is_console_active()) {
1059                                                         break;
1060                                                 }
1061                                         }
1062                                         p->osd->set_console_text_attribute(FOREGROUND_GREEN | FOREGROUND_BLUE | FOREGROUND_INTENSITY);
1063                                         cpu->debug_dasm(cpu->get_next_pc(), buffer, 1024);
1064                                         my_printf(p->osd, _T("next\t%s  %s\n"), my_get_value_and_symbol(cpu, _T("%08X"), cpu->get_next_pc()), buffer);
1065                                         p->osd->set_console_text_attribute(FOREGROUND_RED | FOREGROUND_GREEN | FOREGROUND_BLUE | FOREGROUND_INTENSITY);
1066                                 } else {
1067                                         my_printf(p->osd, _T("invalid parameter number\n"));
1068                                 }
1069                         } else if(_tcsicmp(params[0], _T("Q")) == 0) {
1070                                 p->osd->close_debugger_console();
1071                                 break;
1072                         } else if(_tcsicmp(params[0], _T(">")) == 0) {
1073                                 if(num == 2) {
1074                                         if(logfile != NULL) {
1075                                                 if(logfile->IsOpened()) {
1076                                                         logfile->Fclose();
1077                                                 }
1078                                                 delete logfile;
1079                                                 logfile = NULL;
1080                                         }
1081                                         logfile = new FILEIO();
1082                                         logfile->Fopen(my_absolute_path(params[1]), FILEIO_WRITE_ASCII);
1083                                 } else {
1084                                         my_printf(p->osd, _T("invalid parameter number\n"));
1085                                 }
1086                         } else if(_tcsicmp(params[0], _T("<")) == 0) {
1087                                 if(num == 2) {
1088                                         if(cmdfile != NULL) {
1089                                                 if(cmdfile->IsOpened()) {
1090                                                         cmdfile->Fclose();
1091                                                 }
1092                                         } else {
1093                                                 cmdfile = new FILEIO();
1094                                         }
1095                                         if(!cmdfile->Fopen(my_absolute_path(params[1]), FILEIO_READ_ASCII)) {
1096                                                 delete cmdfile;
1097                                                 cmdfile = NULL;
1098                                                 my_printf(p->osd, _T("can't open %s\n"), params[1]);
1099                                         }
1100                                 } else {
1101                                         my_printf(p->osd, _T("invalid parameter number\n"));
1102                                 }
1103                         } else if(_tcsicmp(params[0], _T("!")) == 0) {
1104                                 if(num == 1) {
1105                                         my_printf(p->osd, _T("invalid parameter number\n"));
1106                                 } else if(_tcsicmp(params[1], _T("RESET")) == 0) {
1107                                         if(num == 2) {
1108                                                 p->vm->reset();
1109                                         } else if(num == 3) {
1110                                                 if(_tcsicmp(params[2], _T("ALL")) == 0) {
1111                                                         p->vm->reset();
1112                                                 } if(_tcsicmp(params[2], _T("CPU")) == 0) {
1113                                                         cpu->reset();
1114                                                 } if(_tcsicmp(params[2], _T("TARGET")) == 0) {
1115                                                         target->reset();
1116                                                 } else {
1117                                                         my_printf(p->osd, _T("unknown device %s\n"), params[2]);
1118                                                 }
1119                                         } else {
1120                                                 my_printf(p->osd, _T("invalid parameter number\n"));
1121                                         }
1122                                 } else if(_tcsicmp(params[1], _T("KEY")) == 0) {
1123                                         if(num == 3 || num == 4) {
1124                                                 int code =  my_hexatoi(target, params[2]) & 0xff, msec = 100;
1125                                                 if(num == 4) {
1126                                                         msec = my_hexatoi(target, params[3]);
1127                                                 }
1128 #ifdef SUPPORT_VARIABLE_TIMING
1129                                                 int frames = (int)(p->vm->get_frame_rate() * (double)msec / 1000.0 + 0.5);
1130 #else
1131                                                 int frames = (int)(FRAMES_PER_SEC * (double)msec / 1000.0 + 0.5);
1132 #endif
1133                                                 p->osd->get_key_buffer()[code] &= 0x7f;
1134                                                 p->osd->get_key_buffer()[code] |= max(1, min(127, frames));
1135 #ifdef NOTIFY_KEY_DOWN
1136                                                 p->vm->key_down(code, false);
1137 #endif
1138                                         } else {
1139                                                 my_printf(p->osd, _T("invalid parameter number\n"));
1140                                         }
1141                                 } else if(_tcsicmp(params[1], _T("DEVICE")) == 0) {
1142                                         if(num == 2) {
1143                                                 for(DEVICE* device = p->vm->first_device; device; device = device->next_device) {
1144                                                         my_printf(p->osd, _T("ID=%02X  %s"), device->this_device_id, device->this_device_name);
1145                                                         if(device == target) {
1146                                                                 p->osd->set_console_text_attribute(FOREGROUND_RED | FOREGROUND_INTENSITY);
1147                                                                 my_printf(p->osd, _T("  <=== target"));
1148                                                                 p->osd->set_console_text_attribute(FOREGROUND_RED | FOREGROUND_GREEN | FOREGROUND_BLUE | FOREGROUND_INTENSITY);
1149                                                         }
1150                                                         my_printf(p->osd, _T("\n"));
1151                                                 }
1152                                         } else if(num == 3) {
1153                                                 DEVICE *device = NULL;
1154                                                 if(_tcsicmp(params[2], _T("CPU")) == 0) {
1155                                                         device = cpu;
1156                                                 } else {
1157                                                         device = p->vm->get_device(my_hexatoi(NULL, params[2]));
1158                                                 }
1159                                                 if(device != NULL) {
1160                                                         if(device != target) {
1161                                                                 target = device;
1162                                                                 target_debugger = (DEBUGGER *)target->get_debugger();
1163                                                                 dump_addr = 0;
1164                                                                 dasm_addr = target->get_next_pc();
1165                                                         }
1166                                                 } else {
1167                                                         my_printf(p->osd, _T("device not found\n"));
1168                                                 }
1169                                         } else {
1170                                                 my_printf(p->osd, _T("invalid parameter number\n"));
1171                                         }
1172                                 } else if(_tcsicmp(params[1], _T("CPU")) == 0) {
1173                                         if(num == 2) {
1174                                                 for(DEVICE* device = p->vm->first_device; device; device = device->next_device) {
1175                                                         if(device->get_debugger() != NULL) {
1176                                                                 my_printf(p->osd, _T("ID=%02X  %s"), device->this_device_id, device->this_device_name);
1177                                                                 if(device == cpu) {
1178                                                                         p->osd->set_console_text_attribute(FOREGROUND_RED | FOREGROUND_INTENSITY);
1179                                                                         my_printf(p->osd, _T("  <=== target"));
1180                                                                         p->osd->set_console_text_attribute(FOREGROUND_RED | FOREGROUND_GREEN | FOREGROUND_BLUE | FOREGROUND_INTENSITY);
1181                                                                 }
1182                                                                 my_printf(p->osd, _T("\n"));
1183                                                         }
1184                                                 }
1185                                         } else if(num == 3) {
1186                                                 DEVICE *device = p->vm->get_device(my_hexatoi(NULL, params[2]));
1187                                                 if(device != NULL && device->get_debugger() != NULL) {
1188                                                         if(device != cpu) {
1189                                                                 DEBUGGER *prev_debugger = debugger;
1190                                                                 cpu = device;
1191                                                                 debugger = (DEBUGGER *)cpu->get_debugger();
1192                                                                 debugger->now_going = false;
1193                                                                 debugger->now_debugging = true;
1194                                                                 prev_debugger->now_debugging = prev_debugger->now_going = prev_debugger->now_suspended = prev_debugger->now_waiting = false;
1195                                                                 wait_count = 0;
1196                                                                 while(!p->request_terminate && !(debugger->now_suspended && debugger->now_waiting)) {
1197                                                                         if((wait_count++) == 100) {
1198                                                                                 p->osd->set_console_text_attribute(FOREGROUND_RED | FOREGROUND_INTENSITY);
1199                                                                                 my_printf(p->osd, _T("waiting until cpu is suspended...\n"));
1200                                                                         }
1201                                                                         p->osd->sleep(10);
1202                                                                 }
1203                                                                 dump_addr = 0;
1204                                                                 dasm_addr = cpu->get_next_pc();
1205                                                                 
1206                                                                 p->osd->set_console_text_attribute(FOREGROUND_RED | FOREGROUND_GREEN | FOREGROUND_BLUE | FOREGROUND_INTENSITY);
1207                                                                 cpu->get_debug_regs_info(buffer, 1024);
1208                                                                 my_printf(p->osd, _T("%s\n"), buffer);
1209                                                                 
1210                                                                 p->osd->set_console_text_attribute(FOREGROUND_RED | FOREGROUND_INTENSITY);
1211                                                                 my_printf(p->osd, _T("breaked at %s\n"), my_get_value_and_symbol(cpu, _T("%08X"), cpu->get_next_pc()));
1212                                                                 
1213                                                                 p->osd->set_console_text_attribute(FOREGROUND_GREEN | FOREGROUND_BLUE | FOREGROUND_INTENSITY);
1214                                                                 cpu->debug_dasm(cpu->get_next_pc(), buffer, 1024);
1215                                                                 my_printf(p->osd, _T("next\t%s  %s\n"), my_get_value_and_symbol(cpu, _T("%08X"), cpu->get_next_pc()), buffer);
1216                                                                 p->osd->set_console_text_attribute(FOREGROUND_RED | FOREGROUND_GREEN | FOREGROUND_BLUE | FOREGROUND_INTENSITY);
1217                                                         }
1218                                                 } else {
1219                                                         my_printf(p->osd, _T("device not found\n"));
1220                                                 }
1221                                         } else {
1222                                                 my_printf(p->osd, _T("invalid parameter number\n"));
1223                                         }
1224                                 } else {
1225                                         my_printf(p->osd, _T("unknown command ! %s\n"), params[1]);
1226                                 }
1227                         } else if(_tcsicmp(params[0], _T("?")) == 0) {
1228                                 my_printf(p->osd, _T("D [<range>] - dump memory\n"));
1229                                 my_printf(p->osd, _T("E[{B,W,D}] <address> <list> - edit memory (byte,word,dword)\n"));
1230                                 my_printf(p->osd, _T("EA <address> \"<value>\" - edit memory (ascii)\n"));
1231                                 my_printf(p->osd, _T("I[{B,W,D}] <port> - input port (byte,word,dword)\n"));
1232                                 my_printf(p->osd, _T("O[{B,W,D}] <port> <value> - output port (byte,word,dword)\n"));
1233                                 my_printf(p->osd, _T("R - show register(s)\n"));
1234                                 my_printf(p->osd, _T("R <reg> <value> - edit register\n"));
1235                                 my_printf(p->osd, _T("S <range> <list> - search\n"));
1236                                 my_printf(p->osd, _T("U [<range>] - unassemble\n"));
1237                                 my_printf(p->osd, _T("UT [<steps>] - unassemble trace\n"));
1238                                 
1239                                 my_printf(p->osd, _T("H <value> <value> - hexadd\n"));
1240                                 my_printf(p->osd, _T("N <filename> - name\n"));
1241                                 my_printf(p->osd, _T("L [<range>] - load binary/hex/symbol file\n"));
1242                                 my_printf(p->osd, _T("W <range> - write binary/hex file\n"));
1243                                 
1244                                 my_printf(p->osd, _T("SC - clear symbol(s)\n"));
1245                                 my_printf(p->osd, _T("SL - list symbol(s)\n"));
1246                                 
1247                                 my_printf(p->osd, _T("BP <address> - set breakpoint\n"));
1248                                 my_printf(p->osd, _T("{R,W}BP <address> - set breakpoint (break at memory access)\n"));
1249                                 my_printf(p->osd, _T("{I,O}BP <port> [<mask>] - set breakpoint (break at i/o access)\n"));
1250                                 my_printf(p->osd, _T("[{R,W,I,O}]B{C,D,E} {*,<list>} - clear/disable/enable breakpoint(s)\n"));
1251                                 my_printf(p->osd, _T("[{R,W,I,O}]BL - list breakpoint(s)\n"));
1252                                 my_printf(p->osd, _T("[{R,W,I,O}]CP <address/port> [<mask>] - set checkpoint (don't break)\n"));
1253                                 
1254                                 my_printf(p->osd, _T("G - go (press esc key to break)\n"));
1255                                 my_printf(p->osd, _T("G <address> - go and break at address\n"));
1256                                 my_printf(p->osd, _T("P - trace one opcode (step over)\n"));
1257                                 my_printf(p->osd, _T("T [<count>] - trace (step in)\n"));
1258                                 my_printf(p->osd, _T("Q - quit\n"));
1259                                 
1260                                 my_printf(p->osd, _T("> <filename> - output logfile\n"));
1261                                 my_printf(p->osd, _T("< <filename> - input commands from file\n"));
1262                                 
1263                                 my_printf(p->osd, _T("! reset [all/cpu/target] - reset\n"));
1264                                 my_printf(p->osd, _T("! key <code> [<msec>] - press key\n"));
1265                                 my_printf(p->osd, _T("! device - enumerate device\n"));
1266                                 my_printf(p->osd, _T("! device <id/cpu> - select target device\n"));
1267                                 my_printf(p->osd, _T("! cpu - enumerate cpu\n"));
1268                                 my_printf(p->osd, _T("! cpu <id> - select target cpu\n"));
1269                                 
1270                                 my_printf(p->osd, _T("<value> - hexa, decimal(%%d), ascii('a')\n"));
1271                         } else {
1272                                 my_printf(p->osd, _T("unknown command %s\n"), params[0]);
1273                         }
1274                 }
1275         }
1276         
1277         // stop debugger
1278         try {
1279                 debugger->now_debugging = debugger->now_going = debugger->now_suspended = debugger->now_waiting = false;
1280         } catch(...) {
1281         }
1282         
1283         // release files
1284         if(logfile != NULL) {
1285                 if(logfile->IsOpened()) {
1286                         logfile->Fclose();
1287                 }
1288                 delete logfile;
1289                 logfile = NULL;
1290         }
1291         if(cmdfile != NULL) {
1292                 if(cmdfile->IsOpened()) {
1293                         cmdfile->Fclose();
1294                 }
1295                 delete cmdfile;
1296                 cmdfile = NULL;
1297         }
1298         
1299         // release console
1300         p->osd->close_console();
1301         
1302         p->running = false;
1303 #ifdef _MSC_VER
1304         _endthreadex(0);
1305         return 0;
1306 #else
1307         //pthread_exit(NULL);
1308         return NULL;
1309 #endif
1310 }
1311
1312 void EMU::initialize_debugger()
1313 {
1314         now_debugging = false;
1315         hDebugger = NULL;
1316 }
1317
1318 void EMU::release_debugger()
1319 {
1320         close_debugger();
1321 }
1322
1323 void EMU::open_debugger(int cpu_index)
1324 {
1325         if(!(now_debugging && debugger_thread_param.cpu_index == cpu_index)) {
1326                 close_debugger();
1327                 if(vm->get_cpu(cpu_index) != NULL && vm->get_cpu(cpu_index)->get_debugger() != NULL) {
1328 //                      debugger_thread_param.emu = this;
1329                         debugger_thread_param.osd = osd;
1330                         debugger_thread_param.vm = vm;
1331                         debugger_thread_param.cpu_index = cpu_index;
1332                         debugger_thread_param.request_terminate = false;
1333 #ifdef _MSC_VER
1334                         if((hDebuggerThread = (HANDLE)_beginthreadex(NULL, 0, debugger_thread, &debugger_thread_param, 0, NULL)) != (HANDLE)0) {
1335 #else
1336 //#elif !defined(_USE_QT)
1337                         if(pthread_create(&debugger_thread_id, NULL, debugger_thread, &debugger_thread_param) == 0) {
1338 //#else // USE_QT
1339 //                      {
1340 #endif
1341                                 stop_record_sound();
1342                                 stop_record_video();
1343                                 now_debugging = true;
1344                         }
1345                 }
1346         }
1347 }
1348
1349 void EMU::close_debugger()
1350 {
1351         if(now_debugging) {
1352                 if(debugger_thread_param.running) {
1353                         debugger_thread_param.request_terminate = true;
1354                 }
1355 #ifdef _MSC_VER
1356                 WaitForSingleObject(hDebuggerThread, INFINITE);
1357                 CloseHandle(hDebuggerThread);
1358 //#elif !defined(_USE_QT)
1359 #else
1360                 pthread_join(debugger_thread_id, NULL);
1361 //#else
1362 //              volatile debugger_thread_t *p = (debugger_thread_t *)(&debugger_thread_param);
1363 //              p->running = false;
1364                 
1365                 //if(logfile != NULL && logfile->IsOpened()) {
1366                 //      logfile->Fclose();
1367                 //}
1368                 // initialize logfile
1369                 //logfile = NULL;
1370 #endif
1371                 now_debugging = false;
1372         }
1373 }
1374
1375 bool EMU::is_debugger_enabled(int cpu_index)
1376 {
1377         return (vm->get_cpu(cpu_index) != NULL && vm->get_cpu(cpu_index)->get_debugger() != NULL);
1378 }
1379
1380 #endif
1381