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 "snapshot.h"
  7. #include "tape.h"
  8. #include "memory.h"
  9. #include "opendlg.h"
  10. #include "draw.h"
  11. #include "config.h"
  12. #include "z80.h"
  13. #include "sshot_png.h"
  14. #include "funcs.h"
  15.  
  16. #include "util.h"
  17.  
  18.  
  19.  
  20. #include <io.h> // фы  access [NS]
  21.  
  22. int readSP();
  23. int readSNA48();
  24. int readSNA128();
  25. int readZ80();
  26. int writeSNA(FILE*);
  27.  
  28. int load_arc(char *fname);
  29.  
  30. //=============================================================================
  31. SNAP what_is(char *filename)
  32. {
  33.    FILE *ff = fopen(filename, "rb");
  34.    if (!ff) return snNOFILE;
  35.    snapsize = unsigned(fread(snbuf, 1, sizeof snbuf, ff));
  36.    fclose(ff);
  37.    if (snapsize == sizeof snbuf) return snTOOLARGE;
  38.    SNAP type = snUNKNOWN;
  39.    char *ptr = strrchr(filename, '.');
  40.    unsigned ext = ptr? (*(unsigned*)(ptr+1) | 0x20202020U) : 0;
  41.    if (snapsize < 32) return type;
  42.  
  43.    if (snapsize == 131103 || snapsize == 147487) type = snSNA_128;
  44.    if (snapsize == 49179) type = snSNA_48;
  45.    if (ext == WORD4('t','a','p',' ')) type = snTAP;
  46.    if (ext == WORD4('z','8','0',' ')) type = snZ80;
  47.    if(ext == WORD4('p', 'a', 'l', ' ') && (snapsize == sizeof(comp.comp_pal)))
  48.    {
  49.        type = snPAL;
  50.        return type;
  51.    }
  52.    if (conf.trdos_present)
  53.    {
  54.       if (!snbuf[13] && snbuf[14] && (int)snapsize == snbuf[14]*256+17) type = snHOB;
  55.       if (snapsize >= 8192 && !(snapsize & 0xFF) && ext == WORD4('t','r','d',' ')) type = snTRD;
  56.  
  57.       if (snapsize >= 8192 && ext == WORD4('i','s','d',' '))
  58.           type = snISD;
  59.  
  60.       if (snapsize >= 8192 && ext == WORD4('p','r','o',' '))
  61.           type = snPRO;
  62.  
  63.       if(snapsize >= 8192 && ext == WORD4('d', 's', 'k', ' '))
  64.           type = snDSK;
  65.  
  66.       if(snapsize >= 8192 && ext == WORD4('i', 'p', 'f', ' '))
  67.           type = snIPF;
  68.  
  69.       if (!memcmp(snbuf, "SINCLAIR", 8))
  70.       {
  71.           unsigned nfiles = snbuf[8];
  72.           unsigned nsec = 0;
  73.           for(unsigned i = 0; i < nfiles; i++)
  74.           {
  75.               nsec += snbuf[9+14*i+13];
  76.           }
  77.          
  78.           if(snapsize >= 9 + nfiles * 14 + nsec * 0x100)
  79.               type = snSCL;
  80.       }
  81.       if (!memcmp(snbuf, "FDI", 3) && *(unsigned short*)(snbuf+4) <= MAX_CYLS && *(unsigned short*)(snbuf+6) <= 2) type = snFDI;
  82.       if (((*(short*)snbuf|0x2020) == WORD2('t','d')) && snbuf[4] >= 10 && snbuf[4] <= 21 && snbuf[9] <= 2) type = snTD0;
  83.       if (*(unsigned*)snbuf == WORD4('U','D','I','!') && *(unsigned*)(snbuf+4)==snapsize-4 && snbuf[9] < MAX_CYLS && snbuf[10]<2 && !snbuf[8]) type = snUDI;
  84.    }
  85.    if (snapsize > 10 && !memcmp(snbuf, "ZXTape!\x1A", 8))
  86.    {
  87.        type = snTZX;
  88.    }
  89.    if (snapsize > 0x22 && !memcmp(snbuf, "Compressed Square Wave\x1A", 23)) type = snCSW;
  90.    if (*(unsigned short*)snbuf == WORD2('S','P') && *(unsigned short*)(snbuf+2)+0x26 == (int)snapsize) type = snSP;
  91.    return type;
  92. }
  93. //=============================================================================
  94.  
  95. static int readPAL();
  96.  
  97. //=============================================================================
  98. int loadsnap(char *filename)
  99. {
  100.     //-------------------------------------------------------------------------
  101.     if (load_arc(filename))
  102.         return 1;
  103.     //-------------------------------------------------------------------------
  104.     SNAP type = what_is(filename);
  105.     //-------------------------------------------------------------------------
  106.     if (type >= snHOB)
  107.     {
  108.         if (trd_toload == -1U)
  109.         {
  110.             unsigned last = -1U;
  111.             for (unsigned i = 0; i < 4; i++)
  112.                 if (trd_loaded[i]) last = i;
  113.             trd_toload = (last == -1U)    ?     0 :
  114.                                                 (
  115.                                                     (type == snHOB)  ?  last :
  116.                                                                         (last+1) & 3
  117.                                                 );
  118.         }
  119.         //---------------------------------------------------------------------
  120.         for (unsigned k = 0; k < 4; k++)
  121.         {
  122.             if ((k != trd_toload) && (!stricmp(comp.fdd[k].name, filename)))
  123.             {
  124.                 // ьхЁчёър  ьхЁчюёЄ№ !!!
  125.                 static char err[] =     "This disk image is already loaded to drive X:\n"
  126.                                         "Do you still want to load it to drive Y:?";
  127.                 err[43] = char(k+'A');
  128.                 err[84] = char(trd_toload+'A');
  129.                 if (MessageBox(GetForegroundWindow(), err, "Warning", MB_YESNO | MB_ICONWARNING) == IDNO)
  130.                     return 1;
  131.             }
  132.         }
  133.         //---------------------------------------------------------------------
  134.         FDD *drive = comp.fdd + trd_toload;
  135.         //---------------------------------------------------------------------
  136.         if (!drive->test())
  137.             return 0;
  138.         //---------------------------------------------------------------------
  139.         comp.wd.Eject(trd_toload);
  140.         int ok = drive->read(type);
  141.         //---------------------------------------------------------------------
  142.         if (ok)
  143.         {
  144.             //-----------------------------------------------------------------
  145.             if (*conf.appendboot)
  146.                 drive->addboot();
  147.             //-----------------------------------------------------------------
  148.             strcpy(drive->name, filename);
  149.             //-----------------------------------------------------------------
  150.             if (GetFileAttributes(filename) & FILE_ATTRIBUTE_READONLY)
  151.                 conf.trdos_wp[trd_toload] = 1;
  152.             //-----------------------------------------------------------------
  153.             drive->snaptype = (type == snHOB || type == snSCL)    ?     snTRD :
  154.                                                                         type;
  155.             trd_loaded[trd_toload] = 1;
  156.            
  157.             //---------Alone Coder
  158.             char *name = filename;
  159.            
  160.             for (char *x = name; *x; x++)
  161.                 if (*x == '\\')
  162.                     name = x + 1;
  163.              
  164.             strcpy(temp.LastSnapName, name);
  165.             char *p = strrchr(temp.LastSnapName, '.');
  166.             if (p)
  167.             {
  168.                 *p = 0;
  169.             }
  170.             //printf("loaded file name printing\n");
  171.             char wintitle[0x200];
  172.             strcpy(wintitle,name);
  173.             //strcat(wintitle," - UnrealSpeccy");
  174.             strcat(wintitle," - Unreal_NS");    //фы  чруЁєцрхьюую фшёъют
  175.             SetWindowText(wnd, wintitle);
  176.             //~---------Alone Coder
  177.         }
  178.         //---------------------------------------------------------------------
  179.         return ok;
  180.     }
  181.     //-------------------------------------------------------------------------
  182.     if (type == snSP)           return readSP();
  183.     if (type == snSNA_48)       return readSNA48();
  184.     if (type == snSNA_128)      return readSNA128();
  185.     if (type == snZ80)          return readZ80();
  186.     if (type == snTAP)          return readTAP();
  187.     if (type == snTZX)          return readTZX();
  188.     if (type == snCSW)          return readCSW();
  189.     if (type == snPAL)          return readPAL();
  190.     //-------------------------------------------------------------------------
  191.     return 0;
  192. }
  193. //=============================================================================
  194.  
  195.  
  196. //=============================================================================
  197. int readSNA128()
  198. {
  199.     //-------------------------------------------------------------------------
  200.     if ((conf.mem_model == MM_PENTAGON) && (conf.Sna128Lock))
  201.     {
  202.        conf.ramsize = 128;
  203.        temp.ram_mask = u8((conf.ramsize-1) >> 4);
  204.     }
  205.     //-------------------------------------------------------------------------
  206.     hdrSNA128 *hdr = (hdrSNA128*)snbuf;
  207.     reset(hdr->trdos ?  RM_DOS :
  208.                         RM_SOS);
  209.     cpu.alt.af = hdr->altaf;
  210.     cpu.alt.bc = hdr->altbc;
  211.     cpu.alt.de = hdr->altde;
  212.     cpu.alt.hl = hdr->althl;
  213.     cpu.af = hdr->af;
  214.     cpu.bc = hdr->bc;
  215.     cpu.de = hdr->de;
  216.     cpu.hl = hdr->hl;
  217.     cpu.ix = hdr->ix;
  218.     cpu.iy = hdr->iy;
  219.     cpu.sp = hdr->sp;
  220.     cpu.pc = hdr->pc;
  221.     cpu.i = hdr->i;
  222.     cpu.r_low = hdr->r;
  223.     cpu.r_hi = hdr->r & 0x80;
  224.     cpu.im = hdr->im;
  225.     cpu.iff1 = cpu.iff2 = (hdr->iff >> 2) & 1;
  226.     comp.p7FFD = hdr->p7FFD;
  227.     comp.pFE = hdr->pFE;
  228.     comp.border_attr = comp.pFE & 7;
  229.     memcpy(memory + PAGE * 5,                   hdr->page5,             PAGE);
  230.     memcpy(memory + PAGE * 2,                   hdr->page2,             PAGE);
  231.     memcpy(memory + PAGE * (hdr->p7FFD & 7),    hdr->active_page,       PAGE);
  232.     unsigned char *newpage = snbuf + 0xC01F;
  233.     unsigned char mapped = u8(0x24U | (1 << (hdr->p7FFD & 7)));
  234.     //-------------------------------------------------------------------------
  235.     for (unsigned char i = 0; i < 8; i++)
  236.     {
  237.         if (!(mapped & (1 << i)))
  238.         {
  239.             memcpy(memory + PAGE*i, newpage, PAGE);
  240.             newpage += PAGE;
  241.         }
  242.     }
  243.     //-------------------------------------------------------------------------
  244.     set_banks();
  245.     return 1;
  246. }
  247. //=============================================================================
  248.  
  249.  
  250. //=============================================================================
  251. int readSNA48()
  252. {
  253.     //conf.mem_model = MM_PENTAGON; conf.ramsize = 128;  // molodcov_alex
  254.     reset(RM_SOS);
  255.     hdrSNA128 *hdr = (hdrSNA128*)snbuf;
  256.     cpu.alt.af = hdr->altaf;
  257.     cpu.alt.bc = hdr->altbc;
  258.     cpu.alt.de = hdr->altde;
  259.     cpu.alt.hl = hdr->althl;
  260.     cpu.af = hdr->af;
  261.     cpu.bc = hdr->bc;
  262.     cpu.de = hdr->de;
  263.     cpu.hl = hdr->hl;
  264.     cpu.ix = hdr->ix;
  265.     cpu.iy = hdr->iy;
  266.     cpu.sp = hdr->sp;
  267.     cpu.i = hdr->i;
  268.     cpu.r_low = hdr->r;
  269.     cpu.r_hi = hdr->r & 0x80;
  270.     cpu.im = hdr->im;
  271.     cpu.iff1 = cpu.iff2 = (hdr->iff >> 2) & 1;
  272.     comp.p7FFD = 0x30;
  273.     comp.pEFF7 |= EFF7_LOCKMEM; //Alone Coder
  274.     comp.pFE = hdr->pFE;
  275.     comp.border_attr = comp.pFE & 7;
  276.     memcpy(memory + PAGE * 5, hdr->page5,       PAGE);
  277.     memcpy(memory + PAGE * 2, hdr->page2,       PAGE);
  278.     memcpy(memory + PAGE * 0, hdr->active_page, PAGE);
  279.     cpu.pc = cpu.DirectRm(cpu.sp) + 0x100 * cpu.DirectRm(cpu.sp + 1);
  280.     cpu.sp += 2;
  281.     set_banks();
  282.     return 1;
  283. }
  284. //=============================================================================
  285.  
  286.  
  287. //=============================================================================
  288. int readSP()
  289. {
  290.     //conf.mem_model = MM_PENTAGON; conf.ramsize = 128;  // molodcov_alex
  291.     reset(RM_SOS);
  292.     hdrSP *hdr = (hdrSP*)snbuf;
  293.     cpu.alt.af = hdr->altaf;
  294.     cpu.alt.bc = hdr->altbc;
  295.     cpu.alt.de = hdr->altde;
  296.     cpu.alt.hl = hdr->althl;
  297.     cpu.af = hdr->af;
  298.     cpu.bc = hdr->bc;
  299.     cpu.de = hdr->de;
  300.     cpu.hl = hdr->hl;
  301.     cpu.ix = hdr->ix;
  302.     cpu.iy = hdr->iy;
  303.     cpu.sp = hdr->sp;
  304.     cpu.pc = hdr->pc;
  305.     cpu.i = hdr->i;
  306.     cpu.r_low = hdr->r;
  307.     cpu.r_hi = hdr->r & 0x80;
  308.     cpu.iff1 = (hdr->flags & 1);
  309.     cpu.im = 1 + ((hdr->flags >> 1) & 1);
  310.     cpu.iff2 = (hdr->flags >> 2) & 1;
  311.     comp.p7FFD = 0x30;
  312.     comp.pEFF7 |= EFF7_LOCKMEM; //Alone Coder
  313.     comp.pFE = hdr->pFE;
  314.     comp.border_attr = comp.pFE & 7;
  315.     for (unsigned i = 0; i < hdr->len; i++)
  316.         cpu.DirectWm(hdr->start + i, snbuf[i + 0x26]);
  317.     set_banks();
  318.     return 1;
  319. }
  320. //=============================================================================
  321.  
  322.  
  323. //=============================================================================
  324. int writeSNA(FILE *ff)
  325. {
  326. /*  if (conf.ramsize != 128)
  327.     {
  328.         MessageBox(GetForegroundWindow(), "SNA format can hold only\r\n128kb memory models", "Save", MB_ICONERROR);
  329.         return 0;
  330.     }*/ //Alone Coder
  331.     hdrSNA128 *hdr = (hdrSNA128*)snbuf;
  332.     hdr->trdos = (comp.flags & CF_TRDOS)   ?    1 :
  333.                                                 0;
  334.     hdr->altaf = u16(cpu.alt.af);
  335.     hdr->altbc = u16(cpu.alt.bc);
  336.     hdr->altde = u16(cpu.alt.de);
  337.     hdr->althl = u16(cpu.alt.hl);
  338.     hdr->af = u16(cpu.af);
  339.     hdr->bc = u16(cpu.bc);
  340.     hdr->de = u16(cpu.de);
  341.     hdr->hl = u16(cpu.hl);
  342.     hdr->ix = u16(cpu.ix);
  343.     hdr->iy = u16(cpu.iy);
  344.     hdr->sp = u16(cpu.sp);
  345.     hdr->pc = u16(cpu.pc);
  346.     hdr->i = cpu.i;
  347.     hdr->r = (cpu.r_low & 0x7F)+cpu.r_hi;
  348.     hdr->im = cpu.im;
  349.     hdr->iff = cpu.iff2    ?    4 :
  350.                                 0;
  351.     hdr->p7FFD = comp.p7FFD;
  352.     hdr->pFE = comp.pFE;
  353.     comp.border_attr = comp.pFE & 7;
  354.     unsigned savesize = sizeof(hdrSNA128);
  355.     unsigned char mapped = u8(0x24U | (1 << (comp.p7FFD & 7)));
  356.     //-------------------------------------------------------------------------
  357.     if (comp.p7FFD == 0x30)     //эю фы  яхэЄруюэр ¤Єю эх чэрўхЄ 48 lock !!!
  358.     { // save 48k
  359.         mapped = 0xFF;
  360.         savesize = 0xC01B;
  361.         hdr->sp -= 2;
  362.         cpu.DirectWm(hdr->sp, cpu.pcl);
  363.         cpu.DirectWm(hdr->sp+1, cpu.pch);
  364.     }
  365.     //-------------------------------------------------------------------------
  366.     memcpy(hdr->page5,          memory+PAGE*5,                  PAGE);
  367.     memcpy(hdr->page2,          memory+PAGE*2,                  PAGE);
  368.     memcpy(hdr->active_page,    memory+PAGE*(comp.p7FFD & 7),   PAGE);
  369.     //-------------------------------------------------------------------------
  370.     if (fwrite(hdr, 1, savesize, ff) != savesize)
  371.         return 0;
  372.     //-------------------------------------------------------------------------
  373.     for (unsigned char i = 0; i < 8; i++)
  374.     {
  375.         if (!(mapped & (1 << i)))
  376.         {
  377.             if (fwrite(memory + PAGE*i, 1, PAGE, ff) != PAGE)
  378.                 return 0;
  379.         }
  380.     }
  381.     //-------------------------------------------------------------------------
  382.     return 1;
  383. }
  384. //=============================================================================
  385.  
  386.  
  387. //=============================================================================
  388. static void unpack_page(unsigned char *dst, unsigned dstlen, unsigned char *src, unsigned srclen)
  389. {
  390.     memset(dst, 0, dstlen);
  391.     while (srclen > 0 && dstlen > 0)
  392.     {
  393.         if (srclen >= 4 && src[0] == 0xED && src[1] == 0xED)
  394.         {
  395.             size_t len = src[2];
  396.             memset(dst, src[3], len);
  397.             dstlen -= len;
  398.             srclen -= 4;
  399.             src += 4;
  400.             dst += len;
  401.         }
  402.         else
  403.         {
  404.             *dst++ = *src++;
  405.             dstlen--;
  406.             srclen--;
  407.         }
  408.     }
  409. }
  410. //=============================================================================
  411.  
  412.  
  413. //=============================================================================
  414. int readZ80()
  415. {
  416.     //conf.mem_model = MM_PENTAGON; conf.ramsize = 128;  // molodcov_alex
  417.     hdrZ80 *hdr = (hdrZ80*)snbuf;
  418.     unsigned char *ptr = snbuf + 30;
  419.     unsigned char model48k = (hdr->model < 3);
  420.     //-------------------------------------------------------------------------
  421.     reset((model48k|(hdr->p7FFD & 0x10))   ?    RM_SOS :
  422.                                                 RM_128);
  423.     //-------------------------------------------------------------------------
  424.     if (hdr->flags == 0xFF)
  425.         hdr->flags = 1;
  426.     //-------------------------------------------------------------------------
  427.     if (hdr->pc == 0)
  428.     { // 2.01
  429.         ptr += 2 + hdr->len;
  430.         hdr->pc = hdr->newpc;
  431.         memset(RAM_BASE_M, 0, PAGE*8); // clear 128k - first 8 pages
  432.  
  433.         unsigned char * const p48[] =
  434.         {
  435.             base_sos_rom,               nullptr,                nullptr,        nullptr,
  436.             RAM_BASE_M + 2 * PAGE,      RAM_BASE_M + 0 * PAGE,  nullptr,        nullptr,
  437.             RAM_BASE_M + 5 * PAGE,      nullptr,                nullptr,        nullptr
  438.         };
  439.         unsigned char * const p128[] =
  440.         {
  441.             base_sos_rom,               base_dos_rom,           base_128_rom,           RAM_BASE_M + 0 * PAGE,
  442.             RAM_BASE_M + 1 * PAGE,      RAM_BASE_M + 2 * PAGE,  RAM_BASE_M + 3 * PAGE,  RAM_BASE_M + 4 * PAGE,
  443.             RAM_BASE_M + 5 * PAGE,      RAM_BASE_M + 6 * PAGE,  RAM_BASE_M + 7 * PAGE,  nullptr
  444.         };
  445.  
  446.         //---------------------------------------------------------------------
  447.         while (ptr < snbuf+snapsize)
  448.         {
  449.             unsigned len = *(unsigned short*)ptr;
  450.             //-----------------------------------------------------------------
  451.             if (ptr[2] > 11)
  452.                 return 0;
  453.             //-----------------------------------------------------------------
  454.             unsigned char *dstpage = model48k ? p48[ptr[2]] :
  455.                                                 p128[ptr[2]];
  456.             //-----------------------------------------------------------------
  457.             if (!dstpage)
  458.                 return 0;
  459.             //-----------------------------------------------------------------
  460.             ptr += 3;
  461.             //-----------------------------------------------------------------
  462.             if (len == 0xFFFF)
  463.             {
  464.                 len = PAGE;
  465.                 memcpy(dstpage, ptr, len);
  466.             }
  467.             else
  468.             {
  469.                 unpack_page(dstpage, PAGE, ptr, len);
  470.             }
  471.             //-----------------------------------------------------------------
  472.             ptr += len;
  473.             //-----------------------------------------------------------------
  474.         }
  475.         //---------------------------------------------------------------------
  476.     }
  477.     else
  478.     {
  479.         unsigned len = snapsize - 30;
  480.         unsigned char *mem48 = ptr;
  481.         //---------------------------------------------------------------------
  482.         if (hdr->flags & 0x20)
  483.             unpack_page(mem48 = snbuf + 4*PAGE, 3*PAGE, ptr, len);
  484.         //---------------------------------------------------------------------
  485.         memcpy(memory + (PAGE * 5), mem48,              PAGE);
  486.         memcpy(memory + (PAGE * 2), mem48 + PAGE,       PAGE);
  487.         memcpy(memory + (PAGE * 0), mem48 + (2 * PAGE), PAGE);
  488.         model48k = 1;
  489.     }
  490.     //-------------------------------------------------------------------------
  491.     cpu.a = hdr->a;
  492.     cpu.f = hdr->f;
  493.     cpu.bc = hdr->bc;
  494.     cpu.de = hdr->de; cpu.hl = hdr->hl;
  495.     cpu.alt.bc = hdr->bc1;
  496.     cpu.alt.de = hdr->de1;
  497.     cpu.alt.hl = hdr->hl1;
  498.     cpu.alt.a = hdr->a1;
  499.     cpu.alt.f = hdr->f1;
  500.     cpu.pc = hdr->pc;
  501.     cpu.sp = hdr->sp;
  502.     cpu.ix = hdr->ix;
  503.     cpu.iy = hdr->iy;
  504.     cpu.i = hdr->i;
  505.     cpu.r_low = hdr->r & 0x7F;
  506.     cpu.r_hi = u8((hdr->flags & 1U) << 7U);
  507.     comp.pFE = (hdr->flags >> 1) & 7;
  508.     comp.border_attr = comp.pFE;
  509.     cpu.iff1 = hdr->iff1;
  510.     cpu.iff2 = hdr->iff2;
  511.     cpu.im = (hdr->im & 3);
  512.     comp.p7FFD = (model48k)  ?  0x30 :
  513.                                 hdr->p7FFD;
  514.     //-------------------------------------------------------------------------
  515.     if (hdr->len == 55)                 // version 3.0 (with 1ffd)
  516.         comp.p1FFD = hdr->p1FFD;
  517.     //-------------------------------------------------------------------------
  518.     if (model48k)
  519.         comp.pEFF7 |= EFF7_LOCKMEM;     //Alone Coder
  520.     //-------------------------------------------------------------------------
  521.     set_banks();
  522.     //-------------------------------------------------------------------------
  523.     return 1;
  524. }
  525. //=============================================================================
  526.  
  527.  
  528. //=============================================================================
  529. static int readPAL()
  530. {
  531.     memcpy(comp.comp_pal, snbuf, snapsize);
  532.     temp.comp_pal_changed = 1;
  533.     if (conf.ula_plus)
  534.     {
  535.         // ┼ёыш яЁшёєЄёЄтєхЄ ULA+, Єю ёЁрчє ш ръЄштшЁєхь хх (ўЄюс√ шчьхэхэш  ярышЄЁ√ с√ыш тшфэ√)
  536.         comp.ula_plus_en = true;
  537.     }
  538.     return 1;
  539. }
  540. //=============================================================================
  541.  
  542.  
  543. //=============================================================================
  544. static int writePAL(FILE *ff)
  545. {
  546.     if ( fwrite(        comp.comp_pal,
  547.                         1,
  548.                         sizeof(comp.comp_pal),
  549.                         ff
  550.                 )
  551.                 != sizeof(comp.comp_pal)
  552.       )
  553.     {
  554.         return 0;
  555.     }
  556.     return 1;
  557. }
  558. //=============================================================================
  559.  
  560. #define arctmp ((char*)rbuf)
  561. static char *arc_fname;
  562.  
  563. //=============================================================================
  564. static INT_PTR CALLBACK ArcDlg(HWND dlg, UINT msg, WPARAM wp, LPARAM lp)
  565. {
  566.     (void)lp;
  567.  
  568.     //-------------------------------------------------------------------------
  569.     if (msg == WM_INITDIALOG)
  570.     {
  571.         for (char *dst = arctmp; *dst; dst += strlen(dst)+1)
  572.             SendDlgItemMessage(dlg, IDC_ARCLIST, LB_ADDSTRING, 0, (LPARAM)dst);
  573.            
  574.         SendDlgItemMessage(dlg, IDC_ARCLIST, LB_SETCURSEL, 0, 0);
  575.         return 1;
  576.     }
  577.     //-------------------------------------------------------------------------
  578.     if (        ((msg == WM_COMMAND) && (wp == IDCANCEL))
  579.                 ||
  580.                 ((msg == WM_SYSCOMMAND) && ((wp & 0xFFF0) == SC_CLOSE))
  581.       )
  582.     {
  583.         EndDialog(dlg, 0);
  584.     }
  585.     //-------------------------------------------------------------------------
  586.     if (        (msg == WM_COMMAND)
  587.                 &&
  588.                 (       (LOWORD(wp) == IDOK)
  589.                         ||
  590.                         ((HIWORD(wp) == LBN_DBLCLK) && (LOWORD(wp) == IDC_ARCLIST))
  591.                 )
  592.       )
  593.     {
  594.         int n = int(SendDlgItemMessage(dlg, IDC_ARCLIST, LB_GETCURSEL, 0, 0));
  595.         char *dst = arctmp;
  596.         for (int q = 0; q < n; q++)
  597.             dst += strlen(dst) + 1;
  598.         arc_fname = dst;
  599.         EndDialog(dlg, 0);
  600.     }
  601.     return 0;
  602. }
  603. //=============================================================================
  604.  
  605.  
  606. //=============================================================================
  607. static bool filename_ok(char *fname)
  608. {
  609.     for (char *wc = skiparc; *wc; wc += strlen(wc) + 1)
  610.         if (wcmatch(fname, wc))
  611.             return 0;
  612.     return 1;
  613. }
  614. //=============================================================================
  615.  
  616.  
  617. //=============================================================================
  618. int load_arc(char *fname)
  619. {
  620.     char *ext = strrchr(fname, '.');
  621.     //-------------------------------------------------------------------------
  622.     if (!ext)
  623.         return 0;
  624.     //-------------------------------------------------------------------------
  625.     ext++;
  626.     char *cmdtmp;
  627.     char done = 0;
  628.     //-------------------------------------------------------------------------
  629.     for (char *x = arcbuffer; *x; x = cmdtmp + strlen(cmdtmp)+1)
  630.     {
  631.         cmdtmp = x + strlen(x) + 1;
  632.         //---------------------------------------------------------------------
  633.         if (stricmp(ext, x))
  634.             continue;
  635.         //---------------------------------------------------------------------
  636.         char dir[0x200];
  637.         GetCurrentDirectory(sizeof dir, dir);
  638.         char tmp[0x200];
  639.         GetTempPath(sizeof tmp, tmp);
  640.         char d1[0x20];
  641.         sprintf(d1, "us%08lX", GetTickCount());
  642.         SetCurrentDirectory(tmp);
  643.         CreateDirectory(d1, nullptr);
  644.         SetCurrentDirectory(d1);
  645.         //---------------------------------------------------------------------
  646.         color();
  647.         char cmdln[0x200]; sprintf(cmdln, cmdtmp, fname);
  648.         STARTUPINFO si = { sizeof si };
  649.         si.dwFlags = STARTF_USESHOWWINDOW; si.wShowWindow = SW_HIDE;
  650.         PROCESS_INFORMATION pi;
  651.         unsigned flags = CREATE_NEW_CONSOLE;
  652.         HANDLE hc = CreateFile("CONOUT$", GENERIC_WRITE, FILE_SHARE_READ|FILE_SHARE_WRITE, nullptr, OPEN_EXISTING, 0, nullptr);
  653.         //---------------------------------------------------------------------
  654.         if (hc != INVALID_HANDLE_VALUE)
  655.         {
  656.             CloseHandle(hc);
  657.             flags = 0;
  658.         }
  659.         //---------------------------------------------------------------------
  660.         if (CreateProcess(nullptr, cmdln, nullptr, nullptr, 0, flags, nullptr, nullptr, &si, &pi)) {
  661.             WaitForSingleObject(pi.hProcess, INFINITE);
  662.             DWORD code; GetExitCodeProcess(pi.hProcess, &code);
  663.             CloseHandle(pi.hThread);
  664.             CloseHandle(pi.hProcess);
  665.             //-----------------------------------------------------------------
  666.             if (!code || MessageBox(GetForegroundWindow(), "Broken archive", nullptr, MB_ICONERROR | MB_OKCANCEL) == IDOK)
  667.             {
  668.                 WIN32_FIND_DATA fd;
  669.                 HANDLE h;
  670.                 char *dst = arctmp;
  671.                 unsigned nfiles = 0;
  672.                 //-------------------------------------------------------------
  673.                 if ((h = FindFirstFile("*.*", &fd)) != INVALID_HANDLE_VALUE)
  674.                 {
  675.                     //---------------------------------------------------------
  676.                     do
  677.                     {
  678.                         if (!(fd.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) && filename_ok(fd.cFileName))
  679.                         {
  680.                             strcpy(dst, fd.cFileName);
  681.                             dst += strlen(dst) + 1;
  682.                             nfiles++;
  683.                         }
  684.                     }
  685.                     while (FindNextFile(h, &fd));
  686.                     //---------------------------------------------------------
  687.                     FindClose(h);
  688.                 }
  689.                 //-------------------------------------------------------------
  690.                 *dst = 0;
  691.                 arc_fname = nullptr;
  692.                 //-------------------------------------------------------------
  693.                 if (nfiles == 1)
  694.                     arc_fname = arctmp;
  695.                 //-------------------------------------------------------------
  696.                 if (nfiles > 1)
  697.                     DialogBox(hIn, MAKEINTRESOURCE(IDD_ARC), GetForegroundWindow(), ArcDlg);
  698.                 //-------------------------------------------------------------
  699.                 if (!nfiles)
  700.                     MessageBox(GetForegroundWindow(), "Empty archive!", nullptr, MB_ICONERROR | MB_OK);
  701.                 //-------------------------------------------------------------
  702.                 char buf[0x200]; strcpy(buf, tmp); strcat(buf, "\\");
  703.                 strcat(buf, d1);
  704.                 strcat(buf, "\\");
  705.                 //-------------------------------------------------------------
  706.                 if (arc_fname)
  707.                 {
  708.                     strcat(buf, arc_fname);
  709.                     arc_fname = buf;
  710.                 }
  711.                 //-------------------------------------------------------------
  712.                 if (arc_fname && !(done = (char)loadsnap(arc_fname)))
  713.                     MessageBox(GetForegroundWindow(), "loading error", arc_fname, MB_ICONERROR);
  714.                 //-------------------------------------------------------------
  715.                 if (!done)
  716.                     done = -1;
  717.                 //-------------------------------------------------------------
  718.             }
  719.             //-----------------------------------------------------------------
  720.             // delete junk
  721.             SetCurrentDirectory(tmp);
  722.             SetCurrentDirectory(d1);
  723.             WIN32_FIND_DATA fd;
  724.             HANDLE h;
  725.             //-----------------------------------------------------------------
  726.             if ((h = FindFirstFile("*.*", &fd)) != INVALID_HANDLE_VALUE)
  727.             {
  728.                 //-------------------------------------------------------------
  729.                 do
  730.                 {
  731.                     DeleteFile(fd.cFileName);
  732.                 }
  733.                 while (FindNextFile(h, &fd));
  734.                 //-------------------------------------------------------------
  735.                 FindClose(h);
  736.             }
  737.         }
  738.         SetCurrentDirectory(tmp);
  739.         RemoveDirectory(d1);
  740.         SetCurrentDirectory(dir);
  741.         eat();
  742.         //---------------------------------------------------------------------
  743.         if (done)
  744.             return done > 0  ?  1 :
  745.                                 0;
  746.         //---------------------------------------------------------------------
  747.     }
  748.     eat();
  749.     return 0;
  750. }
  751. //=============================================================================
  752.  
  753.  
  754. //=============================================================================
  755. void opensnap(unsigned index)
  756. {
  757.     char mask[0x200];
  758.     *mask = 0;
  759.     //-------------------------------------------------------------------------
  760.     for (char *x = arcbuffer; *x; )
  761.     {
  762.         strcat(mask, ";*.");
  763.         strcat(mask, x);
  764.         x += strlen(x) + 1;
  765.         x += strlen(x) + 1;
  766.     }
  767.     //-------------------------------------------------------------------------
  768.     char fline[0x400];
  769.     const char  *src =  "all (sna,z80,sp,tap,tzx,csw,trd,scl,fdi,td0,udi,isd,pro,dsk,ipf,hobeta,pal)\0"
  770.                         "*.sna;*.z80;*.sp;*.tap;*.tzx;*.csw;*.trd;*.scl;*.td0;*.udi;*.fdi;*.isd;*.pro;*.dsk;*.ipf;*.$?;*.!?;*.pal<\0"
  771.                         "Disk B (trd,scl,fdi,td0,udi,isd,pro,dsk,ipf,hobeta)\0*.trd;*.scl;*.fdi;*.udi;*.td0;*.isd;*.pro;*.dsk;*.ipf;*.$?<\0"
  772.                         "Disk C (trd,scl,fdi,td0,udi,isd,pro,dsk,ipf,hobeta)\0*.trd;*.scl;*.fdi;*.udi;*.td0;*.isd;*.pro;*.dsk;*.ipf;*.$?<\0"
  773.                         "Disk D (trd,scl,fdi,td0,udi,isd,pro,dsk,ipf,hobeta)\0*.trd;*.scl;*.fdi;*.udi;*.td0;*.isd;*.pro;*.dsk;*.ipf;*.$?<\0\0>";
  774.     //-------------------------------------------------------------------------
  775.     if (!conf.trdos_present)
  776.                 src =   "ZX files (sna,z80,tap,tzx,csw,pal)\0*.sna;*.z80;*.tap;*.tzx;*.csw;*.pal<\0\0>";
  777.     //-------------------------------------------------------------------------
  778.     for (char *dst = fline; *src != '>'; src++)
  779.     {
  780.         //---------------------------------------------------------------------
  781.         if (*src == '<')
  782.         {
  783.             strcpy(dst, mask);
  784.             dst += strlen(dst);
  785.         }
  786.         //---------------------------------------------------------------------
  787.         else
  788.         {
  789.             *dst++ = *src;
  790.         }
  791.         //---------------------------------------------------------------------
  792.     }
  793.     //-------------------------------------------------------------------------
  794.     OPENFILENAME ofn = { };
  795.     char fname[0x200];
  796.     *fname = 0;
  797.     char dir[0x200];
  798.     GetCurrentDirectory(sizeof dir, dir);
  799.  
  800.     ofn.lStructSize = (WinVerMajor < 5)    ?    OPENFILENAME_SIZE_VERSION_400 :
  801.                                                 sizeof(OPENFILENAME);
  802.     ofn.hwndOwner = GetForegroundWindow();
  803.     ofn.lpstrFilter = fline;
  804.     ofn.lpstrFile = fname;
  805.     ofn.nMaxFile = sizeof fname;
  806.     ofn.lpstrTitle = "Load Snapshot / Disk / Tape";
  807.     ofn.Flags = OFN_FILEMUSTEXIST | OFN_HIDEREADONLY;
  808.     ofn.nFilterIndex = DWORD(index);
  809.     ofn.lpstrInitialDir = dir;
  810. //   __debugbreak();
  811.     //-------------------------------------------------------------------------
  812.     if (GetSnapshotFileName(&ofn, 0))
  813.     {
  814.         trd_toload = ofn.nFilterIndex - 1;
  815.         if (!loadsnap(fname))
  816.             MessageBox(GetForegroundWindow(), fname, "loading error", MB_ICONERROR);
  817.     }
  818.     //-------------------------------------------------------------------------
  819.     eat();
  820. }
  821. //=============================================================================
  822.  
  823.  
  824. //=============================================================================
  825. static const int mx_typs = (1 + 4 * 6);
  826. static unsigned char snaps[mx_typs];
  827. static unsigned exts[mx_typs];
  828. static unsigned drvs[mx_typs];
  829. static unsigned snp;
  830. //=============================================================================
  831.  
  832.  
  833. //=============================================================================
  834. static void addref(LPSTR &ptr, unsigned char sntype, const char *ref, unsigned drv, unsigned ext)
  835. {
  836.     strcpy(ptr, ref);
  837.     ptr += strlen(ptr) + 1;
  838.     strcpy(ptr, ref + strlen(ref) + 1);
  839.     ptr += strlen(ptr) + 1;
  840.     drvs[snp] = drv;
  841.     exts[snp] = ext;
  842.     snaps[snp++] = sntype;
  843. }
  844. //=============================================================================
  845.  
  846.  
  847. //=============================================================================
  848. void savesnap(int diskindex)
  849. {
  850. again:
  851.     OPENFILENAME ofn = { };
  852.     char fname[0x200];
  853.     *fname = 0;
  854.     //-------------------------------------------------------------------------
  855.     if (diskindex >= 0)
  856.     {
  857.         strcpy(fname, comp.fdd[diskindex].name);
  858.         size_t ln = strlen(fname);
  859.         if (ln > 4 && (*(unsigned*)(fname+ln-4) | WORD4(0,0x20,0x20,0x20)) == WORD4('.','s','c','l'))
  860.             *(unsigned*)(fname+ln-4) = WORD4('.','t','r','d');
  861.     }
  862.     //-------------------------------------------------------------------------
  863.     snp = 1;
  864.     char types[600], *ptr = types;
  865.     //-------------------------------------------------------------------------
  866.     if (diskindex < 0)
  867.     {
  868.         exts[snp] = WORD4('s','n','a',0);
  869.         snaps[snp] = snSNA_128; // default
  870.         addref(ptr, snSNA_128, "ZX-Spectrum 128K snapshot (SNA)\0*.sna", -1U, WORD4('s','n','a',0));
  871.  
  872.         exts[snp] = WORD4('p', 'a', 'l', 0);
  873.         snaps[snp] = snPAL;
  874.         addref(ptr, snPAL, "Palette (ULA+)\0*.pal", -1U, WORD4('p', 'a', 'l', 0));
  875.     }
  876.     //-------------------------------------------------------------------------
  877.     ofn.lStructSize = (WinVerMajor < 5)    ?    OPENFILENAME_SIZE_VERSION_400 :
  878.                                                 sizeof(OPENFILENAME);
  879.     ofn.nFilterIndex = 1;
  880.     //-------------------------------------------------------------------------
  881.     if (conf.trdos_present)
  882.     {
  883.         static char mask[] = "Disk A (TRD)\0*.trd";
  884.         //---------------------------------------------------------------------
  885.         static const char ex[][3] =
  886.         {      
  887.             {'T','R','D'},
  888.             {'F','D','I'},
  889.             {'T','D','0'},
  890.             {'U','D','I'},
  891.             {'I','S','D'},
  892.             {'P','R','O'}
  893.         };
  894.         //---------------------------------------------------------------------
  895.         static const unsigned ex2[] =
  896.         {
  897.             snTRD,
  898.             snFDI,
  899.             snTD0,
  900.             snUDI,
  901.             snISD,
  902.             snPRO
  903.         };
  904.         //---------------------------------------------------------------------
  905.         for (unsigned n = 0; n < 4; n++)
  906.         {
  907.             //-----------------------------------------------------------------
  908.             if (!comp.fdd[n].rawdata)
  909.                 continue;
  910.             //-----------------------------------------------------------------
  911.             if (diskindex >= 0 && unsigned(diskindex) != n)
  912.                 continue;
  913.             //-----------------------------------------------------------------
  914.             mask[5] = char('A'+n);
  915.             //-----------------------------------------------------------------
  916.             for (size_t i = 0; i < sizeof ex/sizeof(ex[0]); i++)
  917.             {
  918.                 //-------------------------------------------------------------
  919.                 if ((unsigned(diskindex) == n) && (ex2[i] == comp.fdd[n].snaptype))
  920.                     ofn.nFilterIndex = snp;
  921.                 //-------------------------------------------------------------
  922.                 memcpy(mask+8,  ex[i]3);
  923.                 memcpy(mask+15, ex[i]3);
  924.                 addref( ptr,
  925.                         u8(ex2[i]),
  926.                         mask,
  927.                         n,
  928.                         (*(const unsigned*)ex[i] & 0xFFFFFF) | 0x202020
  929.                       );
  930.             }
  931.             //-----------------------------------------------------------------
  932.         }
  933.         //---------------------------------------------------------------------
  934.     } //conf.trdos_present
  935.     //-------------------------------------------------------------------------
  936.     ofn.lpstrFilter = types;
  937.     *ptr = 0;
  938.     ofn.lpstrFile = fname;
  939.     ofn.nMaxFile = sizeof fname;
  940.     ofn.Flags = OFN_PATHMUSTEXIST | OFN_HIDEREADONLY;
  941.     ofn.hwndOwner = GetForegroundWindow();
  942.     char *path = strrchr(fname, '\\');
  943.     //-------------------------------------------------------------------------
  944.     if (path)
  945.     { // check if directory exists (for files opened from archive)
  946.         char x = *path;
  947.         *path = 0;
  948.         unsigned atr = GetFileAttributes(fname);
  949.         *path = x;
  950.         //---------------------------------------------------------------------
  951.         if (atr == -1U || !(atr & FILE_ATTRIBUTE_DIRECTORY))
  952.             *fname = 0;
  953.         //---------------------------------------------------------------------
  954.     }
  955.     else
  956.     {
  957.         path = fname;
  958.     }
  959.     //-------------------------------------------------------------------------
  960.     path = strrchr(path, '.');
  961.     if (path)
  962.         *path = 0; // delete extension
  963.     //-------------------------------------------------------------------------
  964.     if (GetSnapshotFileName(&ofn, 1))
  965.     {
  966.         //printf("get snapshot filename\n");    //Єюы№ъю яЁш чряшёш
  967.                                                 //яЁш юЄъЁ√Єшш эх ёЁрсрЄ√трхЄ
  968.         char *fn = strrchr(ofn.lpstrFile, '\\');
  969.         fn = fn    ?    fn + 1 :
  970.                         ofn.lpstrFile;
  971.         char *extpos = strrchr(fn, '.');
  972.         //---------------------------------------------------------------------
  973.         if (!extpos || stricmp(extpos+1, (char*)&exts[ofn.nFilterIndex]))
  974.         {
  975.             char *dst = fn + strlen(fn);
  976.             *dst++ = '.';
  977.             *(unsigned*)dst = exts[ofn.nFilterIndex];
  978.         }
  979.         //---------------------------------------------------------------------
  980.         if (    (GetFileAttributes(ofn.lpstrFile) != INVALID_FILE_ATTRIBUTES) &&
  981.                 (IDNO == MessageBox(GetForegroundWindow(), "File exists. Overwrite ?", "Save", MB_ICONQUESTION | MB_YESNO))
  982.           )
  983.         {
  984.             goto again;
  985.         }
  986.         //---------------------------------------------------------------------
  987.         FILE *ff = fopen(ofn.lpstrFile, "wb");
  988.         //---------------------------------------------------------------------
  989.         if (ff)
  990.         {
  991.             int res = 0;
  992.             FDD *saveto = comp.fdd + drvs[ofn.nFilterIndex];
  993.             //-----------------------------------------------------------------
  994.             switch (snaps[ofn.nFilterIndex])
  995.             {
  996.                 case snSNA_128: res = writeSNA(ff);             break;
  997.                 case snPAL:     res = writePAL(ff);             break;
  998.                 case snTRD:     res = saveto->write_trd(ff);    break;
  999.                 case snUDI:     res = saveto->write_udi(ff);    break;
  1000.                 case snFDI:     res = saveto->write_fdi(ff);    break;
  1001.                 case snTD0:     res = saveto->write_td0(ff);    break;
  1002.                 case snISD:     res = saveto->write_isd(ff);    break;
  1003.                 case snPRO:     res = saveto->write_pro(ff);    break;
  1004.             }
  1005.             //-----------------------------------------------------------------
  1006.             fclose(ff);
  1007.             //-----------------------------------------------------------------
  1008.             if (!res)
  1009.                 MessageBox(GetForegroundWindow(), "write error", "Save", MB_ICONERROR);
  1010.             //-----------------------------------------------------------------
  1011.             else if (drvs[ofn.nFilterIndex]!=-1U)
  1012.             {
  1013.                 comp.fdd[drvs[ofn.nFilterIndex]].optype=0;
  1014.                 strcpy(comp.fdd[drvs[ofn.nFilterIndex]].name, ofn.lpstrFile);
  1015.                 //---------Alone Coder
  1016.                 char *name = ofn.lpstrFile;
  1017.                 //printf("snaphot filename printing\n");
  1018.                 //-------------------------------------------------------------
  1019.                 for (char *x = name; *x; x++)
  1020.                 {
  1021.                     if (*x == '\\')
  1022.                         name = x+1;
  1023.                 }
  1024.                 //-------------------------------------------------------------
  1025.                 char wintitle[0x200];
  1026.                 strcpy(wintitle,name);
  1027. //              strcat(wintitle," - UnrealSpeccy");
  1028.                 strcat(wintitle," - Unreal_NS");        // фы  ёюїЁрэхээюую фшёър
  1029.                 SetWindowText(wnd, wintitle);
  1030.                 //~---------Alone Coder
  1031.             }
  1032.             //-----------------------------------------------------------------
  1033.         }
  1034.         //---------------------------------------------------------------------
  1035.         else
  1036.         {
  1037.             MessageBox(GetForegroundWindow(), "Can't open file for writing", "Save", MB_ICONERROR);
  1038.         }
  1039.         //---------------------------------------------------------------------
  1040.     }
  1041.     //-------------------------------------------------------------------------
  1042.     eat();
  1043. }
  1044. //=============================================================================
  1045.  
  1046.  
  1047.  
  1048. //=============================================================================
  1049. void ConvPal8ToBgr24(u8 *dst, u8 *scrbuf, int dx)
  1050. {
  1051.     u8 *ds = dst;
  1052.     //-------------------------------------------------------------------------
  1053.     for(unsigned i = 0; i < temp.oy; i++)       // convert to BGR24 format
  1054.     {
  1055.         unsigned char *src = scrbuf + int(i) * dx;
  1056.         //---------------------------------------------------------------------
  1057.         for (unsigned y = 0; y < temp.ox; y++)
  1058.         {
  1059.             ds[0] = pal0[src[y]].peBlue;
  1060.             ds[1] = pal0[src[y]].peGreen;
  1061.             ds[2] = pal0[src[y]].peRed;
  1062.             ds += 3;
  1063.         }
  1064.         //---------------------------------------------------------------------
  1065.         ds = (PBYTE)(ULONG_PTR(ds + 3) & ~ULONG_PTR(3)); // ърцфр  ёЄЁюър т√Ёртэхэр эр 4
  1066.     }
  1067.     //-------------------------------------------------------------------------
  1068. }
  1069. //=============================================================================
  1070.  
  1071.  
  1072. //=============================================================================
  1073. void ConvRgb15ToBgr24(u8 *dst, u8 *scrbuf, int dx)
  1074. {
  1075.     u8 *ds = dst;
  1076.     //-------------------------------------------------------------------------
  1077.     for(unsigned i = 0; i < temp.oy; i++)       // convert to BGR24 format
  1078.     {
  1079.         unsigned char *src = scrbuf + int(i) * dx;
  1080.         //---------------------------------------------------------------------
  1081.         for (unsigned y = 0; y < temp.ox; y++)
  1082.         {
  1083.             unsigned xx;
  1084.             xx = *(unsigned*)(src + y*2);
  1085.  
  1086.             ds[0] = u8((xx & 0x1F)   << 3);
  1087.             ds[1] = u8((xx & 0x03E0) >> 2);
  1088.             ds[2] = u8((xx & 0x7C00) >> 7);
  1089.             ds += 3;
  1090.         }
  1091.         //---------------------------------------------------------------------
  1092.         ds = (PBYTE)(ULONG_PTR(ds + 3) & ~ULONG_PTR(3)); // ърцфр  ёЄЁюър т√Ёртэхэр эр 4
  1093.     }
  1094.     //-------------------------------------------------------------------------
  1095. }
  1096. //=============================================================================
  1097.  
  1098.  
  1099. //=============================================================================
  1100. void ConvRgb16ToBgr24(u8 *dst, u8 *scrbuf, int dx)
  1101. {
  1102.     u8 *ds = dst;
  1103.     //-------------------------------------------------------------------------
  1104.     for(unsigned i = 0; i < temp.oy; i++)       // convert to BGR24 format
  1105.     {
  1106.         unsigned char *src = scrbuf + int(i) * dx;
  1107.         //---------------------------------------------------------------------
  1108.         for (unsigned y = 0; y < temp.ox; y++)
  1109.         {
  1110.             unsigned xx;
  1111.             xx = *(unsigned*)(src + y*2);
  1112.  
  1113.             ds[0] = u8((xx&0x1F)   << 3);
  1114.             ds[1] = u8((xx&0x07E0) >> 3);
  1115.             ds[2] = u8((xx&0xF800) >> 8);
  1116.             ds += 3;
  1117.         }
  1118.         //---------------------------------------------------------------------
  1119.         ds = (PBYTE)(ULONG_PTR(ds + 3) & ~ULONG_PTR(3)); // ърцфр  ёЄЁюър т√Ёртэхэр эр 4
  1120.     }
  1121.     //-------------------------------------------------------------------------
  1122. }
  1123. //=============================================================================
  1124.  
  1125.  
  1126. //=============================================================================
  1127. void ConvYuy2ToBgr24(u8 *dst, u8 *scrbuf, int dx)
  1128. {
  1129.     u8 *ds = dst;
  1130.     //-------------------------------------------------------------------------
  1131.     for(unsigned i = 0; i < temp.oy; i++) // convert to BGR24 format
  1132.     {
  1133.         unsigned char *src = scrbuf + int(i) * dx;
  1134.         //---------------------------------------------------------------------
  1135.         for (unsigned y = 0; y < temp.ox; y++)
  1136.         {
  1137.             unsigned xx;
  1138.             xx = *(unsigned*)(src + y*2);
  1139.  
  1140.             int u = src[y / 2 * 4 + 1];
  1141.             int v = src[y / 2 * 4 + 3];
  1142.             int Y = src[y * 2];
  1143.             int r = (int)(.4732927654e-2 * u - 255.3076403 + 1.989858012 * v + .9803921569 * Y);
  1144.             int g = (int)(-.9756592292   * v + 186.0716700 - .4780256930 * u + .9803921569 * Y);
  1145.             int b = (int)(.9803921569    * Y + 2.004732928 * u - 255.3076403 - .1014198783e-1 * v); // mapple rulez!
  1146.            
  1147.             if (r < 0) r = 0; if (r > 255) r = 255;
  1148.             if (g < 0) g = 0; if (g > 255) g = 255;
  1149.             if (b < 0) b = 0; if (b > 255) b = 255;
  1150.  
  1151.             ds[0] = u8(b);
  1152.             ds[1] = u8(g);
  1153.             ds[2] = u8(r);
  1154.             ds += 3;
  1155.         }
  1156.         //---------------------------------------------------------------------
  1157.         ds = (PBYTE)(ULONG_PTR(ds + 3) & ~ULONG_PTR(3)); // ърцфр  ёЄЁюър т√Ёртэхэр эр 4
  1158.     }
  1159.     //-------------------------------------------------------------------------
  1160. }
  1161. //=============================================================================
  1162.  
  1163.  
  1164. //=============================================================================
  1165. void ConvBgr32ToBgr24(u8 *dst, u8 *scrbuf, int dx)
  1166. {
  1167.     u8 *ds = dst;
  1168.     //-------------------------------------------------------------------------
  1169.     for(unsigned i = 0; i < temp.oy; i++)       // convert to BGR24 format
  1170.     {
  1171.         unsigned char *src = scrbuf + int(i) * dx;
  1172.         //---------------------------------------------------------------------
  1173.         for (unsigned x = 0; x < temp.ox; x++)
  1174.         {
  1175.             ds[0] = src[0];
  1176.             ds[1] = src[1];
  1177.             ds[2] = src[2];
  1178.             src += 4;
  1179.             ds += 3;
  1180.         }
  1181.         //---------------------------------------------------------------------
  1182.         ds = (PBYTE)(ULONG_PTR(ds + 3) & ~ULONG_PTR(3)); // ърцфр  ёЄЁюър т√Ёртэхэр эр 4
  1183.     }
  1184.     //-------------------------------------------------------------------------
  1185. }
  1186. //=============================================================================
  1187.  
  1188. TColorConverter ConvBgr24 = nullptr;
  1189.  
  1190. //=============================================================================
  1191. static void SaveBmp(FILE *File, u8 *ds)
  1192. {
  1193.     //-------------------------------------------------------------------------
  1194.     static u8 bmpheader32[]=
  1195.     {
  1196.         // BITMAPFILEHEADER
  1197.         0x42, 0x4d,                     // Type
  1198.         0x36, 0x10, 0x0e, 0x00,         // Size
  1199.         0x00, 0x00,                     // Reserved1
  1200.         0x00, 0x00,                     // Reserved2
  1201.         0x36, 0x00, 0x00, 0x00,         // OffBits
  1202.         // BITMAPINFOHEADER
  1203.         0x28, 0x00, 0x00, 0x00,         // Size
  1204.         0x80, 0x02, 0x00, 0x00,         // Width
  1205.         0xe0, 0x01, 0x00, 0x00,         // Height
  1206.         0x01, 0x00,                     // Planes
  1207.         0x18, 0x00,                     // BitCount
  1208.         0x00, 0x00, 0x00, 0x00,         // Compression
  1209.         0x00, 0x10, 0x0e, 0x00,         // SizeImage
  1210.         0x00, 0x00, 0x00, 0x00,         // XPixelsPerMeter
  1211.         0x00, 0x00, 0x00, 0x00,         // YPixelsPerMeter
  1212.         0x00, 0x00, 0x00, 0x00,         // ClrUsed
  1213.         0x00, 0x00, 0x00, 0x00          // ClrImportant
  1214.     };
  1215.     //-------------------------------------------------------------------------
  1216.     *(unsigned*)(bmpheader32 + 2) = temp.ox * temp.oy * 3 + sizeof(bmpheader32); // filesize
  1217.     *(unsigned*)(bmpheader32 + 0x12) = temp.ox;
  1218.     *(unsigned*)(bmpheader32 + 0x16) = temp.oy;
  1219.     //-------------------------------------------------------------------------
  1220.     fwrite(bmpheader32, 1, sizeof(bmpheader32), File);
  1221.     //-------------------------------------------------------------------------
  1222.     for (int y = int(temp.oy - 1); y >= 0 ; y--)
  1223.     {
  1224.         fwrite(ds + ((unsigned(y) * temp.ox * 3 + 3) & ~3U), 1, temp.ox * 3, File);
  1225.     }
  1226.     //-------------------------------------------------------------------------
  1227. }
  1228. //=============================================================================
  1229.  
  1230.  
  1231. //=============================================================================
  1232. static void SavePng(FILE *File, u8 *ds)
  1233. {
  1234.     static png_color bkgColor = {127, 127, 127};
  1235.  
  1236.     if (!temp.PngSupport)
  1237.         return;
  1238.  
  1239.     PngSaveImage(File, ds, int(temp.ox), int(temp.oy), bkgColor);
  1240. }
  1241. //=============================================================================
  1242.  
  1243. #define MAKE_RGBQUAD(r,g,b) (ULONG) (u32(b) | (u32(g)<<8) | (u32(r)<<16))
  1244.  
  1245. //=============================================================================
  1246. static void SaveBmp16c(FILE *File, const u8 *ds)
  1247. {
  1248.     static u8 bmpheader32[]=
  1249.     {
  1250.         // BITMAPFILEHEADER
  1251.         0x42, 0x4d,             // Type
  1252.         0x36, 0x10, 0x0e, 0x00, // Size = 320*200/2 + sizeof(bmpheader32)
  1253.         0x00, 0x00,             // Reserved1
  1254.         0x00, 0x00,             // Reserved2
  1255.         0x76, 0x00, 0x00, 0x00, // OffBits
  1256.         // BITMAPINFOHEADER
  1257.         0x28, 0x00, 0x00, 0x00, // Size
  1258.         0x40, 0x01, 0x00, 0x00, // Width = 320
  1259.         0xc8, 0x00, 0x00, 0x00, // Height = 200
  1260.         0x01, 0x00,             // Planes
  1261.         0x04, 0x00,             // BitCount = 4
  1262.         0x00, 0x00, 0x00, 0x00, // Compression = BI_RGB
  1263.         0x00, 0x10, 0x0e, 0x00, // SizeImage
  1264.         0x00, 0x00, 0x00, 0x00, // XPixelsPerMeter
  1265.         0x00, 0x00, 0x00, 0x00, // YPixelsPerMeter
  1266.         0x00, 0x00, 0x00, 0x00, // ClrUsed
  1267.         0x00, 0x00, 0x00, 0x00, // ClrImportant
  1268.         // PALETTE
  1269.         0, 0, 0, 0,             //  0 bgra
  1270.         0, 0, 0, 0,             //  1 bgra
  1271.         0, 0, 0, 0,             //  2 bgra
  1272.         0, 0, 0, 0,             //  3 bgra
  1273.         0, 0, 0, 0,             //  4 bgra
  1274.         0, 0, 0, 0,             //  5 bgra
  1275.         0, 0, 0, 0,             //  6 bgra
  1276.         0, 0, 0, 0,             //  7 bgra
  1277.         0, 0, 0, 0,             //  8 bgra
  1278.         0, 0, 0, 0,             //  9 bgra
  1279.         0, 0, 0, 0,             // 10 bgra
  1280.         0, 0, 0, 0,             // 11 bgra
  1281.         0, 0, 0, 0,             // 12 bgra
  1282.         0, 0, 0, 0,             // 13 bgra
  1283.         0, 0, 0, 0,             // 14 bgra
  1284.         0, 0, 0, 0              // 15 bgra
  1285.     };
  1286.  
  1287.     *(unsigned*)(bmpheader32 + 2) = 320 * 200 / 2 + sizeof(bmpheader32); // filesize
  1288.     //-------------------------------------------------------------------------
  1289.     for(unsigned i = 0; i < 16; i++)
  1290.     {
  1291.         // ╘юЁьрЄ фрээ√ї ярышЄЁ√ Gg0Rr0Bb
  1292.         // ╨рёъырфър ярышЄЁ√ ¤ьєы ЄюЁр - ULA+
  1293.         unsigned PalIdx = ((i & 8) << 1) | (i & 7);
  1294.         u8 r = u8(u32((comp.comp_pal[PalIdx] >> 3) & 3) * 255 / 3);
  1295.         u8 g = u8(u32((comp.comp_pal[PalIdx] >> 6) & 3) * 255 / 3);
  1296.         u8 b = u8(u32( comp.comp_pal[PalIdx]       & 3) * 255 / 3);
  1297.  
  1298.         *(PULONG)(bmpheader32 + 54 + 4 * i) = MAKE_RGBQUAD(r, g, b);
  1299.     }
  1300.     //-------------------------------------------------------------------------
  1301.     fwrite(bmpheader32, 1, sizeof(bmpheader32), File);
  1302.     fwrite(ds, 1, 320 * 200 / 2, File);
  1303. }
  1304. //=============================================================================
  1305.  
  1306.  
  1307. //=============================================================================
  1308. static void ConvPal16cAtm1(u8 *Buf)
  1309. {
  1310.     static const int ega0_ofs = -4 * PAGE;
  1311.     static const int ega1_ofs = 0;
  1312.     static const int ega2_ofs = -4 * PAGE + 0x2000;
  1313.     static const int ega3_ofs = 0x2000;
  1314.     //-------------------------------------------------------------------------
  1315.     for (int y = 200 - 1; y >= 0; y--)
  1316.     {
  1317.         const u8 *src = temp.base + y * 40;
  1318.         //---------------------------------------------------------------------
  1319.         for(unsigned x = 0; x < 320; x += 8)
  1320.         {
  1321.             u8 v0 = src[ega0_ofs];
  1322.             u8 v1 = src[ega1_ofs];
  1323.             u8 v2 = src[ega2_ofs];
  1324.             u8 v3 = src[ega3_ofs];
  1325.             Buf[0] = u8(((((v0 >> 3) & 8) | (v0 & 0x7)) << 4) | (((v0 & 0x80) | ((v0 << 1) & 0x70)) >> 4));
  1326.             Buf[1] = u8(((((v1 >> 3) & 8) | (v1 & 0x7)) << 4) | (((v1 & 0x80) | ((v1 << 1) & 0x70)) >> 4));
  1327.             Buf[2] = u8(((((v2 >> 3) & 8) | (v2 & 0x7)) << 4) | (((v2 & 0x80) | ((v2 << 1) & 0x70)) >> 4));
  1328.             Buf[3] = u8(((((v3 >> 3) & 8) | (v3 & 0x7)) << 4) | (((v3 & 0x80) | ((v3 << 1) & 0x70)) >> 4));
  1329.          
  1330.             src++;
  1331.             Buf += 4;
  1332.         }
  1333.         //---------------------------------------------------------------------
  1334.     }
  1335.     //-------------------------------------------------------------------------
  1336. }
  1337. //=============================================================================
  1338.  
  1339. #define ConvPal16cAtm2 ConvPal16cAtm1
  1340.  
  1341. typedef void (*TSaver)(FILE *File, u8 *ds);
  1342.  
  1343. //=============================================================================
  1344. void main_scrshot()
  1345. {
  1346.     char fname[FILENAME_MAX];
  1347. //  static unsigned sshot = 999990;//0; // ёЄрЁЄют√щ эюьхЁ ёъЁшэ°юЄр
  1348.     static unsigned int sshot = 0;      // [NS]
  1349.     //-------------------------------------------------------------------------
  1350.     static const char *Format[] =
  1351.     {
  1352.         "scr",
  1353.         "bmp",
  1354.         "png"
  1355.     };
  1356.     //-------------------------------------------------------------------------
  1357.     static const TSaver Saver[] =
  1358.     {
  1359.         SaveBmp,
  1360.         SavePng
  1361.     };
  1362.     //-------------------------------------------------------------------------
  1363.  
  1364.     const char *Ext = Format[conf.scrshot];
  1365.  
  1366.     //-------------------------------------------------------------------------
  1367.     if (    (conf.scrshot == 0)
  1368.             &&
  1369.             (
  1370.                 (
  1371.                     ((conf.mem_model == MM_ATM710) || (conf.mem_model == MM_ATM3))
  1372.                     &&
  1373.                     ((comp.pFF77 & 7) == 0)
  1374.                 )
  1375.                 ||
  1376.                 ((conf.mem_model == MM_ATM450) && (((comp.aFE >> 5) & 3) == 0))
  1377.             )
  1378.         )
  1379.     {
  1380.         Ext = Format[1];
  1381.     }
  1382.     //-------------------------------------------------------------------------
  1383.     // ╧хЁтр  яЁютхЁър шьхэш Їрщыр (ъюуфр яєёЄр  яряър шыш эюьхЁ яюёыхфэхую Їрщыр єцх шчтхёЄхэ) [NS] r0110
  1384.     // printf("%X\n",sshot);
  1385.     snprintf(   fname,
  1386.                 _countof(fname),
  1387.                 //"%s\\%s_%06u.%s",     conf.scrshot_dir,
  1388.                 "%s\\%s_%08u.%s",       conf.scrshot_dir,
  1389.                                         temp.LastSnapName[0] ?  temp.LastSnapName :
  1390.                                                                 "sshot",
  1391.                                         sshot,
  1392.                                         Ext
  1393.                 );
  1394.    
  1395.     fname[FILENAME_MAX-1] = 0;
  1396.     //-------------------------------------------------------------------------
  1397.     // хёыш Єръш Єръюую Їрщыр Єръш эхЄ Єю ьюыўр Єръш ёюїЁрэ хь  [NS] r0110
  1398.     if (access (fname, 0) != 0)
  1399.     {
  1400.         goto screenshot_name_valid;
  1401.     }
  1402.     //-------------------------------------------------------------------------
  1403.     // letz brute new name Єюуфр                                [NS] r0110
  1404.     // эю Єъ сЁєЄшЄ№ 9 ёхэ ьрэют Їрщыют ¤Єю эх ърьшы№Їю
  1405.     // р ъръ яЁртшы№эю яюыєўшЄ№ эюьхЁ яюёыхфэхую Їрщыр ▀╒╟
  1406.     // Єю
  1407.     //
  1408.     { // яЁюёЄю юуЁрэшўхэшх ьхЁёъющ тшфшьюёЄш фы  эюЁьры№эюую фцрьярэ№  эр screenshot_name_valid
  1409.         sshot = 0xFFFFFFFF;
  1410.         unsigned int roll_bit = 0x80000000;     //INT_MIN;      //8000 0000
  1411.         int temp_cnt = 0;
  1412.         bool valid_name_found = FALSE;
  1413.         unsigned int valid_name_cnt = 0;
  1414.         //---------------------------------------------------------------------
  1415.         // ёсЁрё√трхь ърцф√щ сшЄ эюьхЁр ўшёыр юЄ d31 фю d0
  1416.         // ш ётхЁ хь хёЄ№ ыш Єръющ Їрщы
  1417.         while (temp_cnt < 32)
  1418.         {
  1419.             sshot ^= roll_bit;
  1420.             //printf("%X - ",sshot);
  1421.             snprintf(   fname,
  1422.                         _countof(fname),
  1423.                         //"%s\\%s_%06u.%s",     conf.scrshot_dir,
  1424.                         "%s\\%s_%08u.%s",       conf.scrshot_dir,
  1425.                                                 temp.LastSnapName[0] ?  temp.LastSnapName :
  1426.                                                                         "sshot",
  1427.                                                 sshot,
  1428.                                                 Ext
  1429.                     );
  1430.    
  1431.             fname[FILENAME_MAX-1] = 0;
  1432.             //-----------------------------------------------------------------
  1433.             // Єръющ Їрщы хёЄ№
  1434.             if (access (fname, 0) == 0)
  1435.             {
  1436.                 // printf("invalid\n");
  1437.                 sshot ^= roll_bit;      //
  1438.             }
  1439.             //-----------------------------------------------------------------
  1440.             // Єръюую Їрщыр эхЄє
  1441.             else
  1442.             {
  1443.                 // printf("valid\n");
  1444.                 valid_name_found = TRUE;
  1445.                 valid_name_cnt = sshot;
  1446.             }
  1447.             //-----------------------------------------------------------------
  1448.             roll_bit = (roll_bit >> 1);
  1449.             //-----------------------------------------------------------------
  1450.             temp_cnt++;
  1451.             //system ("pause");
  1452.         }
  1453.         //---------------------------------------------------------------------
  1454.         if (valid_name_found)
  1455.         {
  1456.             sshot = valid_name_cnt;
  1457.             goto screenshot_name_valid;
  1458.         }
  1459.         //sshot++;
  1460.     } // яЁюёЄю юуЁрэшўхэшх ьхЁёъющ тшфшьюёЄш фы  эюЁьры№эюую фцрьярэ№  эр screenshot_name_valid
  1461.     //-------------------------------------------------------------------------
  1462.  
  1463.     //-------------------------------------------------------------------------
  1464.     printf("screenshot save error: to big sshot counter\n");
  1465.     return;
  1466.     //-------------------------------------------------------------------------
  1467.    
  1468.     //-------------------------------------------------------------------------
  1469. screenshot_name_valid:
  1470.     //printf("valid %X\n",sshot);
  1471.     snprintf(   fname,
  1472.                 _countof(fname),
  1473.                 //"%s\\%s_%06u.%s",     conf.scrshot_dir,
  1474.                 "%s\\%s_%08u.%s",       conf.scrshot_dir,
  1475.                                         temp.LastSnapName[0] ?  temp.LastSnapName :
  1476.                                                                 "sshot",
  1477.                                         sshot,
  1478.                                         Ext
  1479.             );
  1480.    
  1481.     fname[FILENAME_MAX-1] = 0;
  1482.     //-------------------------------------------------------------------------    
  1483.     FILE *fileShot = fopen(fname, "wb");
  1484.     if (!fileShot)
  1485.     {
  1486.         printf("screenshot save error\n");
  1487.         return;
  1488.     }
  1489.     //-------------------------------------------------------------------------
  1490.     if (conf.scrshot == 0)
  1491.     {
  1492.         //---------------------------------------------------------------------
  1493.         switch (conf.mem_model)
  1494.         {
  1495.             //-----------------------------------------------------------------
  1496.             case MM_ATM710:
  1497.             case MM_ATM3:
  1498.             {
  1499.                 switch(comp.pFF77 & 7)
  1500.                 {
  1501.                     //---------------------------------------------------------
  1502.                     case 0: // EGA 320x200 16c
  1503.                     {
  1504.                         u8 *Buf = (u8 *)malloc(320*200/2);
  1505.                         ConvPal16cAtm2(Buf);
  1506.                         SaveBmp16c(fileShot, Buf);
  1507.                         free(Buf);
  1508.                     }
  1509.                     break;
  1510.                     //---------------------------------------------------------
  1511.                     case 3:
  1512.                         goto standard_zx_mode;
  1513.                     //---------------------------------------------------------
  1514.                 }
  1515.             }
  1516.             break;
  1517.             //-----------------------------------------------------------------
  1518.             case MM_ATM450:
  1519.                 switch((comp.aFE >> 5) & 3)
  1520.                 {
  1521.                     //---------------------------------------------------------
  1522.                     case 0: // EGA 320x200 16c
  1523.                     {
  1524.                         u8 *Buf = (u8 *)malloc(320*200/2);
  1525.                         ConvPal16cAtm1(Buf);
  1526.                         SaveBmp16c(fileShot, Buf);
  1527.                         free(Buf);
  1528.                     }
  1529.                     break;
  1530.                     //---------------------------------------------------------
  1531.                     case 3:
  1532.                         goto standard_zx_mode;
  1533.                     //---------------------------------------------------------
  1534.                 }
  1535.             break;
  1536.             //-----------------------------------------------------------------
  1537.             default:
  1538. standard_zx_mode:;
  1539.                 fwrite(temp.base, 1, 6912, fileShot);
  1540.         }
  1541.         //---------------------------------------------------------------------
  1542.     }
  1543.     //-------------------------------------------------------------------------
  1544.     else
  1545.     {
  1546.         unsigned dx = temp.ox * temp.obpp / 8;
  1547.         unsigned char *scrbuf_unaligned = (unsigned char*)malloc(dx * temp.oy + CACHE_LINE);
  1548.         unsigned char *scrbuf = (unsigned char*)align_by(scrbuf_unaligned, CACHE_LINE);
  1549.         memset(scrbuf, 0, dx * temp.oy);
  1550.         renders[conf.render].func(scrbuf, dx); // render to memory buffer (PAL8, YUY2, RGB15, RGB16, RGB32)
  1551.  
  1552.         u8 *ds = (u8 *)malloc(((temp.ox * 3 + 3) & ~3U) * temp.oy);
  1553.         ConvBgr24(ds, scrbuf, int(dx));
  1554.  
  1555.         Saver[conf.scrshot - 1](fileShot, ds);
  1556.  
  1557.         free(ds);
  1558.         free(scrbuf_unaligned);
  1559.     }
  1560.     //-------------------------------------------------------------------------
  1561.     fclose(fileShot);
  1562.     sprintf(statusline, "saving %s", strrchr(fname, '\\') + 1);
  1563.     statcnt = 30;
  1564.     sshot++;
  1565. }
  1566. //=============================================================================
  1567.  
  1568. /*
  1569. static void VideoFrameSaver()
  1570. {
  1571.    char fname[FILENAME_MAX];
  1572.    static unsigned FrameNum = 0;
  1573.    static const char *Format[] = { "scr", "bmp", "png" };
  1574.    static const TSaver Saver[] = { SaveBmp, SavePng };
  1575.  
  1576.    sprintf(fname, "video%06u.%s", FrameNum, Format[conf.scrshot]);
  1577.    addpath(fname);
  1578.  
  1579.    FILE *fileShot = fopen(fname, "wb");
  1580.    if (!fileShot)
  1581.       return;
  1582.  
  1583.    if (conf.scrshot == 0)
  1584.    {
  1585.       fwrite(temp.base, 1, 6912, fileShot);
  1586.    }
  1587.    else
  1588.    {
  1589.        unsigned dx = temp.ox * temp.obpp / 8;
  1590.        unsigned char *scrbuf_unaligned = (unsigned char*)malloc(dx * temp.oy + CACHE_LINE);
  1591.        unsigned char *scrbuf = (unsigned char*)align_by(scrbuf_unaligned, CACHE_LINE);
  1592.        memset(scrbuf, 0, dx * temp.oy);
  1593.        renders[conf.render].func(scrbuf, dx); // render to memory buffer (PAL8, YUY2, RGB15, RGB16, RGB32)
  1594.  
  1595.        u8 *ds = (u8 *)malloc(((temp.ox * 3 + 3) & ~3) * temp.oy);
  1596.        ConvBgr24(ds, scrbuf, dx);
  1597.  
  1598.        Saver[conf.scrshot - 1](fileShot, ds);
  1599.  
  1600.        free(ds);
  1601.        free(scrbuf_unaligned);
  1602.    }
  1603.    fclose(fileShot);
  1604.    FrameNum++;
  1605. }
  1606. //=============================================================================
  1607. static void VideoNullSaver()
  1608. {
  1609.  
  1610. }
  1611. //=============================================================================
  1612. TVideoSaver VideoSaver = VideoNullSaver;
  1613. //=============================================================================
  1614. void main_savevideo()
  1615. {
  1616.    static bool StartSave = false;
  1617.  
  1618.    if(!StartSave)
  1619.    {
  1620.        sprintf(statusline, "start saving video");
  1621.        StartSave = true;
  1622.        VideoSaver = VideoFrameSaver;
  1623.    }
  1624.    else
  1625.    {
  1626.        sprintf(statusline, "stop saving video");
  1627.        StartSave = false;
  1628.        VideoSaver = VideoNullSaver;
  1629.    }
  1630.  
  1631.    statcnt = 30;
  1632. }
  1633. */
  1634. //=============================================================================
  1635.