Subversion Repositories pentevo

Rev

Rev 716 | Blame | Last modification | View Log | Download | RSS feed

  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. }
  417.