Subversion Repositories pentevo

Rev

Rev 887 | 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.    int virt_addr;
  102.  
  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);
  111.    unsigned l_counter = 0, loaded = 0; char *txt = nullptr;
  112.    size_t l; //Alone Coder 0.36.7
  113.    while (!feof(in)) {
  114.       char line[64];
  115.       if (!fgets(line, sizeof(line), in)) break;
  116.       l_counter++;
  117.       for (/*int*/ l = strlen(line); l && line[l-1] <= ' '; l--);
  118.       line[l] = 0;
  119.       if (!l) continue;
  120.       unsigned val = 0, offset = 0;
  121.       virt_addr = 0;
  122.       if (l >= 6 && line[0]!=':' && line[4] == ' ')
  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.       }
  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.       }
  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.       {
  162. ll_err:
  163.          color(CONSCLR_ERROR);
  164.          printf("error in %s, line %u\n", filename, l_counter);
  165.          continue;
  166.       }
  167.  
  168.       if (!virt_addr && (val < size))
  169.       {
  170.           add(base+val, txt);
  171.           loaded++;
  172.       }
  173.       else if (virt_addr)
  174.       {
  175.           add(((unsigned char *)NULL)+val, txt);
  176.           loaded++;
  177.       }
  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);
  205.    for (const char *lbl = label_chars; *lbl; lbl++) alasm_valid_char[unsigned(*lbl)] = 1;
  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. {
  223.     (void)caption;
  224.  
  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;
  231.          for(unsigned k = sz; k > 5;)
  232.          {
  233.              k--;
  234.              lbl[ptr++] = char(base[k]);
  235.          }
  236.          lbl[ptr] = 0;
  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;
  243.             default: bs = nullptr;
  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";
  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.    }
  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;
  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;
  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;
  293.             default: bs = nullptr;
  294.          }
  295.          if(bs)
  296.          {
  297.              add(bs + (val & 0x3FFF), lbl);
  298.              count++;
  299.          }
  300.          ptr -= 9; if (ptr < RAM_BASE_M+base+9) break;
  301.       }
  302.    }
  303.    sort();
  304.    char ln[64]; sprintf(ln, "imported %u labels", count);
  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.  
  313.    MENUITEM items[MAX_ALASM_LTABLES+4] = { };
  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) {
  322.       sprintf(alasm_text[0], "No ALASM labels in whole %uK memory", conf.ramsize);
  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++) {
  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);
  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];
  356.    sprintf(tmp, "loaded %u labels from\r\n%s", count, userfile);
  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.  
  366. static char curlabel[64];
  367. static unsigned lcount;
  368.  
  369. static void ShowLabels()
  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.  
  377.    size_t ln = strlen(curlabel); lcount = 0;
  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];
  396.          sprintf(zz, "%04X %s", unsigned((label - base) + (p * PAGE)), name);
  397.          SendMessage(list, LB_ADDSTRING, 0, (LPARAM)zz); lcount++;
  398.       }
  399.    }
  400.    SendMessage(list, LB_SETCURSEL, 0, 0);
  401.    SetFocus(list);
  402. }
  403.  
  404. static INT_PTR CALLBACK LabelsDlg(HWND dlg, UINT msg, WPARAM wp, LPARAM lp)
  405. {
  406.     (void)lp;
  407.  
  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.    {
  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;
  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);
  462.       unsigned n = unsigned(SendMessage(list, LB_GETCURSEL, 0, 0));
  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. }
  482.