OSDN Git Service

[VM][General] Merge Upstream 2015-06-25.
[csp-qt/common_source_project-fm7.git] / source / src / qt / debugger / qt_debugger.cpp
1 /*
2         Skelton for retropc emulator
3
4         Author : K.Ohta <whatisthis.sowhat _at_ gmail.com>
5         Date   : 2015.04.09 -
6         History: 09 Apr, 2015 : Initial from Takeda.Toshiya's w32_debugger.cpp.
7         [ debugger console ]
8 */
9
10 #include <stdio.h>
11 #include <string.h>
12 #include <fcntl.h>
13 //#include "res/resource.h"
14 #include "../../emu.h"
15 #include "../../vm/device.h"
16 #include "../../vm/debugger.h"
17 #include "../../vm/vm.h"
18 #include "../../fileio.h"
19 #include <SDL2/SDL.h>
20 #include "qt_debugger.h"
21 #include <QThread>
22 #include <QMainWindow>
23 #include "../../qt/3rdparty/qtermwidget/lib/qtermwidget.h"
24
25 #ifdef USE_DEBUGGER
26
27 void my_printf(FILE *hStdOut, const _TCHAR *format, ...)
28 {
29         DWORD dwWritten;
30         _TCHAR buffer[4096];
31         va_list ap;
32         
33         va_start(ap, format);
34         _vstprintf_s(buffer, 4096, format, ap);
35         va_end(ap);
36         
37         fputs(buffer, hStdOut);
38 }
39
40 void my_putch(FILE *hStdOut, _TCHAR c)
41 {
42         DWORD dwWritten;
43
44         fputc(c, hStdOut);
45 }
46
47 uint32 my_hexatoi(_TCHAR *str)
48 {
49         _TCHAR *s;
50         
51         if(str == NULL || strlen(str) == 0) {
52                 return 0;
53         } else if(strlen(str) == 3 && str[0] == _T('\'') && str[2] == _T('\'')) {
54                 // ank
55                 return str[1] & 0xff;
56         } else if((s = strstr(str, _T(":"))) != NULL) {
57                 // 0000:0000
58                 s[0] = _T('\0');
59                 return (my_hexatoi(str) << 4) + my_hexatoi(s + 1);
60         } else if(str[0] == _T('%')) {
61                 // decimal
62                 return atoi(str + 1);
63         }
64         return strtol(str, NULL, 16);
65 }
66
67 break_point_t *get_break_point(DEBUGGER *debugger, _TCHAR *command)
68 {
69         if(command[0] == _T('B') || command[0] == _T('b')) {
70                 return &debugger->bp;
71         } else if(command[0] == _T('R') || command[0] == _T('r')) {
72                 return &debugger->rbp;
73         } else if(command[0] == _T('W') || command[0] == _T('w')) {
74                 return &debugger->wbp;
75         } else if(command[0] == _T('I') || command[0] == _T('i')) {
76                 return &debugger->ibp;
77         } else if(command[0] == _T('O') || command[0] == _T('o')) {
78                 return &debugger->obp;
79         }
80         return NULL;
81 }
82
83
84 void Sleep(uint32_t tick) 
85 {
86         QThread::msleep(tick);
87 }
88
89 int debugger_main(void *debugger_)
90 {
91         
92         volatile debugger_thread_t *p = (debugger_thread_t *)debugger_;
93         p->running = true;
94         
95         DEVICE *cpu = p->vm->get_cpu(p->cpu_index);
96         DEBUGGER *debugger = (DEBUGGER *)cpu->get_debugger();
97         
98         debugger->now_going = false;
99         debugger->now_debugging = true;
100         //while(!debugger->now_suspended) {
101         //      SDL_Delay(10);
102         //}
103         
104         uint32 prog_addr_mask = cpu->debug_prog_addr_mask();
105         uint32 data_addr_mask = cpu->debug_data_addr_mask();
106         uint32 dump_addr = 0;
107         uint32 dasm_addr = cpu->get_next_pc();
108         
109         // initialize console
110         _TCHAR buffer[1024];
111         snprintf(buffer, 1024, _T("Debugger - %s"), _T(DEVICE_NAME));
112         //AllocConsole();
113         //SetConsoleTitle(buffer);
114         
115         FILE *hStdIn = stdin;
116         FILE *hStdOut = stdout;
117         bool cp932 = false; //(GetConsoleCP() == 932);
118    
119         //COORD coord;
120         //coord.X = 80;
121         //coord.Y = 4000;
122
123         // Now, pure write to stdin / stdout. Will implement with Qt widget. (20150409)
124         //SetConsoleScreenBufferSize(hStdOut, coord);
125         //SetConsoleTextAttribute(hStdOut, FOREGROUND_RED | FOREGROUND_GREEN | FOREGROUND_BLUE | FOREGROUND_INTENSITY);
126         //RemoveMenu(GetSystemMenu(GetConsoleWindow(), FALSE), SC_CLOSE, MF_BYCOMMAND);
127         
128         //SetConsoleTextAttribute(hStdOut, FOREGROUND_RED | FOREGROUND_GREEN | FOREGROUND_BLUE | FOREGROUND_INTENSITY);
129         cpu->debug_regs_info(buffer, 1024);
130         my_printf(hStdOut, _T("%s\n"), buffer);
131         
132         //SetConsoleTextAttribute(hStdOut, FOREGROUND_RED | FOREGROUND_INTENSITY);
133         my_printf(hStdOut, _T("breaked at %08X\n"), cpu->get_next_pc());
134         
135         //SetConsoleTextAttribute(hStdOut, FOREGROUND_GREEN | FOREGROUND_BLUE | FOREGROUND_INTENSITY);
136         cpu->debug_dasm(cpu->get_next_pc(), buffer, 1024);
137         my_printf(hStdOut, _T("next\t%08X  %s\n"), cpu->get_next_pc(), buffer);
138         //SetConsoleTextAttribute(hStdOut, FOREGROUND_RED | FOREGROUND_GREEN | FOREGROUND_BLUE | FOREGROUND_INTENSITY);
139         
140         #define MAX_COMMAND_LEN 64
141         
142         _TCHAR command[MAX_COMMAND_LEN + 1];
143         _TCHAR prev_command[MAX_COMMAND_LEN + 1];
144         
145         memset(prev_command, 0, sizeof(prev_command));
146         
147 //      hConsole->show();
148         while(!p->request_terminate) {
149                 my_printf(hStdOut, _T("- "));
150                 
151                 // get command
152                 int ptr = 0;
153                 bool enter_done = false;
154                 
155                 while(!p->request_terminate && !enter_done) {
156                         uint32 dwRead;
157                         _TCHAR ir[32];
158
159                         
160                         if(fgets(ir, 32, hStdIn) != NULL) {
161                                 dwRead = strlen(ir);
162                                 for(unsigned int i = 0; i < dwRead; i++) {
163                                                 _TCHAR chr = ir[i];
164                                                 if(chr == 0x0d || chr == 0x0a) {
165                                                         if(ptr == 0 && prev_command[0] != _T('\0')) {
166                                                                 memcpy(command, prev_command, sizeof(command));
167                                                                 my_printf(hStdOut, _T("%s\n"), command);
168                                                                 enter_done = true;
169                                                                 break;
170                                                         } else if(ptr > 0) {
171                                                                 command[ptr] = _T('\0');
172                                                                 memcpy(prev_command, command, sizeof(command));
173                                                                 my_printf(hStdOut, _T("\n"));
174                                                                 enter_done = true;
175                                                                 break;
176                                                         }
177                                                 } else if(chr == 0x08) {
178                                                         if(ptr > 0) {
179                                                                 ptr--;
180                                                                 my_putch(hStdOut, chr);
181                                                                 my_putch(hStdOut, _T(' '));
182                                                                 my_putch(hStdOut, chr);
183                                                         }
184                                                 } else if(chr >= 0x20 && chr <= 0x7e && ptr < MAX_COMMAND_LEN && !(chr == 0x20 && ptr == 0)) {
185                                                         command[ptr++] = chr;
186                                                         my_putch(hStdOut, chr);
187                                                 }
188
189                                 }
190                            
191                         }
192                    
193                 }
194                 Sleep(10);
195
196                 
197                 // process command
198                 if(!p->request_terminate && enter_done) {
199                         _TCHAR *params[32], *token = NULL, *context = NULL;
200                         int num = 0;
201                         
202                         if((token = strtok_r(command, _T(" "), &context)) != NULL) {
203                                 params[num++] = token;
204                                 while(num < 32 && (token = strtok_r(NULL, _T(" "), &context)) != NULL) {
205                                         params[num++] = token;
206                                 }
207                         }
208                         if(strcasecmp(params[0], _T("D")) == 0) {
209                                 if(num <= 3) {
210                                         uint32 start_addr = dump_addr;
211                                         if(num >= 2) {
212                                                 start_addr = my_hexatoi(params[1]);
213                                         }
214                                         start_addr &= data_addr_mask;
215                                         
216                                         uint32 end_addr = start_addr + 8 * 16 - 1;
217                                         if(num == 3) {
218                                                 end_addr = my_hexatoi(params[2]);
219                                         }
220                                         end_addr &= data_addr_mask;
221                                         
222                                         if(start_addr > end_addr) {
223                                                 end_addr = data_addr_mask;
224                                         }
225                                         for(uint64 addr = start_addr & ~0x0f; addr <= end_addr; addr++) {
226                                                 if(addr > data_addr_mask) {
227                                                         end_addr = data_addr_mask;
228                                                         break;
229                                                 }
230                                                 if((addr & 0x0f) == 0) {
231                                                         my_printf(hStdOut, _T("%08X "), addr & data_addr_mask);
232                                                         memset(buffer, 0, sizeof(buffer));
233                                                 }
234                                                 if(addr < start_addr) {
235                                                         my_printf(hStdOut, _T("   "));
236                                                         buffer[addr & 0x0f] = _T(' ');
237                                                 } else {
238                                                         uint32 data = cpu->debug_read_data8(addr & data_addr_mask);
239                                                         my_printf(hStdOut, _T(" %02X"), data);
240                                                         buffer[addr & 0x0f] = ((data >= 0x20 && data <= 0x7e) || (cp932 && data >= 0xa1 && data <= 0xdf)) ? data : _T('.');
241                                                 }
242                                                 if((addr & 0x0f) == 0x0f) {
243                                                         my_printf(hStdOut, _T("  %s\n"), buffer);
244                                                 }
245                                         }
246                                         if((end_addr & 0x0f) != 0x0f) {
247                                                 for(uint32 addr = (end_addr & 0x0f) + 1; addr <= 0x0f; addr++) {
248                                                         my_printf(hStdOut, _T("   "));
249                                                 }
250                                                 my_printf(hStdOut, _T("  %s\n"), buffer);
251                                         }
252                                         dump_addr = (end_addr + 1) & data_addr_mask;
253                                         prev_command[1] = _T('\0'); // remove parameters to dump continuously
254                                 } else {
255                                         my_printf(hStdOut, _T("invalid parameter number\n"));
256                                 }
257                         } else if(strcasecmp(params[0], _T("E")) == 0 || strcasecmp(params[0], _T("EB")) == 0) {
258                                 if(num >= 3) {
259                                         uint32 addr = my_hexatoi(params[1]) & data_addr_mask;
260                                         for(int i = 2; i < num; i++) {
261                                                 cpu->debug_write_data8(addr, my_hexatoi(params[i]) & 0xff);
262                                                 addr = (addr + 1) & data_addr_mask;
263                                         }
264                                 } else {
265                                         my_printf(hStdOut, _T("invalid parameter number\n"));
266                                 }
267                         } else if(strcasecmp(params[0], _T("EW")) == 0) {
268                                 if(num >= 3) {
269                                         uint32 addr = my_hexatoi(params[1]) & data_addr_mask;
270                                         for(int i = 2; i < num; i++) {
271                                                 cpu->debug_write_data16(addr, my_hexatoi(params[i]) & 0xffff);
272                                                 addr = (addr + 2) & data_addr_mask;
273                                         }
274                                 } else {
275                                         my_printf(hStdOut, _T("invalid parameter number\n"));
276                                 }
277                         } else if(strcasecmp(params[0], _T("ED")) == 0) {
278                                 if(num >= 3) {
279                                         uint32 addr = my_hexatoi(params[1]) & data_addr_mask;
280                                         for(int i = 2; i < num; i++) {
281                                                 cpu->debug_write_data32(addr, my_hexatoi(params[i]));
282                                                 addr = (addr + 4) & data_addr_mask;
283                                         }
284                                 } else {
285                                         my_printf(hStdOut, _T("invalid parameter number\n"));
286                                 }
287                         } else if(strcasecmp(params[0], _T("EA")) == 0) {
288                                 if(num >= 3) {
289                                         uint32 addr = my_hexatoi(params[1]) & data_addr_mask;
290                                         strncpy(buffer, prev_command, 1024);
291                                         if((token = strtok_r(buffer, _T("\""), &context)) != NULL && (token = strtok_r(NULL, _T("\""), &context)) != NULL) {
292                                                 int len = strlen(token);
293                                                 for(int i = 0; i < len; i++) {
294                                                         cpu->debug_write_data8(addr, token[i] & 0xff);
295                                                         addr = (addr + 1) & data_addr_mask;
296                                                 }
297                                         } else {
298                                                 my_printf(hStdOut, _T("invalid parameter\n"));
299                                         }
300                                 } else {
301                                         my_printf(hStdOut, _T("invalid parameter number\n"));
302                                 }
303                         } else if(strcasecmp(params[0], _T("I")) == 0 || strcasecmp(params[0], _T("IB")) == 0) {
304                                 if(num == 2) {
305                                         my_printf(hStdOut, _T("%02X\n"), cpu->debug_read_io8(my_hexatoi(params[1])) & 0xff);
306                                 } else {
307                                         my_printf(hStdOut, _T("invalid parameter number\n"));
308                                 }
309                         } else if(strcasecmp(params[0], _T("IW")) == 0) {
310                                 if(num == 2) {
311                                         my_printf(hStdOut, _T("%02X\n"), cpu->debug_read_io16(my_hexatoi(params[1])) & 0xffff);
312                                 } else {
313                                         my_printf(hStdOut, _T("invalid parameter number\n"));
314                                 }
315                         } else if(strcasecmp(params[0], _T("ID")) == 0) {
316                                 if(num == 2) {
317                                         my_printf(hStdOut, _T("%02X\n"), cpu->debug_read_io32(my_hexatoi(params[1])));
318                                 } else {
319                                         my_printf(hStdOut, _T("invalid parameter number\n"));
320                                 }
321                         } else if(strcasecmp(params[0], _T("O")) == 0 || strcasecmp(params[0], _T("OB")) == 0) {
322                                 if(num == 3) {
323                                         cpu->debug_write_io8(my_hexatoi(params[1]), my_hexatoi(params[2]) & 0xff);
324                                 } else {
325                                         my_printf(hStdOut, _T("invalid parameter number\n"));
326                                 }
327                         } else if(strcasecmp(params[0], _T("OW")) == 0) {
328                                 if(num == 3) {
329                                         cpu->debug_write_io16(my_hexatoi(params[1]), my_hexatoi(params[2]) & 0xffff);
330                                 } else {
331                                         my_printf(hStdOut, _T("invalid parameter number\n"));
332                                 }
333                         } else if(strcasecmp(params[0], _T("OD")) == 0) {
334                                 if(num == 3) {
335                                         cpu->debug_write_io32(my_hexatoi(params[1]), my_hexatoi(params[2]));
336                                 } else {
337                                         my_printf(hStdOut, _T("invalid parameter number\n"));
338                                 }
339                         } else if(strcasecmp(params[0], _T("R")) == 0) {
340                                 if(num == 1) {
341                                         cpu->debug_regs_info(buffer, 1024);
342                                         my_printf(hStdOut, _T("%s\n"), buffer);
343                                 } else if(num == 3) {
344                                         if(!cpu->debug_write_reg(params[1], my_hexatoi(params[2]))) {
345                                                 my_printf(hStdOut, _T("unknown register %s\n"), params[1]);
346                                         }
347                                 } else {
348                                         my_printf(hStdOut, _T("invalid parameter number\n"));
349                                 }
350                         } else if(strcasecmp(params[0], _T("S")) == 0) {
351                                 if(num >= 4) {
352                                         uint32 start_addr = my_hexatoi(params[1]) & data_addr_mask;
353                                         uint32 end_addr = my_hexatoi(params[2]) & data_addr_mask;
354                                         uint8 list[32];
355                                         for(int i = 3, j = 0; i < num; i++, j++) {
356                                                 list[j] = my_hexatoi(params[i]);
357                                         }
358                                         for(uint64 addr = start_addr; addr <= end_addr; addr++) {
359                                                 bool found = true;
360                                                 for(int i = 3, j = 0; i < num; i++, j++) {
361                                                         if(cpu->debug_read_data8((addr + j) & data_addr_mask) != list[j]) {
362                                                                 found = false;
363                                                                 break;
364                                                         }
365                                                 }
366                                                 if(found) {
367                                                         my_printf(hStdOut, _T("%08X\n"), addr);
368                                                 }
369                                         }
370                                 } else {
371                                         my_printf(hStdOut, _T("invalid parameter number\n"));
372                                 }
373                         } else if(strcasecmp(params[0], _T("U")) == 0) {
374                                 if(num <= 3) {
375                                         if(num >= 2) {
376                                                 dasm_addr = my_hexatoi(params[1]) & prog_addr_mask;
377                                         }
378                                         if(num == 3) {
379                                                 uint32 end_addr = my_hexatoi(params[2]) & prog_addr_mask;
380                                                 while(dasm_addr <= end_addr) {
381                                                         int len = cpu->debug_dasm(dasm_addr, buffer, 1024);
382                                                         my_printf(hStdOut, _T("%08X  %s\n"), dasm_addr, buffer);
383                                                         dasm_addr = (dasm_addr + len) & prog_addr_mask;
384                                                 }
385                                         } else {
386                                                 for(int i = 0; i < 16; i++) {
387                                                         int len = cpu->debug_dasm(dasm_addr, buffer, 1024);
388                                                         my_printf(hStdOut, _T("%08X  %s\n"), dasm_addr, buffer);
389                                                         dasm_addr = (dasm_addr + len) & prog_addr_mask;
390                                                 }
391                                         }
392                                         prev_command[1] = _T('\0'); // remove parameters to disassemble continuously
393                                 } else {
394                                         my_printf(hStdOut, _T("invalid parameter number\n"));
395                                 }
396                         } else if(strcasecmp(params[0], _T("H")) == 0) {
397                                 if(num == 3) {
398                                         uint32 l = my_hexatoi(params[1]);
399                                         uint32 r = my_hexatoi(params[2]);
400                                         my_printf(hStdOut, _T("%08X  %08X\n"), l + r, l - r);
401                                 } else {
402                                         my_printf(hStdOut, _T("invalid parameter number\n"));
403                                 }
404                         } else if(strcasecmp(params[0], _T("N")) == 0) {
405                                 if(num >= 2 && params[1][0] == _T('\"')) {
406                                         strncpy(buffer, prev_command, 1024);
407                                         if((token = strtok_r(buffer, _T("\""), &context)) != NULL && (token = strtok_r(NULL, _T("\""), &context)) != NULL) {
408                                                  strncpy(debugger->file_path, token, _MAX_PATH);
409                                         } else {
410                                                 my_printf(hStdOut, _T("invalid parameter\n"));
411                                         }
412                                 } else if(num == 2) {
413                                         strncpy(debugger->file_path, params[1], _MAX_PATH);
414                                 } else {
415                                         my_printf(hStdOut, _T("invalid parameter number\n"));
416                                 }
417                         } else if(strcasecmp(params[0], _T("L")) == 0) {
418                                 if(num == 3) {
419                                         uint32 start_addr = my_hexatoi(params[1]) & data_addr_mask, end_addr = my_hexatoi(params[2]) & data_addr_mask;
420                                         FILEIO* fio = new FILEIO();
421                                         if(fio->Fopen(debugger->file_path, FILEIO_READ_BINARY)) {
422                                                 for(uint32 addr = start_addr; addr <= end_addr; addr++) {
423                                                         int data = fio->Fgetc();
424                                                         if(data == EOF) {
425                                                                 break;
426                                                         }
427                                                         cpu->debug_write_data8(addr & data_addr_mask, data);
428                                                 }
429                                                 fio->Fclose();
430                                         } else {
431                                                 my_printf(hStdOut, _T("can't open %s\n"), debugger->file_path);
432                                         }
433                                         delete fio;
434                                 } else {
435                                         my_printf(hStdOut, _T("invalid parameter number\n"));
436                                 }
437                         } else if(strcasecmp(params[0], _T("W")) == 0) {
438                                 if(num == 3) {
439                                         uint32 start_addr = my_hexatoi(params[1]) & data_addr_mask, end_addr = my_hexatoi(params[2]) & data_addr_mask;
440                                         FILEIO* fio = new FILEIO();
441                                         if(fio->Fopen(debugger->file_path, FILEIO_WRITE_BINARY)) {
442                                                 for(uint32 addr = start_addr; addr <= end_addr; addr++) {
443                                                         fio->Fputc(cpu->debug_read_data8(addr & data_addr_mask));
444                                                 }
445                                                 fio->Fclose();
446                                         } else {
447                                                 my_printf(hStdOut, _T("can't open %s\n"), debugger->file_path);
448                                         }
449                                         delete fio;
450                                 } else {
451                                         my_printf(hStdOut, _T("invalid parameter number\n"));
452                                 }
453                         } else if(strcasecmp(params[0], _T( "BP")) == 0 || strcasecmp(params[0], _T("RBP")) == 0 || strcasecmp(params[0], _T("WBP")) == 0) {
454                                 break_point_t *bp = get_break_point(debugger, params[0]);
455                                 if(num == 2) {
456                                         uint32 addr = my_hexatoi(params[1]);
457                                         bool found = false;
458                                         for(int i = 0; i < MAX_BREAK_POINTS && !found; i++) {
459                                                 if(bp->table[i].status == 0 || (bp->table[i].addr == addr && bp->table[i].mask == prog_addr_mask)) {
460                                                         bp->table[i].addr = addr;
461                                                         bp->table[i].mask = prog_addr_mask;
462                                                         bp->table[i].status = 1;
463                                                         found = true;
464                                                 }
465                                         }
466                                         if(!found) {
467                                                 my_printf(hStdOut, _T("too many break points\n"));
468                                         }
469                                 } else {
470                                         my_printf(hStdOut, _T("invalid parameter number\n"));
471                                 }
472                         } else if(strcasecmp(params[0], _T("IBP")) == 0 || strcasecmp(params[0], _T("OBP")) == 0) {
473                                 break_point_t *bp = get_break_point(debugger, params[0]);
474                                 if(num == 2 || num == 3) {
475                                         uint32 addr = my_hexatoi(params[1]), mask = 0xff;
476                                         if(num == 3) {
477                                                 mask = my_hexatoi(params[2]);
478                                         }
479                                         bool found = false;
480                                         for(int i = 0; i < MAX_BREAK_POINTS && !found; i++) {
481                                                 if(bp->table[i].status == 0 || (bp->table[i].addr == addr && bp->table[i].mask == mask)) {
482                                                         bp->table[i].addr = addr;
483                                                         bp->table[i].mask = mask;
484                                                         bp->table[i].status = 1;
485                                                         found = true;
486                                                 }
487                                         }
488                                         if(!found) {
489                                                 my_printf(hStdOut, _T("too many break points\n"));
490                                         }
491                                 } else {
492                                         my_printf(hStdOut, _T("invalid parameter number\n"));
493                                 }
494                         } else if(strcasecmp(params[0], _T("BC")) == 0 || strcasecmp(params[0], _T("RBC")) == 0 || strcasecmp(params[0], _T("WBC")) == 0 || strcasecmp(params[0], _T("IBC")) == 0 || strcasecmp(params[0], _T("OBC")) == 0) {
495                                 break_point_t *bp = get_break_point(debugger, params[0]);
496                                 if(num == 2 && strcasecmp(params[1], _T("ALL")) == 0) {
497                                         memset(bp->table, 0, sizeof(bp->table));
498                                 } else if(num >= 2) {
499                                         for(int i = 1; i < num; i++) {
500                                                 int index = my_hexatoi(params[i]);
501                                                 if(!(index >= 1 && index <= MAX_BREAK_POINTS)) {
502                                                         my_printf(hStdOut, _T("invalid index %x\n"), index);
503                                                 } else {
504                                                         bp->table[index - 1].addr = bp->table[index - 1].mask = 0;
505                                                         bp->table[index - 1].status = 0;
506                                                 }
507                                         }
508                                 } else {
509                                         my_printf(hStdOut, _T("invalid parameter number\n"));
510                                 }
511                         } else if(strcasecmp(params[0], _T("BD")) == 0 || strcasecmp(params[0], _T("RBD")) == 0 || strcasecmp(params[0], _T("WBD")) == 0 || strcasecmp(params[0], _T("IBD")) == 0 || strcasecmp(params[0], _T("OBD")) == 0 ||
512                                   strcasecmp(params[0], _T("BE")) == 0 || strcasecmp(params[0], _T("RBE")) == 0 || strcasecmp(params[0], _T("WBE")) == 0 || strcasecmp(params[0], _T("IBE")) == 0 || strcasecmp(params[0], _T("OBE")) == 0) {
513                                 break_point_t *bp = get_break_point(debugger, params[0]);
514                                 bool enabled = (params[0][1] == _T('E') || params[0][1] == _T('e') || params[0][2] == _T('E') || params[0][2] == _T('e'));
515                                 if(num == 2 && strcasecmp(params[1], _T("ALL")) == 0) {
516                                         for(int i = 0; i < MAX_BREAK_POINTS; i++) {
517                                                 if(bp->table[i].status != 0) {
518                                                         bp->table[i].status = enabled ? 1 : -1;
519                                                 }
520                                         }
521                                 } else if(num >= 2) {
522                                         for(int i = 1; i < num; i++) {
523                                                 int index = my_hexatoi(params[i]);
524                                                 if(!(index >= 1 && index <= MAX_BREAK_POINTS)) {
525                                                         my_printf(hStdOut, _T("invalid index %x\n"), index);
526                                                 } else if(bp->table[index - 1].status == 0) {
527                                                         my_printf(hStdOut, _T("break point %x is null\n"), index);
528                                                 } else {
529                                                         bp->table[index - 1].status = enabled ? 1 : -1;
530                                                 }
531                                         }
532                                 } else {
533                                         my_printf(hStdOut, _T("invalid parameter number\n"));
534                                 }
535                         } else if(strcasecmp(params[0], _T("BL")) == 0 || strcasecmp(params[0], _T("RBL")) == 0 || strcasecmp(params[0], _T("WBL")) == 0) {
536                                 if(num == 1) {
537                                         break_point_t *bp = get_break_point(debugger, params[0]);
538                                         for(int i = 0; i < MAX_BREAK_POINTS; i++) {
539                                                 if(bp->table[i].status) {
540                                                         my_printf(hStdOut, _T("%d %c %08X\n"), i + 1, bp->table[i].status == 1 ? _T('e') : _T('d'), bp->table[i].addr);
541                                                 }
542                                         }
543                                 } else {
544                                         my_printf(hStdOut, _T("invalid parameter number\n"));
545                                 }
546                         } else if(strcasecmp(params[0], _T("IBL")) == 0 || strcasecmp(params[0], _T("OBL")) == 0) {
547                                 if(num == 1) {
548                                         break_point_t *bp = get_break_point(debugger, params[0]);
549                                         for(int i = 0; i < MAX_BREAK_POINTS; i++) {
550                                                 if(bp->table[i].status) {
551                                                         my_printf(hStdOut, _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);
552                                                 }
553                                         }
554                                 } else {
555                                         my_printf(hStdOut, _T("invalid parameter number\n"));
556                                 }
557                         } else if(strcasecmp(params[0], _T("G")) == 0) {
558                                 if(num == 1 || num == 2) {
559                                         if(num >= 2) {
560                                                 debugger->store_break_points();
561                                                 debugger->bp.table[0].addr = my_hexatoi(params[1]) & prog_addr_mask;
562                                                 debugger->bp.table[0].mask = prog_addr_mask;
563                                                 debugger->bp.table[0].status = 1;
564                                         }
565                                         debugger->now_going = true;
566                                         debugger->now_suspended = false;
567                                         while(!p->request_terminate && !debugger->now_suspended) {
568                                         //      if((GetAsyncKeyState(VK_ESCAPE) & 0x8000) != 0) {
569                                         //              break;
570                                         //      }
571                                                 Sleep(10);
572                                         }
573                                         // break cpu
574                                         debugger->now_going = false;
575                                         while(!p->request_terminate && !debugger->now_suspended) {
576                                                 Sleep(10);
577                                         }
578                                         dasm_addr = cpu->get_next_pc();
579                                         
580                                         ////SetConsoleTextAttribute(hStdOut, FOREGROUND_GREEN | FOREGROUND_BLUE | FOREGROUND_INTENSITY);
581                                         cpu->debug_dasm(cpu->get_pc(), buffer, 1024);
582                                         my_printf(hStdOut, _T("done\t%08X  %s\n"), cpu->get_pc(), buffer);
583                                         
584                                         ////SetConsoleTextAttribute(hStdOut, FOREGROUND_RED | FOREGROUND_GREEN | FOREGROUND_BLUE | FOREGROUND_INTENSITY);
585                                         cpu->debug_regs_info(buffer, 1024);
586                                         my_printf(hStdOut, _T("%s\n"), buffer);
587                                         
588                                         if(debugger->hit()) {
589                                                 ////SetConsoleTextAttribute(hStdOut, FOREGROUND_RED | FOREGROUND_INTENSITY);
590                                                 if(debugger->bp.hit) {
591                                                         my_printf(hStdOut, _T("breaked at %08X\n"), cpu->get_next_pc());
592                                                 } else if(debugger->rbp.hit) {
593                                                         my_printf(hStdOut, _T("breaked at %08X: memory %08X was read at %08X\n"), cpu->get_next_pc(), debugger->rbp.hit_addr, cpu->get_pc());
594                                                 } else if(debugger->wbp.hit) {
595                                                         my_printf(hStdOut, _T("breaked at %08X: memory %08X was written at %08X\n"), cpu->get_next_pc(), debugger->wbp.hit_addr, cpu->get_pc());
596                                                 } else if(debugger->ibp.hit) {
597                                                         my_printf(hStdOut, _T("breaked at %08X: port %08X was read at %08X\n"), cpu->get_next_pc(), debugger->ibp.hit_addr, cpu->get_pc());
598                                                 } else if(debugger->obp.hit) {
599                                                         my_printf(hStdOut, _T("breaked at %08X: port %08X was written at %08X\n"), cpu->get_next_pc(), debugger->obp.hit_addr, cpu->get_pc());
600                                                 }
601                                                 debugger->bp.hit = debugger->rbp.hit = debugger->wbp.hit = debugger->ibp.hit = debugger->obp.hit = false;
602                                         } else {
603                                                 ////SetConsoleTextAttribute(hStdOut, FOREGROUND_RED | FOREGROUND_INTENSITY);
604                                                 my_printf(hStdOut, _T("breaked at %08X: esc key was pressed\n"), cpu->get_next_pc());
605                                         }
606                                         if(num >= 2) {
607                                                 debugger->restore_break_points();
608                                         }
609                                         ////SetConsoleTextAttribute(hStdOut, FOREGROUND_GREEN | FOREGROUND_BLUE | FOREGROUND_INTENSITY);
610                                         cpu->debug_dasm(cpu->get_next_pc(), buffer, 1024);
611                                         my_printf(hStdOut, _T("next\t%08X  %s\n"), cpu->get_next_pc(), buffer);
612                                         ////SetConsoleTextAttribute(hStdOut, FOREGROUND_RED | FOREGROUND_GREEN | FOREGROUND_BLUE | FOREGROUND_INTENSITY);
613                                 } else {
614                                         my_printf(hStdOut, _T("invalid parameter number\n"));
615                                 }
616                         } else if(strcasecmp(params[0], _T("T")) == 0) {
617                                 if(num == 1 || num == 2) {
618                                         int steps = 1;
619                                         if(num >= 2) {
620                                                 steps = my_hexatoi(params[1]);
621                                         }
622                                         for(int i = 0; i < steps; i++) {
623                                                 debugger->now_going = false;
624                                                 debugger->now_suspended = false;
625                                                 while(!p->request_terminate && !debugger->now_suspended) {
626                                                         Sleep(10);
627                                                 }
628                                                 dasm_addr = cpu->get_next_pc();
629                                                 
630                                                 ////SetConsoleTextAttribute(hStdOut, FOREGROUND_GREEN | FOREGROUND_BLUE | FOREGROUND_INTENSITY);
631                                                 cpu->debug_dasm(cpu->get_pc(), buffer, 1024);
632                                                 my_printf(hStdOut, _T("done\t%08X  %s\n"), cpu->get_pc(), buffer);
633                                                 
634                                                 ////SetConsoleTextAttribute(hStdOut, FOREGROUND_RED | FOREGROUND_GREEN | FOREGROUND_BLUE | FOREGROUND_INTENSITY);
635                                                 cpu->debug_regs_info(buffer, 1024);
636                                                 my_printf(hStdOut, _T("%s\n"), buffer);
637                                                 
638                                                 //if(debugger->hit() || (GetAsyncKeyState(VK_ESCAPE) & 0x8000) != 0) {
639                                                 if(debugger->hit()) {
640                                                         break;
641                                                 }
642                                         }
643                                         if(debugger->hit()) {
644                                                 //SetConsoleTextAttribute(hStdOut, FOREGROUND_RED | FOREGROUND_INTENSITY);
645                                                 if(debugger->bp.hit) {
646                                                         my_printf(hStdOut, _T("breaked at %08X\n"), cpu->get_next_pc());
647                                                 } else if(debugger->rbp.hit) {
648                                                         my_printf(hStdOut, _T("breaked at %08X: memory %08X was read at %08X\n"), cpu->get_next_pc(), debugger->rbp.hit_addr, cpu->get_pc());
649                                                 } else if(debugger->wbp.hit) {
650                                                         my_printf(hStdOut, _T("breaked at %08X: memory %08X was written at %08X\n"), cpu->get_next_pc(), debugger->wbp.hit_addr, cpu->get_pc());
651                                                 } else if(debugger->ibp.hit) {
652                                                         my_printf(hStdOut, _T("breaked at %08X: port %08X was read at %08X\n"), cpu->get_next_pc(), debugger->ibp.hit_addr, cpu->get_pc());
653                                                 } else if(debugger->obp.hit) {
654                                                         my_printf(hStdOut, _T("breaked at %08X: port %08X was written at %08X\n"), cpu->get_next_pc(), debugger->obp.hit_addr, cpu->get_pc());
655                                                 }
656                                                 debugger->bp.hit = debugger->rbp.hit = debugger->wbp.hit = debugger->ibp.hit = debugger->obp.hit = false;
657                                         }
658                                         //SetConsoleTextAttribute(hStdOut, FOREGROUND_GREEN | FOREGROUND_BLUE | FOREGROUND_INTENSITY);
659                                         cpu->debug_dasm(cpu->get_next_pc(), buffer, 1024);
660                                         my_printf(hStdOut, _T("next\t%08X  %s\n"), cpu->get_next_pc(), buffer);
661                                         //SetConsoleTextAttribute(hStdOut, FOREGROUND_RED | FOREGROUND_GREEN | FOREGROUND_BLUE | FOREGROUND_INTENSITY);
662                                 } else {
663                                         my_printf(hStdOut, _T("invalid parameter number\n"));
664                                 }
665                         } else if(strcasecmp(params[0], _T("Q")) == 0) {
666                                 //PostMessage(p->emu->main_window_handle, WM_COMMAND, ID_CLOSE_DEBUGGER, 0L);
667                                 break;
668                         } else if(strcasecmp(params[0], _T("!")) == 0) {
669                                 if(num == 1) {
670                                         my_printf(hStdOut, _T("invalid parameter number\n"));
671                                 } else if(strcasecmp(params[1], _T("RESET")) == 0) {
672                                         if(num == 2) {
673                                                 p->vm->reset();
674                                         } else if(num == 3) {
675                                                 if(strcasecmp(params[2], _T("ALL")) == 0) {
676                                                         p->vm->reset();
677                                                 } if(strcasecmp(params[2], _T("CPU")) == 0) {
678                                                         cpu->reset();
679                                                 } else {
680                                                         my_printf(hStdOut, _T("unknown device %s\n"), params[2]);
681                                                 }
682                                         } else {
683                                                 my_printf(hStdOut, _T("invalid parameter number\n"));
684                                         }
685                                 } else if(strcasecmp(params[1], _T("KEY")) == 0) {
686                                         if(num == 3 || num == 4) {
687                                                 int code =  my_hexatoi(params[2]) & 0xff, msec = 100;
688                                                 if(num == 4) {
689                                                         msec = my_hexatoi(params[3]);
690                                                 }
691 #ifdef SUPPORT_VARIABLE_TIMING
692                                                 p->emu->key_buffer()[code] = (int)fmax(p->vm->frame_rate() * (double)msec / 1000.0 + 0.5, 1.0);
693 #else
694                                                 p->emu->key_buffer()[code] = (int)fmax(FRAMES_PER_SEC * (double)msec / 1000.0 + 0.5, 1.0);
695 #endif
696 #ifdef NOTIFY_KEY_DOWN
697                                                 p->vm->key_down(code, false);
698 #endif
699                                         } else {
700                                                 my_printf(hStdOut, _T("invalid parameter number\n"));
701                                         }
702                                 } else {
703                                         my_printf(hStdOut, _T("unknown command ! %s\n"), params[1]);
704                                 }
705                         } else if(strcasecmp(params[0], _T("?")) == 0) {
706                                 my_printf(hStdOut, _T("D [<range>] - dump memory\n"));
707                                 my_printf(hStdOut, _T("E[{B,W,D}] <address> <list> - edit memory (byte,word,dword)\n"));
708                                 my_printf(hStdOut, _T("EA <address> \"<value>\" - edit memory (ascii)\n"));
709                                 my_printf(hStdOut, _T("I[{B,W,D}] <port> - input port (byte,word,dword)\n"));
710                                 my_printf(hStdOut, _T("O[{B,W,D}] <port> <value> - output port (byte,word,dword)\n"));
711                                 my_printf(hStdOut, _T("R - show register(s)\n"));
712                                 my_printf(hStdOut, _T("R <reg> <value> - edit register\n"));
713                                 my_printf(hStdOut, _T("S <range> <list> - search\n"));
714                                 my_printf(hStdOut, _T("U [<range>] - unassemble\n"));
715                                 
716                                 my_printf(hStdOut, _T("H <value> <value> - hexadd\n"));
717                                 my_printf(hStdOut, _T("N <filename> - name\n"));
718                                 my_printf(hStdOut, _T("L <range> - load file\n"));
719                                 my_printf(hStdOut, _T("W <range> - write file\n"));
720                                 
721                                 my_printf(hStdOut, _T("BP <address> - set breakpoint\n"));
722                                 my_printf(hStdOut, _T("{R,W}BP <address> - set breakpoint (break at memory access)\n"));
723                                 my_printf(hStdOut, _T("{I,O}BP <port> [<mask>] - set breakpoint (break at i/o access)\n"));
724                                 my_printf(hStdOut, _T("[{R,W,I,O}]B{C,D,E} {all,<list>} - clear/disable/enable breakpoint(s)\n"));
725                                 my_printf(hStdOut, _T("[{R,W,I,O}]BL - list breakpoint(s)\n"));
726                                 
727                                 my_printf(hStdOut, _T("G - go (press esc key to break)\n"));
728                                 my_printf(hStdOut, _T("G <address> - go and break at address\n"));
729                                 my_printf(hStdOut, _T("T [<count>] - trace\n"));
730                                 my_printf(hStdOut, _T("Q - quit\n"));
731                                 
732                                 my_printf(hStdOut, _T("! reset [cpu] - reset\n"));
733                                 my_printf(hStdOut, _T("! key <code> [<msec>] - press key\n"));
734                                 
735                                 my_printf(hStdOut, _T("<value> - hexa, decimal(%%d), ascii('a')\n"));
736                         } else {
737                                 my_printf(hStdOut, _T("unknown command %s\n"), params[0]);
738                         }
739                 }
740         }
741    
742         
743         // stop debugger
744         try {
745                 debugger->now_debugging = debugger->now_going = debugger->now_suspended = false;
746         } catch(...) {
747         }
748         
749         // release console
750         //FreeConsole();
751         
752         p->running = false;
753         //_endthreadex(0);
754         return 0;
755 }
756
757
758 void CSP_Debugger::doWork(QObject *parent)
759 {
760         if(thread != NULL) {
761                 SDL_DetachThread(thread);
762         }
763         thread = SDL_CreateThread(debugger_main, "CSP:DEBUGGER", &debugger_thread_param);
764 }
765
766 void CSP_Debugger::doExit(void)
767 {
768         debugger_thread_param.request_terminate = true;
769         if(thread != NULL) {
770                 SDL_DetachThread(thread);
771                 thread = NULL;
772         }
773 }
774
775
776 CSP_Debugger::~CSP_Debugger()
777 {
778 //      delete hConsole;
779 //      delete debug_window;
780 }
781    
782 CSP_Debugger::CSP_Debugger(QObject *parent) : QObject(parent)
783 {
784 //      debug_window = new QMainWindow();
785 //      hConsole = new QTermWidget(0);
786         thread = NULL;
787 #ifdef Q_WS_MAC
788         font.setFamily("Monaco");
789 #elif defined(Q_WS_QWS)
790         font.setFamily("fixed");
791 #else
792         font.setFamily("Monospace");
793 #endif
794         font.setPointSize(14);
795 //      hConsole->setTerminalFont(font);
796 //      hConsole->setScrollBarPosition(QTermWidget::ScrollBarRight);
797 //      debug_window->setCentralWidget(hConsole);
798 //      debug_window->resize(600, 400);
799 //      QObject::connect(hConsole, SIGNAL(finished()), debug_window, SLOT(close()));
800 //      debug_window->show();
801 }
802
803
804 void EMU::initialize_debugger()
805 {
806         now_debugging = false;
807         hDebuggerThread = NULL;
808         hDebugger = NULL;
809 }
810
811 void EMU::release_debugger()
812 {
813         close_debugger();
814 }
815
816 void EMU::open_debugger(int cpu_index)
817 {
818         if(!(now_debugging && debugger_thread_param.cpu_index == cpu_index)) {
819                 close_debugger();
820                 if(vm->get_cpu(cpu_index) != NULL && vm->get_cpu(cpu_index)->get_debugger() != NULL) {
821
822                         hDebugger = new CSP_Debugger(NULL);
823                         hDebuggerThread = new QThread;
824                         hDebugger->debugger_thread_param.emu = this;
825                         hDebugger->debugger_thread_param.vm = vm;
826                         hDebugger->debugger_thread_param.cpu_index = cpu_index;
827                         hDebugger->debugger_thread_param.request_terminate = false;
828                         stop_rec_sound();
829                         stop_rec_video();
830                         now_debugging = true;
831                         //hDebugger->moveToThread(hDebuggerThread);
832                         //QMetaObject::invokeMethod(hDebugger, "start", Qt::QueuedConnection);
833                         hDebugger->doWork(NULL);                   
834                 }
835         }
836 }
837
838 void EMU::close_debugger()
839 {
840         if(now_debugging) {
841                 if(hDebugger->debugger_thread_param.running && (hDebugger->thread != NULL)) {
842                         hDebugger->debugger_thread_param.request_terminate = true;
843                         SDL_WaitThread(hDebugger->thread, NULL);
844                         //WaitForSingleObject(hDebuggerThread, INFINITE);
845                 }
846                 delete hDebuggerThread;
847                 delete hDebugger;
848                 hDebuggerThread = NULL;
849                 hDebugger = NULL;
850                 now_debugging = false;
851         }
852 }
853
854 bool EMU::debugger_enabled(int cpu_index)
855 {
856         return (vm->get_cpu(cpu_index) != NULL && vm->get_cpu(cpu_index)->get_debugger() != NULL);
857 }
858
859 #endif
860