OSDN Git Service

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