Subversion Repositories pentevo

Rev

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