OSDN Git Service

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