Subversion Repositories pentevo

Rev

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

  1. #include "std.h"
  2.  
  3. #include "resource.h"
  4. #include "emul.h"
  5. #include "vars.h"
  6. #include "dxr_text.h"
  7. #include "fntsrch.h"
  8.  
  9. #include "util.h"
  10.  
  11. #ifdef MOD_SETTINGS
  12. static unsigned font_maxmem = 0xFFFF;
  13. static unsigned char r21=1, r30=1, r41=1, r61=1, r80=1, rae=1, rf0=0, roth=0;
  14. static unsigned char linear = 0, right = 1, x100 = 1;
  15. static unsigned char rmask[0x100];
  16. static unsigned font_address;
  17. static unsigned char fontdata2[0x900*2];
  18. static unsigned fontsize = 8;
  19. static unsigned block_font_dialog = 0;
  20. static unsigned char *font_base;
  21.  
  22.  
  23. static void update_rmask()
  24. {
  25.    memset(rmask, 0, sizeof rmask);
  26.    if (r21) memset(rmask+0x21, 1, 0x0F);
  27.    if (r30) memset(rmask+0x30, 1, 10);
  28.    if (r41) memset(rmask+0x41, 1, 26);
  29.    if (r61) memset(rmask+0x61, 1, 26);
  30.    if (r80) memset(rmask+0x80, 1, 32);
  31.    if(rae)
  32.    {
  33.        memset(rmask + 0xA0, 1, 16);
  34.        memset(rmask + 0xE0, 1, 16);
  35.    }
  36.    if (rf0) rmask[0xF0] = rmask[0xF1] = 1;
  37.    if(roth)
  38.    {
  39.        memset(rmask + 1, 1, 0x1F);
  40.        memset(rmask + 0xB0, 1, 0x30);
  41.        memset(rmask + 0xF2, 1, 13);
  42.        memset(rmask + 0x3A, 1, 7);
  43.        memset(rmask + 0x5B, 1, 6);
  44.        memset(rmask + 0x7B, 1, 5);
  45.    }
  46. }
  47.  
  48. static void get_ranges(HWND dlg)
  49. {
  50.    char ln[64]; GetDlgItemText(dlg, IDE_ADDRESS, ln, sizeof ln);
  51.    sscanf(ln, "%X", &font_address); font_address &= font_maxmem;
  52.  
  53.    linear = (IsDlgButtonChecked(dlg, IDC_LINEAR) == BST_CHECKED)? 1 : 0;
  54.    right = (IsDlgButtonChecked(dlg, IDC_RIGHT) == BST_CHECKED)? 1 : 0;
  55.    x100 = (IsDlgButtonChecked(dlg, IDC_100) == BST_CHECKED)? 1 : 0;
  56.  
  57.    r21 = IsDlgButtonChecked(dlg, IDC_R212F) == BST_CHECKED;
  58.    r30 = IsDlgButtonChecked(dlg, IDC_R3039) == BST_CHECKED;
  59.    r41 = IsDlgButtonChecked(dlg, IDC_R415A) == BST_CHECKED;
  60.    r61 = IsDlgButtonChecked(dlg, IDC_R617A) == BST_CHECKED;
  61.    r80 = IsDlgButtonChecked(dlg, IDC_R809F) == BST_CHECKED;
  62.    rae = IsDlgButtonChecked(dlg, IDC_RA0AF) == BST_CHECKED;
  63.    rf0 = IsDlgButtonChecked(dlg, IDC_RF0F1) == BST_CHECKED;
  64.    roth = IsDlgButtonChecked(dlg, IDC_ROTH2) == BST_CHECKED;
  65.    fontsize = unsigned(5 + SendDlgItemMessage(dlg, IDC_FONTSIZE, CB_GETCURSEL, 0, 0));
  66.    update_rmask();
  67. }
  68.  
  69. static void paint_font(HWND dlg, int paint=0)
  70. {
  71.    const int sz = 340;
  72.    char *buf = (char*)malloc(sz*sz);
  73.    if (!buf) return;
  74.    RECT rc; GetWindowRect(GetDlgItem(dlg, IDC_FRAME), &rc);
  75.    RECT r2; GetWindowRect(dlg, &r2);
  76.    rc.top -= r2.top; rc.bottom -= r2.top; rc.left -= r2.left; rc.right -= r2.left;
  77.    static struct {
  78.       BITMAPINFO header;
  79.       RGBQUAD waste[0x100];
  80.    } gdibmp = { { { sizeof(BITMAPINFOHEADER), sz, -sz, 1, 8, BI_RGB } } };
  81.    static RGBQUAD cl[] = { { 0xFF, 0, 0, 0 }, { 0xC0, 0xC0, 0xC0, 0 }, { 0, 0, 0, 0 } };
  82.    memcpy(gdibmp.header.bmiColors, cl, sizeof(cl));
  83.    memset(buf, 0, sz*sz);
  84.  
  85.    unsigned next_pixel, next_char;
  86.    if(linear)
  87.    {
  88.        next_pixel = 1;
  89.        next_char = 8;
  90.    }
  91.    else
  92.    {
  93.        next_pixel = 0x100;
  94.        next_char = 1;
  95.    }
  96.  
  97.    unsigned t1[4], t2[4];
  98.    for (unsigned j = 0; j < 4; j++) {
  99.       unsigned mask = (j >> 1)*0xFFFF + (j & 1)*0xFFFF0000;
  100.       t1[j] = mask & 0x01010101; t2[j] = mask & 0x02020202;
  101.    }
  102.  
  103.    for (unsigned ch = 0; ch < 0x100; ch++) {
  104.       unsigned x = ch & 0x0F, y = ch / 0x10;
  105.       x = x*20 + ((x>>2)&3) * 2;
  106.       y = y*20 + ((y>>2)&3) * 2;
  107.       x += 10; y += 10;
  108.       for (unsigned i = 0; i < fontsize; i++) {
  109.          unsigned char byte = font_base[(font_address + i*next_pixel + ch*next_char) & font_maxmem];
  110.          unsigned *t0 = t1;
  111.          if (right || !rmask[ch]) t0 = t2;
  112.          *(unsigned*)(buf+sz*(y+2*i) + x) = t0[byte >> 6];
  113.          *(unsigned*)(buf+sz*(y+2*i) + x + 4) = t0[(byte >> 4) & 3];
  114.          *(unsigned*)(buf+sz*(y+2*i+1) + x) = t0[byte >> 6];
  115.          *(unsigned*)(buf+sz*(y+2*i+1) + x + 4) = t0[(byte >> 4) & 3];
  116.  
  117.          t0 = t1;
  118.          if (!right || !rmask[ch]) t0 = t2;
  119.          *(unsigned*)(buf+sz*(y+2*i) + x + 8) = t0[(byte >> 2) & 3];
  120.          *(unsigned*)(buf+sz*(y+2*i) + x + 12) = t0[byte & 3];
  121.          *(unsigned*)(buf+sz*(y+2*i+1) + x + 8) = t0[(byte >> 2) & 3];
  122.          *(unsigned*)(buf+sz*(y+2*i+1) + x + 12) = t0[byte & 3];
  123.       }
  124.    }
  125.  
  126.    PAINTSTRUCT ps;
  127.    if (paint) BeginPaint(dlg, &ps); else ps.hdc = GetDC(dlg);
  128.    SetDIBitsToDevice(ps.hdc, rc.left + (int)(rc.right-rc.left-sz)/2, rc.top + (int)(rc.bottom-rc.top-sz)/2, sz, sz, 0, 0, 0, sz, buf, &gdibmp.header, DIB_RGB_COLORS);
  129.    if (paint) EndPaint(dlg, &ps); else ReleaseDC(dlg, ps.hdc);
  130.    free(buf);
  131.    char ln[64];
  132.    if (font_base == RAM_BASE_M)
  133.       sprintf(ln, "bank #%02X, offset %04X", (font_address & font_maxmem) >> 14, font_address & 0x3FFF);
  134.    else
  135.       sprintf(ln, "file offset %04X", font_address);
  136.    SetDlgItemText(dlg, IDC_ADDRESS, ln);
  137. }
  138.  
  139. static unsigned char pattern[12][8];
  140.  
  141. static void kill_pattern(unsigned x, unsigned y, unsigned mode)
  142. {
  143.    unsigned sx[64], sy[64], sp = 1;
  144.    sx[0] = x; sy[0] = y;
  145.    pattern[y][x] = 0;
  146.    while (sp--) {
  147.       x = sx[sp]; y = sy[sp];
  148.       if(pattern[y - 1][x])
  149.       {
  150.           pattern[y - 1][x] = 0;
  151.           sx[sp] = x;
  152.           sy[sp] = y - 1;
  153.           sp++;
  154.       }
  155.       if(pattern[y + 1][x])
  156.       {
  157.           pattern[y + 1][x] = 0;
  158.           sx[sp] = x;
  159.           sy[sp] = y + 1;
  160.           sp++;
  161.       }
  162.       if(pattern[y][x - 1])
  163.       {
  164.           pattern[y][x - 1] = 0;
  165.           sx[sp] = x - 1;
  166.           sy[sp] = y;
  167.           sp++;
  168.       }
  169.       if(pattern[y][x + 1])
  170.       {
  171.           pattern[y][x + 1] = 0;
  172.           sx[sp] = x + 1;
  173.           sy[sp] = y;
  174.           sp++;
  175.       }
  176.       if (mode) {
  177.           if(pattern[y - 1][x + 1])
  178.           {
  179.               pattern[y - 1][x + 1] = 0;
  180.               sx[sp] = x + 1;
  181.               sy[sp] = y - 1;
  182.               sp++;
  183.           }
  184.           if(pattern[y + 1][x + 1])
  185.           {
  186.               pattern[y + 1][x + 1] = 0;
  187.               sx[sp] = x + 1;
  188.               sy[sp] = y + 1;
  189.               sp++;
  190.           }
  191.           if(pattern[y - 1][x - 1])
  192.           {
  193.               pattern[y - 1][x - 1] = 0;
  194.               sx[sp] = x - 1;
  195.               sy[sp] = y - 1;
  196.               sp++;
  197.           }
  198.           if(pattern[y + 1][x - 1])
  199.           {
  200.               pattern[y + 1][x - 1] = 0;
  201.               sx[sp] = x - 1;
  202.               sy[sp] = y + 1;
  203.               sp++;
  204.           }
  205.       }
  206.    }
  207. }
  208.  
  209. static unsigned kill_raw(unsigned x, unsigned y, unsigned mode)
  210. {
  211.    unsigned result = 0;
  212.    if(pattern[y][x])
  213.    {
  214.        kill_pattern(x, y, mode);
  215.        result++;
  216.    }
  217.    if(pattern[y][x + 1])
  218.    {
  219.        kill_pattern(x + 1, y, mode);
  220.        result++;
  221.    }
  222.    if(pattern[y][x + 2])
  223.    {
  224.        kill_pattern(x + 2, y, mode);
  225.        result++;
  226.    }
  227.    if(pattern[y][x + 3])
  228.    {
  229.        kill_pattern(x + 3, y, mode);
  230.        result++;
  231.    }
  232.    return result;
  233. }
  234.  
  235. static unsigned count_lnk(unsigned mode)
  236. {
  237.    unsigned result = 0;
  238.    for (;;) {
  239.       unsigned r1 = result;
  240.       for (unsigned line = 1; line < 11; line++) {
  241.          if (*(unsigned*)&(pattern[line][0])) result += kill_raw(0, line, mode);
  242.          if (*(unsigned*)&(pattern[line][4])) result += kill_raw(4, line, mode);
  243.       }
  244.       if (result == r1) break;
  245.    }
  246.    return result;
  247. }
  248.  
  249. static union { unsigned v32; unsigned char v8[4]; } c_map0[16];
  250. static union { unsigned v32; unsigned char v8[4]; } c_map1[16];
  251. static union { unsigned v32; unsigned char v8[4]; } c_map2[16];
  252. static union { unsigned v32; unsigned char v8[4]; } c_map3[16];
  253. static union { unsigned v32; unsigned char v8[4]; } c_map4[16];
  254.  
  255. static void create_maps()
  256. {
  257.    unsigned i; //Alone Coder 0.36.7
  258.    for (/*unsigned*/ i = 0; i < 16; i++)
  259.       for (unsigned j = 0; j < 4; j++)
  260.          c_map0[i].v8[3-j] = (i >> j) & 1;
  261.    for (i = 0; i < 16; i++) {
  262.       c_map1[i].v32 = c_map0[i >> 1].v32;
  263.       c_map2[i].v32 = c_map0[(i & 1) << 3].v32;
  264.       c_map3[i].v32 = c_map0[(((~i) >> 2) | 4) & 0x07].v32;
  265.       c_map4[i].v32 = c_map0[(((~i) << 2) | 2) & 0x0E].v32;
  266.    }
  267. }
  268.  
  269. static unsigned linked_cells(unsigned sym)
  270. {
  271.    unsigned pix = 0x100, shift = right? 0 : 4;
  272.    if(linear)
  273.    {
  274.        sym *= 8;
  275.        pix = 1;
  276.    }
  277.    sym += font_address;
  278. //   *(unsigned*)&(pattern[0][0]) = *(unsigned*)&(pattern[0][4]) = 0;
  279.    for(unsigned i = 0; i < fontsize; i++, sym += pix)
  280.    {
  281.        *(unsigned*)&(pattern[i + 1][0]) = c_map1[(font_base[sym & font_maxmem] >> shift) & 0x0F].v32;
  282.        *(unsigned*)&(pattern[i + 1][4]) = c_map2[(font_base[sym & font_maxmem] >> shift) & 0x0F].v32;
  283.    }
  284.    *(unsigned*)&(pattern[fontsize+1][0]) = *(unsigned*)&(pattern[fontsize+1][4]) = 0;
  285.    *(unsigned*)&(pattern[fontsize+2][0]) = *(unsigned*)&(pattern[fontsize+2][4]) = 0;
  286. //   *(unsigned*)&(pattern[fontsize+3][0]) = *(unsigned*)&(pattern[fontsize+3][4]) = 0;
  287.    return count_lnk(1);
  288. }
  289.  
  290. static unsigned linked_empties(unsigned sym)
  291. {
  292.    unsigned pix = 0x100, shift = right? 0 : 4;
  293.    if(linear)
  294.    {
  295.        sym *= 8;
  296.        pix = 1;
  297.    }
  298.    sym += font_address;
  299. //   *(unsigned*)&(pattern[0][0]) = *(unsigned*)&(pattern[0][4]) = 0;
  300.    *(unsigned*)&(pattern[1][0]) = WORD4(0, 1, 1, 1);
  301.    *(unsigned*)&(pattern[1][4]) = WORD4(1, 1, 1, 0);
  302.    for(unsigned i = 0; i < fontsize; i++, sym += pix)
  303.    {
  304.        *(unsigned*)&(pattern[i + 2][0]) = c_map3[(font_base[sym & font_maxmem] >> shift) & 0x0F].v32;
  305.        *(unsigned*)&(pattern[i + 2][4]) = c_map4[(font_base[sym & font_maxmem] >> shift) & 0x0F].v32;
  306.    }
  307.    *(unsigned*)&(pattern[fontsize + 2][0]) = WORD4(0, 1, 1, 1);
  308.    *(unsigned*)&(pattern[fontsize + 2][4]) = WORD4(1, 1, 1, 0);
  309. //   *(unsigned*)&(pattern[fontsize+3][0]) = *(unsigned*)&(pattern[fontsize+3][4]) = 0;
  310.    return count_lnk(0);
  311. }
  312.  
  313. static unsigned char is_font()
  314. {
  315.    const int max_err = 2;
  316.    int err = 0;
  317.    #define RET_ERR { if (++err > max_err) return 0; }
  318.    if (r21) {
  319.       if (linked_cells('!') != 2) RET_ERR
  320.       if (linked_empties('!') != 1) RET_ERR
  321.       if (linked_cells('*') != 1) RET_ERR
  322.       if (linked_empties('*') != 1) RET_ERR
  323.       if (linked_cells('(') != 1) RET_ERR
  324.       if (linked_empties('(') != 1) RET_ERR
  325.       if (linked_cells(')') != 1) RET_ERR
  326.       if (linked_empties(')') != 1) RET_ERR
  327.       if (linked_cells('$') != 1) RET_ERR
  328.    }
  329.    if (r30) {
  330.       if (linked_cells('1') != 1) RET_ERR
  331.       if (linked_empties('1') != 1) RET_ERR
  332.       if (linked_cells('6') != 1) RET_ERR
  333.       if (linked_empties('6') != 2) RET_ERR
  334.       if (linked_cells('8') != 1) RET_ERR
  335.       if (linked_empties('8') != 3) RET_ERR
  336.       if (linked_cells('9') != 1) RET_ERR
  337.       if (linked_empties('9') != 2) RET_ERR
  338.       if (linked_cells('0') != 1) RET_ERR
  339.       unsigned e = linked_empties('0');
  340.       if (e != 2 && e != 3) RET_ERR
  341.    }
  342.    if (r41) {
  343.       if (linked_cells('A') != 1) RET_ERR
  344.       if (linked_empties('A') != 2) RET_ERR
  345.       if (linked_cells('O') != 1) RET_ERR
  346.       if (linked_empties('O') != 2) RET_ERR
  347.       if (linked_cells('S') != 1) RET_ERR
  348.       if (linked_empties('S') != 1) RET_ERR
  349.       if (linked_cells('T') != 1) RET_ERR
  350.       if (linked_empties('T') != 1) RET_ERR
  351.       if (linked_cells('Z') != 1) RET_ERR
  352.       if (linked_empties('Z') != 1) RET_ERR
  353.    }
  354.    if (r61) {
  355.       if (linked_cells('b') != 1) RET_ERR
  356.       if (linked_empties('b') != 2) RET_ERR
  357.       if (linked_cells('o') != 1) RET_ERR
  358.       if (linked_empties('o') != 2) RET_ERR
  359.       if (linked_cells('s') != 1) RET_ERR
  360.       if (linked_empties('s') != 1) RET_ERR
  361.       if (linked_cells('t') != 1) RET_ERR
  362.       if (linked_empties('t') != 1) RET_ERR
  363.       if (linked_cells('z') != 1) RET_ERR
  364.       if (linked_empties('z') != 1) RET_ERR
  365.    }
  366.    if (r80) {
  367.       if (linked_cells(0x80) != 1) RET_ERR // A
  368.       if (linked_empties(0x80) != 2) RET_ERR
  369.       if (linked_cells(0x81) != 1) RET_ERR // Б
  370.       if (linked_empties(0x81) != 2) RET_ERR
  371.       if (linked_cells(0x83) != 1) RET_ERR // Г
  372.       if (linked_empties(0x83) != 1) RET_ERR
  373.       if (linked_cells(0x9F) != 1) RET_ERR // Я
  374.       if (linked_empties(0x9F) != 2) RET_ERR
  375.    }
  376.    if (rae) {
  377.       if (linked_cells(0xAE) != 1) RET_ERR // o
  378.       if (linked_empties(0xAE) != 2) RET_ERR
  379.       if (linked_cells(0xE1) != 1) RET_ERR // c
  380.       if (linked_empties(0xE1) != 1) RET_ERR
  381.       if (linked_cells(0xE2) != 1) RET_ERR // T
  382.       if (linked_empties(0xE2) != 1) RET_ERR
  383.    }
  384.    if (rf0) {
  385.       // if (linked_cells(0xF0) != 1) RET_ERR // Ё
  386.    }
  387.    if (roth) {
  388.       if (linked_cells(':') != 2) RET_ERR
  389.       if (linked_empties(':') != 1) RET_ERR
  390.       if (linked_cells(';') != 2) RET_ERR
  391.       if (linked_empties(';') != 1) RET_ERR
  392.    }
  393.    #undef RET_ERR
  394.    return 1;
  395. }
  396.  
  397. static inline int pretest_font(unsigned pix, unsigned chr, unsigned shift)
  398. {
  399.    unsigned i; //Alone Coder 0.36.7
  400.    // check space
  401.    for (/*unsigned*/ i = 0; i < fontsize; i++)
  402.       if ((font_base[(font_address + i*pix + chr * 0x20) & font_maxmem] >> shift) & 0x0F) return 0;
  403.    // check non-spaces
  404.    for (i = 0; i < 0x100; i++) {
  405.       if (!rmask[i]) continue;
  406.       unsigned char s = 0;
  407.       for (unsigned k = 0; k < fontsize; k++)
  408.          s += (font_base[(font_address + k*pix + i*chr) & font_maxmem] >> shift) & 0x0F;
  409.       if (!s) return 0;
  410.    }
  411.    return 1;
  412. }
  413.  
  414. static void set_data(HWND dlg)
  415. {
  416.    unsigned prev = block_font_dialog;
  417.    block_font_dialog = 1;
  418.    char ln[64]; sprintf(ln, "0%04X", font_address);
  419.    SetDlgItemText(dlg, IDE_ADDRESS, ln);
  420.  
  421.    if(linear)
  422.    {
  423.        CheckDlgButton(dlg, IDC_PLANES, BST_UNCHECKED);
  424.        CheckDlgButton(dlg, IDC_LINEAR, BST_CHECKED);
  425.    }
  426.    else
  427.    {
  428.        CheckDlgButton(dlg, IDC_PLANES, BST_CHECKED);
  429.        CheckDlgButton(dlg, IDC_LINEAR, BST_UNCHECKED);
  430.    }
  431.  
  432.    if(right)
  433.    {
  434.        CheckDlgButton(dlg, IDC_LEFT, BST_UNCHECKED);
  435.        CheckDlgButton(dlg, IDC_RIGHT, BST_CHECKED);
  436.    }
  437.    else
  438.    {
  439.        CheckDlgButton(dlg, IDC_LEFT, BST_CHECKED);
  440.        CheckDlgButton(dlg, IDC_RIGHT, BST_UNCHECKED);
  441.    }
  442.    block_font_dialog = prev;
  443. }
  444.  
  445. static void fnt_search(HWND dlg)
  446. {
  447.    create_maps();
  448.    memset(pattern, 0, sizeof pattern);
  449.  
  450.    unsigned start = font_address,
  451.             st_linear = linear, st_right = right;
  452.  
  453.    unsigned pix = linear? 1 : 0x100,
  454.             chr = linear? 8 : 1,
  455.             shift = right? 0 : 4;
  456.  
  457.    for (;;) {
  458.       font_address = (font_address+1) & font_maxmem;
  459.       if (font_address == start) {
  460.          right ^= 1; shift = right? 0 : 4;
  461.          if (right == st_right) {
  462.             linear ^= 1; pix = linear? 1 : 0x100; chr = linear? 8 : 1;
  463.             if (linear == st_linear) {
  464.                MessageBox(dlg, "font not found", "font searcher", MB_OK | MB_ICONWARNING);
  465.                return;
  466.             }
  467.          }
  468.       }
  469.       if (!pretest_font(pix, chr, shift)) continue;
  470.       if (is_font()) break;
  471.    }
  472.    paint_font(dlg);
  473.    set_data(dlg);
  474. }
  475.  
  476. static void save_font()
  477. {
  478.    unsigned chr = 1, line = 0x100, shift = 4;
  479.    if(linear)
  480.    {
  481.        chr = 8;
  482.        line = 1;
  483.    }
  484.    if (right) shift = 0;
  485.    unsigned char *dst = fontdata2;
  486.  
  487.    unsigned j; //Alone Coder 0.36.7
  488.    for (unsigned i = 0; i < 0x100; i++) {
  489.       if (!i || i == 0x20) continue;
  490.       if (!rmask[i]) continue;
  491.       unsigned chardata = font_address + i*chr;
  492.       unsigned char sum = 0;
  493.       for (/*unsigned*/ j = 0; j < fontsize; j++) sum |= font_base[(chardata + j*line) & font_maxmem];
  494.       if (!((sum >> shift) & 0x0F)) continue;
  495.       *dst++ = (unsigned char)i;
  496.       for (j = 0; j < 8; j++)
  497.          *dst++ = j < fontsize?
  498.                    (font_base[(chardata + j*line) & font_maxmem] >> shift) & 0x0F : 0;
  499.    }
  500.    *dst = 0;
  501.    fontdata = fontdata2;
  502. }
  503.  
  504. static void FontFromFile(HWND dlg)
  505. {
  506.    OPENFILENAME ofn = { };
  507.    char fname[0x200]; *fname = 0;
  508.  
  509.    ofn.lStructSize = (WinVerMajor < 5) ? OPENFILENAME_SIZE_VERSION_400 : sizeof(OPENFILENAME);
  510.    ofn.hwndOwner = dlg;
  511.    ofn.lpstrFilter = "font files (*.FNT,*.FNX)\0*.fnt;*.fnx\0All files\0*.*\0";
  512.    ofn.lpstrFile = fname; ofn.nMaxFile = sizeof fname;
  513.    ofn.lpstrTitle = "Load font from file";
  514.    ofn.Flags = OFN_FILEMUSTEXIST | OFN_NOCHANGEDIR | OFN_HIDEREADONLY;
  515.    if (!GetOpenFileName(&ofn)) return;
  516.  
  517.    FILE *ff = fopen(fname, "rb"); if (!ff) return;
  518.    memset(font_base = snbuf, 0, sizeof snbuf);
  519.    size_t size = fread(snbuf, 1, sizeof snbuf, ff);
  520.    fclose(ff);
  521.  
  522.    for (font_maxmem = 0x800; font_maxmem < size; font_maxmem *= 2);
  523.    font_maxmem--;
  524.  
  525.    SetDlgItemText(dlg, IDE_ADDRESS, "0");
  526.    get_ranges(dlg);
  527.    paint_font(dlg);
  528. }
  529.  
  530. static INT_PTR CALLBACK fonts_dlg(HWND dlg, UINT msg, WPARAM wp, LPARAM lp)
  531. {
  532.    if (msg == WM_INITDIALOG) {
  533.       block_font_dialog = 1;
  534.       font_maxmem = conf.ramsize * 1024 - 1;
  535.       font_base = RAM_BASE_M;
  536.       CheckDlgButton(dlg, IDC_100, x100? BST_CHECKED : BST_UNCHECKED);
  537.       CheckDlgButton(dlg, IDC_R212F, r21? BST_CHECKED : BST_UNCHECKED);
  538.       CheckDlgButton(dlg, IDC_R3039, r30? BST_CHECKED : BST_UNCHECKED);
  539.       CheckDlgButton(dlg, IDC_R415A, r41? BST_CHECKED : BST_UNCHECKED);
  540.       CheckDlgButton(dlg, IDC_R617A, r61? BST_CHECKED : BST_UNCHECKED);
  541.       CheckDlgButton(dlg, IDC_R809F, r80? BST_CHECKED : BST_UNCHECKED);
  542.       CheckDlgButton(dlg, IDC_RA0AF, rae? BST_CHECKED : BST_UNCHECKED);
  543.       CheckDlgButton(dlg, IDC_RF0F1, rf0? BST_CHECKED : BST_UNCHECKED);
  544.       CheckDlgButton(dlg, IDC_ROTH2, roth? BST_CHECKED : BST_UNCHECKED);
  545.       SendDlgItemMessage(dlg, IDC_FONTSIZE, CB_ADDSTRING, 0, (LPARAM)"5 pixels");
  546.       SendDlgItemMessage(dlg, IDC_FONTSIZE, CB_ADDSTRING, 0, (LPARAM)"6 pixels");
  547.       SendDlgItemMessage(dlg, IDC_FONTSIZE, CB_ADDSTRING, 0, (LPARAM)"7 pixels");
  548.       SendDlgItemMessage(dlg, IDC_FONTSIZE, CB_ADDSTRING, 0, (LPARAM)"8 pixels");
  549.       SendDlgItemMessage(dlg, IDC_FONTSIZE, CB_SETCURSEL, fontsize-5, 0);
  550.       set_data(dlg);
  551.       update_rmask();
  552.       block_font_dialog = 0;
  553.       return 1;
  554.    }
  555.  
  556.    if (msg == WM_PAINT) { paint_font(dlg, 1); return 1; }
  557.    if (msg == WM_SYSCOMMAND && (wp & 0xFFF0) == SC_CLOSE) EndDialog(dlg, 0);
  558.  
  559.    if (block_font_dialog) return 0;
  560.  
  561.    if (msg == WM_NOTIFY && wp == IDC_SPIN) {
  562.       char ln[64]; GetDlgItemText(dlg, IDE_ADDRESS, ln, sizeof ln);
  563.       sscanf(ln, "%X", &font_address);
  564.       font_address = unsigned(int(font_address) + ((LPNMUPDOWN)lp)->iDelta * (x100? 0x100 : 1));
  565.       font_address &= font_maxmem;
  566.       sprintf(ln, "0%04X", font_address); SetDlgItemText(dlg, IDE_ADDRESS, ln);
  567.       paint_font(dlg);
  568.       return 0;
  569.    }
  570.  
  571.    if (msg != WM_COMMAND) return 0;
  572.    unsigned id = LOWORD(wp), code = HIWORD(wp);
  573.  
  574.    if ((id == IDE_ADDRESS && code == EN_CHANGE) ||
  575.        (id == IDC_FONTSIZE && code == CBN_SELCHANGE) ||
  576.        ((id == IDC_LINEAR || id == IDC_PLANES ||
  577.          id == IDC_LEFT || id == IDC_RIGHT || id == IDC_100 ||
  578.          id == IDC_R212F || id == IDC_R3039 || id == IDC_R415A ||
  579.          id == IDC_R617A || id == IDC_R809F || id == IDC_RA0AF ||
  580.          id == IDC_RF0F1 || id == IDC_ROTH2) && code == BN_CLICKED))
  581.    {
  582.       get_ranges(dlg);
  583.       paint_font(dlg);
  584.    }
  585.  
  586.    if (id == IDC_FILE) FontFromFile(dlg);
  587.    if (id == IDC_FIND) fnt_search(dlg);
  588.    if (id == IDCANCEL) EndDialog(dlg, 0);
  589.    if(id == IDOK)
  590.    {
  591.        save_font();
  592.        EndDialog(dlg, 0);
  593.    }
  594.  
  595.    return 0;
  596. }
  597.  
  598. void font_setup(HWND dlg)
  599. {
  600.    DialogBox(hIn, MAKEINTRESOURCE(IDD_FONTS), dlg, fonts_dlg);
  601. }
  602. #endif // MOD_SETTINGS
  603.