Subversion Repositories pentevo

Rev

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

  1. #include "std.h"
  2.  
  3. #include "emul.h"
  4. #include "vars.h"
  5. #include "draw.h"
  6. #include "drawnomc.h"
  7. #include "dx.h"
  8. #include "dxr_text.h"
  9. #include "dxr_rsm.h"
  10. #include "dxr_advm.h"
  11. #include "memory.h"
  12. #include "config.h"
  13.  
  14. #include "util.h"
  15.  
  16. #ifdef CACHE_ALIGNED
  17. CACHE_ALIGNED unsigned char rbuf[sizeof_rbuf];
  18. #else // __declspec(align) not available, force QWORD align with old method
  19. __int64 rbuf__[sizeof_rbuf/sizeof(__int64)];
  20. unsigned char * const rbuf = (unsigned char*)rbuf__;
  21. #endif
  22.  
  23. unsigned char * const rbuf_s = rbuf + rb2_offs; // frames to mix with noflic and resampler filters
  24. unsigned char * const save_buf = rbuf_s + rb2_offs*MAX_BUFFERS; // used in monitor
  25.  
  26. T t;
  27.  
  28. videopoint *vcurr; // ╙ърчрЄхы№ эр Єхъє∙шщ ¤ыхьхэЄ шч video[]
  29. // ╠рёёшт тшфхюёЄЁюъ тъы■ўр  сюЁф■Ё
  30. // video[i] - эрўрыю ёЄЁюъш (шёяюы№чєхЄё  Єюы№ъю next_t)
  31. // video[i+1] - ъюэхЎ ёЄЁюъш  (шёяюы№чє■Єё  тёх ярЁрьхЄЁ√)
  32. static videopoint video[4*MAX_HEIGHT];
  33. unsigned vmode;  // what are drawing: 0-not visible, 1-border, 2-screen
  34. static unsigned prev_t; // ЄръЄ эр ъюЄюЁюь с√ы юЄЁшёютрэ яюёыхфэшщ яшъёхы№
  35. unsigned *atrtab;
  36.  
  37. unsigned char colortab[0x100];// map zx attributes to pc attributes
  38. // colortab shifted to 8 and 24
  39. unsigned colortab_s8[0x100];
  40. unsigned colortab_s24[0x100];
  41.  
  42. /*
  43. #include "drawnomc.cpp"
  44. #include "draw_384.cpp"
  45. */
  46.  
  47. PALETTEENTRY pal0[0x100]; // emulator palette
  48.  
  49. void AtmVideoController::PrepareFrameATM2(int VideoMode)
  50. {
  51.     for (int y=0; y<256; y++)
  52.     {
  53.         if ( VideoMode == 6 )
  54.         {
  55.             // ёьх∙хэш  т ЄхъёЄютюь тшфхюЁхцшьх
  56.             Scanlines[y].Offset = 64*(y/8);
  57.         } else {
  58.             // ёьх∙хэш  т ЁрёЄЁютюь тшфхюЁхцшьх
  59.             Scanlines[y].Offset = (y<56) ? 0 : 40*(y-56);
  60.         }
  61.         Scanlines[y].VideoMode = VideoMode;
  62.     }
  63.     CurrentRayLine = 0;
  64.     IncCounter_InRaster = 0;
  65.     IncCounter_InBorder = 0;
  66. }
  67.  
  68. void AtmVideoController::PrepareFrameATM1(int VideoMode)
  69. {
  70.     for (int y=56; y<256; y++)
  71.     {
  72.         Scanlines[y].Offset = 40*(y-56);
  73.         Scanlines[y].VideoMode = VideoMode;
  74.     }
  75. }
  76.  
  77.  
  78. AtmVideoController AtmVideoCtrl;
  79.  
  80. void video_permanent_tables()
  81. {
  82.    // pixel doubling table
  83.    unsigned i; //Alone Coder 0.36.7
  84.    for (/*unsigned*/ i = 0; i < 0x100; i++) {
  85.       unsigned res = 0;
  86.       for (unsigned j = 0x80; j; j/=2) {
  87.          res <<= 2;
  88.          if(i & j)
  89.          {
  90.              res |= 3;
  91.          }
  92.       }
  93.       t.dbl[i] = res;
  94.    }
  95.  
  96.    for (i = 0; i < 0x100; i++) {
  97.       unsigned r1 = 0, r2 = 0;
  98.       if(i & 0x01)
  99.       {
  100.           r1++; r2 += 1;
  101.       }
  102.       if(i & 0x02)
  103.       {
  104.           r1++; r2 += 1;
  105.       }
  106.       if(i & 0x04)
  107.       {
  108.           r1++; r2 += 0x100;
  109.       }
  110.       if(i & 0x08)
  111.       {
  112.           r1++; r2 += 0x100;
  113.       }
  114.       if(i & 0x10)
  115.       {
  116.           r1 += 0x100; r2 += 0x10000;
  117.       }
  118.       if(i & 0x20)
  119.       {
  120.           r1 += 0x100; r2 += 0x10000;
  121.       }
  122.       if(i & 0x40)
  123.       {
  124.           r1 += 0x100; r2 += 0x1000000;
  125.       }
  126.       if(i & 0x80)
  127.       {
  128.           r1 += 0x100; r2 += 0x1000000;
  129.       }
  130.       // low byte of settab - number of pixels in low nibble of i
  131.       // high byte of low word of settab - number of pixels in high nibble of i
  132.       t.settab[i] = r1;
  133.       t.settab2[i] = r2*4; // *4 - convert square 2x2 to 4x4
  134.    }
  135.  
  136.    i = 0; // calc screen addresses
  137.    for(unsigned p = 0; p < 4; p++)
  138.    {
  139.        for(unsigned y = 0; y < 8; y++)
  140.        {
  141.            for(unsigned o = 0; o < 8; o++, i++)
  142.            {
  143.                t.scrtab[i] = p * 0x800 + y * 0x20 + o * 0x100;
  144.                t.atrtab_hwmc[i] = t.scrtab[i] + 0x2000;
  145.                t.atrtab[i] = 0x1800 + (p * 8 + y) * 32;
  146.            }
  147.        }
  148.    }
  149.  
  150.    // alco table
  151.    static unsigned disp_0[] = { 0x0018, 0x2000, 0x2008, 0x2010, 0x2018, 0x0008 };
  152.    static unsigned base_s[] = { 0x10000, 0x14000, 0x14800, 0x15000, 0x11800 };
  153.    static unsigned base_a[] = { 0x11000, 0x15800, 0x15900, 0x15A00, 0x11300 };
  154.    for (unsigned y = 0; y < 304; y++)
  155.       for (unsigned x = 0; x < 6; x++) {
  156.          unsigned disp = disp_0[x] + (y & 0x38)*4;
  157.          ::t.alco[y][x].a = memory + base_a[y/64] + disp;
  158.          ::t.alco[y][x].s = memory + base_s[y/64] + disp + (y & 7)*0x100;
  159.       }
  160.  
  161.    #ifdef MOD_VID_VD
  162.    // this code is only for ygrbYGRB palette
  163.    for (unsigned byte = 0; byte < 0x100; byte++)
  164.       for (int bit = 0; bit < 8; bit++)
  165.          t.vdtab[0][0][byte].m64_u8[7-bit] = (byte & (1 << bit))? 0x11 : 0;
  166.    for (int pl = 1; pl < 4; pl++)
  167.       for (unsigned byte = 0; byte < 0x100; byte++)
  168.          t.vdtab[0][pl][byte] = _mm_slli_pi32(t.vdtab[0][0][byte], pl);
  169.    for (i = 0; i < sizeof t.vdtab[0]; i++)
  170.       ((unsigned char*)t.vdtab[1])[i] = ((unsigned char*)t.vdtab[0])[i] & 0x0F;
  171.    _mm_empty();
  172.    #endif
  173.  
  174.    temp.offset_vscroll_prev = 0;
  175.    temp.offset_vscroll = 0;
  176.    temp.offset_hscroll_prev = 0;
  177.    temp.offset_hscroll = 0;
  178. }
  179.  
  180. static unsigned getYUY2(unsigned r, unsigned g, unsigned b)
  181. {
  182.    int y = (int)(0.29*r + 0.59*g + 0.14*b);
  183.    int u = (int)(128.0 - 0.14*r - 0.29*g + 0.43*b);
  184.    int v = (int)(128.0 + 0.36*r - 0.29*g - 0.07*b);
  185.    if (y < 0) y = 0; if (y > 255) y = 255;
  186.    if (u < 0) u = 0; if (u > 255) u = 255;
  187.    if (v < 0) v = 0; if (v > 255) v = 255;
  188.    return WORD4(y,u,y,v);
  189. }
  190.  
  191. static void create_palette()
  192. {
  193.     if((temp.rflags & RF_8BPCH) && temp.obpp == 8)
  194.     {
  195.         temp.rflags |= RF_GRAY;
  196.         conf.flashcolor = 0;
  197.     }
  198.  
  199.     PALETTE_OPTIONS *pl = &pals[conf.pal];
  200.     //                                Ii          Ii          Ii          Ii
  201.     //                                00          01          10          11
  202.     unsigned char brights[4] = { u8(pl->ZZ), u8(pl->ZN), u8(pl->NN), u8(pl->BB) };
  203.     unsigned char brtab[16] =
  204.     {   //   ZZ          NN          ZZ          BB
  205.         u8(pl->ZZ), u8(pl->ZN), u8(pl->ZZ), u8(pl->ZB), // ZZ
  206.         u8(pl->ZN), u8(pl->NN), u8(pl->ZN), u8(pl->NB), // NN
  207.         u8(pl->ZZ), u8(pl->ZN), u8(pl->ZZ), u8(pl->ZB), // ZZ (bright=1,ink=0)
  208.         u8(pl->ZB), u8(pl->NB), u8(pl->ZB), u8(pl->BB)  // BB
  209.     };
  210.  
  211.     for(unsigned i = 0; i < 0x100; i++)
  212.     {
  213.         unsigned r0, g0, b0;
  214.         if(temp.rflags & RF_GRAY)
  215.         { // grayscale palette
  216.             r0 = g0 = b0 = i;
  217.         }
  218.         else if(temp.rflags & RF_PALB)
  219.         { // palette index:
  220.             if(comp.ula_plus_en) // gggrrrbb (ULA+)
  221.             { // ╦шэхщэр  шэЄхЁяюы Ўш   ЁъюёЄш
  222.                 b0 = ((i & 3) * 255) / 3; // 2 сшЄр
  223.                 r0 = (((i >> 2) & 7) * 255) / 7; // 3 сшЄр
  224.                 g0 = (((i >> 5) & 7) * 255) / 7; // 3 сшЄр
  225.             }
  226.             else // gg0rr0bb (ATM / profi / bilinear filter)
  227.             { // ═хышэхщэр  ъюЁЁхъЎш   ЁъюёЄш (эр 2 сшЄр) яю ЄрсышЎх ярышЄЁ√ шч .ini Їрщыр
  228.                 b0 = brights[i & 3];
  229.                 r0 = brights[(i >> 3) & 3];
  230.                 g0 = brights[(i >> 6) & 3];
  231.             }
  232.         }
  233.         else
  234.         { // palette index: ygrbYGRB (юс√ўэ√щ zx Ёхцшь схч ярышЄЁ√)
  235.           // ═хышэхщэр  ъюЁЁхъЎш   ЁъюёЄш (эр 4 сшЄр) яю ЄрсышЎх ярышЄЁ√ шч .ini Їрщыр
  236.             b0 = brtab[((i >> 0) & 1) + ((i >> 2) & 2) + ((i >> 2) & 4) + ((i >> 4) & 8)]; // brtab[ybYB]
  237.             r0 = brtab[((i >> 1) & 1) + ((i >> 2) & 2) + ((i >> 3) & 4) + ((i >> 4) & 8)]; // brtab[yrYR]
  238.             g0 = brtab[((i >> 2) & 1) + ((i >> 2) & 2) + ((i >> 4) & 4) + ((i >> 4) & 8)]; // brtab[ygYG]
  239.         }
  240.  
  241.         // transform with current settings
  242.         unsigned r = 0xFF & ((r0 * pl->r11 + g0 * pl->r12 + b0 * pl->r13) / 0x100);
  243.         unsigned g = 0xFF & ((r0 * pl->r21 + g0 * pl->r22 + b0 * pl->r23) / 0x100);
  244.         unsigned b = 0xFF & ((r0 * pl->r31 + g0 * pl->r32 + b0 * pl->r33) / 0x100);
  245.  
  246.         // prepare palette in bitmap header for GDI renderer
  247.         gdibmp.header.bmiColors[i].rgbRed = pal0[i].peRed = BYTE(r);
  248.         gdibmp.header.bmiColors[i].rgbGreen = pal0[i].peGreen = BYTE(g);
  249.         gdibmp.header.bmiColors[i].rgbBlue = pal0[i].peBlue = BYTE(b);
  250.     }
  251.     memcpy(syspalette + 10, pal0 + 10, (246 - 9) * sizeof *syspalette);
  252.  
  253.     if(conf.mem_model == MM_PROFI)
  254.     {
  255.         // profi palette mapping (port out to palette index)
  256.         for(unsigned i = 0; i < 0x100; i++)
  257.         {
  258.             unsigned dst;
  259.             dst = i; // Gg0Rr0Bb => Gg0Rr0Bb
  260.             t.profi_pal_map[i] = dst;
  261.         }
  262.     }
  263. }
  264.  
  265. void atm_zc_tables();//forward
  266.  
  267. // make colortab: zx-attr -> pc-attr
  268. static void make_colortab(char flash_active)
  269. {
  270.    if (conf.flashcolor || conf.ula_plus)
  271.        flash_active = 0;
  272.  
  273.    for (unsigned a = 0; a < 0x100; a++) // a - zx-attr
  274.    {
  275.       unsigned char ink = a & 7;
  276.       unsigned char paper = (a >> 3) & 7;
  277.       unsigned char bright = (a >> 6) & 1;
  278.       unsigned char flash = (a >> 7) & 1;
  279.  
  280. //      if((conf.flashcolor && ink) || !conf.flashcolor)
  281.       ink |= bright << 3;
  282.  
  283. //      if((conf.flashcolor && paper) || !conf.flashcolor)
  284.           paper |= ((conf.flashcolor || (conf.ula_plus && comp.ula_plus_en)) ? flash : bright) << 3;
  285.  
  286.       if (flash_active && flash)
  287.       {
  288.           unsigned char t = ink;
  289.           ink = paper;
  290.           paper = t;
  291.       }
  292.  
  293.       u8 color = u8((paper << 4) | ink); // color - pc-attr
  294.  
  295.       colortab[a] = color;
  296.       colortab_s8[a] = unsigned(color << 8U);
  297.       colortab_s24[a] = unsigned(color << 24U);
  298.    }
  299.  
  300.    if (conf.mem_model == MM_ATM710 || conf.mem_model == MM_ATM3 || conf.mem_model == MM_ATM450)
  301.        atm_zc_tables(); // update with new flash bit
  302. }
  303.  
  304. // make attrtab: pc-attr + 0x100*pixel -> palette index
  305. static void attr_tables()
  306. {
  307.    unsigned char flashcolor = (temp.rflags & RF_MON)? 0 : conf.flashcolor;
  308.    for (unsigned a = 0; a < 0x100; a++)
  309.    {
  310.       unsigned char ink = (a & 0x0F), paper = u8(a >> 4);
  311.       if (flashcolor)
  312.           paper = (paper & 7) + (ink & 8); // paper_bright from ink
  313.  
  314.       if (temp.rflags & RF_GRAY)
  315.       { // grayscale palette
  316.          t.attrtab[a] = paper*16;
  317.          t.attrtab[a+0x100] = ink*16;
  318.       }
  319.       else if (temp.rflags & RF_COMPPAL)
  320.       {
  321.           // ╧рышЄЁр т ЇюЁьрЄх ULA+
  322.           u8 paper_idx; // fb1ppp
  323.           u8 ink_idx;   // fb0iii
  324.           if(comp.ula_plus_en)
  325.           {
  326.               u8 flash = (a & 0x80) >> 7;
  327.               u8 bright = (a & 8) >> 3;
  328.               paper &= 7;
  329.               ink &= 7;
  330.               u8 pal_no = u8(((flash << 1) | bright) << 4);
  331.               paper_idx = u8(pal_no | 8 | paper);
  332.               ink_idx   = u8(pal_no | 0 | ink);
  333.           }
  334.           else
  335.           { //------ for ATM / profi palette - direct values from palette registers
  336.               paper = a >> 4;
  337.               ink = a & 0x0F;
  338.               paper_idx = u8(((paper & 8) << 1) | (paper & 7));
  339.               ink_idx = u8(((ink & 8) << 1) | (ink & 7));
  340.           }
  341.           t.attrtab[a] = comp.comp_pal[paper_idx]; // paper
  342.           t.attrtab[a | 0x100] = comp.comp_pal[ink_idx]; // ink
  343.       }
  344.       else if (temp.rflags & RF_PALB)
  345.       { //----------------------------- for bilinear
  346.          unsigned char b0,b1, r0,r1, g0,g1;
  347.          b0 = (paper >> 0) & 1; r0 = (paper >> 1) & 1; g0 = (paper >> 2) & 1;
  348.          b1 = (ink >> 0) & 1; r1 = (ink >> 1) & 1; g1 = (ink >> 2) & 1;
  349.  
  350.          if (flashcolor && (a & 0x80))
  351.          {
  352.              b1 += b0; r1 += r0; g1 += g0;
  353.              r0 = b0 = g0 = 0;
  354.          }
  355.          else
  356.          {
  357.              b0 *= 2; r0 *= 2; g0 *= 2;
  358.              b1 *= 2; r1 *= 2; g1 *= 2;
  359.          }
  360.  
  361.          unsigned char br1 = (ink >> 3) & 1;
  362.          if (r1) r1 += br1;
  363.          if (g1) g1 += br1;
  364.          if (b1) b1 += br1;
  365.  
  366.          unsigned char br0 = (paper >> 3) & 1;
  367.          if (r0) r0 += br0;
  368.          if (g0) g0 += br0;
  369.          if (b0) b0 += br0;
  370.  
  371.          // palette index: gg0rr0bb
  372.          t.attrtab[a+0x100]  = u8((g1 << 6) + (r1 << 3) + b1);
  373.          t.attrtab[a]        = u8((g0 << 6) + (r0 << 3) + b0);
  374.       }
  375.       else //------------------------------------ all others
  376.       {
  377.          // palette index: ygrbYGRB
  378.          if (flashcolor && (a & 0x80))
  379.          {
  380.              t.attrtab[a] = 0;
  381.              t.attrtab[a+0x100] = u8(ink+(paper<<4));
  382.          }
  383.          else
  384.          {
  385.              t.attrtab[a] = paper * 0x11; // p[3..0]:p[3..0] (єфтюхэшх)
  386.              t.attrtab[a+0x100] = ink * 0x11; // i[3..0]:i[3..0] (єфтюхэшх)
  387.          }
  388.       }
  389.    }
  390. }
  391.  
  392. static void p4bpp_tables()
  393. {
  394.    for (unsigned pass = 0; pass < 2; pass++) {
  395.       for (unsigned bt = 0; bt < 0x100; bt++) {
  396.          unsigned lf = ((bt >> 3) & 7) + ((bt >> 4) & 8);
  397.          unsigned rt = (bt & 7) + ((bt >> 3) & 8);
  398.          if (temp.obpp == 8) {
  399.             t.p4bpp8[pass][bt] = (t.sctab8[pass][0x0F+0x10*rt] & 0xFFFF) +
  400.                                    (t.sctab8[pass][0x0F+0x10*lf] & 0xFFFF0000);
  401.          } else if (temp.obpp == 16) {
  402.              t.p4bpp16[pass][bt * 2 + 0] = t.sctab16[pass][0x03 + 4 * rt];
  403.              t.p4bpp16[pass][bt * 2 + 1] = t.sctab16[pass][0x03 + 4 * lf];
  404.          } else /* if (temp.obpp == 32) */ {
  405.              t.p4bpp32[pass][bt * 2 + 0] = t.sctab32[pass][0x100 + rt];
  406.              t.p4bpp32[pass][bt * 2 + 1] = t.sctab32[pass][0x100 + lf];
  407.          }
  408.       }
  409.    }
  410. }
  411.  
  412. void atm_zc_tables() // atm,profi screens (use normal zx-flash)
  413. {
  414.    for (unsigned pass = 0; pass < 2; pass++) {
  415.       for (unsigned at = 0; at < 0x100; at++) {
  416.          unsigned pc_attr = colortab[at];
  417.          if(temp.obpp == 8)
  418.          {
  419.              for(unsigned j = 0; j < 4; j++)
  420.              {
  421.                  t.zctab8ad[pass][at * 4 + j] = t.sctab8d[pass][pc_attr * 4 + j];
  422.              }
  423.          }
  424.          else if(temp.obpp == 16)
  425.          {
  426.              t.zctab16ad[pass][at] = t.sctab16d[pass][pc_attr];
  427.              t.zctab16ad[pass][at + 0x100] = t.sctab16d[pass][pc_attr + 0x100];
  428.          }
  429.          else /* if (temp.obpp == 32) */
  430.          {
  431.              t.zctab32ad[pass][at] = t.sctab32[pass][pc_attr];
  432.              t.zctab32ad[pass][at + 0x100] = t.sctab32[pass][pc_attr + 0x100];
  433.          }
  434.       }
  435.    }
  436.  
  437.    // atm palette mapping (port out to palette index)
  438.    for (unsigned i = 0; i < 0x100; i++) {
  439.       unsigned v = i ^ 0xFF, dst;
  440.       if (conf.mem_model == MM_ATM450)
  441.          dst = // ATM1: --grbGRB => Gg0Rr0Bb
  442.                ((v & 0x20) << 1) | // g
  443.                ((v & 0x10) >> 1) | // r
  444.                ((v & 0x08) >> 3) | // b
  445.                ((v & 0x04) << 5) | // G
  446.                ((v & 0x02) << 3) | // R
  447.                ((v & 0x01) << 1);  // B
  448.       else
  449.          dst = // ATM2: grbG--RB => Gg0Rr0Bb
  450.                ((v & 0x80) >> 1) | // g
  451.                ((v & 0x40) >> 3) | // r
  452.                ((v & 0x20) >> 5) | // b
  453.                ((v & 0x10) << 3) | // G
  454.                ((v & 0x02) << 3) | // R
  455.                ((v & 0x01) << 1);  // B
  456.       t.atm_pal_map[i] = dst;
  457.    }
  458. }
  459.  
  460. static void hires_sc_tables()  // atm,profi screens (use zx-attributes & flash -> paper_bright)
  461. {
  462.    for (unsigned pass = 0; pass < 2; pass++) {
  463.       for (unsigned at = 0; at < 0x100; at++) {
  464.          unsigned pc_attr = (at & 0x80) + (at & 0x38)*2 + (at & 0x40)/8 + (at & 7);
  465.          if (temp.obpp == 8)
  466.             for (unsigned j = 0; j < 16; j++)
  467.                t.zctab8[pass][at*0x10+j] = t.sctab8[pass][pc_attr*0x10+j];
  468.          else if (temp.obpp == 16)
  469.             for (unsigned j = 0; j < 4; j++)
  470.                t.zctab16[pass][at*4+j] = t.sctab16[pass][pc_attr*4+j];
  471.          else /* if (temp.obpp == 32) */
  472.             for (unsigned j = 0; j < 2; j++)
  473.                t.zctab32[pass][at+0x100*j] = t.sctab32[pass][pc_attr+0x100*j];
  474.       }
  475.    }
  476. }
  477.  
  478. static void calc_noflic_16_32()
  479. {
  480.    unsigned at, pass;
  481.    if (temp.obpp == 16) {
  482.       for (pass = 0; pass < 2; pass++) {
  483.          for (at = 0; at < 2*0x100; at++)
  484.             t.sctab16d_nf[pass][at] = (t.sctab16d[pass][at] & temp.shift_mask)/2;
  485.          for (at = 0; at < 4*0x100; at++)
  486.             t.sctab16_nf[pass][at] = (t.sctab16[pass][at] & temp.shift_mask)/2;
  487.          for (at = 0; at < 2*0x100; at++)
  488.             t.p4bpp16_nf[pass][at] = (t.p4bpp16[pass][at] & temp.shift_mask)/2;
  489.       }
  490.    }
  491.    if (temp.obpp == 32) {
  492.       unsigned shift_mask = 0xFEFEFEFE;
  493.       for (pass = 0; pass < 2; pass++) {
  494.          for (at = 0; at < 2*0x100; at++)
  495.             t.sctab32_nf[pass][at] = (t.sctab32[pass][at] & shift_mask)/2;
  496.          for (at = 0; at < 2*0x100; at++)
  497.             t.p4bpp32_nf[pass][at] = (t.p4bpp32[pass][at] & shift_mask)/2;
  498.       }
  499.    }
  500. }
  501.  
  502. // pal.index => raw video data, shadowed with current scanline pass
  503. static unsigned raw_data(unsigned index, unsigned pass, unsigned bpp)
  504. {
  505.    if (bpp == 8)
  506.    {
  507.       if (pass)
  508.       {
  509.          if (!conf.scanbright)
  510.              return 0;
  511.          // palette too small to realize noflic/atari with shaded scanlines
  512.          if (conf.scanbright < 100 && !conf.noflic && !conf.atariset[0])
  513.          {
  514.             if (temp.rflags & RF_PALB)
  515.                 index = (index & (index << 1) & 0x92) | ((index ^ 0xFF) & (index >> 1) & 0x49);
  516.             else
  517.                 index &= 0x0F;
  518.          }
  519.       }
  520.       return index * 0x01010101; // 4 Єюўъш (8bit)
  521.    }
  522.  
  523.    unsigned r = pal0[index].peRed, g = pal0[index].peGreen, b = pal0[index].peBlue;
  524.    if (pass)
  525.    {
  526.        r = r * conf.scanbright / 100;
  527.        g = g * conf.scanbright / 100;
  528.        b = b * conf.scanbright / 100;
  529.    }
  530.  
  531.    if (bpp == 32)
  532.        return WORD4(b,g,r,0); // 1 Єюўър (32bit)
  533.  
  534.    // else (bpp == 16)
  535.    if (temp.hi15==0)
  536.        return ((b/8) + ((g/4)<<5) + ((r/8)<<11)) * 0x10001; // 2 Єюўъш (16bit)
  537.    if (temp.hi15==1)
  538.        return ((b/8) + ((g/8)<<5) + ((r/8)<<10)) * 0x10001; // 2 Єюўъш (16bit)
  539.    if (temp.hi15==2)
  540.        return getYUY2(r,g,b); // yuyv (32bit)
  541.    return 0;
  542. }
  543.  
  544. static unsigned atari_to_raw(unsigned at, unsigned pass)
  545. {
  546.    unsigned c1 = at/0x10, c2 = at & 0x0F;
  547.    unsigned raw0 = raw_data(t.attrtab[c1+0x100], pass, temp.obpp);
  548.    unsigned raw1 = raw_data(t.attrtab[c2+0x100], pass, temp.obpp);
  549.    if (raw0 == raw1) return raw1;
  550.  
  551.    if (temp.obpp == 8)
  552.       return (temp.rflags & RF_PALB)? (0x49494949 & ((raw0&raw1)^((raw0^raw1)>>1))) |
  553.                                       (0x92929292 & ((raw0&raw1)|((raw0|raw1)&((raw0&raw1)<<1))))
  554.                                     : (0x0F0F0F0F & raw0) | (0xF0F0F0F0 & raw1);
  555.  
  556.    return (raw0 & temp.shift_mask)/2 + (raw1 & temp.shift_mask)/2;
  557. }
  558.  
  559. void pixel_tables()
  560. {
  561.     attr_tables();
  562.     for(unsigned pass = 0; pass < 2; pass++)
  563.     {
  564.         for(unsigned at = 0; at < 0x100; at++)
  565.         {
  566.             unsigned px0 = t.attrtab[at]; // ╥юўър т√ъы■ўхэр (шэфхъё ярышЄЁ√ ¤ьєы ЄюЁр, ярышЄЁр 8[idx]->32[xrgb])
  567.             unsigned px1 = t.attrtab[at + 0x100]; // ╥юўър тъы■ўхэр (шэфхъё ярышЄЁ√ ¤ьєы ЄюЁр, ярышЄЁр 8[idx]->32[xrgb])
  568.  
  569.             // 4 Єюўъш (юфшэръют√ї, єўхЄтхЁхэшх) фы  8bpp
  570.             // 2 Єюўъш (юфшэръют√ї, єфтюхэшх) фы  16bpp
  571.             // 1 Єюўър фы  32bpp
  572.             unsigned p0 = raw_data(px0, pass, temp.obpp); // ╥юўър т√ъы■ўхэр (фрээ√х фы  pc тшфхюярь Єш)
  573.             unsigned p1 = raw_data(px1, pass, temp.obpp); // ╥юўър тъы■ўхэр (фрээ√х фы  pc тшфхюярь Єш)
  574.  
  575.             // sctab32 required for frame resampler in 16-bit mode, so temp.obpp=16 here
  576.             // ┬їюфэ√х фрээ√х 1 сшЄ
  577.             t.sctab32[pass][at] = raw_data(px0, pass, 32); // ╥юўър т√ъы■ўхэр (фрээ√х фы  pc тшфхюярь Єш xrgb)
  578.             t.sctab32[pass][at + 0x100] = raw_data(px1, pass, 32); // ╥юўър тъы■ўхэр (фрээ√х фы  pc тшфхюярь Єш xrgb)
  579.  
  580.             // 8 bit
  581.             unsigned j;
  582.             for(j = 0; j < 0x10; j++) // j - ┬їюфэ√х фрээ√х (чэрўхэшх ў/с яшъёхыхщ) 4сшЄр (16 ъюьсшэрЎшщ)
  583.             {
  584.                 unsigned mask = (j >> 3) * 0xFF + (j & 0x04)*(0xFF00 / 4) +
  585.                     (j & 0x02)*(0xFF0000 / 2) + (j & 1) * 0xFF000000;
  586.                 t.sctab8[pass][j + at * 0x10] = (mask & p1) + (~mask & p0); // ─рээ√х фы  pc тшфхюярь Єш 4 Єюўъш
  587.             }
  588.             for(j = 0; j < 4; j++) // j - ┬їюфэ√х фрээ√х (чэрўхэшх ў/с яшъёхыхщ) 2сшЄр (4 ъюьсшэрЎшш)
  589.             {
  590.                 unsigned mask = (j >> 1) * 0xFFFF + (j & 1) * 0xFFFF0000;
  591.                 t.sctab8d[pass][j + at * 4] = (mask & p1) + (~mask & p0); // ─рээ√х фы  pc тшфхюярь Єш 2 Єюўъш ё єфтюхэшхь
  592.             }
  593.             // ┬їюфэ√х фрээ√х (чэрўхэшх ў/с яшъёхыхщ) 1сшЄ (2 ъюьсшэрЎшш)
  594.             t.sctab8q[at] = p0; t.sctab8q[at + 0x100] = p1; // ─рээ√х фы  pc тшфхюярь Єш 1 Єюўър ё єўхЄтхЁхэшхь
  595.  
  596.             // 16 bit
  597.             for(j = 0; j < 4; j++) // j - ┬їюфэ√х фрээ√х (чэрўхэшх ў/с яшъёхыхщ) 2сшЄр (4 ъюьсшэрЎшш)
  598.             {
  599.                 unsigned mask = (j >> 1) * 0xFFFF + (j & 1) * 0xFFFF0000;
  600.                 t.sctab16[pass][j + at * 4] = (mask & p1) + (~mask & p0); // ─рээ√х фы  pc тшфхюярь Єш 2 Єюўъш
  601.             }
  602.             // ┬їюфэ√х фрээ√х (чэрўхэшх ў/с яшъёхыхщ) 1сшЄ (2 ъюьсшэрЎшш)
  603.             t.sctab16d[pass][at] = p0; t.sctab16d[pass][at + 0x100] = p1; // ─рээ√х фы  pc тшфхюярь Єш 1 Єюўър ё єфтюхэшхь
  604.  
  605.             unsigned atarimode;
  606.             if(!(temp.rflags & RF_MON) && (atarimode = temp.ataricolors[at]))
  607.             {
  608.                 unsigned rawdata[4], i;
  609.                 for(i = 0; i < 4; i++)
  610.                 {
  611.                     rawdata[i] = atari_to_raw((atarimode >> (8 * i)) & 0xFF, pass);
  612.                 }
  613.                 for(i = 0; i < 16; i++)
  614.                 {
  615.                     t.sctab8[pass][at * 0x10 + i] = rawdata[i / 4] + 16 * rawdata[i & 3];
  616.                 }
  617.                 for(i = 0; i < 4; i++)
  618.                 {
  619.                     t.sctab8d[pass][at * 4 + i] = rawdata[i];
  620.                 }
  621.                 for(i = 0; i < 4; i++)
  622.                 {
  623.                     t.sctab16[pass][at * 4 + i] = rawdata[i];
  624.                 }
  625.             }
  626.         }
  627.     }
  628.  
  629.     p4bpp_tables(); // used for ATM2+ mode0 and Pentagon-4bpp
  630.  
  631.     if(temp.obpp > 8 && conf.noflic)
  632.     {
  633.         calc_noflic_16_32();
  634.     }
  635.  
  636.     if((temp.rflags & (RF_DRIVER | RF_2X | RF_USEFONT)) == (RF_DRIVER | RF_2X) && // render="double"
  637.         (conf.mem_model == MM_ATM450 || conf.mem_model == MM_ATM710 || conf.mem_model == MM_ATM3 || conf.mem_model == MM_PROFI))
  638.     {
  639.         hires_sc_tables();
  640.     }
  641. }
  642.  
  643. void video_color_tables()
  644. {
  645.    temp.shift_mask = 0xFEFEFEFE; // 32bit, 16bit YUY2
  646.    if (temp.obpp == 16 && temp.hi15==0) temp.shift_mask = 0xF7DEF7DE;
  647.    if (temp.obpp == 16 && temp.hi15==1) temp.shift_mask = 0x7BDE7BDE;
  648.  
  649.    create_palette();
  650.    pixel_tables();
  651.    make_colortab(0);
  652.  
  653.    if (temp.rflags & (RF_USEC32 | RF_USE32AS16)) {
  654.       for (unsigned at = 0; at < 0x100; at++) {
  655.          for (unsigned vl = 0; vl <= 0x10; vl++) {
  656.             unsigned br = (at & 0x40) ? 0xFF : 0xBF;
  657.             unsigned c1, c2, res;
  658.             c1 = (at & 1) >> 0; c2 = (at & 0x08) >> 3;
  659.             unsigned b = (c1*vl + c2*(0x10-vl))*br/0x10;
  660.             c1 = (at & 2) >> 1; c2 = (at & 0x10) >> 4;
  661.             unsigned r = (c1*vl + c2*(0x10-vl))*br/0x10;
  662.             c1 = (at & 4) >> 2; c2 = (at & 0x20) >> 5;
  663.             unsigned g = (c1*vl + c2*(0x10-vl))*br/0x10;
  664.             if (temp.rflags & RF_USE32AS16) {
  665.                if (temp.hi15==0) res = (b/8) + ((g/4)<<5) + ((r/8)<<11);
  666.                if (temp.hi15==1) res = (b/8) + ((g/8)<<5) + ((r/8)<<10);
  667.                if (temp.hi15==2) res = getYUY2(r,g,b);
  668.                else res *= 0x10001; // for hi15=0,1
  669.             } else res =  WORD4(b,g,r,0);
  670.             t.c32tab[at][vl] = res;
  671.          }
  672.       }
  673.    }
  674.    setpal(0);
  675. }
  676.  
  677. void video_timing_tables()
  678. {
  679.    if (conf.frame < 2000)
  680.    {
  681.        conf.frame = 2000;
  682.        cpu.SetTpi(conf.frame);
  683.    }
  684.    if (conf.t_line < 128) conf.t_line = 128;
  685.    conf.nopaper &= 1;
  686.    atrtab = (comp.pEFF7 & EFF7_HWMC) ? t.atrtab_hwmc : t.atrtab;
  687.  
  688. //   conf.bordersize=2;
  689. //   temp.scx = 384, temp.scy = 300;
  690.    #define p2cc(p) ((p)/4) // ╧хЁхтюф тхышўшэ√ т яшъёхы ї т ўшёыю чэръюьхёЄ ё єўхЄюь рЄЁшсєЄют (ърцфюх чэръюьхёЄю чрэшьрхЄ 2 срщЄр, срщЄ фрээ√ї ш срщЄ рЄЁшсєЄют)
  691.    const unsigned width = p2cc(temp.scx); // ╪шЁшэр ¤ъЁрэр т чэръюьхёЄрї * 2 (Є.ъ. шёяюы№чє■Єё  яшъёхыш ш рЄЁшсєЄ√ эр 1 чэръюьхёЄю)
  692.    //temp.vidbufsize = temp.scx*temp.scy/4;
  693.  
  694.    // make video table
  695.    unsigned mid_lines = 192; // ╫шёыю ёЄЁюъ т ЎхэЄЁры№эющ ўрёЄш ¤ъЁрэр (схч сюЁф■Ёр)
  696.    const unsigned buf_mid = 256; // ╫шёыю яшъёхыхщ т ЎхэЄЁры№эющ ўрёЄш ¤ъЁрэр (схч сюЁф■Ёр)
  697.  
  698.    // ╨рёўхЄ ЁрчьхЁ сюЁф■Ёр т яшъёхы ї (1 яшъёхы№ = 2 ЄръЄр)
  699.    temp.b_bottom = temp.b_top = conf.b_top_small; temp.b_left = conf.b_left_small; // border small
  700.    if (conf.bordersize==0) temp.b_top = temp.b_left = 0; // border none
  701.    if (conf.bordersize==2) { temp.b_top = conf.b_top_full; temp.b_left = conf.b_left_full; } // border full
  702.  
  703.    // temp.scx - ўшёыю Єюўхъ т ьєы№ЄшъюыюЁх яю уюЁшчюэЄрыш
  704.    // temp.scy - ўшёыю ёЄЁюъ т ьєы№ЄшъюыюЁх
  705.    // 256x192 - border none
  706.    // 320x240 - border small
  707.    // 384x300 - border full, pentagon: ((36+128+28)*2=384)x(304=64+192+48), scorpion: ((24+128+32)*2=368)x(296=64+192+40)))
  708.    temp.b_right = temp.scx - buf_mid - temp.b_left; // ╨рёўхЄ ЁрчьхЁр яЁртющ ўрёЄш сюЁф■Ёр т яшъёхы ї (1 яшъёхы№ = 1/2 ЄръЄр)
  709.    temp.b_bottom = temp.scy - mid_lines - temp.b_top; // ╨рёўхЄ ЁрчьхЁр эшцэхщ ўрёЄш сюЁф■Ёр т яшъёхы ї (1 яшъёхы№ = 1/2 ЄръЄр)
  710.  
  711.    if(conf.nopaper) // ╨хцшь nopaper (ЁрёЄЁ т ёхЁхфшэх ¤ъЁрэр юЄёєЄёЄтєхЄ)
  712.    {
  713.        temp.b_bottom += mid_lines;
  714.        mid_lines = 0;
  715.    }
  716.    int inx = 0;
  717.  
  718.    unsigned i;
  719.    #define ts(t) (((int)(t) < 0) ? 0 : t)
  720.    #define p2t(p) ((p)/2) // ╧хЁхтюф яшъёхыхщ т ЄръЄ√
  721.    // conf.paper - ╫шёыю ЄръЄют юЄ эрўрыр ЁрёЄЁр фю ЎхэЄЁры№эющ ўрёЄш spectrum ¤ъЁрэр
  722.    // (тъы■ўрхЄ эхтшфшьє■ ўрёЄ№ + яюыэюёЄ№■ тхЁїэшщ сюЁф■Ё + эрўрыю ёЄЁюъш °шЁшэющ hblank + ыхт√щ сюЁф■Ё)
  723.    // ─ы  pentagon 128: (16+64)*(32+36+128+28)+32+36 = 17988 ЄръЄют
  724.    // 16 ёЄЁюъ эрф тхЁїэшь сюЁф■Ёюь
  725.    // 64 ёЄЁюъш - тхЁїэшщ сюЁф■Ё
  726.    // ърцфр  ёЄЁюър 224 ЄръЄр:
  727.    // 32 ЄръЄр hblank
  728.    // 36 ЄръЄют - ыхт√щ сюЁф■Ё
  729.    // 128 ЄръЄют - ЎхэЄЁ ¤ъЁрэр
  730.    // 28 ЄръЄют - яЁрт√щ сюЁф■Ё
  731.    unsigned t = conf.paper - temp.b_top*conf.t_line; // ╫шёыю ЄръЄют фю эрўрыр тхЁїэхую сюЁф■Ёр (тъы■ўр  hblank + ыхт√щ сюЁф■Ё т яхЁтющ ёЄЁюъх paper)
  732.    const unsigned hblank = conf.t_line - p2t(temp.scx); // ╫шёыю ЄръЄют т hblank
  733.    video[inx++].next_t = ts(t - p2t(temp.b_left)); // ╚ёъы■ўхэшх ыхтюую сюЁф■Ёр (next_t - ЄръЄ эрўрыр яхЁтющ ёЄЁюъш тхЁїэхую сюЁф■Ёр)
  734. //   printf("btop: temp.b_top=%u, conf.b_top_full=%u\n", temp.b_top, conf.b_top_full);
  735.    for (i = 0; i < temp.b_top; i++)
  736.    { // тхЁїэшщ сюЁф■Ё
  737.       video[inx].next_t = ts(t + p2t(buf_mid+temp.b_right)); // ╩юэхЎ яЁртюую сюЁф■Ёр (ЄръЄ ъюэЎр Єхъє∙хщ ёЄЁюъш)
  738.       video[inx].screen_ptr = rbuf+width*i; // ╙ърчрЄхы№ эр эр ўрыю Єхъє∙хщ ёЄЁюъш т сєЇхЁх юЄЁшёютъш
  739.       video[inx].nextvmode = 0; // hblank (яхЁхїюф ъ эютющ ёЄЁюъх)
  740. //      printf("%3u: b=%u, e=%u, o=%u\n", i, video[inx-1].next_t, video[inx].next_t, width*i);
  741.  
  742.        // ╧хЁхїюф ъ ёыхфє■∙хщ ёЄЁюъх (t - ЄръЄ эрўрыр paper ёыхфє■∙хщ ёЄЁюъш hblank + ыхт√щ сюЁф■Ё)
  743.       inx++; t += conf.t_line;
  744.       video[inx++].next_t = ts(t - p2t(temp.b_left)); // ╚ёъы■ўхэшх ыхтюую сюЁф■Ёр (ЄръЄ эрўрыр ыхтюую сюЁф■Ёр эр ёыхфє■∙хщ ёЄЁюъх)
  745.    }
  746. //   printf("paper:\n");
  747.    for (i = 0; i < mid_lines; i++)
  748.    { // hblank + ыхт√щ сюЁф■Ё + ¤ъЁрэ + яЁрт√щ сюЁф■Ё
  749.       video[inx].next_t = ts(t); // ╩юэхЎ ыхтюую сюЁф■Ёр (ЄръЄ эрўрыр paper эр Єхъє∙хщ ёЄЁюъх)
  750.       video[inx].screen_ptr = rbuf+width*(i+temp.b_top); // ╙ърчрЄхы№ эр эрўрыю iщ ёЄЁюъш ыхтюую сюЁф■Ёр т сєЇхЁх юЄЁшёютъш
  751.       video[inx].nextvmode = 2; // ─рыхх яЁюЁшёют√трхЄё  paper
  752. //      printf("%3u: b=%u ", i, video[inx-1].next_t);
  753.  
  754.       inx++;
  755.       video[inx].next_t = ts(t + p2t(buf_mid)); // ╩юэхЎ paper (ЄръЄ эрўрыр яЁртюую сюЁф■Ёр эр Єхъє∙хщ ёЄЁюъх)
  756.       video[inx].screen_ptr = rbuf+width*(i+temp.b_top)+p2cc(temp.b_left);// ╙ърчрЄхы№ эр эрўрыю iщ ёЄЁюъш paper т сєЇхЁх юЄЁшёютъш
  757.       video[inx].scr_offs = ::t.scrtab[i]; // ╤ьх∙хэшх юЄ эрўрыр zx ¤ъЁрэр (яшъёхыш)
  758.       video[inx].atr_offs = atrtab[i]; // ╤ьх∙хэшх юЄ эрўрыр чюэ√ рЄЁшсєЄют zx ¤ъЁрэр
  759.  
  760.       inx++;
  761.       video[inx].next_t = ts(t + p2t(buf_mid+temp.b_right));  // ╩юэхЎ яЁртюую сюЁф■Ёр (ЄръЄ ъюэЎр Єхъє∙хщ ёЄЁюъш)
  762.       video[inx].screen_ptr = rbuf+width*(i+temp.b_top)+p2cc(buf_mid+temp.b_left); // ╙ърчрЄхы№ эр эрўрыю iщ ёЄЁюъш яЁртюую сюЁф■Ёр т сєЇхЁх юЄЁшёютъш
  763.       video[inx].nextvmode = 0; // hblank (яхЁхїюф ъ эютющ ёЄЁюъх)
  764.  
  765. //      printf("e=%u\n", video[inx].next_t);
  766.        // ╧хЁхїюф ъ ёыхфє■∙хщ ёЄЁюъх (t - ЄръЄ эрўрыр paper ёыхфє■∙хщ ёЄЁюъш hblank + ыхт√щ сюЁф■Ё)
  767.       inx++; t += conf.t_line;
  768.       video[inx++].next_t = ts(t - p2t(temp.b_left)); // ╚ёъы■ўхэшх ыхтюую сюЁф■Ёр (ЄръЄ эрўрыр ёыхфє■∙хщ ёЄЁюъш)
  769.    }
  770. //   printf("bbot:\n");
  771.    for (i = 0; i < temp.b_bottom; i++)
  772.    { // эшцэшщ сюЁф■Ё
  773.       video[inx].next_t = ts(t + p2t(buf_mid+temp.b_right)); // ╩юэхЎ яЁртюую сюЁф■Ёр (ЄръЄ ъюэЎр Єхъє∙хщ ёЄЁюъш)
  774.       video[inx].screen_ptr = rbuf+width*(i+temp.b_top+mid_lines); // ╙ърчрЄхы№ эр эр ўрыю iщ ёЄЁюъш эшцэхую сюЁф■Ёр т сєЇхЁх юЄЁшёютъш
  775.       video[inx].nextvmode = 0; // hblank (яхЁхїюф ъ эютющ ёЄЁюъх)
  776. //      printf("%3u: b=%u, e=%u\n", i, video[inx-1].next_t, video[inx].next_t);
  777.  
  778.        // ╧хЁхїюф ъ ёыхфє■∙хщ ёЄЁюъх (t - ЄръЄ эрўрыр paper ёыхфє■∙хщ ёЄЁюъш hblank + ыхт√щ сюЁф■Ё)
  779.       inx++; t += conf.t_line;
  780.       video[inx++].next_t = ts(t - p2t(temp.b_left)); // ╚ёъы■ўхэшх ыхтюую сюЁф■Ёр (ЄръЄ эрўрыр ёыхфє■∙хщ ёЄЁюъш)
  781.    }
  782.    video[inx-1].next_t = 0x7FFFFFFF; // ╧Ёшчэръ яюёыхфэхщ ёЄЁюъш
  783. //   exit(0);
  784.  
  785.    temp.evenM1_C0 = conf.even_M1 ? 0xC0 : 0x00;
  786.    temp.border_add = conf.border_4T ? 6 : 0;
  787.    temp.border_and = conf.border_4T ? 0xFFFFFFFC : 0xFFFFFFFF;
  788.  
  789.    for (i = 0; i < NUM_LEDS; i++)
  790.    {
  791.       unsigned z = *(&conf.led.ay + i);
  792.       int x = (signed short)(z & 0xFFFF);
  793.       int y = (signed short)(((z >> 16) & 0x7FFF) + ((z >> 15) & 0x8000));
  794.       if (x < 0) x += width*8;
  795.       if (y < 0) y += temp.scy;
  796.       *(&temp.led.ay+i) = (z & 0x80000000) ? rbuf + ((x>>2)&0xFE) + unsigned(y)*width : nullptr;
  797.    }
  798.  
  799.    if (temp.rflags & RF_USEFONT)
  800.        create_font_tables();
  801.  
  802.    needclr = 2;
  803. }
  804.  
  805. void set_video()
  806. {
  807. //   printf("%s\n", __FUNCTION__);
  808.    set_vidmode();
  809.    video_color_tables();
  810. }
  811.  
  812. void apply_video()
  813. {
  814. //   printf("%s\n", __FUNCTION__);
  815.    load_ula_preset();
  816.  
  817.    if(conf.mem_model == MM_ATM710 || conf.mem_model == MM_ATM3 || conf.mem_model == MM_ATM450 || conf.mem_model == MM_PROFI)
  818.    {
  819.        conf.render = 1; // ─ы  ьюфхыхщ ё ¤ъЁрэюь 640x200 яюффхЁцштрхЄё  Єюы№ъю redner = double (640x480)
  820.    }
  821.  
  822.    temp.rflags = renders[conf.render].flags;
  823.    if (conf.use_comp_pal && (conf.mem_model == MM_ATM710 || conf.mem_model == MM_ATM3 || conf.mem_model == MM_ATM450 || conf.mem_model == MM_PROFI))
  824.    {
  825.       temp.rflags |= RF_COMPPAL | RF_PALB;
  826.       // disable palette noflic, only if it is really used
  827.       if (temp.obpp == 8 && (temp.rflags & (RF_DRIVER | RF_USEFONT | RF_8BPCH)) == RF_DRIVER)
  828.       conf.noflic = 0;
  829.    }
  830.  
  831.    if(conf.ula_plus/* && comp.ula_plus_en*/)
  832.    {
  833.        temp.rflags |= RF_COMPPAL | RF_PALB;
  834.    }
  835.  
  836.    if (renders[conf.render].func == render_rsm)
  837.        conf.flip = 1; // todo: revert back after returning from frame resampler //Alone Coder
  838.  
  839.    if (renders[conf.render].func == render_advmame)
  840.    {
  841.       if (conf.videoscale == 2)
  842.           temp.rflags |= RF_2X;
  843.       if (conf.videoscale == 3)
  844.           temp.rflags |= RF_3X;
  845.       if (conf.videoscale == 4)
  846.           temp.rflags |= RF_4X;
  847.    } //Alone Coder
  848.  
  849.    set_video();
  850.    calc_rsm_tables();
  851.    video_timing_tables();
  852. }
  853.  
  854. __inline unsigned char *raypointer()
  855. {
  856.    if (prev_t > conf.frame)
  857.        return rbuf + rb2_offs;
  858.    if (!vmode)
  859.        return vcurr[1].screen_ptr;
  860.    unsigned offs = (prev_t - vcurr[-1].next_t) / 4;
  861.    return vcurr->screen_ptr + (offs+1) * 2;
  862. }
  863.  
  864. __inline void clear_until_ray()
  865. {
  866.    unsigned char *dst = raypointer();
  867.    while(dst < rbuf + rb2_offs)
  868.    {
  869.        *dst++ = 0;
  870.        *dst++ = 0x55;
  871.    }
  872. }
  873.  
  874. void paint_scr(char alt) // alt=0/1 - main/alt screen, alt=2 - ray-painted
  875. {
  876.     if(alt == 2)
  877.     {
  878.         update_screen();
  879.         clear_until_ray();
  880.     }
  881.     else
  882.     {
  883.         if(alt)
  884.         {
  885.             comp.p7FFD ^= 8;
  886.             set_banks();
  887.         }
  888.         draw_screen();
  889.         if(alt)
  890.         {
  891.             comp.p7FFD ^= 8;
  892.             set_banks();
  893.         }
  894.     }
  895. }
  896.  
  897. // ┬√ч√трхЄё  яЁш чряшёш т тшфхюярь Є№/(яюЁЄ√ FE/7FFD) эютюую чэрўхэш 
  898. // ╧ЁюшчтюфшЄ юЄЁшёютъє сюЁф■Ёр/¤ъЁрэр т яЁюьхцєЄюўэ√щ сєЇхЁ ё шёяюы№чютрэшхь pc рЄЁшсєЄют
  899. void update_screen()
  900. {
  901.    unsigned last_t = (cpu.t + temp.border_add) & temp.border_and;
  902.    unsigned t = prev_t; // ┬√яюыэ хЄё  юЄЁшёютър юЄ яюёыхфэхую юЄЁшёютрээюую ЄръЄр prev_t фю Єхъє∙хую юъЁєуыхээюую ЄръЄр last_t
  903. //   printf("upd_scr: t=%u, lt=%u, vm=%u\n", t, last_t, vmode);
  904.    if (t >= last_t) // ═хтшфшьр  ўрёЄ№ ёЄЁюъш (hblank ышсю эхтшфшь√х ёЄЁюъш тхЁїэхую сюЁф■Ёр)
  905.        return;
  906.  
  907.    unsigned char b = comp.border_attr;
  908.    b |= (b<<4); // └ЄЁшсєЄ√ сюЁф■Ёр фєсышЁє■Єё  т ЇюЁьрЄх pc рЄЁшсєЄют ink=paper
  909.  
  910.    if(vmode == 1)
  911.    {
  912.        goto mode1; // border
  913.    }
  914.  
  915.    if(vmode == 2) // screen
  916.    {
  917.        goto mode2;
  918.    }
  919.  
  920. mode0: // not visible
  921.    {
  922.       vmode = 1;
  923.       t = vcurr->next_t; // ╥ръЄ эрўрыр ёЄЁюъш
  924.       vcurr++; // ╧хЁхїюф ъ ъюэЎє ёЄЁюъш
  925.       if (t >= last_t)
  926.       {
  927. done:
  928.           prev_t = t; // ╧юёыхфэшщ юЄЁшёютрээ√щ ЄръЄ
  929.           return;
  930.       }
  931.    }
  932. mode1: // border
  933.    {
  934.       unsigned offs = (t - vcurr[-1].next_t); // ╤ьх∙хэшх т ЄръЄрї юЄ эрўрыр ёЄЁюъш (1 ЄръЄ = 2 яшъёхы )
  935.       unsigned char *ptr = vcurr->screen_ptr + offs/2; // ╙ърчрЄхы№ эр рфЁхё Єюўъш т яЁюьхцєЄюўэюь сєЇхЁх (ёЄЁєъЄєЁр сєЇхЁр 8pix:attr)
  936. //      u8 *pp =ptr;
  937.       ptr = (unsigned char*)(ULONG_PTR(ptr) & ~ULONG_PTR(1)); // ┬√Ёртрэшх фю ўхЄэюую рфЁхёр
  938.       if(offs & 3)
  939.       { // ╤ьхэр ЎтхЄр сюЁф■Ёр яЁюшчю°ыр эх яю уЁрэшЎх чэръюьхёЄр (фтр ЎтхЄр сюЁф■Ёр тэєЄЁш юфэюую чэръюьхёЄр, ¤ьєышЁє■Єё  ўхЁхч ink/paper)
  940.           u8 old_b = (ptr[1] & 0x0F);
  941.           if(old_b ^ (b & 0xF)) // ╓тхЄ сюЁф■Ёр шчьхэшыё  яю ёЁртэхэш■ ё яЁхф√фє∙шь
  942.           {
  943.               u8 mask = u8((unsigned)0xFF00 >> ((offs & 3) * 2)); // ╠рёър яшъёхыхщ (фы  1 - шёяюы№чєхЄё  ЎтхЄ ink, фы  0 - paper)
  944.               *ptr = mask;
  945.               ptr++;
  946.               t += 4 - (offs & 3);
  947.               *ptr = old_b | (b & 0xF0); // └ЄЁшсєЄ√ (ink - ёЄрЁ√щ ЎтхЄ сюЁф■Ёр, paper - Єхъє∙шщ ЎтхЄ сюЁф■Ёр)
  948.               ptr++;
  949.           }
  950.       }
  951.       unsigned end = min(vcurr->next_t, last_t);
  952. //      printf("upd_scr_m1: o=%uT, p=%u, t=%uT, end=%uT\n", offs, pp - rbuf, t, end);
  953.       for (; t < end; t+=4) // ╬сЁрсюЄър яшъёхыхщ яю чэръюьхёЄрь (яю 8 Єюўхъ)
  954.       {
  955.          *ptr++ = 0; // ╧шъёхыш эх шёяюы№чє■Єё 
  956.          *ptr++ = b; // └ЄЁшсєЄ√
  957.       }
  958.       t = end;
  959.       if (t == vcurr->next_t)
  960.       { // ╤ЄЁюър чръюэўшырё№,  яхЁхїюф ъ ёыхфє■∙хщ Єюўъх
  961.           vmode = vcurr->nextvmode;
  962.           vcurr++;
  963.       }
  964.       if (t == last_t) // ╬ЄЁшёютър чръюэўхэр, т√їюф
  965.           goto done;
  966.  
  967.       if (!vmode) // ═рўрыю ёыхфє■∙хщ ёЄЁюъш
  968.           goto mode0;
  969.    }
  970. mode2: // screen
  971.    {
  972.       unsigned offs = (t - vcurr[-1].next_t)/4; // ╤ьх∙хэшх т чэръюьхёЄрї юЄ эрўрыр ёЄЁюъш (1 чэръюьхёЄю = 4 ЄръЄр = 8 яшъёхыхщ)
  973.       unsigned char *scr = temp.base + vcurr->scr_offs + offs; // spectrum яшъёхыш
  974.       unsigned char *atr = temp.base + vcurr->atr_offs + offs; // spectrum рЄЁшсєЄ√
  975.       unsigned char *ptr = vcurr->screen_ptr + offs*2; // ╤ЄЁєъЄєЁр сєЇхЁр 8pix:attr
  976.       unsigned end = min(last_t, vcurr->next_t);
  977.       for (int i = 0; t < end; t += 4, i++)
  978.       {
  979.          ptr[2*i] = scr[i]; // ╩юяшЁютрэшх spectrum яшъёхыхщ
  980.          ptr[2*i+1] = colortab[atr[i]]; // ╩юэтхЁЄшЁютрэшх spectrum рЄЁшсєЄют т pc рЄЁшсєЄ√
  981.       }
  982.       t = end;
  983.       if (t == vcurr->next_t)
  984.       { // ╓хэЄЁры№эр  ўрёЄ№ ¤ъЁрэр чръюэўшырё№, юЄЁшёютър яЁртюую сюЁф■Ёр
  985.           vmode = 1; // border
  986.           vcurr++;
  987.       }
  988.       if (t == last_t) // ╬ЄЁшёютър чръюэўхэр, т√їюф
  989.           goto done;
  990.       goto mode1; // ╬ЄЁшёютър яЁртюую сюЁф■Ёр
  991.    }
  992. }
  993.  
  994. void init_frame()
  995. {
  996.    // recreate colors with flash attribute
  997.    unsigned char frame = (unsigned char)comp.frame_counter;
  998.    if (!(frame & 15) /* && !conf.flashcolor */ )
  999.        make_colortab(frame & 16);
  1000.  
  1001.    prev_t = -1U; // block MCR
  1002.    temp.base_2 = nullptr; // block paper trace
  1003.  
  1004.    if (temp.vidblock)
  1005.        return;
  1006.  
  1007. /* [vv] ╬Єъы■ўхэ, Є.ъ. ¤ЄюЄ сшЄ шёяюы№чєхЄё  фы  DDp scroll
  1008.    // AlCo384 - no border/paper rendering
  1009.    if (comp.pEFF7 & EFF7_384)
  1010.        return;
  1011. */
  1012.    // GIGASCREEN - no paper rendering
  1013. //   if (comp.pEFF7 & EFF7_GIGASCREEN) goto allow_border; //Alone Coder
  1014.  
  1015.    // disable multicolors, border still works
  1016.    if ((temp.rflags & RF_BORDER) || // chunk/etc filter
  1017.        (conf.mem_model == MM_PROFI && (comp.pDFFD & 0x80)) ||   // profi hires screen
  1018.        ((conf.mem_model == MM_ATM710 || conf.mem_model == MM_ATM3)&& (comp.pFF77 & 7) != 3) ||  // ATM-2 hires screen
  1019.        (conf.mem_model == MM_ATM450 && (comp.aFE & 0x60) != 0x60)) // ATM-1 hires screen
  1020.    {
  1021.        if ((conf.mem_model == MM_ATM710 || conf.mem_model == MM_ATM3))
  1022.        {
  1023.            // ATM2, юфшэ шч Ёрё°шЁхээ√ї тшфхюЁхцшьют
  1024.            AtmVideoCtrl.PrepareFrameATM2(comp.pFF77 & 7);
  1025.        }
  1026.  
  1027.        if (conf.mem_model == MM_ATM450)
  1028.        {
  1029.            // ATM1, юфшэ шч Ёрё°шЁхээ√ї тшфхюЁхцшьют
  1030.            AtmVideoCtrl.PrepareFrameATM1( (comp.aFE >> 5) & 3 );
  1031.  
  1032.        }
  1033.        
  1034.       // if border update disabled, dont show anything on zx-screen
  1035.       if (!conf.updateb)
  1036.           return;
  1037.    }
  1038.  
  1039.    // paper + border
  1040.    temp.base_2 = temp.base;
  1041. //allow_border:
  1042.    prev_t = vmode = 0;
  1043.    vcurr = video;
  1044. }
  1045.  
  1046. void flush_frame()
  1047. {
  1048.    if (temp.vidblock)
  1049.        return;
  1050.    if (prev_t != -1U)
  1051.    { // MCR on
  1052.       if (prev_t)
  1053.       {  // paint until end of frame
  1054.          // paint until screen bottom, even if n_lines*t_line < cpu.t (=t_frame)
  1055.          unsigned t = cpu.t;
  1056.          cpu.t = 0x7FFF0000;
  1057.          update_screen();
  1058.          cpu.t = t;
  1059. //         if (comp.pEFF7 & EFF7_GIGASCREEN) draw_gigascreen_no_border(); //Alone Coder
  1060.       }
  1061.       else
  1062.       { // MCR on, but no screen updates in last frame - use fast painter
  1063.          if (temp.base_2 /*|| (comp.pEFF7 & EFF7_GIGASCREEN)*/ /*Alone Coder*/)
  1064.              draw_screen();
  1065.          else
  1066.              draw_border();
  1067.       }
  1068.       return;
  1069.    }
  1070.    if (comp.pEFF7 & EFF7_384)
  1071.        draw_alco();
  1072. }
  1073.  
  1074. // spectrum colors -> palette indexes (RF_PALB - gggrrrbb format)
  1075. static const u8 comp_pal[16] =
  1076. {
  1077.     // normal bright  g   r   b   g  r  b
  1078.     0x00, // black   000|000|00  00|00|00
  1079.     0x02, // blue    000|000|10  00|00|10
  1080.     0x10, // red     000|100|00  00|10|00
  1081.     0x12, // magenta 000|100|10  00|10|10
  1082.     0x80, // green   100|000|00  10|00|00
  1083.     0x82, // cyan    100|000|10  10|00|10
  1084.     0x90, // yellow  100|100|00  10|10|00
  1085.     0x92, // white   100|100|10  10|10|10
  1086.  
  1087.     // high bright    g   r   b   g  r  b
  1088.     0x00, // black   000|000|00  00|00|00
  1089.     0x03, // blue    000|000|11  00|00|11
  1090.     0x1C, // red     000|111|00  00|11|00
  1091.     0x1F, // magenta 000|111|11  00|11|11
  1092.     0xE0, // green   111|000|00  11|00|00
  1093.     0xE3, // cyan    111|000|11  11|00|11
  1094.     0xFC, // yellow  111|111|00  11|11|00
  1095.     0xFF  // white   111|111|11  11|11|11
  1096. };
  1097.  
  1098. void load_spec_colors()
  1099. {
  1100.     for(unsigned flash = 0; flash < 2; flash++)
  1101.     {
  1102.         for(unsigned bright = 0; bright < 2; bright++)
  1103.         {
  1104.             unsigned PalNo = ((flash << 1) | bright) << 4;
  1105.             memcpy(comp.comp_pal + (PalNo | (0 << 3)), comp_pal + (bright << 3), sizeof(comp_pal) / 2); // ink
  1106.             memcpy(comp.comp_pal + (PalNo | (1 << 3)), comp_pal + (bright << 3), sizeof(comp_pal) / 2); // paper
  1107.         }
  1108.     }
  1109.     temp.comp_pal_changed = 1;
  1110. }
  1111.