Subversion Repositories pentevo

Rev

Rev 887 | Details | Compare with Previous | Last modification | View Log | RSS feed

Rev Author Line No. Line
716 lvd 1
#include "std.h"
2
 
3
#include "resource.h"
4
 
5
#include "emul.h"
6
#include "vars.h"
7
#include "debug.h"
8
#include "dbgpaint.h"
9
#include "dbglabls.h"
10
#include "memory.h"
11
#include "config.h"
12
#include "util.h"
13
 
14
MON_LABELS mon_labels;
15
 
16
void MON_LABELS::start_watching_labels()
17
{
18
   addpath(userfile, "?");
19
   hNewUserLabels = FindFirstChangeNotification(userfile, 0, FILE_NOTIFY_CHANGE_FILE_NAME | FILE_NOTIFY_CHANGE_LAST_WRITE);
20
   addpath(userfile, "user.l");
21
}
22
 
23
void MON_LABELS::stop_watching_labels()
24
{
25
   if (!hNewUserLabels || hNewUserLabels == INVALID_HANDLE_VALUE) return;
26
   CloseHandle(hNewUserLabels);
27
   hNewUserLabels = INVALID_HANDLE_VALUE;
28
}
29
 
30
void MON_LABELS::notify_user_labels()
31
{
32
   if (hNewUserLabels == INVALID_HANDLE_VALUE) return;
33
   // load labels at first check
784 DimkaM 34
   if (hNewUserLabels == nullptr) { start_watching_labels(); import_file(); return; }
716 lvd 35
 
36
   if (WaitForSingleObject(hNewUserLabels, 0) != WAIT_OBJECT_0) return;
37
 
38
   import_file();
39
   FindNextChangeNotification(hNewUserLabels);
40
}
41
 
42
unsigned MON_LABELS::add_name(char *name)
43
{
784 DimkaM 44
   size_t len = strlen(name)+1, new_size = names_size + len;
45
   if (new_size > align_by(names_size, 4096U))
46
      names = (char*)realloc(names, align_by(new_size, 4096U));
716 lvd 47
   unsigned result = names_size;
48
   memcpy(names + result, name, len);
784 DimkaM 49
   names_size = unsigned(new_size);
716 lvd 50
   return result;
51
}
52
 
53
void MON_LABELS::clear(unsigned char *start, unsigned size)
54
{
55
   unsigned dst = 0;
56
   for (unsigned src = 0; src < n_pairs; src++)
57
      if ((unsigned)(pairs[src].address - start) > size)
58
         pairs[dst++] = pairs[src];
59
   n_pairs = dst;
60
   // pack `names'
784 DimkaM 61
   char *pnames = names; names = nullptr; names_size = 0;
716 lvd 62
   for (unsigned l = 0; l < n_pairs; l++)
63
      pairs[l].name_offs = add_name(pnames + pairs[l].name_offs);
64
   free(pnames);
65
}
66
 
784 DimkaM 67
static int __cdecl labels_sort_func(const void *e1, const void *e2)
716 lvd 68
{
784 DimkaM 69
    const MON_LABEL *a = (const MON_LABEL*)e1;
70
    const MON_LABEL *b = (const MON_LABEL*)e2;
71
   return int(ptrdiff_t(a->address - b->address));
716 lvd 72
}
73
 
74
void MON_LABELS::sort()
75
{
76
   qsort(pairs, n_pairs, sizeof(MON_LABEL), labels_sort_func);
77
}
78
 
79
void MON_LABELS::add(unsigned char *address, char *name)
80
{
784 DimkaM 81
   if (n_pairs >= align_by(n_pairs, 1024U))
82
      pairs = (MON_LABEL*)realloc(pairs, sizeof(MON_LABEL) * align_by(n_pairs+1, 1024U));
716 lvd 83
   pairs[n_pairs].address = address;
84
   pairs[n_pairs].name_offs = add_name(name);
85
   n_pairs++;
86
}
87
 
88
char *MON_LABELS::find(unsigned char *address)
89
{
90
   unsigned l = 0, r = n_pairs;
91
   for (;;) {
784 DimkaM 92
      if (l >= r) return nullptr;
716 lvd 93
      unsigned m = (l+r)/2;
94
      if (pairs[m].address == address) return names + pairs[m].name_offs;
95
      if (pairs[m].address < address) l = m+1; else r = m;
96
   }
97
}
98
 
99
unsigned MON_LABELS::load(char *filename, unsigned char *base, unsigned size)
100
{
887 lvd 101
   int virt_addr;
102
 
716 lvd 103
   FILE *in = fopen(filename, "rt");
104
   if (!in)
105
   {
106
       errmsg("can't find label file %s", filename);
107
       return 0;
108
   }
109
 
110
   clear(base, size);
784 DimkaM 111
   unsigned l_counter = 0, loaded = 0; char *txt = nullptr;
112
   size_t l; //Alone Coder 0.36.7
716 lvd 113
   while (!feof(in)) {
114
      char line[64];
115
      if (!fgets(line, sizeof(line), in)) break;
116
      l_counter++;
784 DimkaM 117
      for (/*int*/ l = strlen(line); l && line[l-1] <= ' '; l--);
118
      line[l] = 0;
716 lvd 119
      if (!l) continue;
120
      unsigned val = 0, offset = 0;
887 lvd 121
      virt_addr = 0;
122
      if (l >= 6 && line[0]!=':' && line[4] == ' ')
716 lvd 123
      { // адрес без номера банка xxxx label
124
         for (l = 0; l < 4; l++)
125
         {
126
            if (!ishex(line[l]))
127
                goto ll_err;
128
            val = (val * 0x10) + hex(line[l]);
129
         }
130
         txt = line+5;
131
      }
887 lvd 132
      else if (l >= 7 && line[0]==':' && line[5] == ' ')
133
      { // :xxxx label -- virtual addresses (in Z80 addr space, not coupled to pages)
134
         for (l = 1; l < 5; l++)
135
         {
136
            if (!ishex(line[l]))
137
               goto ll_err;
138
            val = (val * 0x10) + hex(line[l]);
139
         }
140
         txt = line+6;
141
         virt_addr = 1;
142
      }
716 lvd 143
      else if (l >= 9 && line[2] == ':' && line[7] == ' ')
144
      { // адрес сномером банка bb:xxxx label
145
         for (l = 0; l < 2; l++)
146
         {
147
            if (!ishex(line[l]))
148
                goto ll_err;
149
            val = (val * 0x10) + hex(line[l]);
150
         }
151
         for (l = 3; l < 7; l++)
152
         {
153
            if (!ishex(line[l]))
154
                goto ll_err;
155
            offset = (offset * 0x10) + hex(line[l]);
156
         }
157
         val = val*PAGE + (offset & (PAGE-1));
158
         txt = line+8;
159
      }
160
      else
161
      {
887 lvd 162
ll_err:
716 lvd 163
         color(CONSCLR_ERROR);
784 DimkaM 164
         printf("error in %s, line %u\n", filename, l_counter);
716 lvd 165
         continue;
166
      }
167
 
887 lvd 168
      if (!virt_addr && (val < size))
169
      {
170
          add(base+val, txt);
171
          loaded++;
172
      }
173
      else if (virt_addr)
174
      {
883 lvd 175
          add(((unsigned char *)NULL)+val, txt);
716 lvd 176
          loaded++;
887 lvd 177
      }
716 lvd 178
   }
179
   fclose(in);
180
   sort();
181
   return loaded;
182
}
183
 
184
unsigned MON_LABELS::alasm_chain_len(unsigned char *page, unsigned offset, unsigned &end)
185
{
186
   unsigned count = 0;
187
   for (;;) {
188
      if (offset >= 0x3FFC) return 0;
189
      unsigned s1 = page[offset], sz = s1 & 0x3F;
190
      if (!s1 || offset == 0x3E00) { end = offset+1; return count; }
191
      if (sz < 6) return 0;
192
      unsigned char sym = page[offset+sz-1];
193
      if (sym >= '0' && sym <= '9') return 0;
194
      for (unsigned ptr = 5; ptr < sz; ptr++)
195
         if (!alasm_valid_char[page[offset+ptr]]) return 0;
196
      if (!(s1 & 0xC0)) count++;
197
      offset += sz;
198
   }
199
}
200
 
201
void MON_LABELS::find_alasm()
202
{
203
   static const char label_chars[] = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz@$_";
204
   memset(alasm_valid_char, 0, sizeof alasm_valid_char);
784 DimkaM 205
   for (const char *lbl = label_chars; *lbl; lbl++) alasm_valid_char[unsigned(*lbl)] = 1;
716 lvd 206
 
207
   alasm_found_tables = 0;
208
   for (unsigned page = 0; page < conf.ramsize*1024; page += PAGE) {
209
      for (unsigned offset = 0; offset < PAGE; offset++) {
210
         unsigned end, count = alasm_chain_len(RAM_BASE_M + page, offset, end);
211
         if (count < 2) continue;
212
         alasm_count[alasm_found_tables] = count;
213
         alasm_offset[alasm_found_tables] = page + offset;
214
         offset = end; alasm_found_tables++;
215
         if (alasm_found_tables == MAX_ALASM_LTABLES) return;
216
      }
217
   }
218
}
219
 
220
 
221
void MON_LABELS::import_alasm(unsigned offset, char *caption)
222
{
784 DimkaM 223
    (void)caption;
224
 
716 lvd 225
   clear_ram();
226
   unsigned char *base = RAM_BASE_M + offset;
227
   for (;;) { // #FE00/FF00/FFFC - end of labels?
228
      unsigned char sz = *base; if (!sz) break;
229
      if (!(sz & 0xC0)) {
230
         char lbl[64]; unsigned ptr = 0;
784 DimkaM 231
         for(unsigned k = sz; k > 5;)
232
         {
233
             k--;
234
             lbl[ptr++] = char(base[k]);
235
         }
236
         lbl[ptr] = 0;
716 lvd 237
         unsigned val = *(unsigned short*)(base+1);
238
         unsigned char *bs;
239
         switch (val & 0xC000) {
240
            case 0x4000: bs = RAM_BASE_M+5*PAGE; break;
241
            case 0x8000: bs = RAM_BASE_M+2*PAGE; break;
242
            case 0xC000: bs = RAM_BASE_M+0*PAGE; break;
784 DimkaM 243
            default: bs = nullptr;
716 lvd 244
         }
245
         if (bs) add(bs+(val & 0x3FFF), lbl);
246
      }
247
      base += (sz & 0x3F);
248
   }
249
   sort();
250
}
251
 
252
void MON_LABELS::find_xas()
253
{
254
   char look_page_6 = 0;
255
   const char *err = "XAS labels not found in bank #06";
784 DimkaM 256
   if(conf.mem_model == MM_PENTAGON && conf.ramsize > 128)
257
   {
258
       err = "XAS labels not found in banks #06,#46";
259
       look_page_6 = 1;
260
   }
716 lvd 261
   xaspage = 0;
262
   if (look_page_6 && RAM_BASE_M[PAGE*14+0x3FFF] == 5 && RAM_BASE_M[PAGE*14+0x1FFF] == 5) xaspage = 0x46;
263
   if (!xaspage && RAM_BASE_M[PAGE*6+0x3FFF] == 5 && RAM_BASE_M[PAGE*6+0x1FFF] == 5) xaspage = 0x06;
264
   if (!xaspage) strcpy(xas_errstr, err);
265
   else sprintf(xas_errstr, "XAS labels from bank #%02X", xaspage);
266
}
267
 
268
void MON_LABELS::import_xas()
269
{
270
   if (!xaspage) return;
271
   unsigned base = (xaspage == 0x46)? 0x0E*PAGE : (unsigned)xaspage*PAGE;
272
 
273
   clear_ram(); unsigned count = 0;
274
   int i; //Alone Coder 0.36.7
275
   for (int k = 0; k < 2; k++) {
276
      unsigned char *ptr = RAM_BASE_M + base + (k? 0x3FFD : 0x1FFD);
277
      for (;;) {
278
         if (ptr[2] < 5 || (ptr[2] & 0x80)) break;
784 DimkaM 279
         char lbl[16];
280
         for(/*int*/ i = 0; i < 7; i++)
281
         {
282
             lbl[i] = char(ptr[i - 7]);
283
         }
284
         for (i = 7; i && lbl[i-1]==' '; i--);
285
 
286
         lbl[i] = 0;
716 lvd 287
         unsigned val = *(unsigned short*)ptr;
288
         unsigned char *bs;
289
         switch (val & 0xC000) {
290
            case 0x4000: bs = RAM_BASE_M+5*PAGE; break;
291
            case 0x8000: bs = RAM_BASE_M+2*PAGE; break;
292
            case 0xC000: bs = RAM_BASE_M+0*PAGE; break;
784 DimkaM 293
            default: bs = nullptr;
716 lvd 294
         }
784 DimkaM 295
         if(bs)
296
         {
297
             add(bs + (val & 0x3FFF), lbl);
298
             count++;
299
         }
716 lvd 300
         ptr -= 9; if (ptr < RAM_BASE_M+base+9) break;
301
      }
302
   }
303
   sort();
784 DimkaM 304
   char ln[64]; sprintf(ln, "imported %u labels", count);
716 lvd 305
   MessageBox(GetForegroundWindow(), ln, xas_errstr, MB_OK | MB_ICONINFORMATION);
306
}
307
 
308
void MON_LABELS::import_menu()
309
{
310
   find_xas();
311
   find_alasm();
312
 
784 DimkaM 313
   MENUITEM items[MAX_ALASM_LTABLES+4] = { };
716 lvd 314
   unsigned menuptr = 0;
315
 
316
   items[menuptr].text = xas_errstr;
317
   items[menuptr].flags = xaspage? (MENUITEM::FLAGS)0 : MENUITEM::DISABLED;
318
   menuptr++;
319
 
320
   char alasm_text[MAX_ALASM_LTABLES][64];
321
   if (!alasm_found_tables) {
784 DimkaM 322
      sprintf(alasm_text[0], "No ALASM labels in whole %uK memory", conf.ramsize);
716 lvd 323
      items[menuptr].text = alasm_text[0];
324
      items[menuptr].flags = MENUITEM::DISABLED;
325
      menuptr++;
326
   } else {
327
      for (unsigned i = 0; i < alasm_found_tables; i++) {
784 DimkaM 328
         sprintf(alasm_text[i], "%u ALASM labels in page %u, offset #%04X", alasm_count[i], alasm_offset[i]/PAGE, (alasm_offset[i] & 0x3FFF) | 0xC000);
716 lvd 329
         items[menuptr].text = alasm_text[i];
330
         items[menuptr].flags = (MENUITEM::FLAGS)0;
331
         menuptr++;
332
      }
333
   }
334
 
335
   items[menuptr].text = nil;
336
   items[menuptr].flags = MENUITEM::DISABLED;
337
   menuptr++;
338
 
339
   items[menuptr].text = "CANCEL";
340
   items[menuptr].flags = MENUITEM::CENTER;
341
   menuptr++;
342
 
343
   MENUDEF menu = { items, menuptr, "import labels" };
344
   if (!handle_menu(&menu)) return;
345
   if (menu.pos == 0) import_xas();
346
   menu.pos--;
347
   if ((unsigned)menu.pos < alasm_found_tables) import_alasm(alasm_offset[menu.pos], alasm_text[menu.pos]);
348
}
349
 
350
void MON_LABELS::import_file()
351
{
352
   FILE *ff = fopen(userfile, "rb"); if (!ff) return; fclose(ff);
353
   unsigned count = load(userfile, RAM_BASE_M, conf.ramsize * 1024);
354
   if (!count) return;
355
   char tmp[0x200];
784 DimkaM 356
   sprintf(tmp, "loaded %u labels from\r\n%s", count, userfile);
716 lvd 357
   puts(tmp);
358
   //MessageBox(GetForegroundWindow(), tmp, "unreal discovered changes in user labels", MB_OK | MB_ICONINFORMATION);//removed by Alone Coder
359
}
360
 
361
void load_labels(char *filename, unsigned char *base, unsigned size)
362
{
363
   mon_labels.load(filename, base, size);
364
}
365
 
784 DimkaM 366
static char curlabel[64];
367
static unsigned lcount;
716 lvd 368
 
784 DimkaM 369
static void ShowLabels()
716 lvd 370
{
371
   SetDlgItemText(dlg, IDC_LABEL_TEXT, curlabel);
372
   HWND list = GetDlgItem(dlg, IDC_LABELS);
373
 
374
   while (SendMessage(list, LB_GETCOUNT, 0, 0))
375
      SendMessage(list, LB_DELETESTRING, 0, 0);
376
 
784 DimkaM 377
   size_t ln = strlen(curlabel); lcount = 0;
716 lvd 378
   char *s; //Alone Coder 0.36.7
379
   for (unsigned p = 0; p < 4; p++)
380
   {
381
      unsigned char *base = am_r(p*PAGE);
382
      for (unsigned i = 0; i < mon_labels.n_pairs; i++)
383
      {
384
         unsigned char *label = mon_labels.pairs[i].address;
385
         if (label < base || label >= base + PAGE)
386
             continue;
387
         char *name = mon_labels.pairs[i].name_offs + mon_labels.names;
388
         if (ln)
389
         {
390
            // unfortunately, strstr() is case sensitive, use loop
391
            for (/*char * */s = name; *s; s++)
392
               if (!strnicmp(s, curlabel, ln)) break;
393
            if (!*s) continue;
394
         }
395
         char zz[0x400];
784 DimkaM 396
         sprintf(zz, "%04X %s", unsigned((label - base) + (p * PAGE)), name);
716 lvd 397
         SendMessage(list, LB_ADDSTRING, 0, (LPARAM)zz); lcount++;
398
      }
399
   }
400
   SendMessage(list, LB_SETCURSEL, 0, 0);
401
   SetFocus(list);
402
}
403
 
784 DimkaM 404
static INT_PTR CALLBACK LabelsDlg(HWND dlg, UINT msg, WPARAM wp, LPARAM lp)
716 lvd 405
{
784 DimkaM 406
    (void)lp;
407
 
716 lvd 408
   ::dlg = dlg;
409
   if (msg == WM_INITDIALOG)
410
   {
411
      *curlabel = 0;
412
      ShowLabels();
413
      return 1;
414
   }
415
 
416
   if (msg == WM_SYSCOMMAND && (wp & 0xFFF0) == SC_CLOSE) EndDialog(dlg, 0);
417
 
418
   if (msg == WM_VKEYTOITEM)
419
   {
784 DimkaM 420
       size_t sz = strlen(curlabel);
421
       wp = LOWORD(wp);
422
       if(wp == VK_BACK)
423
       {
424
           if(sz)
425
           {
426
               curlabel[sz - 1] = 0;
427
               ShowLabels();
428
           }
429
           else { deadkey: Beep(300, 100); }
430
       }
431
       else if((unsigned)(wp - '0') < 10 || (unsigned)(wp - 'A') < 26 || wp == '_')
432
       {
433
           if(sz == sizeof(curlabel) - 1)
434
           {
435
               goto deadkey;
436
           }
437
           curlabel[sz] = char(wp);
438
           curlabel[sz + 1] = 0;
439
           ShowLabels();
440
           if(!lcount)
441
           {
442
               curlabel[sz] = 0;
443
               ShowLabels();
444
               goto deadkey;
445
           }
446
       }
447
       else
448
       {
449
           return -1;
450
       }
451
       return -2;
716 lvd 452
   }
453
 
454
   if (msg != WM_COMMAND) return 0;
455
 
456
   unsigned id = LOWORD(wp), code = HIWORD(wp);
457
   if (id == IDCANCEL || id == IDOK) EndDialog(dlg, 0);
458
 
459
   if (id == IDOK || (id == IDC_LABELS && code == LBN_DBLCLK))
460
   {
461
      HWND list = GetDlgItem(dlg, IDC_LABELS);
784 DimkaM 462
      unsigned n = unsigned(SendMessage(list, LB_GETCURSEL, 0, 0));
716 lvd 463
      if (n >= lcount) return 0;
464
      char zz[0x400]; SendMessage(list, LB_GETTEXT, n, (LPARAM)zz);
465
      unsigned address; sscanf(zz, "%X", &address);
466
 
467
      void push_pos(); push_pos();
468
      CpuMgr.Cpu().trace_curs = CpuMgr.Cpu().trace_top = address;
469
      activedbg = WNDTRACE;
470
 
471
      EndDialog(dlg, 1);
472
      return 1;
473
   }
474
 
475
   return 0;
476
}
477
 
478
void mon_show_labels()
479
{
480
   DialogBox(hIn, MAKEINTRESOURCE(IDD_LABELS), wnd, LabelsDlg);
481
}