Subversion Repositories pentevo

Rev

Details | Last modification | View Log | RSS feed

Rev Author Line No. Line
716 lvd 1
#include "std.h"
2
 
3
#include "resource.h"
4
#include "emul.h"
5
#include "vars.h"
6
#include "debug.h"
7
#include "config.h"
8
#include "util.h"
9
 
10
enum
11
{
12
   DB_STOP = 0,
13
   DB_CHAR,
14
   DB_SHORT,
15
   DB_PCHAR,
16
   DB_PSHORT,
17
   DB_PINT,
18
   DB_PFUNC
19
};
20
 
21
typedef bool (__cdecl *func_t)();
22
 
23
unsigned calcerr;
24
unsigned calc(const Z80 *cpu, uintptr_t *script)
25
{
26
   unsigned stack[64];
27
   unsigned *sp = stack-1, x;
28
   while (*script) {
29
      switch (*script++) {
30
         case 'M':             *sp = cpu->DirectRm(*sp);   break;
31
         case '!':             *sp = !*sp;     break;
32
         case '~':             *sp = ~*sp;     break;
33
         case '+':             *(sp-1) += *sp; goto arith;
34
         case '-':             *(sp-1) -= *sp; goto arith;
35
         case '*':             *(sp-1) *= *sp; goto arith;
36
         case '/':             if (*sp) *(sp-1) /= *sp; goto arith;
37
         case '%':             if (*sp) *(sp-1) %= *sp; goto arith;
38
         case '&':             *(sp-1) &= *sp; goto arith;
39
         case '|':             *(sp-1) |= *sp; goto arith;
40
         case '^':             *(sp-1) ^= *sp; goto arith;
41
         case WORD2('-','>'):  *(sp-1) = cpu->DirectRm(*sp + sp[-1]); goto arith;
42
         case WORD2('>','>'):  *(sp-1) >>= *sp;goto arith;
43
         case WORD2('<','<'):  *(sp-1) <<= *sp;goto arith;
44
         case WORD2('!','='):  *(sp-1) = (sp[-1]!=*sp);goto arith;
45
         case '=':
46
         case WORD2('=','='):  *(sp-1) = (sp[-1]==*sp);goto arith;
47
         case WORD2('<','='):  *(sp-1) = (sp[-1]<=*sp);goto arith;
48
         case WORD2('>','='):  *(sp-1) = (sp[-1]>=*sp);goto arith;
49
         case WORD2('|','|'):  *(sp-1) = (sp[-1]||*sp);goto arith;
50
         case WORD2('&','&'):  *(sp-1) = (sp[-1]&&*sp);goto arith;
51
         case '<':             *(sp-1) = (sp[-1]<*sp);goto arith;
52
         case '>':             *(sp-1) = (sp[-1]>*sp);goto arith;
53
         arith:                sp--;  break;
54
         case DB_CHAR:
55
         case DB_SHORT:        x = *script++; goto push;
56
         case DB_PCHAR:        x = *(unsigned char*)*script++; goto push;
57
         case DB_PSHORT:       x = 0xFFFF & *(unsigned*)*script++; goto push;
58
         case DB_PINT:         x = *(unsigned*)*script++; goto push;
59
         case DB_PFUNC:        x = ((func_t)*script++)(); goto push;
60
         push:                 *++sp = x; break;
61
      } // switch (*script)
62
   } // while
63
   if (sp != stack) calcerr = 1;
64
   return *sp;
65
}
66
 
67
static bool __cdecl get_dos_flag()
68
{
69
    return (comp.flags & CF_DOSPORTS) != 0;
70
}
71
 
72
#define DECL_REGS(var, cpu)                        \
73
   static struct                                   \
74
   {                                               \
75
      unsigned reg;                                \
76
      const void *ptr;                             \
77
      unsigned char size;                          \
78
   } var[] =                                       \
79
   {                                               \
80
                                                   \
81
      { WORD4('D','O','S',0), (const void *)get_dos_flag, 0 },  \
82
      { WORD4('O','U','T',0), &brk_port_out, 4 },  \
83
      { WORD2('I','N'), &brk_port_in, 4 },         \
84
      { WORD4('V','A','L',0), &brk_port_val, 1 },  \
85
      { WORD2('F','D'), &comp.p7FFD, 1 },          \
86
                                                   \
87
      { WORD4('A','F','\'',0), &cpu.alt.af, 2 },   \
88
      { WORD4('B','C','\'',0), &cpu.alt.bc, 2 },   \
89
      { WORD4('D','E','\'',0), &cpu.alt.de, 2 },   \
90
      { WORD4('H','L','\'',0), &cpu.alt.hl, 2 },   \
91
      { WORD2('A','\''), &cpu.alt.a, 1 },          \
92
      { WORD2('F','\''), &cpu.alt.f, 1 },          \
93
      { WORD2('B','\''), &cpu.alt.b, 1 },          \
94
      { WORD2('C','\''), &cpu.alt.c, 1 },          \
95
      { WORD2('D','\''), &cpu.alt.d, 1 },          \
96
      { WORD2('E','\''), &cpu.alt.e, 1 },          \
97
      { WORD2('H','\''), &cpu.alt.h, 1 },          \
98
      { WORD2('L','\''), &cpu.alt.l, 1 },          \
99
                                                   \
100
      { WORD2('A','F'), &cpu.af, 2 },              \
101
      { WORD2('B','C'), &cpu.bc, 2 },              \
102
      { WORD2('D','E'), &cpu.de, 2 },              \
103
      { WORD2('H','L'), &cpu.hl, 2 },              \
104
      { 'A', &cpu.a, 1 },                          \
105
      { 'F', &cpu.f, 1 },                          \
106
      { 'B', &cpu.b, 1 },                          \
107
      { 'C', &cpu.c, 1 },                          \
108
      { 'D', &cpu.d, 1 },                          \
109
      { 'E', &cpu.e, 1 },                          \
110
      { 'H', &cpu.h, 1 },                          \
111
      { 'L', &cpu.l, 1 },                          \
112
                                                   \
113
      { WORD2('P','C'), &cpu.pc, 2 },              \
114
      { WORD2('S','P'), &cpu.sp, 2 },              \
115
      { WORD2('I','X'), &cpu.ix, 2 },              \
116
      { WORD2('I','Y'), &cpu.iy, 2 },              \
117
                                                   \
118
      { 'I', &cpu.i, 1 },                          \
119
      { 'R', &cpu.r_low, 1 },                      \
120
   }
121
 
122
 
123
static unsigned char toscript(char *script, uintptr_t *dst)
124
{
125
   uintptr_t *d1 = dst;
126
   static struct {
127
      unsigned short op;
128
      unsigned char prior;
129
   } prio[] = {
130
      { '(', 10 },
131
      { ')', 0 },
132
      { '!', 1 },
133
      { '~', 1 },
134
      { 'M', 1 },
135
      { WORD2('-','>'), 1 },
136
      { '*', 2 },
137
      { '%', 2 },
138
      { '/', 2 },
139
      { '+', 3 },
140
      { '-', 3 },
141
      { WORD2('>','>'), 4 },
142
      { WORD2('<','<'), 4 },
143
      { '>', 5 },
144
      { '<', 5 },
145
      { '=', 5 },
146
      { WORD2('>','='), 5 },
147
      { WORD2('<','='), 5 },
148
      { WORD2('=','='), 5 },
149
      { WORD2('!','='), 5 },
150
      { '&', 6 },
151
      { '^', 7 },
152
      { '|', 8 },
153
      { WORD2('&','&'), 9 },
154
      { WORD2('|','|'), 10 }
155
   };
156
 
157
   const Z80 &cpu = CpuMgr.Cpu();
158
 
159
   DECL_REGS(regs, cpu);
160
 
161
   unsigned sp = 0;
162
   uintptr_t stack[128];
163
   for (char *p = script; *p; p++)
164
       if (p[1] != 0x27)
165
           *p = toupper(*p);
166
 
167
   while (*script)
168
   {
169
      if (*(unsigned char*)script <= ' ')
170
      {
171
          script++;
172
          continue;
173
      }
174
 
175
      if (*script == '\'')
176
      { // char
177
         *dst++ = DB_CHAR;
178
         *dst++ = script[1];
179
         if (script[2] != '\'') return 0;
180
         script += 3; continue;
181
      }
182
 
183
      if (isalnum(*script) && *script != 'M')
184
      {
185
         unsigned r = -1, p = *(unsigned*)script;
186
         unsigned ln = 0;
187
         for (int i = 0; i < _countof(regs); i++)
188
         {
189
            unsigned mask = 0xFF; ln = 1;
190
            if (regs[i].reg & 0xFF00) mask = 0xFFFF, ln = 2;
191
            if (regs[i].reg & 0xFF0000) mask = 0xFFFFFF, ln = 3;
192
            if (regs[i].reg == (p & mask)) { r = i; break; }
193
         }
194
         if (r != -1)
195
         {
196
            script += ln;
197
            switch (regs[r].size)
198
            {
199
               case 0: *dst++ = DB_PFUNC; break;
200
               case 1: *dst++ = DB_PCHAR; break;
201
               case 2: *dst++ = DB_PSHORT; break;
202
               case 4: *dst++ = DB_PINT; break;
203
               default: errexit("BUG01");
204
            }
205
            *dst++ = (uintptr_t)regs[r].ptr;
206
         }
207
         else
208
         { // number
209
            if (*script > 'F') return 0;
210
            for (r = 0; isalnum(*script) && *script <= 'F'; script++)
211
               r = r*0x10 + ((*script >= 'A') ? *script-'A'+10 : *script-'0');
212
            *dst++ = DB_SHORT;
213
            *dst++ = r;
214
         }
215
         continue;
216
      }
217
      // find operation
218
      unsigned char pr = 0xFF;
219
      unsigned r = *script++;
220
      if (strchr("<>=&|-!", (char)r) && strchr("<>=&|", *script))
221
         r = r + 0x100 * (*script++);
222
      for (int i = 0; i < _countof(prio); i++)
223
      {
224
         if (prio[i].op == r)
225
         {
226
             pr = prio[i].prior;
227
             break;
228
         }
229
      }
230
      if (pr == 0xFF)
231
          return 0;
232
      if (r != '(')
233
      {
234
          while (sp && ((stack[sp] >> 16 <= pr) || (r == ')' && (stack[sp] & 0xFF) != '(')))
235
          { // get from stack
236
             *dst++ = stack[sp--] & 0xFFFF;
237
          }
238
      }
239
      if (r == ')')
240
          sp--; // del opening bracket
241
      else
242
          stack[++sp] = r+0x10000*pr; // put to stack
243
      if ((int)sp < 0)
244
          return 0; // no opening bracket
245
   }
246
   // empty stack
247
   while (sp)
248
   {
249
      if ((stack[sp] & 0xFF) == '(')
250
          return 0; // no closing bracket
251
      *dst++ = stack[sp--] & 0xFFFF;
252
   }
253
   *dst = DB_STOP;
254
 
255
   calcerr = 0;
256
   calc(&cpu, d1);
257
   return (1-calcerr);
258
}
259
 
260
static void script2text(char *dst, const uintptr_t *src)
261
{
262
   char stack[64][0x200], tmp[0x200];
263
   unsigned sp = 0, r;
264
 
265
   const Z80 &cpu = CpuMgr.Cpu();
266
 
267
   DECL_REGS(regs, cpu);
268
 
269
   while ((r = *src++))
270
   {
271
      if (r == DB_CHAR)
272
      {
273
         sprintf(stack[sp++], "'%c'", *src++);
274
         continue;
275
      }
276
      if (r == DB_SHORT)
277
      {
278
         sprintf(stack[sp], "0%X", *src++);
279
         if (isdigit(stack[sp][1])) strcpy(stack[sp], stack[sp]+1);
280
         sp++;
281
         continue;
282
      }
283
      if (r >= DB_PCHAR && r <= DB_PFUNC)
284
      {
285
         int i; //Alone Coder 0.36.7
286
         for (/*int*/ i = 0; i < _countof(regs); i++)
287
         {
288
            if (*src == (uintptr_t)regs[i].ptr)
289
                break;
290
         }
291
         *(unsigned*)&(stack[sp++]) = regs[i].reg;
292
         src++;
293
         continue;
294
      }
295
      if (r == 'M' || r == '~' || r == '!')
296
      { // unary operators
297
         sprintf(tmp, "%c(%s)", r, stack[sp-1]);
298
         strcpy(stack[sp-1], tmp);
299
         continue;
300
      }
301
      // else binary operators
302
      sprintf(tmp, "(%s%s%s)", stack[sp-2], (char*)&r, stack[sp-1]);
303
      sp--; strcpy(stack[sp-1], tmp);
304
   }
305
   if (!sp)
306
       *dst = 0;
307
   else
308
       strcpy(dst, stack[sp-1]);
309
}
310
 
311
void SetBpxButtons(HWND dlg)
312
{
313
   int focus = -1, text = 0, box = 0;
314
   HWND focusedWnd = GetFocus();
315
   if (focusedWnd == GetDlgItem(dlg, IDE_CBP) || focusedWnd == GetDlgItem(dlg, IDC_CBP))
316
      focus = 0, text = IDE_CBP, box = IDC_CBP;
317
   if (focusedWnd == GetDlgItem(dlg, IDE_BPX) || focusedWnd == GetDlgItem(dlg, IDC_BPX))
318
      focus = 1, text = IDE_BPX, box = IDC_BPX;
319
   if (focusedWnd == GetDlgItem(dlg, IDE_MEM) || focusedWnd == GetDlgItem(dlg, IDC_MEM) ||
320
       focusedWnd == GetDlgItem(dlg, IDC_MEM_R) || focusedWnd == GetDlgItem(dlg, IDC_MEM_W))
321
      focus = 2, text = IDE_MEM, box = IDC_MEM;
322
 
323
   SendDlgItemMessage(dlg, IDE_CBP, EM_SETREADONLY, (BOOL)(focus != 0), 0);
324
   SendDlgItemMessage(dlg, IDE_BPX, EM_SETREADONLY, (BOOL)(focus != 1), 0);
325
   SendDlgItemMessage(dlg, IDE_MEM, EM_SETREADONLY, (BOOL)(focus != 2), 0);
326
 
327
   int del0 = 0, add0 = 0, del1 = 0, add1 = 0, del2 = 0, add2 = 0;
328
   unsigned max = SendDlgItemMessage(dlg, box, LB_GETCOUNT, 0, 0),
329
            cur = SendDlgItemMessage(dlg, box, LB_GETCURSEL, 0, 0),
330
            len = SendDlgItemMessage(dlg, text, WM_GETTEXTLENGTH, 0, 0);
331
 
332
   if (max && cur >= max) SendDlgItemMessage(dlg, box, LB_SETCURSEL, cur = 0, 0);
333
 
334
   if (focus == 0) { if (len && max < MAX_CBP) add0 = 1; if (cur < max) del0 = 1; }
335
   if (focus == 1) { if (len) add1 = 1; if (cur < max) del1 = 1; }
336
   if (focus == 2) {
337
      if (IsDlgButtonChecked(dlg, IDC_MEM_R) == BST_UNCHECKED && IsDlgButtonChecked(dlg, IDC_MEM_W) == BST_UNCHECKED) len = 0;
338
      if (len) add2 = 1; if (cur < max) del2 = 1;
339
   }
340
 
341
   EnableWindow(GetDlgItem(dlg, IDB_CBP_ADD), add0);
342
   EnableWindow(GetDlgItem(dlg, IDB_CBP_DEL), del0);
343
   EnableWindow(GetDlgItem(dlg, IDB_BPX_ADD), add1);
344
   EnableWindow(GetDlgItem(dlg, IDB_BPX_DEL), del1);
345
   EnableWindow(GetDlgItem(dlg, IDB_MEM_ADD), add2);
346
   EnableWindow(GetDlgItem(dlg, IDB_MEM_DEL), del2);
347
 
348
   unsigned defid = 0;
349
   if (add0) defid = IDB_CBP_ADD;
350
   if (add1) defid = IDB_BPX_ADD;
351
   if (add2) defid = IDB_MEM_ADD;
352
   if (defid) SendMessage(dlg, DM_SETDEFID, defid, 0);
353
}
354
 
355
void ClearListBox(HWND box)
356
{
357
   while (SendMessage(box, LB_GETCOUNT, 0, 0))
358
      SendMessage(box, LB_DELETESTRING, 0, 0);
359
}
360
 
361
void FillCondBox(HWND dlg, unsigned cursor)
362
{
363
   HWND box = GetDlgItem(dlg, IDC_CBP);
364
   ClearListBox(box);
365
 
366
   Z80 &cpu = CpuMgr.Cpu();
367
   for (unsigned i = 0; i < cpu.cbpn; i++)
368
   {
369
      char tmp[0x200]; script2text(tmp, cpu.cbp[i]);
370
      SendMessage(box, LB_ADDSTRING, 0, (LPARAM)tmp);
371
   }
372
   SendMessage(box, LB_SETCURSEL, cursor, 0);
373
}
374
 
375
void FillBpxBox(HWND dlg, unsigned address)
376
{
377
   HWND box = GetDlgItem(dlg, IDC_BPX);
378
   ClearListBox(box);
379
   unsigned selection = 0;
380
 
381
   Z80 &cpu = CpuMgr.Cpu();
382
   unsigned end; //Alone Coder 0.36.7
383
   for (unsigned start = 0; start < 0x10000; )
384
   {
385
      if (!(cpu.membits[start] & MEMBITS_BPX))
386
      { start++; continue; }
387
      for (/*unsigned*/ end = start; end < 0xFFFF && (cpu.membits[end+1] & MEMBITS_BPX); end++);
388
      char tmp[16];
389
      if (start == end) sprintf(tmp, "%04X", start);
390
      else sprintf(tmp, "%04X-%04X", start, end);
391
      SendMessage(box, LB_ADDSTRING, 0, (LPARAM)tmp);
392
      if (start <= address && address <= end)
393
         selection = SendMessage(box, LB_GETCOUNT, 0, 0);
394
      start = end+1;
395
   }
396
   if (selection) SendMessage(box, LB_SETCURSEL, selection-1, 0);
397
}
398
 
399
void FillMemBox(HWND dlg, unsigned address)
400
{
401
   HWND box = GetDlgItem(dlg, IDC_MEM);
402
   ClearListBox(box);
403
   unsigned selection = 0;
404
 
405
   Z80 &cpu = CpuMgr.Cpu();
406
   unsigned end; //Alone Coder 0.36.7
407
   for (unsigned start = 0; start < 0x10000; ) {
408
      const unsigned char mask = MEMBITS_BPR | MEMBITS_BPW;
409
      if (!(cpu.membits[start] & mask)) { start++; continue; }
410
      unsigned active = cpu.membits[start];
411
      for (/*unsigned*/ end = start; end < 0xFFFF && !((active ^ cpu.membits[end+1]) & mask); end++);
412
      char tmp[16];
413
      if (start == end) sprintf(tmp, "%04X ", start);
414
      else sprintf(tmp, "%04X-%04X ", start, end);
415
      if (active & MEMBITS_BPR) strcat(tmp, "R");
416
      if (active & MEMBITS_BPW) strcat(tmp, "W");
417
      SendMessage(box, LB_ADDSTRING, 0, (LPARAM)tmp);
418
      if (start <= address && address <= end)
419
         selection = SendMessage(box, LB_GETCOUNT, 0, 0);
420
      start = end+1;
421
   }
422
   if (selection) SendMessage(box, LB_SETCURSEL, selection-1, 0);
423
}
424
 
425
char MoveBpxFromBoxToEdit(HWND dlg, unsigned box, unsigned edit)
426
{
427
   HWND hBox = GetDlgItem(dlg, box);
428
   unsigned max = SendDlgItemMessage(dlg, box, LB_GETCOUNT, 0, 0),
429
            cur = SendDlgItemMessage(dlg, box, LB_GETCURSEL, 0, 0);
430
   if (cur >= max) return 0;
431
   char tmp[0x200];
432
   SendMessage(hBox, LB_GETTEXT, cur, (LPARAM)tmp);
433
   if (box == IDC_MEM && *tmp) {
434
      char *last = tmp + strlen(tmp);
435
      unsigned r = BST_UNCHECKED, w = BST_UNCHECKED;
436
      if (last[-1] == 'W') w = BST_CHECKED, last--;
437
      if (last[-1] == 'R') r = BST_CHECKED, last--;
438
      if (last[-1] == ' ') last--;
439
      *last = 0;
440
      CheckDlgButton(dlg, IDC_MEM_R, r);
441
      CheckDlgButton(dlg, IDC_MEM_W, w);
442
   }
443
   SetDlgItemText(dlg, edit, tmp);
444
   return 1;
445
}
446
 
447
struct MEM_RANGE { unsigned start, end; };
448
 
449
int GetMemRamge(char *str, MEM_RANGE &range)
450
{
451
   while (*str == ' ') str++;
452
   for (range.start = 0; ishex(*str); str++)
453
      range.start = range.start*0x10 + hex(*str);
454
   if (*str == '-') {
455
      for (range.end = 0, str++; ishex(*str); str++)
456
         range.end = range.end*0x10 + hex(*str);
457
   } else range.end = range.start;
458
   while (*str == ' ') str++;
459
   if (*str) return 0;
460
 
461
   if (range.start > 0xFFFF || range.end > 0xFFFF || range.start > range.end) return 0;
462
   return 1;
463
}
464
 
465
 
466
INT_PTR CALLBACK conddlg(HWND dlg, UINT msg, WPARAM wp, LPARAM lp)
467
{
468
   if (msg == WM_INITDIALOG)
469
   {
470
      FillCondBox(dlg, 0);
471
      FillBpxBox(dlg, 0);
472
      FillMemBox(dlg, 0);
473
      SetFocus(GetDlgItem(dlg, IDE_CBP));
474
 
475
set_buttons_and_return:
476
      SetBpxButtons(dlg);
477
      return 1;
478
   }
479
   if (msg == WM_SYSCOMMAND && (wp & 0xFFF0) == SC_CLOSE) EndDialog(dlg, 0);
480
   if (msg != WM_COMMAND) return 0;
481
 
482
   unsigned id = LOWORD(wp), code = HIWORD(wp); unsigned char mask = 0;
483
   if (id == IDCANCEL || id == IDOK) EndDialog(dlg, 0);
484
   char tmp[0x200];
485
 
486
   if (((id == IDE_BPX || id == IDE_CBP || id == IDE_MEM) && (code == EN_SETFOCUS || code == EN_CHANGE)) ||
487
       ((id == IDC_BPX || id == IDC_CBP || id == IDC_MEM) && code == LBN_SETFOCUS)) goto set_buttons_and_return;
488
 
489
   if (id == IDC_MEM_R || id == IDC_MEM_W) goto set_buttons_and_return;
490
 
491
   if (code == LBN_DBLCLK)
492
   {
493
      if (id == IDC_CBP && MoveBpxFromBoxToEdit(dlg, IDC_CBP, IDE_CBP)) goto del_cond;
494
      if (id == IDC_BPX && MoveBpxFromBoxToEdit(dlg, IDC_BPX, IDE_BPX)) goto del_bpx;
495
      if (id == IDC_MEM && MoveBpxFromBoxToEdit(dlg, IDC_MEM, IDE_MEM)) goto del_mem;
496
   }
497
 
498
   if (id == IDB_CBP_ADD)
499
   {
500
      SendDlgItemMessage(dlg, IDE_CBP, WM_GETTEXT, sizeof tmp, (LPARAM)tmp);
501
      SetFocus(GetDlgItem(dlg, IDE_CBP));
502
      Z80 &cpu = CpuMgr.Cpu();
503
      if (!toscript(tmp, cpu.cbp[cpu.cbpn])) {
504
         MessageBox(dlg, "Error in expression\nPlease do RTFM", 0, MB_ICONERROR);
505
         return 1;
506
      }
507
      SendDlgItemMessage(dlg, IDE_CBP, WM_SETTEXT, 0, 0);
508
      FillCondBox(dlg, cpu.cbpn++);
509
      cpu.dbgchk = isbrk(cpu);
510
      goto set_buttons_and_return;
511
   }
512
 
513
   if (id == IDB_BPX_ADD)
514
   {
515
      SendDlgItemMessage(dlg, IDE_BPX, WM_GETTEXT, sizeof tmp, (LPARAM)tmp);
516
      SetFocus(GetDlgItem(dlg, IDE_BPX));
517
      MEM_RANGE range;
518
      if (!GetMemRamge(tmp, range))
519
      {
520
         MessageBox(dlg, "Invalid breakpoint address / range", 0, MB_ICONERROR);
521
         return 1;
522
      }
523
 
524
      Z80 &cpu = CpuMgr.Cpu();
525
      for (unsigned i = range.start; i <= range.end; i++)
526
         cpu.membits[i] |= MEMBITS_BPX;
527
      SendDlgItemMessage(dlg, IDE_BPX, WM_SETTEXT, 0, 0);
528
      FillBpxBox(dlg, range.start);
529
      cpu.dbgchk = isbrk(cpu);
530
      goto set_buttons_and_return;
531
   }
532
 
533
   if (id == IDB_MEM_ADD)
534
   {
535
      SendDlgItemMessage(dlg, IDE_MEM, WM_GETTEXT, sizeof tmp, (LPARAM)tmp);
536
      SetFocus(GetDlgItem(dlg, IDE_MEM));
537
      MEM_RANGE range;
538
      if (!GetMemRamge(tmp, range))
539
      {
540
         MessageBox(dlg, "Invalid watch address / range", 0, MB_ICONERROR);
541
         return 1;
542
      }
543
      unsigned char mask = 0;
544
      if (IsDlgButtonChecked(dlg, IDC_MEM_R) == BST_CHECKED) mask |= MEMBITS_BPR;
545
      if (IsDlgButtonChecked(dlg, IDC_MEM_W) == BST_CHECKED) mask |= MEMBITS_BPW;
546
 
547
      Z80 &cpu = CpuMgr.Cpu();
548
      for (unsigned i = range.start; i <= range.end; i++)
549
          cpu.membits[i] |= mask;
550
      SendDlgItemMessage(dlg, IDE_MEM, WM_SETTEXT, 0, 0);
551
      CheckDlgButton(dlg, IDC_MEM_R, BST_UNCHECKED);
552
      CheckDlgButton(dlg, IDC_MEM_W, BST_UNCHECKED);
553
      FillMemBox(dlg, range.start);
554
      cpu.dbgchk = isbrk(cpu);
555
      goto set_buttons_and_return;
556
   }
557
 
558
   if (id == IDB_CBP_DEL)
559
   {
560
del_cond:
561
      SetFocus(GetDlgItem(dlg, IDE_CBP));
562
      unsigned cur = SendDlgItemMessage(dlg, IDC_CBP, LB_GETCURSEL, 0, 0);
563
      Z80 &cpu = CpuMgr.Cpu();
564
      if (cur >= cpu.cbpn)
565
          return 0;
566
      cpu.cbpn--;
567
      memcpy(cpu.cbp[cur], cpu.cbp[cur+1], sizeof(cpu.cbp[0])*(cpu.cbpn-cur));
568
 
569
      if (cur && cur == cpu.cbpn)
570
          cur--;
571
      FillCondBox(dlg, cur);
572
      cpu.dbgchk = isbrk(cpu);
573
      goto set_buttons_and_return;
574
   }
575
 
576
   if (id == IDB_BPX_DEL)
577
   {
578
del_bpx:
579
      SetFocus(GetDlgItem(dlg, IDE_BPX));
580
      id = IDC_BPX; mask = ~MEMBITS_BPX;
581
del_range:
582
      unsigned cur = SendDlgItemMessage(dlg, id, LB_GETCURSEL, 0, 0),
583
               max = SendDlgItemMessage(dlg, id, LB_GETCOUNT, 0, 0);
584
      if (cur >= max) return 0;
585
      SendDlgItemMessage(dlg, id, LB_GETTEXT, cur, (LPARAM)tmp);
586
      unsigned start, end;
587
      sscanf(tmp, "%X", &start);
588
      if (tmp[4] == '-') sscanf(tmp+5, "%X", &end); else end = start;
589
 
590
      Z80 &cpu = CpuMgr.Cpu();
591
      for (unsigned i = start; i <= end; i++)
592
          cpu.membits[i] &= mask;
593
      if (id == IDC_BPX) FillBpxBox(dlg, 0); else FillMemBox(dlg, 0);
594
      if (cur && cur == max)
595
          cur--;
596
      SendDlgItemMessage(dlg, id, LB_SETCURSEL, cur, 0);
597
      cpu.dbgchk = isbrk(cpu);
598
      goto set_buttons_and_return;
599
   }
600
 
601
   if (id == IDB_MEM_DEL)
602
   {
603
del_mem:
604
      SetFocus(GetDlgItem(dlg, IDE_MEM));
605
      id = IDC_MEM; mask = ~(MEMBITS_BPR | MEMBITS_BPW);
606
      goto del_range;
607
   }
608
 
609
   return 0;
610
}
611
 
612
void mon_bpdialog()
613
{
614
   DialogBox(hIn, MAKEINTRESOURCE(IDD_COND), wnd, conddlg);
615
}
616
 
617
INT_PTR CALLBACK watchdlg(HWND dlg, UINT msg, WPARAM wp, LPARAM lp)
618
{
619
   char tmp[0x200]; unsigned i;
620
   static const int ids1[] = { IDC_W1_ON, IDC_W2_ON, IDC_W3_ON, IDC_W4_ON };
621
   static const int ids2[] = { IDE_W1, IDE_W2, IDE_W3, IDE_W4 };
622
   if (msg == WM_INITDIALOG) {
623
      for (i = 0; i < 4; i++) {
624
         CheckDlgButton(dlg, ids1[i], watch_enabled[i] ? BST_CHECKED : BST_UNCHECKED);
625
         script2text(tmp, watch_script[i]); SetWindowText(GetDlgItem(dlg, ids2[i]), tmp);
626
      }
627
      CheckDlgButton(dlg, IDC_TR_RAM, trace_ram ? BST_CHECKED : BST_UNCHECKED);
628
      CheckDlgButton(dlg, IDC_TR_ROM, trace_ram ? BST_CHECKED : BST_UNCHECKED);
629
reinit:
630
      for (i = 0; i < 4; i++)
631
         EnableWindow(GetDlgItem(dlg, ids2[i]), watch_enabled[i]);
632
      return 1;
633
   }
634
   if (msg == WM_COMMAND && (LOWORD(wp)==ids1[0] || LOWORD(wp)==ids1[1] || LOWORD(wp)==ids1[2] || LOWORD(wp)==ids1[3])) {
635
      for (i = 0; i < 4; i++)
636
         watch_enabled[i] = IsDlgButtonChecked(dlg, ids1[i]) == BST_CHECKED;
637
      goto reinit;
638
   }
639
   if ((msg == WM_SYSCOMMAND && (wp & 0xFFF0) == SC_CLOSE) || (msg == WM_COMMAND && LOWORD(wp) == IDCANCEL)) {
640
      trace_ram = IsDlgButtonChecked(dlg, IDC_TR_RAM) == BST_CHECKED;
641
      trace_rom = IsDlgButtonChecked(dlg, IDC_TR_ROM) == BST_CHECKED;
642
      for (i = 0; i < 4; i++)
643
         if (watch_enabled[i]) {
644
            SendDlgItemMessage(dlg, ids2[i], WM_GETTEXT, sizeof tmp, (LPARAM)tmp);
645
            if (!toscript(tmp, watch_script[i])) {
646
               sprintf(tmp, "Watch %d: error in expression\nPlease do RTFM", i+1);
647
               MessageBox(dlg, tmp, 0, MB_ICONERROR); watch_enabled[i] = 0;
648
               SetFocus(GetDlgItem(dlg, ids2[i]));
649
               return 0;
650
            }
651
         }
652
      EndDialog(dlg, 0);
653
   }
654
   return 0;
655
}
656
 
657
void mon_watchdialog()
658
{
659
   DialogBox(hIn, MAKEINTRESOURCE(IDD_OSW), wnd, watchdlg);
660
}
661
 
662
static void LoadBpx()
663
{
664
    char Line[100];
665
    char BpxFileName[FILENAME_MAX];
666
 
667
    addpath(BpxFileName, "bpx.ini");
668
 
669
    FILE *BpxFile = fopen(BpxFileName, "rt");
670
    if(!BpxFile)
671
        return;
672
 
673
    while(!feof(BpxFile))
674
    {
675
        fgets(Line, sizeof(Line), BpxFile);
676
        Line[sizeof(Line)-1] = 0;
677
        char Type = -1;
678
        int Start = -1, End = -1, CpuIdx = -1;
679
        int n = sscanf(Line, "%c%1d=%i-%i", &Type, &CpuIdx, &Start, &End);
680
        if(n < 3 || CpuIdx < 0 || CpuIdx >= (int)CpuMgr.GetCount() || Start < 0)
681
            continue;
682
 
683
        if(End < 0)
684
            End = Start;
685
 
686
        unsigned mask = 0;
687
        switch(Type)
688
        {
689
        case 'r': mask |= MEMBITS_BPR; break;
690
        case 'w': mask |= MEMBITS_BPW; break;
691
        case 'x': mask |= MEMBITS_BPX; break;
692
        default: continue;
693
        }
694
 
695
        Z80 &cpu = CpuMgr.Cpu(CpuIdx);
696
        for (unsigned i = unsigned(Start); i <= unsigned(End); i++)
697
            cpu.membits[i] |= mask;
698
        cpu.dbgchk = isbrk(cpu);
699
    }
700
    fclose(BpxFile);
701
}
702
 
703
static void SaveBpx()
704
{
705
    char BpxFileName[FILENAME_MAX];
706
 
707
    addpath(BpxFileName, "bpx.ini");
708
 
709
    FILE *BpxFile = fopen(BpxFileName, "wt");
710
    if(!BpxFile)
711
        return;
712
 
713
    for(unsigned CpuIdx = 0; CpuIdx < CpuMgr.GetCount(); CpuIdx++)
714
    {
715
        Z80 &cpu = CpuMgr.Cpu(CpuIdx);
716
 
717
        for(int i = 0; i < 3; i++)
718
        {
719
            for (unsigned Start = 0; Start < 0x10000; )
720
            {
721
               static const unsigned Mask[] = { MEMBITS_BPR, MEMBITS_BPW, MEMBITS_BPX };
722
               if (!(cpu.membits[Start] & Mask[i]))
723
               {
724
                   Start++;
725
                   continue;
726
               }
727
               unsigned active = cpu.membits[Start];
728
               unsigned End;
729
               for (End = Start; End < 0xFFFF && !((active ^ cpu.membits[End+1]) & Mask[i]); End++);
730
 
731
               static const char Type[] = { 'r', 'w', 'x' };
732
               if(active & Mask[i])
733
               {
734
                   if (Start == End)
735
                       fprintf(BpxFile, "%c%1d=0x%04X\n", Type[i], CpuIdx, Start);
736
                   else
737
                       fprintf(BpxFile, "%c%1d=0x%04X-0x%04X\n", Type[i], CpuIdx, Start, End);
738
               }
739
 
740
               Start = End + 1;
741
            }
742
        }
743
    }
744
 
745
    fclose(BpxFile);
746
}
747
 
748
void init_bpx()
749
{
750
    LoadBpx();
751
}
752
 
753
void done_bpx()
754
{
755
    SaveBpx();
756
}