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