Subversion Repositories pentevo

Rev

Rev 883 | Details | Compare with Previous | Last modification | View Log | RSS feed

Rev Author Line No. Line
716 lvd 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
{
784 DimkaM 12
    unsigned i;
13
    for(i = 0; i < line_size_d; i++)
14
    {
15
        line_buffer_d[i] = bias;
16
    }
716 lvd 17
 
784 DimkaM 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
    }
716 lvd 62
}
63
 
64
void RSM_DATA::prepare_line_16(unsigned char *src0)
65
{
784 DimkaM 66
    unsigned i;
67
    for(i = 0; i < line_size_d; i++)
68
    {
69
        line_buffer_d[i] = bias;
70
    }
716 lvd 71
 
784 DimkaM 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
    }
716 lvd 103
}
104
 
105
void RSM_DATA::prepare_line_8(unsigned char *src0)
106
{
784 DimkaM 107
    unsigned i;
108
    for(i = 0; i < line_size_d; i++)
109
    {
110
        line_buffer_d[i] = bias;
111
    }
716 lvd 112
 
784 DimkaM 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
    }
716 lvd 147
}
148
 
784 DimkaM 149
static void rend_rsm_8(unsigned char *dst, unsigned pitch, unsigned char *src)
716 lvd 150
{
784 DimkaM 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
    }
716 lvd 161
}
162
 
784 DimkaM 163
static void rend_rsm_16(unsigned char *dst, unsigned pitch, unsigned char *src)
716 lvd 164
{
784 DimkaM 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
        }
716 lvd 192
 
784 DimkaM 193
        dst += pitch; src += delta;
194
    }
716 lvd 195
}
196
 
784 DimkaM 197
static void rend_rsm_16o(unsigned char *dst, unsigned pitch, unsigned char *src)
716 lvd 198
{
784 DimkaM 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
        }
716 lvd 207
 
784 DimkaM 208
        dst += pitch; src += delta;
209
    }
716 lvd 210
}
211
 
784 DimkaM 212
static void rend_rsm_32(unsigned char *dst, unsigned pitch, unsigned char *src)
716 lvd 213
{
784 DimkaM 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
    }
716 lvd 224
}
225
 
226
void __fastcall render_rsm(unsigned char *dst, unsigned pitch)
227
{
784 DimkaM 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;
716 lvd 230
 
784 DimkaM 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
    }
716 lvd 250
 
784 DimkaM 251
#ifndef MOD_SSE2
252
    _mm_empty(); // EMMS
253
#endif // MOD_SSE2
716 lvd 254
}
255
 
784 DimkaM 256
static unsigned gcd(unsigned x, unsigned y)
716 lvd 257
{
784 DimkaM 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;
716 lvd 270
}
271
 
784 DimkaM 272
static unsigned lcm(unsigned x, unsigned y)
716 lvd 273
{
784 DimkaM 274
    return x * y / gcd(x, y);
716 lvd 275
}
276
 
277
void calc_rsm_tables()
278
{
784 DimkaM 279
    rsm.rbuf_dst = rsm.frame = 0;
716 lvd 280
 
784 DimkaM 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
    }
716 lvd 288
 
784 DimkaM 289
    rsm.mode = (temp.obpp == 8) ? 2 : 0;
290
    if(temp.obpp == 16 && temp.hi15 == 2)
291
    {
292
        rsm.mode = 1;
293
    }
716 lvd 294
 
784 DimkaM 295
    rsm.line_size_d = (temp.scx >> rsm.mode);
716 lvd 296
 
784 DimkaM 297
    unsigned fmax = lcm(conf.intfq, temp.ofq);
298
    rsm.period = fmax / conf.intfq;
299
    unsigned step = fmax / temp.ofq;
716 lvd 300
 
784 DimkaM 301
    rsm.mix_frames = (conf.rsm.mode == RSM_SIMPLE) ? 2 : conf.rsm.mix_frames;
716 lvd 302
 
784 DimkaM 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
    }
716 lvd 316
 
784 DimkaM 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;
716 lvd 320
 
784 DimkaM 321
    double *weights = (double*)alloca(rsm.period * rsm.mix_frames * sizeof(double));
322
    double *dst = weights;
716 lvd 323
 
784 DimkaM 324
    unsigned low_bias = 0, dynamic_range = 0xFF;
716 lvd 325
 
784 DimkaM 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));
716 lvd 330
 
784 DimkaM 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
        }
716 lvd 340
 
784 DimkaM 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
        }
716 lvd 354
 
784 DimkaM 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
716 lvd 363
 
784 DimkaM 364
            unsigned nextpos = pos + step, nextframe = nextpos / rsm.period;
365
            if(frame + 1 != rsm.period)
366
            {
367
                nextframe++;
368
            } // (nextpos % rsm.period) != 0
716 lvd 369
 
784 DimkaM 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
716 lvd 401
 
784 DimkaM 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
    }
716 lvd 413
 
784 DimkaM 414
    rsm.bias = 0x01010101 * low_bias;
716 lvd 415
 
784 DimkaM 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
            {
716 lvd 424
            case 0: // rgb 16/32bit - reorder table, MMX processes 2 truecolor pixels at one op
784 DimkaM 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;
716 lvd 446
            case 1: // YUY2 overlay - reorder table, MMX processes 4 overlay pixels at one op
784 DimkaM 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;
716 lvd 461
            default:
784 DimkaM 462
            __assume(0);
463
            }
716 lvd 464
 
784 DimkaM 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
    }
716 lvd 481
}