Subversion Repositories pentevo

Rev

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