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 "dxr_rsm.h"
  7.  
  8. RSM_DATA rsm;
  9.  
  10. void RSM_DATA::prepare_line_32(unsigned char *src0)
  11. {
  12.     unsigned i;
  13.     for(i = 0; i < line_size_d; i++)
  14.     {
  15.         line_buffer_d[i] = bias;
  16.     }
  17.  
  18.     unsigned line_size = line_size_d / (sizeof(__m_vec) / sizeof(DWORD)), frame = 0;
  19.     const __m_vec *tab = colortab;
  20.     for(;;)
  21.     {
  22.         unsigned char *src = src0;
  23.         for(i = 0; i < line_size; )
  24.         {
  25. #ifdef MOD_SSE2
  26.             // ┬√тюф 16 Єюўхъ, ърцф√щ _mm_add_epi8 юсЁрсрЄ√трхЄ 4 Єюўъш чр Ёрч
  27.             // s=[ap|ap]
  28.             unsigned s = *(unsigned*)src, attr = (s >> 4) & 0xFF0;
  29.             line_buffer[i + 0] = _mm_add_epi8(line_buffer[i + 0], tab[((s >> 4) & 0xF) + attr]);
  30.             line_buffer[i + 1] = _mm_add_epi8(line_buffer[i + 1], tab[((s >> 0) & 0xF) + attr]);
  31.             attr = (s >> 20) & 0xFF0;
  32.             line_buffer[i + 2] = _mm_add_epi8(line_buffer[i + 2], tab[((s >> 20) & 0xF) + attr]);
  33.             line_buffer[i + 3] = _mm_add_epi8(line_buffer[i + 3], tab[((s >> 16) & 0xF) + attr]);
  34.             i += 4;
  35.             src += 4;
  36. #else
  37.             unsigned s = *(unsigned*)src, attr = (s >> 6) & 0x3FC;
  38.             line_buffer[i + 0] = _mm_add_pi8(line_buffer[i + 0], tab[((s >> 6) & 3) + attr]);
  39.             line_buffer[i + 1] = _mm_add_pi8(line_buffer[i + 1], tab[((s >> 4) & 3) + attr]);
  40.             line_buffer[i + 2] = _mm_add_pi8(line_buffer[i + 2], tab[((s >> 2) & 3) + attr]);
  41.             line_buffer[i + 3] = _mm_add_pi8(line_buffer[i + 3], tab[((s >> 0) & 3) + attr]);
  42.             attr = (s >> 22) & 0x3FC;
  43.             line_buffer[i + 4] = _mm_add_pi8(line_buffer[i + 4], tab[((s >> 22) & 3) + attr]);
  44.             line_buffer[i + 5] = _mm_add_pi8(line_buffer[i + 5], tab[((s >> 20) & 3) + attr]);
  45.             line_buffer[i + 6] = _mm_add_pi8(line_buffer[i + 6], tab[((s >> 18) & 3) + attr]);
  46.             line_buffer[i + 7] = _mm_add_pi8(line_buffer[i + 7], tab[((s >> 16) & 3) + attr]);
  47.             i += 8;
  48.             src += 4;
  49. #endif // MOD_SSE2
  50.         }
  51.         if(++frame == mix_frames)
  52.         {
  53.             break;
  54.         }
  55.         src0 += rb2_offs;
  56.         if(src0 >= rbuf_s + rb2_offs * mix_frames)
  57.         {
  58.             src0 -= rb2_offs * mix_frames;
  59.         }
  60.         tab += 0x100 * (1 << (sizeof(__m_vec) / sizeof(DWORD)));
  61.     }
  62. }
  63.  
  64. void RSM_DATA::prepare_line_16(unsigned char *src0)
  65. {
  66.     unsigned i;
  67.     for(i = 0; i < line_size_d; i++)
  68.     {
  69.         line_buffer_d[i] = bias;
  70.     }
  71.  
  72.     unsigned line_size = line_size_d / 2, frame = 0;
  73.     const __m_vec *tab = colortab;
  74.     for(;;)
  75.     {
  76.         unsigned char *src = src0;
  77.         for(i = 0; i < line_size; )
  78.         {
  79. #ifdef MOD_SSE2
  80.             // ═х Ёхрышчютрээю
  81.             src += 4; i += 4;
  82. #else
  83.             unsigned s = *(unsigned*)src, attr = (s >> 4) & 0xFF0;
  84.             line_buffer[i + 0] = _mm_add_pi8(line_buffer[i + 0], tab[((s >> 4) & 0xF) + attr]);
  85.             line_buffer[i + 1] = _mm_add_pi8(line_buffer[i + 1], tab[((s >> 0) & 0xF) + attr]);
  86.             attr = (s >> 20) & 0xFF0;
  87.             line_buffer[i + 2] = _mm_add_pi8(line_buffer[i + 2], tab[((s >> 20) & 0xF) + attr]);
  88.             line_buffer[i + 3] = _mm_add_pi8(line_buffer[i + 3], tab[((s >> 16) & 0xF) + attr]);
  89.             src += 4; i += 4;
  90. #endif // MOD_SSE2
  91.         }
  92.         if(++frame == mix_frames)
  93.         {
  94.             break;
  95.         }
  96.         src0 += rb2_offs;
  97.         if(src0 >= rbuf_s + rb2_offs * mix_frames)
  98.         {
  99.             src0 -= rb2_offs * mix_frames;
  100.         }
  101.         tab += 0x100 * 16;
  102.     }
  103. }
  104.  
  105. void RSM_DATA::prepare_line_8(unsigned char *src0)
  106. {
  107.     unsigned i;
  108.     for(i = 0; i < line_size_d; i++)
  109.     {
  110.         line_buffer_d[i] = bias;
  111.     }
  112.  
  113.     unsigned frame = 0;
  114.     const DWORD *tab = (const DWORD*)colortab;
  115.     for(;;)
  116.     {
  117.         unsigned char *src = src0;
  118.         for(i = 0; i < line_size_d; )
  119.         {
  120.             unsigned s = *(unsigned*)src, attr = (s >> 4) & 0xFF0;
  121.             line_buffer_d[i + 0] += tab[((s >> 4) & 0xF) + attr];
  122.             line_buffer_d[i + 1] += tab[((s >> 0) & 0xF) + attr];
  123.             attr = (s >> 20) & 0xFF0;
  124.             line_buffer_d[i + 2] += tab[((s >> 20) & 0xF) + attr];
  125.             line_buffer_d[i + 3] += tab[((s >> 16) & 0xF) + attr];
  126.             s = *(unsigned*)(src + 4);
  127.             attr = (s >> 4) & 0xFF0;
  128.             line_buffer_d[i + 4] += tab[((s >> 4) & 0xF) + attr];
  129.             line_buffer_d[i + 5] += tab[((s >> 0) & 0xF) + attr];
  130.             attr = (s >> 20) & 0xFF0;
  131.             line_buffer_d[i + 6] += tab[((s >> 20) & 0xF) + attr];
  132.             line_buffer_d[i + 7] += tab[((s >> 16) & 0xF) + attr];
  133.             src += 8;
  134.             i += 8;
  135.         }
  136.         if(++frame == mix_frames)
  137.         {
  138.             break;
  139.         }
  140.         src0 += rb2_offs;
  141.         if(src0 >= rbuf_s + rb2_offs * mix_frames)
  142.         {
  143.             src0 -= rb2_offs * mix_frames;
  144.         }
  145.         tab += 0x100 * 16;
  146.     }
  147. }
  148.  
  149. static void rend_rsm_8(unsigned char *dst, unsigned pitch, unsigned char *src)
  150. {
  151.     unsigned delta = temp.scx / 4;
  152.     for(unsigned y = 0; y < temp.scy; y++)
  153.     {
  154.         rsm.prepare_line_8(src);
  155.         for(unsigned i = 0; i < rsm.line_size_d; i++)
  156.         {
  157.             *(unsigned*)(dst + i * 4) = rsm.line_buffer_d[i];
  158.         }
  159.         dst += pitch; src += delta;
  160.     }
  161. }
  162.  
  163. static void rend_rsm_16(unsigned char *dst, unsigned pitch, unsigned char *src)
  164. {
  165.     unsigned delta = temp.scx / 4;
  166.     for(unsigned y = 0; y < temp.scy; y++)
  167.     {
  168.         rsm.prepare_line_32(src);
  169.         // pack truecolor pixel to 16 bit
  170.         if(temp.hi15 == 0)
  171.         {
  172.             for(unsigned i = 0; i < rsm.line_size_d; i += 2)
  173.             {
  174.                 unsigned c1 = rsm.line_buffer_d[i];
  175.                 unsigned c2 = rsm.line_buffer_d[i + 1];
  176.                 *(unsigned*)(dst + i * 2) =
  177.                     ((c1 >> 3) & 0x1F) + ((c1 >> 5) & 0x07E0) + ((c1 >> 8) & 0xF800) +
  178.                     ((c2 << 13) & 0x1F0000) + ((c2 << 11) & 0x07E00000) + ((c2 << 8) & 0xF8000000);
  179.             }
  180.         }
  181.         else /* if (temp.hi15 == 1) */
  182.         {
  183.             for(unsigned i = 0; i < rsm.line_size_d; i += 2)
  184.             {
  185.                 unsigned c1 = rsm.line_buffer_d[i];
  186.                 unsigned c2 = rsm.line_buffer_d[i + 1];
  187.                 *(unsigned*)(dst + i * 2) =
  188.                     ((c1 >> 3) & 0x1F) + ((c1 >> 6) & 0x03E0) + ((c1 >> 9) & 0x7C00) +
  189.                     ((c2 << 13) & 0x1F0000) + ((c2 << 10) & 0x03E00000) + ((c2 << 7) & 0x7C000000);
  190.             }
  191.         }
  192.  
  193.         dst += pitch; src += delta;
  194.     }
  195. }
  196.  
  197. static void rend_rsm_16o(unsigned char *dst, unsigned pitch, unsigned char *src)
  198. {
  199.     unsigned delta = temp.scx / 4;
  200.     for(unsigned y = 0; y < temp.scy; y++)
  201.     {
  202.         rsm.prepare_line_16(src);
  203.         for(unsigned i = 0; i < rsm.line_size_d; i++)
  204.         {
  205.             *(unsigned*)(dst + i * 4) = rsm.line_buffer_d[i];
  206.         }
  207.  
  208.         dst += pitch; src += delta;
  209.     }
  210. }
  211.  
  212. static void rend_rsm_32(unsigned char *dst, unsigned pitch, unsigned char *src)
  213. {
  214.     unsigned delta = temp.scx / 4;
  215.     for(unsigned y = 0; y < temp.scy; y++)
  216.     {
  217.         rsm.prepare_line_32(src);
  218.         for(unsigned i = 0; i < rsm.line_size_d; i++)
  219.         {
  220.             *(unsigned*)(dst + i * 4) = rsm.line_buffer_d[i];
  221.         }
  222.         dst += pitch; src += delta;
  223.     }
  224. }
  225.  
  226. void __fastcall render_rsm(unsigned char *dst, unsigned pitch)
  227. {
  228.     rsm.colortab = (const RSM_DATA::__m_vec*)(((const u8 *)rsm.tables) + rsm.frame * rsm.frame_table_size);
  229.     unsigned char *src = rbuf_s + rb2_offs * rsm.rbuf_dst;
  230.  
  231.     if(temp.obpp == 8)
  232.     {
  233.         rend_rsm_8(dst, pitch, src);
  234.     }
  235.     if(temp.obpp == 16)
  236.     {
  237.         if(rsm.mode == 0)
  238.         {
  239.             rend_rsm_16(dst, pitch, src);
  240.         }
  241.         else
  242.         {
  243.             rend_rsm_16o(dst, pitch, src);
  244.         }
  245.     }
  246.     if(temp.obpp == 32)
  247.     {
  248.         rend_rsm_32(dst, pitch, src);
  249.     }
  250.  
  251. #ifndef MOD_SSE2
  252.     _mm_empty(); // EMMS
  253. #endif // MOD_SSE2
  254. }
  255.  
  256. static unsigned gcd(unsigned x, unsigned y)
  257. {
  258.     while(x != y)
  259.     {
  260.         if(x > y)
  261.         {
  262.             x -= y;
  263.         }
  264.         else
  265.         {
  266.             y -= x;
  267.         }
  268.     }
  269.     return x;
  270. }
  271.  
  272. static unsigned lcm(unsigned x, unsigned y)
  273. {
  274.     return x * y / gcd(x, y);
  275. }
  276.  
  277. void calc_rsm_tables()
  278. {
  279.     rsm.rbuf_dst = rsm.frame = 0;
  280.  
  281.     if(renders[conf.render].func != render_rsm)
  282.     {
  283.         rsm.mix_frames = rsm.period = 1;
  284.         static unsigned char one = 1;
  285.         rsm.needframes = &one; // rsm.needframes[0]=1
  286.         return;
  287.     }
  288.  
  289.     rsm.mode = (temp.obpp == 8) ? 2 : 0;
  290.     if(temp.obpp == 16 && temp.hi15 == 2)
  291.     {
  292.         rsm.mode = 1;
  293.     }
  294.  
  295.     rsm.line_size_d = (temp.scx >> rsm.mode);
  296.  
  297.     unsigned fmax = lcm(conf.intfq, temp.ofq);
  298.     rsm.period = fmax / conf.intfq;
  299.     unsigned step = fmax / temp.ofq;
  300.  
  301.     rsm.mix_frames = (conf.rsm.mode == RSM_SIMPLE) ? 2 : conf.rsm.mix_frames;
  302.  
  303.     rsm.frame_table_size = rsm.mix_frames * 0x100;
  304.     if(rsm.mode == 0)
  305.     {
  306.         rsm.frame_table_size *= (1 << (sizeof(RSM_DATA::__m_vec) / sizeof(DWORD))) * sizeof(RSM_DATA::__m_vec);
  307.     }
  308.     if(rsm.mode == 1)
  309.     {
  310.         rsm.frame_table_size *= 16 * sizeof(RSM_DATA::__m_vec);
  311.     }
  312.     if(rsm.mode == 2)
  313.     {
  314.         rsm.frame_table_size *= 16 * sizeof(DWORD);
  315.     }
  316.  
  317.     rsm.data = (unsigned char*)realloc(rsm.data, rsm.period * (rsm.frame_table_size + 1));
  318.     rsm.tables = (RSM_DATA::__m_vec*)rsm.data;
  319.     rsm.needframes = rsm.data + rsm.frame_table_size * rsm.period;
  320.  
  321.     double *weights = (double*)alloca(rsm.period * rsm.mix_frames * sizeof(double));
  322.     double *dst = weights;
  323.  
  324.     unsigned low_bias = 0, dynamic_range = 0xFF;
  325.  
  326.     if(conf.rsm.mode != RSM_SIMPLE)
  327.     {
  328.         unsigned fsize = rsm.period * rsm.mix_frames;
  329.         double *flt = (double*)alloca((fsize + 1) * sizeof(double));
  330.  
  331.         double cutoff = 0.9;
  332.         if(conf.rsm.mode == RSM_FIR1)
  333.         {
  334.             cutoff = 0.5;
  335.         }
  336.         if(conf.rsm.mode == RSM_FIR2)
  337.         {
  338.             cutoff = 0.33333333;
  339.         }
  340.  
  341.         cutoff *= 1 / (double)rsm.period; // cutoff scale = inftq/maxfq = 1/rsm.period
  342.         double c1 = 0.54 / M_PI, c2 = 0.46 / M_PI;
  343.         for(unsigned i = 0; i <= fsize; i++)
  344.         {
  345.             if(i == fsize / 2)
  346.             {
  347.                 flt[i] = cutoff;
  348.             }
  349.             else
  350.             {
  351.                 flt[i] = sin(M_PI*cutoff*((double)i - fsize / 2)) * (c1 - c2 * cos(2 * M_PI*(double)i / fsize)) / ((double)i - fsize / 2);
  352.             }
  353.         }
  354.  
  355.         double low_b = 0, high_b = 0;
  356.         for(unsigned frame = 0; frame < rsm.period; frame++)
  357.         {
  358.             unsigned pos = frame * step, srcframe = pos / rsm.period;
  359.             if(frame)
  360.             {
  361.                 srcframe++;
  362.             }// (pos % rsm.period) != 0
  363.  
  364.             unsigned nextpos = pos + step, nextframe = nextpos / rsm.period;
  365.             if(frame + 1 != rsm.period)
  366.             {
  367.                 nextframe++;
  368.             } // (nextpos % rsm.period) != 0
  369.  
  370.             rsm.needframes[frame] = u8(nextframe - srcframe);
  371.             double low = 0, high = 0;
  372.             unsigned offset = (srcframe * rsm.period) - pos;
  373.             for(unsigned ch = 0; ch < rsm.mix_frames; ch++)
  374.             {
  375.                 double weight = flt[offset] * rsm.period;
  376.                 if(weight < 0)
  377.                 {
  378.                     low += weight;
  379.                 }
  380.                 else
  381.                 {
  382.                     high += weight;
  383.                 }
  384.                 *dst++ = weight;
  385.                 offset += rsm.period;
  386.             }
  387.             if(low < low_b)
  388.             {
  389.                 low_b = low;
  390.             }
  391.             if(high > high_b)
  392.             {
  393.                 high_b = high;
  394.             }
  395.         }
  396.         low_bias = (unsigned)((-low_b) * 0xFF);
  397.         dynamic_range = (0xFF - low_bias);
  398.     }
  399.     else
  400.     { // RSM_SIMPLE
  401.  
  402.         double div = 1 / (double)step;
  403.         for(unsigned frame = 0; frame < rsm.period; frame++)
  404.         {
  405.             unsigned pos = frame * step, srcframe = pos / rsm.period;
  406.             unsigned nextpos = pos + step, nextframe = nextpos / rsm.period;
  407.             unsigned offset = (srcframe == nextframe) ? step : (nextpos - nextframe * rsm.period);
  408.             rsm.needframes[frame] = u8(nextframe - srcframe);
  409.             *dst++ = offset * div;
  410.             *dst++ = (step - offset) * div;
  411.         }
  412.     }
  413.  
  414.     rsm.bias = 0x01010101 * low_bias;
  415.  
  416.     unsigned char *dst32 = (unsigned char*)rsm.tables;
  417.     for(unsigned frame = 0; frame < rsm.period; frame++)
  418.     {
  419.         for(unsigned ch = 0; ch < rsm.mix_frames; ch++)
  420.         {
  421.             unsigned char *start_frame = dst32;
  422.             switch(rsm.mode)
  423.             {
  424.             case 0: // rgb 16/32bit - reorder table, MMX processes 2 truecolor pixels at one op
  425.                 for(unsigned a = 0; a < 0x100; a++)
  426.                 {
  427. #ifdef MOD_SSE2
  428.                     for(unsigned pix = 0; pix < 16; pix++) // 4 ў/с яшъёхы  16 ъюьсшэрЎшш
  429.                     {
  430.                         *(DWORD*)(dst32 + 0*4) = t.sctab32[0][((pix >> 3) & 1) * 0x100 + a]; // ╟эрўхэш  pc тшфхюярь Єш xrgb32, тїюф 1 ў/с яшъёхы№ + рЄЁшсєЄ
  431.                         *(DWORD*)(dst32 + 1*4) = t.sctab32[0][((pix >> 2) & 1) * 0x100 + a]; // ╟эрўхэш  pc тшфхюярь Єш xrgb32, тїюф 1 ў/с яшъёхы№ + рЄЁшсєЄ
  432.                         *(DWORD*)(dst32 + 2*4) = t.sctab32[0][((pix >> 1) & 1) * 0x100 + a]; // ╟эрўхэш  pc тшфхюярь Єш xrgb32, тїюф 1 ў/с яшъёхы№ + рЄЁшсєЄ
  433.                         *(DWORD*)(dst32 + 3*4) = t.sctab32[0][((pix >> 0) & 1) * 0x100 + a]; // ╟эрўхэш  pc тшфхюярь Єш xrgb32, тїюф 1 ў/с яшъёхы№ + рЄЁшсєЄ
  434.                         dst32 += 4*4;
  435.                     }
  436. #else
  437.                     for(unsigned pix = 0; pix < 4; pix++) // 2 ў/с яшъёхы  4 ъюьсшэрЎшш
  438.                     {
  439.                         *(DWORD*)(dst32 + 0) = t.sctab32[0][(pix >> 1) * 0x100 + a]; // ╟эрўхэш  pc тшфхюярь Єш xrgb32, тїюф 1 ў/с яшъёхы№ + рЄЁшсєЄ
  440.                         *(DWORD*)(dst32 + 4) = t.sctab32[0][(pix & 1) * 0x100 + a]; // ╟эрўхэш  pc тшфхюярь Єш xrgb32, тїюф 1 ў/с яшъёхы№ + рЄЁшсєЄ
  441.                         dst32 += 8;
  442.                     }
  443. #endif // MOD_SSE2
  444.                 }
  445.             break;
  446.             case 1: // YUY2 overlay - reorder table, MMX processes 4 overlay pixels at one op
  447.                 for(unsigned a = 0; a < 0x100; a++)
  448.                 {
  449.                     for(unsigned pix = 0; pix < 16; pix++) // 4 ў/с яшъёхы  16 ъюьсшэрЎшш
  450.                     {
  451.                         *(DWORD*)(dst32 + 0) = t.sctab16[0][a * 4 + (pix >> 2)]; // ╧ю 2 чэрўхэш  pc тшфхюярь Єш, тїюф 2 ў/с яшъёхы  + рЄЁшсєЄ
  452.                         *(DWORD*)(dst32 + 4) = t.sctab16[0][a * 4 + (pix & 3)]; // ╧ю 2 чэрўхэш  pc тшфхюярь Єш, тїюф 2 ў/с яшъёхы  + рЄЁшсєЄ
  453.                         dst32 += 8;
  454.                     }
  455.                 }
  456.             break;
  457.             case 2: // 8bit, tables: 16*attr+4pix => 4 pixels in DWORD
  458.                 memcpy(dst32, t.sctab8[0], 0x100 * 16 * sizeof(DWORD));
  459.                 dst32 += 0x100 * 16 * sizeof(DWORD);
  460.             break;
  461.             default:
  462.             __assume(0);
  463.             }
  464.  
  465.             double scale = *weights++ * dynamic_range * (1.0 / 256.0);
  466.             for(unsigned char *ptr = start_frame; ptr < dst32; ptr++)
  467.             {
  468.                 double color = scale * *ptr;
  469.                 if(color > 255.0)
  470.                 {
  471.                     color = 255.0;
  472.                 }
  473.                 if(color < 0.0)
  474.                 {
  475.                     color += 256.0;
  476.                 } // color = 0.0;
  477.                 *ptr = (unsigned char)color;
  478.             }
  479.         }
  480.     }
  481. }
  482.