OSDN Git Service

[General][Qt] Merge updtream 2016-03-05 (1).FTBFSs exist yet.
[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 #if !defined(_MSC_VER)
10 #include <SDL.h>
11 #endif
12 #include <stdlib.h>
13 #include <io.h>
14 #include <fcntl.h>
15 #include "vm/device.h"
16 #include "vm/debugger.h"
17 #include "vm/vm.h"
18 #include "fileio.h"
19 #if defined(OSD_QT)
20 #include "emu_thread.h"
21 #endif
22
23 #ifdef USE_DEBUGGER
24
25 #ifndef FOREGROUND_BLUE
26 #define FOREGROUND_BLUE      0x0001 // text color contains blue.
27 #endif
28 #ifndef FOREGROUND_GREEN
29 #define FOREGROUND_GREEN     0x0002 // text color contains green.
30 #endif
31 #ifndef FOREGROUND_RED
32 #define FOREGROUND_RED       0x0004 // text color contains red.
33 #endif
34 #ifndef FOREGROUND_INTENSITY
35 #define FOREGROUND_INTENSITY 0x0008 // text color is intensified.
36 #endif
37
38 static FILEIO* logfile = NULL;
39
40 void my_printf(OSD *osd, const _TCHAR *format, ...)
41 {
42         _TCHAR buffer[1024];
43         va_list ap;
44         
45         va_start(ap, format);
46         my_vstprintf_s(buffer, 1024, format, ap);
47         va_end(ap);
48 #if defined(_MSC_VER)   
49         if(logfile != NULL && logfile->IsOpened()) {
50                 logfile->Fwrite(buffer, lstrlen(buffer) * sizeof(_TCHAR), 1);
51         }
52 #else   
53         if(logfile != NULL && logfile->IsOpened()) {
54                 logfile->Fwrite(buffer, strlen(buffer) * sizeof(_TCHAR), 1);
55         }
56 #endif
57         osd->write_console(buffer, _tcslen(buffer));
58 }
59
60 void my_putch(OSD *osd, _TCHAR c)
61 {
62         if(logfile != NULL && logfile->IsOpened()) {
63                 logfile->Fwrite(&c, sizeof(_TCHAR), 1);
64         }
65         osd->write_console(&c, 1);
66 }
67
68 uint32_t my_hexatoi(const _TCHAR *str)
69 {
70         _TCHAR tmp[1024], *s;
71         
72         if(str == NULL || _tcslen(str) == 0) {
73                 return 0;
74         }
75         my_tcscpy_s(tmp, 1024, str);
76         
77         if(_tcslen(tmp) == 3 && tmp[0] == _T('\'') && tmp[2] == _T('\'')) {
78                 // ank
79                 return tmp[1] & 0xff;
80         } else if((s = _tcsstr(tmp, _T(":"))) != NULL) {
81                 // 0000:0000
82                 s[0] = _T('\0');
83                 return (my_hexatoi(tmp) << 4) + my_hexatoi(s + 1);
84         } else if(tmp[0] == _T('%')) {
85                 // decimal
86 #if defined(__MINGW32__)
87                 return atoi(tmp + 1);
88 #else
89                 return _tstoi(tmp + 1);
90 #endif
91         }
92         return _tcstoul(tmp, NULL, 16);
93 }
94
95 uint8_t my_hexatob(char *value)
96 {
97         char tmp[3];
98         tmp[0] = value[0];
99         tmp[1] = value[1];
100         tmp[2] = '\0';
101         return (uint8_t)strtoul(tmp, NULL, 16);
102 }
103
104 uint16_t my_hexatow(char *value)
105 {
106         char tmp[5];
107         tmp[0] = value[0];
108         tmp[1] = value[1];
109         tmp[2] = value[2];
110         tmp[3] = value[3];
111         tmp[4] = '\0';
112         return (uint16_t)strtoul(tmp, NULL, 16);
113 }
114
115 break_point_t *get_break_point(DEBUGGER *debugger, const _TCHAR *command)
116 {
117         if(command[0] == _T('B') || command[0] == _T('b')) {
118                 return &debugger->bp;
119         } else if(command[0] == _T('R') || command[0] == _T('r')) {
120                 return &debugger->rbp;
121         } else if(command[0] == _T('W') || command[0] == _T('w')) {
122                 return &debugger->wbp;
123         } else if(command[0] == _T('I') || command[0] == _T('i')) {
124                 return &debugger->ibp;
125         } else if(command[0] == _T('O') || command[0] == _T('o')) {
126                 return &debugger->obp;
127         }
128         return NULL;
129 }
130
131 static uint32_t dump_addr;
132 static uint32_t dasm_addr;
133
134 int debugger_command(debugger_thread_t *p, _TCHAR *command, _TCHAR *prev_command, bool cp932)
135 {
136         DEVICE *cpu = p->vm->get_cpu(p->cpu_index);
137         DEBUGGER *debugger = (DEBUGGER *)cpu->get_debugger();
138         uint32_t prog_addr_mask = cpu->debug_prog_addr_mask();
139         uint32_t data_addr_mask = cpu->debug_data_addr_mask();
140         //while(!debugger->now_suspended) {
141         //              p->osd->sleep(10);
142         //}
143         
144         // initialize console
145         _TCHAR buffer[1024];
146         if(strlen(command) > 0) {
147                         _TCHAR *params[32], *token = NULL, *context = NULL;
148                         int num = 0;
149                         
150                         if((token = my_tcstok_s(command, _T(" "), &context)) != NULL) {
151                                 params[num++] = token;
152                                 while(num < 32 && (token = my_tcstok_s(NULL, _T(" "), &context)) != NULL) {
153                                         params[num++] = token;
154                                 }
155                         }
156                         if(_tcsicmp(params[0], _T("D")) == 0) {
157                                 if(num <= 3) {
158                                         uint32_t start_addr = dump_addr;
159                                         if(num >= 2) {
160                                                 start_addr = my_hexatoi(params[1]);
161                                         }
162                                         start_addr &= data_addr_mask;
163                                         
164                                         uint32_t end_addr = start_addr + 8 * 16 - 1;
165                                         if(num == 3) {
166                                                 end_addr = my_hexatoi(params[2]);
167                                         }
168                                         end_addr &= data_addr_mask;
169                                         
170                                         if(start_addr > end_addr) {
171                                                 end_addr = data_addr_mask;
172                                         }
173                                         for(uint64_t addr = start_addr & ~0x0f; addr <= end_addr; addr++) {
174                                                 if(addr > data_addr_mask) {
175                                                         end_addr = data_addr_mask;
176                                                         break;
177                                                 }
178                                                 if((addr & 0x0f) == 0) {
179                                                         my_printf(p->osd, _T("%08X "), addr & data_addr_mask);
180                                                         memset(buffer, 0, sizeof(buffer));
181                                                 }
182                                                 if(addr < start_addr) {
183                                                         my_printf(p->osd, _T("   "));
184                                                         buffer[addr & 0x0f] = _T(' ');
185                                                 } else {
186                                                         uint32_t data = cpu->read_debug_data8(addr & data_addr_mask);
187                                                         my_printf(p->osd, _T(" %02X"), data);
188                                                         buffer[addr & 0x0f] = ((data >= 0x20 && data <= 0x7e) || (cp932 && data >= 0xa1 && data <= 0xdf)) ? data : _T('.');
189                                                 }
190                                                 if((addr & 0x0f) == 0x0f) {
191                                                         my_printf(p->osd, _T("  %s\n"), buffer);
192                                                 }
193                                         }
194                                         if((end_addr & 0x0f) != 0x0f) {
195                                                 for(uint32_t addr = (end_addr & 0x0f) + 1; addr <= 0x0f; addr++) {
196                                                         my_printf(p->osd, _T("   "));
197                                                 }
198                                                 my_printf(p->osd, _T("  %s\n"), buffer);
199                                         }
200                                         dump_addr = (end_addr + 1) & data_addr_mask;
201                                         prev_command[1] = _T('\0'); // remove parameters to dump continuously
202                                 } else {
203                                         my_printf(p->osd, _T("invalid parameter number\n"));
204                                 }
205                         } else if(_tcsicmp(params[0], _T("E")) == 0 || _tcsicmp(params[0], _T("EB")) == 0) {
206                                 if(num >= 3) {
207                                         uint32_t addr = my_hexatoi(params[1]) & data_addr_mask;
208                                         for(int i = 2; i < num; i++) {
209                                                 cpu->write_debug_data8(addr, my_hexatoi(params[i]) & 0xff);
210                                                 addr = (addr + 1) & data_addr_mask;
211                                         }
212                                 } else {
213                                         my_printf(p->osd, _T("invalid parameter number\n"));
214                                 }
215                         } else if(_tcsicmp(params[0], _T("EW")) == 0) {
216                                 if(num >= 3) {
217                                         uint32_t addr = my_hexatoi(params[1]) & data_addr_mask;
218                                         for(int i = 2; i < num; i++) {
219                                                 cpu->write_debug_data16(addr, my_hexatoi(params[i]) & 0xffff);
220                                                 addr = (addr + 2) & data_addr_mask;
221                                         }
222                                 } else {
223                                         my_printf(p->osd, _T("invalid parameter number\n"));
224                                 }
225                         } else if(_tcsicmp(params[0], _T("ED")) == 0) {
226                                 if(num >= 3) {
227                                         uint32_t addr = my_hexatoi(params[1]) & data_addr_mask;
228                                         for(int i = 2; i < num; i++) {
229                                                 cpu->write_debug_data32(addr, my_hexatoi(params[i]));
230                                                 addr = (addr + 4) & data_addr_mask;
231                                         }
232                                 } else {
233                                         my_printf(p->osd, _T("invalid parameter number\n"));
234                                 }
235                         } else if(_tcsicmp(params[0], _T("EA")) == 0) {
236                                 if(num >= 3) {
237                                         uint32_t addr = my_hexatoi(params[1]) & data_addr_mask;
238                                         my_tcscpy_s(buffer, 1024, prev_command);
239                                         if((token = my_tcstok_s(buffer, _T("\""), &context)) != NULL && (token = my_tcstok_s(NULL, _T("\""), &context)) != NULL) {
240                                                 int len = _tcslen(token);
241                                                 for(int i = 0; i < len; i++) {
242                                                         cpu->write_debug_data8(addr, token[i] & 0xff);
243                                                         addr = (addr + 1) & data_addr_mask;
244                                                 }
245                                         } else {
246                                                 my_printf(p->osd, _T("invalid parameter\n"));
247                                         }
248                                 } else {
249                                         my_printf(p->osd, _T("invalid parameter number\n"));
250                                 }
251                         } else if(_tcsicmp(params[0], _T("I")) == 0 || _tcsicmp(params[0], _T("IB")) == 0) {
252                                 if(num == 2) {
253                                         my_printf(p->osd, _T("%02X\n"), cpu->read_debug_io8(my_hexatoi(params[1])) & 0xff);
254                                 } else {
255                                         my_printf(p->osd, _T("invalid parameter number\n"));
256                                 }
257                         } else if(_tcsicmp(params[0], _T("IW")) == 0) {
258                                 if(num == 2) {
259                                         my_printf(p->osd, _T("%02X\n"), cpu->read_debug_io16(my_hexatoi(params[1])) & 0xffff);
260                                 } else {
261                                         my_printf(p->osd, _T("invalid parameter number\n"));
262                                 }
263                         } else if(_tcsicmp(params[0], _T("ID")) == 0) {
264                                 if(num == 2) {
265                                         my_printf(p->osd, _T("%02X\n"), cpu->read_debug_io32(my_hexatoi(params[1])));
266                                 } else {
267                                         my_printf(p->osd, _T("invalid parameter number\n"));
268                                 }
269                         } else if(_tcsicmp(params[0], _T("O")) == 0 || _tcsicmp(params[0], _T("OB")) == 0) {
270                                 if(num == 3) {
271                                         cpu->write_debug_io8(my_hexatoi(params[1]), my_hexatoi(params[2]) & 0xff);
272                                 } else {
273                                         my_printf(p->osd, _T("invalid parameter number\n"));
274                                 }
275                         } else if(_tcsicmp(params[0], _T("OW")) == 0) {
276                                 if(num == 3) {
277                                         cpu->write_debug_io16(my_hexatoi(params[1]), my_hexatoi(params[2]) & 0xffff);
278                                 } else {
279                                         my_printf(p->osd, _T("invalid parameter number\n"));
280                                 }
281                         } else if(_tcsicmp(params[0], _T("OD")) == 0) {
282                                 if(num == 3) {
283                                         cpu->write_debug_io32(my_hexatoi(params[1]), my_hexatoi(params[2]));
284                                 } else {
285                                         my_printf(p->osd, _T("invalid parameter number\n"));
286                                 }
287                         } else if(_tcsicmp(params[0], _T("R")) == 0) {
288                                 if(num == 1) {
289                                         cpu->debug_regs_info(buffer, 1024);
290                                         my_printf(p->osd, _T("%s\n"), buffer);
291                                 } else if(num == 3) {
292                                         if(!cpu->write_debug_reg(params[1], my_hexatoi(params[2]))) {
293                                                 my_printf(p->osd, _T("unknown register %s\n"), params[1]);
294                                         }
295                                 } else {
296                                         my_printf(p->osd, _T("invalid parameter number\n"));
297                                 }
298                         } else if(_tcsicmp(params[0], _T("S")) == 0) {
299                                 if(num >= 4) {
300                                         uint32_t start_addr = my_hexatoi(params[1]) & data_addr_mask;
301                                         uint32_t end_addr = my_hexatoi(params[2]) & data_addr_mask;
302                                         uint8_t list[32];
303                                         for(int i = 3, j = 0; i < num; i++, j++) {
304                                                 list[j] = my_hexatoi(params[i]);
305                                         }
306                                         for(uint64_t addr = start_addr; addr <= end_addr; addr++) {
307                                                 bool found = true;
308                                                 for(int i = 3, j = 0; i < num; i++, j++) {
309                                                         if(cpu->read_debug_data8((addr + j) & data_addr_mask) != list[j]) {
310                                                                 found = false;
311                                                                 break;
312                                                         }
313                                                 }
314                                                 if(found) {
315                                                         my_printf(p->osd, _T("%08X\n"), addr);
316                                                 }
317                                         }
318                                 } else {
319                                         my_printf(p->osd, _T("invalid parameter number\n"));
320                                 }
321                         } else if(_tcsicmp(params[0], _T("U")) == 0) {
322                                 if(num <= 3) {
323                                         if(num >= 2) {
324                                                 dasm_addr = my_hexatoi(params[1]) & prog_addr_mask;
325                                         }
326                                         if(num == 3) {
327                                                 uint32_t end_addr = my_hexatoi(params[2]) & prog_addr_mask;
328                                                 while(dasm_addr <= end_addr) {
329                                                         int len = cpu->debug_dasm(dasm_addr, buffer, 1024);
330                                                         my_printf(p->osd, _T("%08X  "), dasm_addr);
331                                                         for(int i = 0; i < len; i++) {
332                                                                 my_printf(p->osd, _T("%02X"), cpu->read_debug_data8((dasm_addr + i) & data_addr_mask));
333                                                         }
334                                                         for(int i = len; i < 8; i++) {
335                                                                 my_printf(p->osd, _T("  "));
336                                                         }
337                                                         my_printf(p->osd, _T("  %s\n"), buffer);
338                                                         dasm_addr = (dasm_addr + len) & prog_addr_mask;
339                                                 }
340                                         } else {
341                                                 for(int i = 0; i < 16; i++) {
342                                                         int len = cpu->debug_dasm(dasm_addr, buffer, 1024);
343                                                         my_printf(p->osd, _T("%08X  "), dasm_addr);
344                                                         for(int i = 0; i < len; i++) {
345                                                                 my_printf(p->osd, _T("%02X"), cpu->read_debug_data8((dasm_addr + i) & data_addr_mask));
346                                                         }
347                                                         for(int i = len; i < 8; i++) {
348                                                                 my_printf(p->osd, _T("  "));
349                                                         }
350                                                         my_printf(p->osd, _T("  %s\n"), buffer);
351                                                         dasm_addr = (dasm_addr + len) & prog_addr_mask;
352                                                 }
353                                         }
354                                         prev_command[1] = _T('\0'); // remove parameters to disassemble continuously
355                                 } else {
356                                         my_printf(p->osd, _T("invalid parameter number\n"));
357                                 }
358                         } else if(_tcsicmp(params[0], _T("H")) == 0) {
359                                 if(num == 3) {
360                                         uint32_t l = my_hexatoi(params[1]);
361                                         uint32_t r = my_hexatoi(params[2]);
362                                         my_printf(p->osd, _T("%08X  %08X\n"), l + r, l - r);
363                                 } else {
364                                         my_printf(p->osd, _T("invalid parameter number\n"));
365                                 }
366                         } else if(_tcsicmp(params[0], _T("N")) == 0) {
367                                 if(num >= 2 && params[1][0] == _T('\"')) {
368                                         my_tcscpy_s(buffer, 1024, prev_command);
369                                         if((token = my_tcstok_s(buffer, _T("\""), &context)) != NULL && (token = my_tcstok_s(NULL, _T("\""), &context)) != NULL) {
370                                                 my_tcscpy_s(debugger->file_path, _MAX_PATH, token);
371                                         } else {
372                                                 my_printf(p->osd, _T("invalid parameter\n"));
373                                         }
374                                 } else if(num == 2) {
375                                         my_tcscpy_s(debugger->file_path, _MAX_PATH, params[1]);
376                                 } else {
377                                         my_printf(p->osd, _T("invalid parameter number\n"));
378                                 }
379                         } else if(_tcsicmp(params[0], _T("L")) == 0) {
380                                 FILEIO* fio = new FILEIO();
381                                 if(check_file_extension(debugger->file_path, _T(".hex"))) {
382                                         if(fio->Fopen(debugger->file_path, FILEIO_READ_ASCII)) {
383                                                 uint32_t start_addr = 0, linear = 0, segment = 0;
384                                                 if(num >= 2) {
385                                                         start_addr = my_hexatoi(params[1]);
386                                                 }
387                                                 char line[1024];
388                                                 while(fio->Fgets(line, sizeof(line)) != NULL) {
389                                                         if(line[0] != ':') continue;
390                                                         int type = my_hexatob(line + 7);
391                                                         if(type == 0x00) {
392                                                                 uint32_t bytes = my_hexatob(line + 1);
393                                                                 uint32_t addr = my_hexatow(line + 3) + start_addr + linear + segment;
394                                                                 for(uint32_t i = 0; i < bytes; i++) {
395                                                                         cpu->write_debug_data8((addr + i) & data_addr_mask, my_hexatob(line + 9 + 2 * i));
396                                                                 }
397                                                         } else if(type == 0x01) {
398                                                                 break;
399                                                         } else if(type == 0x02) {
400                                                                 segment = my_hexatow(line + 9) << 4;
401                                                                 start_addr = 0;
402                                                         } else if(type == 0x04) {
403                                                                 linear = my_hexatow(line + 9) << 16;
404                                                                 start_addr = 0;
405                                                         }
406                                                 }
407                                                 fio->Fclose();
408                                         } else {
409                                                 my_printf(p->osd, _T("can't open %s\n"), debugger->file_path);
410                                         }
411                                 } else {
412                                         if(fio->Fopen(debugger->file_path, FILEIO_READ_BINARY)) {
413                                                 uint32_t start_addr = 0x100, end_addr = data_addr_mask;
414                                                 if(num >= 2) {
415                                                         start_addr = my_hexatoi(params[1]) & data_addr_mask;
416                                                 }
417                                                 if(num >= 3) {
418                                                         end_addr = my_hexatoi(params[2]) & data_addr_mask;
419                                                 }
420                                                 for(uint32_t addr = start_addr; addr <= end_addr; addr++) {
421                                                         int data = fio->Fgetc();
422                                                         if(data == EOF) {
423                                                                 break;
424                                                         }
425                                                         cpu->write_debug_data8(addr & data_addr_mask, data);
426                                                 }
427                                                 fio->Fclose();
428                                         } else {
429                                                 my_printf(p->osd, _T("can't open %s\n"), debugger->file_path);
430                                         }
431                                 }
432                                 delete fio;
433                         } else if(_tcsicmp(params[0], _T("W")) == 0) {
434                                 if(num == 3) {
435                                         uint32_t start_addr = my_hexatoi(params[1]) & data_addr_mask, end_addr = my_hexatoi(params[2]) & data_addr_mask;
436                                         FILEIO* fio = new FILEIO();
437                                         if(check_file_extension(debugger->file_path, _T(".hex"))) {
438                                                 // write intel hex format file
439                                                 if(fio->Fopen(debugger->file_path, FILEIO_WRITE_ASCII)) {
440                                                         uint32_t addr = start_addr;
441                                                         while(addr <= end_addr) {
442                                                                 uint32_t len = min(end_addr - addr + 1, (uint32_t)16);
443                                                                 uint32_t sum = len + ((addr >> 8) & 0xff) + (addr & 0xff) + 0x00;
444                                                                 fio->Fprintf(":%02X%04X%02X", len, addr & 0xffff, 0x00);
445                                                                 for(uint32_t i = 0; i < len; i++) {
446                                                                         uint8_t data = cpu->read_debug_data8((addr++) & data_addr_mask);
447                                                                         sum += data;
448                                                                         fio->Fprintf("%02X", data);
449                                                                 }
450                                                                 fio->Fprintf("%02X\n", (0x100 - (sum & 0xff)) & 0xff);
451                                                         }
452                                                         fio->Fprintf(":00000001FF\n");
453                                                         fio->Fclose();
454                                                 } else {
455                                                         my_printf(p->osd, _T("can't open %s\n"), debugger->file_path);
456                                                 }
457                                         } else {
458                                                 if(fio->Fopen(debugger->file_path, FILEIO_WRITE_BINARY)) {
459                                                         for(uint32_t addr = start_addr; addr <= end_addr; addr++) {
460                                                                 fio->Fputc(cpu->read_debug_data8(addr & data_addr_mask));
461                                                         }
462                                                         fio->Fclose();
463                                                 } else {
464                                                         my_printf(p->osd, _T("can't open %s\n"), debugger->file_path);
465                                                 }
466                                         }
467                                         delete fio;
468                                 } else {
469                                         my_printf(p->osd, _T("invalid parameter number\n"));
470                                 }
471                         } else if(_tcsicmp(params[0], _T( "BP")) == 0 || _tcsicmp(params[0], _T("RBP")) == 0 || _tcsicmp(params[0], _T("WBP")) == 0) {
472                                 break_point_t *bp = get_break_point(debugger, params[0]);
473                                 if(num == 2) {
474                                         uint32_t addr = my_hexatoi(params[1]);
475                                         bool found = false;
476                                         for(int i = 0; i < MAX_BREAK_POINTS && !found; i++) {
477                                                 if(bp->table[i].status == 0 || (bp->table[i].addr == addr && bp->table[i].mask == prog_addr_mask)) {
478                                                         bp->table[i].addr = addr;
479                                                         bp->table[i].mask = prog_addr_mask;
480                                                         bp->table[i].status = 1;
481                                                         found = true;
482                                                 }
483                                         }
484                                         if(!found) {
485                                                 my_printf(p->osd, _T("too many break points\n"));
486                                         }
487                                 } else {
488                                         my_printf(p->osd, _T("invalid parameter number\n"));
489                                 }
490                         } else if(_tcsicmp(params[0], _T("IBP")) == 0 || _tcsicmp(params[0], _T("OBP")) == 0) {
491                                 break_point_t *bp = get_break_point(debugger, params[0]);
492                                 if(num == 2 || num == 3) {
493                                         uint32_t addr = my_hexatoi(params[1]), mask = 0xff;
494                                         if(num == 3) {
495                                                 mask = my_hexatoi(params[2]);
496                                         }
497                                         bool found = false;
498                                         for(int i = 0; i < MAX_BREAK_POINTS && !found; i++) {
499                                                 if(bp->table[i].status == 0 || (bp->table[i].addr == addr && bp->table[i].mask == mask)) {
500                                                         bp->table[i].addr = addr;
501                                                         bp->table[i].mask = mask;
502                                                         bp->table[i].status = 1;
503                                                         found = true;
504                                                 }
505                                         }
506                                         if(!found) {
507                                                 my_printf(p->osd, _T("too many break points\n"));
508                                         }
509                                 } else {
510                                         my_printf(p->osd, _T("invalid parameter number\n"));
511                                 }
512                         } 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) {
513                                 break_point_t *bp = get_break_point(debugger, params[0]);
514                                 if(num == 2 && (_tcsicmp(params[1], _T("*")) == 0 || _tcsicmp(params[1], _T("ALL")) == 0)) {
515                                         memset(bp->table, 0, sizeof(bp->table));
516                                 } else if(num >= 2) {
517                                         for(int i = 1; i < num; i++) {
518                                                 int index = my_hexatoi(params[i]);
519                                                 if(!(index >= 1 && index <= MAX_BREAK_POINTS)) {
520                                                         my_printf(p->osd, _T("invalid index %x\n"), index);
521                                                 } else {
522                                                         bp->table[index - 1].addr = bp->table[index - 1].mask = 0;
523                                                         bp->table[index - 1].status = 0;
524                                                 }
525                                         }
526                                 } else {
527                                         my_printf(p->osd, _T("invalid parameter number\n"));
528                                 }
529                         } 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 ||
530                                   _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) {
531                                 break_point_t *bp = get_break_point(debugger, params[0]);
532                                 bool enabled = (params[0][1] == _T('E') || params[0][1] == _T('e') || params[0][2] == _T('E') || params[0][2] == _T('e'));
533                                 if(num == 2 && (_tcsicmp(params[1], _T("*")) == 0 || _tcsicmp(params[1], _T("ALL")) == 0)) {
534                                         for(int i = 0; i < MAX_BREAK_POINTS; i++) {
535                                                 if(bp->table[i].status != 0) {
536                                                         bp->table[i].status = enabled ? 1 : -1;
537                                                 }
538                                         }
539                                 } else if(num >= 2) {
540                                         for(int i = 1; i < num; i++) {
541                                                 int index = my_hexatoi(params[i]);
542                                                 if(!(index >= 1 && index <= MAX_BREAK_POINTS)) {
543                                                         my_printf(p->osd, _T("invalid index %x\n"), index);
544                                                 } else if(bp->table[index - 1].status == 0) {
545                                                         my_printf(p->osd, _T("break point %x is null\n"), index);
546                                                 } else {
547                                                         bp->table[index - 1].status = enabled ? 1 : -1;
548                                                 }
549                                         }
550                                 } else {
551                                         my_printf(p->osd, _T("invalid parameter number\n"));
552                                 }
553                         } else if(_tcsicmp(params[0], _T("BL")) == 0 || _tcsicmp(params[0], _T("RBL")) == 0 || _tcsicmp(params[0], _T("WBL")) == 0) {
554                                 if(num == 1) {
555                                         break_point_t *bp = get_break_point(debugger, params[0]);
556                                         for(int i = 0; i < MAX_BREAK_POINTS; i++) {
557                                                 if(bp->table[i].status) {
558                                                         my_printf(p->osd, _T("%d %c %08X\n"), i + 1, bp->table[i].status == 1 ? _T('e') : _T('d'), bp->table[i].addr);
559                                                 }
560                                         }
561                                 } else {
562                                         my_printf(p->osd, _T("invalid parameter number\n"));
563                                 }
564                         } else if(_tcsicmp(params[0], _T("IBL")) == 0 || _tcsicmp(params[0], _T("OBL")) == 0) {
565                                 if(num == 1) {
566                                         break_point_t *bp = get_break_point(debugger, params[0]);
567                                         for(int i = 0; i < MAX_BREAK_POINTS; i++) {
568                                                 if(bp->table[i].status) {
569                                                         my_printf(p->osd, _T("%d %c %08X %08X\n"), i + 1, bp->table[i].status == 1 ? _T('e') : _T('d'), bp->table[i].addr, bp->table[i].mask);
570                                                 }
571                                         }
572                                 } else {
573                                         my_printf(p->osd, _T("invalid parameter number\n"));
574                                 }
575                         } else if(_tcsicmp(params[0], _T("G")) == 0) {
576                                 if(num == 1 || num == 2) {
577                                         if(num >= 2) {
578                                                 debugger->store_break_points();
579                                                 debugger->bp.table[0].addr = my_hexatoi(params[1]) & prog_addr_mask;
580                                                 debugger->bp.table[0].mask = prog_addr_mask;
581                                                 debugger->bp.table[0].status = 1;
582                                         }
583                                         debugger->now_going = true;
584                                         debugger->now_suspended = false;
585 #if defined(_MSC_VER)                                      
586                                         while(!p->request_terminate && !debugger->now_suspended) {
587                                                 if(p->osd->is_console_key_pressed(VK_ESCAPE) && p->osd->is_console_active()) {
588                                                         break;
589                                                 }
590                                                 p->osd->sleep(10);
591                                         }
592 #elif defined(OSD_QT)
593                                         while(!p->request_terminate && !debugger->now_suspended) {
594                                                 if(p->osd->console_input_string() != NULL && p->osd->is_console_active()) {
595                                                         p->osd->clear_console_input_string();
596                                                         break;
597                                                 }
598                                                 p->osd->sleep(10);
599                                         }
600 #endif                                     
601                                         // break cpu
602                                         debugger->now_going = false;
603                                         while(!p->request_terminate && !debugger->now_suspended) {
604                                                 p->osd->sleep(10);
605                                         }
606                                         dasm_addr = cpu->get_next_pc();
607                                         
608                                         p->osd->set_console_text_attribute(FOREGROUND_GREEN | FOREGROUND_BLUE | FOREGROUND_INTENSITY);
609                                         cpu->debug_dasm(cpu->get_pc(), buffer, 1024);
610                                         my_printf(p->osd, _T("done\t%08X  %s\n"), cpu->get_pc(), buffer);
611                                         
612                                         p->osd->set_console_text_attribute(FOREGROUND_RED | FOREGROUND_GREEN | FOREGROUND_BLUE | FOREGROUND_INTENSITY);
613                                         cpu->debug_regs_info(buffer, 1024);
614                                         my_printf(p->osd, _T("%s\n"), buffer);
615                                         
616                                         if(debugger->hit()) {
617                                                 p->osd->set_console_text_attribute(FOREGROUND_RED | FOREGROUND_INTENSITY);
618                                                 if(debugger->bp.hit) {
619                                                         my_printf(p->osd, _T("breaked at %08X\n"), cpu->get_next_pc());
620                                                 } else if(debugger->rbp.hit) {
621                                                         my_printf(p->osd, _T("breaked at %08X: memory %08X was read at %08X\n"), cpu->get_next_pc(), debugger->rbp.hit_addr, cpu->get_pc());
622                                                 } else if(debugger->wbp.hit) {
623                                                         my_printf(p->osd, _T("breaked at %08X: memory %08X was written at %08X\n"), cpu->get_next_pc(), debugger->wbp.hit_addr, cpu->get_pc());
624                                                 } else if(debugger->ibp.hit) {
625                                                         my_printf(p->osd, _T("breaked at %08X: port %08X was read at %08X\n"), cpu->get_next_pc(), debugger->ibp.hit_addr, cpu->get_pc());
626                                                 } else if(debugger->obp.hit) {
627                                                         my_printf(p->osd, _T("breaked at %08X: port %08X was written at %08X\n"), cpu->get_next_pc(), debugger->obp.hit_addr, cpu->get_pc());
628                                                 }
629                                                 debugger->bp.hit = debugger->rbp.hit = debugger->wbp.hit = debugger->ibp.hit = debugger->obp.hit = false;
630                                         } else {
631                                                 p->osd->set_console_text_attribute(FOREGROUND_RED | FOREGROUND_INTENSITY);
632                                                 my_printf(p->osd, _T("breaked at %08X: esc key was pressed\n"), cpu->get_next_pc());
633                                         }
634                                         if(num >= 2) {
635                                                 debugger->restore_break_points();
636                                         }
637                                         p->osd->set_console_text_attribute(FOREGROUND_GREEN | FOREGROUND_BLUE | FOREGROUND_INTENSITY);
638                                         cpu->debug_dasm(cpu->get_next_pc(), buffer, 1024);
639                                         my_printf(p->osd, _T("next\t%08X  %s\n"), cpu->get_next_pc(), buffer);
640                                         p->osd->set_console_text_attribute(FOREGROUND_RED | FOREGROUND_GREEN | FOREGROUND_BLUE | FOREGROUND_INTENSITY);
641                                 } else {
642                                         my_printf(p->osd, _T("invalid parameter number\n"));
643                                 }
644                         } else if(_tcsicmp(params[0], _T("T")) == 0) {
645                                 if(num == 1 || num == 2) {
646                                         int steps = 1;
647                                         if(num >= 2) {
648                                                 steps = my_hexatoi(params[1]);
649                                         }
650                                         for(int i = 0; i < steps; i++) {
651                                                 debugger->now_going = false;
652                                                 debugger->now_suspended = false;
653                                                 while(!p->request_terminate && !debugger->now_suspended) {
654                                                         p->osd->sleep(10);
655                                                 }
656                                                 dasm_addr = cpu->get_next_pc();
657                                                 
658                                                 p->osd->set_console_text_attribute(FOREGROUND_GREEN | FOREGROUND_BLUE | FOREGROUND_INTENSITY);
659                                                 cpu->debug_dasm(cpu->get_pc(), buffer, 1024);
660                                                 my_printf(p->osd, _T("done\t%08X  %s\n"), cpu->get_pc(), buffer);
661                                                 
662                                                 p->osd->set_console_text_attribute(FOREGROUND_RED | FOREGROUND_GREEN | FOREGROUND_BLUE | FOREGROUND_INTENSITY);
663                                                 cpu->debug_regs_info(buffer, 1024);
664                                                 my_printf(p->osd, _T("%s\n"), buffer);
665                                                 if(debugger->hit() || (p->osd->is_console_key_pressed(VK_ESCAPE) && p->osd->is_console_active())) {
666                                                         //p->osd->clear_console_input_string();
667                                                         break;
668                                                 }
669                                         }
670                                         if(debugger->hit()) {
671                                                 p->osd->set_console_text_attribute(FOREGROUND_RED | FOREGROUND_INTENSITY);
672                                                 if(debugger->bp.hit) {
673                                                         my_printf(p->osd, _T("breaked at %08X\n"), cpu->get_next_pc());
674                                                 } else if(debugger->rbp.hit) {
675                                                         my_printf(p->osd, _T("breaked at %08X: memory %08X was read at %08X\n"), cpu->get_next_pc(), debugger->rbp.hit_addr, cpu->get_pc());
676                                                 } else if(debugger->wbp.hit) {
677                                                         my_printf(p->osd, _T("breaked at %08X: memory %08X was written at %08X\n"), cpu->get_next_pc(), debugger->wbp.hit_addr, cpu->get_pc());
678                                                 } else if(debugger->ibp.hit) {
679                                                         my_printf(p->osd, _T("breaked at %08X: port %08X was read at %08X\n"), cpu->get_next_pc(), debugger->ibp.hit_addr, cpu->get_pc());
680                                                 } else if(debugger->obp.hit) {
681                                                         my_printf(p->osd, _T("breaked at %08X: port %08X was written at %08X\n"), cpu->get_next_pc(), debugger->obp.hit_addr, cpu->get_pc());
682                                                 }
683                                                 debugger->bp.hit = debugger->rbp.hit = debugger->wbp.hit = debugger->ibp.hit = debugger->obp.hit = false;
684                                         }
685                                         p->osd->set_console_text_attribute(FOREGROUND_GREEN | FOREGROUND_BLUE | FOREGROUND_INTENSITY);
686                                         cpu->debug_dasm(cpu->get_next_pc(), buffer, 1024);
687                                         my_printf(p->osd, _T("next\t%08X  %s\n"), cpu->get_next_pc(), buffer);
688                                         p->osd->set_console_text_attribute(FOREGROUND_RED | FOREGROUND_GREEN | FOREGROUND_BLUE | FOREGROUND_INTENSITY);
689                                 } else {
690                                         my_printf(p->osd, _T("invalid parameter number\n"));
691                                 }
692                         } else if(_tcsicmp(params[0], _T("Q")) == 0) {
693                                 p->osd->close_debugger_console();
694                                 return -1;
695                         } else if(_tcsicmp(params[0], _T(">")) == 0) {
696                                 if(num == 2) {
697                                         if(logfile != NULL) {
698                                                 if(logfile->IsOpened()) {
699                                                         logfile->Fclose();
700                                                 }
701                                                 delete logfile;
702                                                 logfile = NULL;
703                                         }
704                                         logfile = new FILEIO();
705                                         logfile->Fopen(params[1], FILEIO_WRITE_ASCII);
706                                 } else {
707                                         my_printf(p->osd, _T("invalid parameter number\n"));
708                                 }
709                         } else if(_tcsicmp(params[0], _T("!")) == 0) {
710                                 if(num == 1) {
711                                         my_printf(p->osd, _T("invalid parameter number\n"));
712                                 } else if(_tcsicmp(params[1], _T("RESET")) == 0) {
713                                         if(num == 2) {
714                                                 p->vm->reset();
715                                         } else if(num == 3) {
716                                                 if(_tcsicmp(params[2], _T("ALL")) == 0) {
717                                                         p->vm->reset();
718                                                 } if(_tcsicmp(params[2], _T("CPU")) == 0) {
719                                                         cpu->reset();
720                                                 } else {
721                                                         my_printf(p->osd, _T("unknown device %s\n"), params[2]);
722                                                 }
723                                         } else {
724                                                 my_printf(p->osd, _T("invalid parameter number\n"));
725                                         }
726                                 } else if(_tcsicmp(params[1], _T("KEY")) == 0) {
727                                         if(num == 3 || num == 4) {
728                                                 int code =  my_hexatoi(params[2]) & 0xff, msec = 100;
729                                                 if(num == 4) {
730                                                         msec = my_hexatoi(params[3]);
731                                                 }
732 #ifdef SUPPORT_VARIABLE_TIMING
733                                                 p->osd->modify_key_buffer(code, max((int)(p->vm->get_frame_rate() * (double)msec / 1000.0 + 0.5), 1));
734 #else
735                                                 p->osd->modify_key_buffer(code, max((int)(FRAMES_PER_SEC * (double)msec / 1000.0 + 0.5), 1));
736 #endif
737 #ifdef NOTIFY_KEY_DOWN
738                                                 p->vm->key_down(code, false);
739 #endif
740                                         } else {
741                                                 my_printf(p->osd, _T("invalid parameter number\n"));
742                                         }
743                                 } else {
744                                         my_printf(p->osd, _T("unknown command ! %s\n"), params[1]);
745                                 }
746                         } else if(_tcsicmp(params[0], _T("?")) == 0) {
747                                 my_printf(p->osd, _T("D [<range>] - dump memory\n"));
748                                 my_printf(p->osd, _T("E[{B,W,D}] <address> <list> - edit memory (byte,word,dword)\n"));
749                                 my_printf(p->osd, _T("EA <address> \"<value>\" - edit memory (ascii)\n"));
750                                 my_printf(p->osd, _T("I[{B,W,D}] <port> - input port (byte,word,dword)\n"));
751                                 my_printf(p->osd, _T("O[{B,W,D}] <port> <value> - output port (byte,word,dword)\n"));
752                                 my_printf(p->osd, _T("R - show register(s)\n"));
753                                 my_printf(p->osd, _T("R <reg> <value> - edit register\n"));
754                                 my_printf(p->osd, _T("S <range> <list> - search\n"));
755                                 my_printf(p->osd, _T("U [<range>] - unassemble\n"));
756                                 
757                                 my_printf(p->osd, _T("H <value> <value> - hexadd\n"));
758                                 my_printf(p->osd, _T("N <filename> - name\n"));
759                                 my_printf(p->osd, _T("L [<range>] - load file\n"));
760                                 my_printf(p->osd, _T("W <range> - write file\n"));
761                                 
762                                 my_printf(p->osd, _T("BP <address> - set breakpoint\n"));
763                                 my_printf(p->osd, _T("{R,W}BP <address> - set breakpoint (break at memory access)\n"));
764                                 my_printf(p->osd, _T("{I,O}BP <port> [<mask>] - set breakpoint (break at i/o access)\n"));
765                                 my_printf(p->osd, _T("[{R,W,I,O}]B{C,D,E} {*,<list>} - clear/disable/enable breakpoint(s)\n"));
766                                 my_printf(p->osd, _T("[{R,W,I,O}]BL - list breakpoint(s)\n"));
767                                 
768                                 my_printf(p->osd, _T("G - go (press esc key to break)\n"));
769                                 my_printf(p->osd, _T("G <address> - go and break at address\n"));
770                                 my_printf(p->osd, _T("T [<count>] - trace\n"));
771                                 my_printf(p->osd, _T("Q - quit\n"));
772                                 
773                                 my_printf(p->osd, _T("> <filename> - output logfile\n"));
774                                 
775                                 my_printf(p->osd, _T("! reset [cpu] - reset\n"));
776                                 my_printf(p->osd, _T("! key <code> [<msec>] - press key\n"));
777                                 
778                                 my_printf(p->osd, _T("<value> - hexa, decimal(%%d), ascii('a')\n"));
779                         } else {
780                                 my_printf(p->osd, _T("unknown command %s\n"), params[0]);
781                         }
782                 }
783         return 0;
784 }
785    
786 #ifdef _MSC_VER
787 unsigned __stdcall debugger_thread(void *lpx)
788 #else
789 int debugger_thread(void *lpx)
790 #endif
791 {
792         volatile debugger_thread_t *p = (debugger_thread_t *)lpx;
793         p->running = true;
794         
795         DEVICE *cpu = p->vm->get_cpu(p->cpu_index);
796         DEBUGGER *debugger = (DEBUGGER *)cpu->get_debugger();
797         
798         debugger->now_going = false;
799         debugger->now_debugging = true;
800         while(!debugger->now_suspended) {
801                 p->osd->sleep(10);
802         }
803         
804         uint32_t prog_addr_mask = cpu->debug_prog_addr_mask();
805         uint32_t data_addr_mask = cpu->debug_data_addr_mask();
806         dump_addr = 0;
807         dasm_addr = cpu->get_next_pc();
808         
809         // initialize console
810         _TCHAR buffer[1024];
811         bool cp932 = (p->osd->get_console_code_page() == 932);
812         
813         p->osd->open_console((_TCHAR *)create_string(_T("Debugger - %s"), _T(DEVICE_NAME)));
814         p->osd->set_console_text_attribute(FOREGROUND_RED | FOREGROUND_GREEN | FOREGROUND_BLUE | FOREGROUND_INTENSITY);
815         cpu->debug_regs_info(buffer, 1024);
816         my_printf(p->osd, _T("%s\n"), buffer);
817         
818         p->osd->set_console_text_attribute(FOREGROUND_RED | FOREGROUND_INTENSITY);
819         my_printf(p->osd, _T("breaked at %08X\n"), cpu->get_next_pc());
820         
821         p->osd->set_console_text_attribute(FOREGROUND_GREEN | FOREGROUND_BLUE | FOREGROUND_INTENSITY);
822         cpu->debug_dasm(cpu->get_next_pc(), buffer, 1024);
823         my_printf(p->osd, _T("next\t%08X  %s\n"), cpu->get_next_pc(), buffer);
824         p->osd->set_console_text_attribute(FOREGROUND_RED | FOREGROUND_GREEN | FOREGROUND_BLUE | FOREGROUND_INTENSITY);
825         
826         // initialize logfile
827         logfile = NULL;
828         
829         #define MAX_COMMAND_LEN 64
830         
831         _TCHAR command[MAX_COMMAND_LEN + 1];
832         _TCHAR prev_command[MAX_COMMAND_LEN + 1];
833         
834         memset(prev_command, 0, sizeof(prev_command));
835         while(!p->request_terminate) {
836                 my_printf(p->osd, _T("- "));
837                 
838                 // get command
839                 int ptr = 0;
840                 bool enter_done = false;
841                 
842                 while(!p->request_terminate && !enter_done) {
843                         _TCHAR ir[16];
844                         int count = p->osd->read_console_input(ir);
845
846                         for(int i = 0; i < count; i++) {
847                                 _TCHAR chr = ir[i];
848                                 
849                                 if(chr == '\n' || chr == '\r') {
850                                         if(ptr == 0 && prev_command[0] != _T('\0')) {
851                                                 memcpy(command, prev_command, sizeof(command));
852                                                 my_printf(p->osd, _T("%s\n"), command);
853                                                 enter_done = true;
854                                                 break;
855                                         } else if(ptr > 0) {
856                                                 command[ptr] = _T('\0');
857                                                 memcpy(prev_command, command, sizeof(command));
858                                                 my_printf(p->osd, _T("\n"));
859                                                 enter_done = true;
860                                                 break;
861                                         }
862                                 } else if(chr == 0x08) {
863                                         if(ptr > 0) {
864                                                 ptr--;
865                                                 my_putch(p->osd, chr);
866                                                 my_putch(p->osd, _T(' '));
867                                                 my_putch(p->osd, chr);
868                                         }
869                                 } else if(chr >= 0x20 && chr <= 0x7e && ptr < MAX_COMMAND_LEN && !(chr == 0x20 && ptr == 0)) {
870                                         command[ptr++] = chr;
871                                         my_putch(p->osd, chr);
872                                 }
873                         }
874                         p->osd->sleep(10);
875                 }
876                 // process command
877                 if(!p->request_terminate && enter_done) {
878                         if(debugger_command((debugger_thread_t *)p, command, prev_command, cp932) < 0) break;
879                 }
880         }
881    
882         // stop debugger
883         try {
884                 debugger->now_debugging = debugger->now_going = debugger->now_suspended = false;
885         } catch(...) {
886         }
887         
888         // release logfile
889         if(logfile != NULL) {
890                 if(logfile->IsOpened()) {
891                         logfile->Fclose();
892                 }
893                 delete logfile;
894                 logfile = NULL;
895         }
896         
897         // release console
898         p->osd->close_console();
899         
900         p->running = false;
901 #ifdef _MSC_VER
902         _endthreadex(0);
903         return 0;
904 #else
905         return 0;
906 #endif
907 }
908
909 void EMU::initialize_debugger()
910 {
911         now_debugging = false;
912 }
913
914 void EMU::release_debugger()
915 {
916         close_debugger();
917 }
918
919 void EMU::open_debugger(int cpu_index)
920 {
921         if(!(now_debugging && debugger_thread_param.cpu_index == cpu_index)) {
922                 close_debugger();
923                 if(vm->get_cpu(cpu_index) != NULL && vm->get_cpu(cpu_index)->get_debugger() != NULL) {
924 //                      debugger_thread_param.emu = this;
925                         debugger_thread_param.osd = osd;
926                         debugger_thread_param.vm = vm;
927                         debugger_thread_param.cpu_index = cpu_index;
928                         debugger_thread_param.request_terminate = false;
929 #ifdef _MSC_VER
930                         if((hDebuggerThread = (HANDLE)_beginthreadex(NULL, 0, debugger_thread, &debugger_thread_param, 0, NULL)) != (HANDLE)0) {
931 #elif !defined(_USE_QT)
932                         if((debugger_thread_id = SDL_CreateThread(debugger_thread, "DebuggerThread", (void *)&debugger_thread_param)) != 0) {
933 #else // USE_QT
934                                 {
935                                         volatile debugger_thread_t *p = (debugger_thread_t *)(&debugger_thread_param);
936                                         p->running = true;
937                                         
938                                         DEVICE *cpu = p->vm->get_cpu(p->cpu_index);
939                                         DEBUGGER *debugger = (DEBUGGER *)cpu->get_debugger();
940                                         
941                                         debugger->now_going = false;
942                                         debugger->now_debugging = true;
943                                         //while(!debugger->now_suspended) {
944                                         //      p->osd->sleep(10);
945                                         //}
946                                         
947                                         uint32_t prog_addr_mask = cpu->debug_prog_addr_mask();
948                                         uint32_t data_addr_mask = cpu->debug_data_addr_mask();
949                                         dump_addr = 0;
950                                         dasm_addr = cpu->get_next_pc();
951         
952                                         // initialize console
953                                         _TCHAR buffer[1024];
954                                         my_stprintf_s(buffer, 1024, _T("Debugger - %s"), _T(DEVICE_NAME));
955                                         
956                                         p->osd->open_console(buffer);
957                                         
958                                         bool cp932 = (p->osd->get_console_code_page() == 932);
959                                         
960                                         p->osd->set_console_text_attribute(FOREGROUND_RED | FOREGROUND_GREEN | FOREGROUND_BLUE | FOREGROUND_INTENSITY);
961                                         cpu->debug_regs_info(buffer, 1024);
962                                         my_printf(p->osd, _T("%s\n"), buffer);
963                                         
964                                         p->osd->set_console_text_attribute(FOREGROUND_RED | FOREGROUND_INTENSITY);
965                                         my_printf(p->osd, _T("breaked at %08X\n"), cpu->get_next_pc());
966                                         
967                                         p->osd->set_console_text_attribute(FOREGROUND_GREEN | FOREGROUND_BLUE | FOREGROUND_INTENSITY);
968                                         cpu->debug_dasm(cpu->get_next_pc(), buffer, 1024);
969                                         my_printf(p->osd, _T("next\t%08X  %s\n"), cpu->get_next_pc(), buffer);
970                                         p->osd->set_console_text_attribute(FOREGROUND_RED | FOREGROUND_GREEN | FOREGROUND_BLUE | FOREGROUND_INTENSITY);
971         
972                                         // initialize logfile
973                                         if(logfile != NULL && logfile->IsOpened()) {
974                                                 logfile->Fclose();
975                                         }
976                                         logfile = NULL;
977 #endif
978                                         stop_record_sound();
979                                         stop_record_video();
980                                         now_debugging = true;
981                         }
982                 }
983         }
984 }
985
986 void EMU::close_debugger()
987 {
988         if(now_debugging) {
989                 if(debugger_thread_param.running) {
990                         debugger_thread_param.request_terminate = true;
991                 }
992 #ifdef _MSC_VER
993                 WaitForSingleObject(hDebuggerThread, INFINITE);
994                 CloseHandle(hDebuggerThread);
995 #elif !defined(_USE_QT)
996                 //pthread_join(debugger_thread_id, NULL);
997                 SDL_DetachThread(debugger_thread_id);
998 #else
999                 volatile debugger_thread_t *p = (debugger_thread_t *)(&debugger_thread_param);
1000                 p->running = false;
1001                 
1002                 if(logfile != NULL && logfile->IsOpened()) {
1003                         logfile->Fclose();
1004                 }
1005                 // initialize logfile
1006                 logfile = NULL;
1007                 
1008 #endif
1009                 now_debugging = false;
1010         }
1011 }
1012
1013 bool EMU::is_debugger_enabled(int cpu_index)
1014 {
1015         return (vm->get_cpu(cpu_index) != NULL && vm->get_cpu(cpu_index)->get_debugger() != NULL);
1016 }
1017
1018 #endif
1019