Subversion Repositories pentevo

Rev

Rev 796 | Blame | Compare with Previous | Last modification | View Log | Download | RSS feed | ?url?

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