Subversion Repositories pentevo

Rev

Details | 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 "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
videopoint video[4*MAX_HEIGHT];
33
unsigned vmode;  // what are drawing: 0-not visible, 1-border, 2-screen
34
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 (int j = 0x80; j; j/=2) {
87
         res <<= 2; if (i & j) res |= 3;
88
      }
89
      t.dbl[i] = res;
90
   }
91
 
92
   for (i = 0; i < 0x100; i++) {
93
      unsigned r1 = 0, r2 = 0;
94
      if (i & 0x01) r1++,        r2 += 1;
95
      if (i & 0x02) r1++,        r2 += 1;
96
      if (i & 0x04) r1++,        r2 += 0x100;
97
      if (i & 0x08) r1++,        r2 += 0x100;
98
      if (i & 0x10) r1 += 0x100, r2 += 0x10000;
99
      if (i & 0x20) r1 += 0x100, r2 += 0x10000;
100
      if (i & 0x40) r1 += 0x100, r2 += 0x1000000;
101
      if (i & 0x80) r1 += 0x100, r2 += 0x1000000;
102
      // low byte of settab - number of pixels in low nibble of i
103
      // high byte of low word of settab - number of pixels in high nibble of i
104
      t.settab[i] = r1;
105
      t.settab2[i] = r2*4; // *4 - convert square 2x2 to 4x4
106
   }
107
 
108
   i = 0; // calc screen addresses
109
   for (int p = 0; p < 4; p++)
110
      for (int y = 0; y < 8; y++)
111
         for (int o = 0; o < 8; o++, i++)
112
            t.scrtab[i] = p*0x800 + y*0x20 + o*0x100,
113
            t.atrtab_hwmc[i] = t.scrtab[i] + 0x2000,
114
            t.atrtab[i] = 0x1800 + (p*8+y)*32;
115
 
116
   // alco table
117
   static unsigned disp_0[] = { 0x0018, 0x2000, 0x2008, 0x2010, 0x2018, 0x0008 };
118
   static unsigned base_s[] = { 0x10000, 0x14000, 0x14800, 0x15000, 0x11800 };
119
   static unsigned base_a[] = { 0x11000, 0x15800, 0x15900, 0x15A00, 0x11300 };
120
   for (unsigned y = 0; y < 304; y++)
121
      for (unsigned x = 0; x < 6; x++) {
122
         unsigned disp = disp_0[x] + (y & 0x38)*4;
123
         ::t.alco[y][x].a = memory + base_a[y/64] + disp;
124
         ::t.alco[y][x].s = memory + base_s[y/64] + disp + (y & 7)*0x100;
125
      }
126
 
127
   #ifdef MOD_VID_VD
128
   // this code is only for ygrbYGRB palette
129
   for (unsigned byte = 0; byte < 0x100; byte++)
130
      for (int bit = 0; bit < 8; bit++)
131
         t.vdtab[0][0][byte].m64_u8[7-bit] = (byte & (1 << bit))? 0x11 : 0;
132
   for (int pl = 1; pl < 4; pl++)
133
      for (unsigned byte = 0; byte < 0x100; byte++)
134
         t.vdtab[0][pl][byte] = _mm_slli_pi32(t.vdtab[0][0][byte], pl);
135
   for (i = 0; i < sizeof t.vdtab[0]; i++)
136
      ((unsigned char*)t.vdtab[1])[i] = ((unsigned char*)t.vdtab[0])[i] & 0x0F;
137
   _mm_empty();
138
   #endif
139
 
140
   temp.offset_vscroll_prev = 0;
141
   temp.offset_vscroll = 0;
142
   temp.offset_hscroll_prev = 0;
143
   temp.offset_hscroll = 0;
144
}
145
 
146
unsigned getYUY2(unsigned r, unsigned g, unsigned b)
147
{
148
   int y = (int)(0.29*r + 0.59*g + 0.14*b);
149
   int u = (int)(128.0 - 0.14*r - 0.29*g + 0.43*b);
150
   int v = (int)(128.0 + 0.36*r - 0.29*g - 0.07*b);
151
   if (y < 0) y = 0; if (y > 255) y = 255;
152
   if (u < 0) u = 0; if (u > 255) u = 255;
153
   if (v < 0) v = 0; if (v > 255) v = 255;
154
   return WORD4(y,u,y,v);
155
}
156
 
157
void create_palette()
158
{
159
   if ((temp.rflags & RF_8BPCH) && temp.obpp == 8) temp.rflags |= RF_GRAY, conf.flashcolor = 0;
160
 
161
   PALETTE_OPTIONS *pl = &pals[conf.pal];
162
   unsigned char brights[4] = { u8(pl->ZZ), u8(pl->ZN), u8(pl->NN), u8(pl->BB) };
163
   unsigned char brtab[16] =
164
      {  //  ZZ          NN          ZZ          BB
165
        u8(pl->ZZ), u8(pl->ZN), u8(pl->ZZ), u8(pl->ZB),    // ZZ
166
        u8(pl->ZN), u8(pl->NN), u8(pl->ZN), u8(pl->NB),    // NN
167
        u8(pl->ZZ), u8(pl->ZN), u8(pl->ZZ), u8(pl->ZB),    // ZZ (bright=1,ink=0)
168
        u8(pl->ZB), u8(pl->NB), u8(pl->ZB), u8(pl->BB)     // BB
169
      };
170
 
171
   for (unsigned i = 0; i < 0x100; i++) {
172
      unsigned r0, g0, b0;
173
      if (temp.rflags & RF_GRAY) { // grayscale palette
174
         r0 = g0 = b0 = i;
175
      } else if (temp.rflags & RF_PALB) { // palette index: gg0rr0bb
176
         b0 = brights[i & 3];
177
         r0 = brights[(i >> 3) & 3];
178
         g0 = brights[(i >> 6) & 3];
179
      } else { // palette index: ygrbYGRB
180
         b0 = brtab[((i>>0)&1)+((i>>2)&2)+((i>>2)&4)+((i>>4)&8)]; // brtab[ybYB]
181
         r0 = brtab[((i>>1)&1)+((i>>2)&2)+((i>>3)&4)+((i>>4)&8)]; // brtab[yrYR]
182
         g0 = brtab[((i>>2)&1)+((i>>2)&2)+((i>>4)&4)+((i>>4)&8)]; // brtab[ygYG]
183
      }
184
 
185
      // transform with current settings
186
      unsigned r = 0xFF & ((r0 * pl->r11 + g0 * pl->r12 + b0 * pl->r13) / 0x100);
187
      unsigned g = 0xFF & ((r0 * pl->r21 + g0 * pl->r22 + b0 * pl->r23) / 0x100);
188
      unsigned b = 0xFF & ((r0 * pl->r31 + g0 * pl->r32 + b0 * pl->r33) / 0x100);
189
 
190
      // prepare palette in bitmap header for GDI renderer
191
      gdibmp.header.bmiColors[i].rgbRed   = pal0[i].peRed   = r;
192
      gdibmp.header.bmiColors[i].rgbGreen = pal0[i].peGreen = g;
193
      gdibmp.header.bmiColors[i].rgbBlue  = pal0[i].peBlue  = b;
194
   }
195
   memcpy(syspalette + 10, pal0 + 10, (246-9) * sizeof *syspalette);
196
}
197
 
198
void atm_zc_tables();//forward
199
 
200
// make colortab: zx-attr -> pc-attr
201
void make_colortab(char flash_active)
202
{
203
   if (conf.flashcolor)
204
       flash_active = 0;
205
 
206
   for (unsigned a = 0; a < 0x100; a++)
207
   {
208
      unsigned char ink = a & 7;
209
      unsigned char paper = (a >> 3) & 7;
210
      unsigned char bright = (a >> 6) & 1;
211
      unsigned char flash = (a >> 7) & 1;
212
 
213
      if((conf.flashcolor && ink) || !conf.flashcolor)
214
          ink |= bright << 3;
215
 
216
      if((conf.flashcolor && paper) || !conf.flashcolor)
217
          paper |= (conf.flashcolor ? flash : bright) << 3;
218
 
219
      if (flash_active && flash)
220
      {
221
          unsigned char t = ink;
222
          ink = paper;
223
          paper = t;
224
      }
225
 
226
      u8 color = (paper << 4) | ink;
227
 
228
      colortab[a] = color;
229
      colortab_s8[a] = color << 8;
230
      colortab_s24[a] = color << 24;
231
   }
232
 
233
   if (conf.mem_model == MM_ATM710 || conf.mem_model == MM_ATM3 || conf.mem_model == MM_ATM450)
234
       atm_zc_tables(); // update with new flash bit
235
}
236
 
237
// make attrtab: pc-attr + 0x100*pixel -> palette index
238
void attr_tables()
239
{
240
   unsigned char flashcolor = (temp.rflags & RF_MON)? 0 : conf.flashcolor;
241
   for (unsigned a = 0; a < 0x100; a++)
242
   {
243
      unsigned char ink = (a & 0x0F), paper = (a >> 4);
244
      if (flashcolor)
245
          paper = (paper & 7) + (ink & 8); // paper_bright from ink
246
 
247
      if (temp.rflags & RF_GRAY)
248
      { // grayscale palette
249
         t.attrtab[a] = paper*16;
250
         t.attrtab[a+0x100] = ink*16;
251
      }
252
      else if (temp.rflags & RF_COMPPAL)
253
      { //------ for ATM palette - direct values from palette registers
254
         t.attrtab[a] = comp.comp_pal[a >> 4];
255
         t.attrtab[a+0x100] = comp.comp_pal[a & 0x0F];
256
      }
257
      else if (temp.rflags & RF_PALB)
258
      { //----------------------------- for bilinear
259
         unsigned char b0,b1, r0,r1, g0,g1;
260
         b0 = (paper >> 0) & 1, r0 = (paper >> 1) & 1, g0 = (paper >> 2) & 1;
261
         b1 = (ink >> 0) & 1, r1 = (ink >> 1) & 1, g1 = (ink >> 2) & 1;
262
 
263
         if (flashcolor && (a & 0x80))
264
         {
265
            b1 += b0, r1 += r0, g1 += g0;
266
            r0 = b0 = g0 = 0;
267
         }
268
         else
269
         {
270
            b0 *= 2, r0 *= 2, g0 *=2,
271
            b1 *= 2, r1 *= 2, g1 *=2;
272
         }
273
 
274
         unsigned char br1 = (ink >> 3) & 1;
275
         if (r1) r1 += br1;
276
         if (g1) g1 += br1;
277
         if (b1) b1 += br1;
278
 
279
         unsigned char br0 = (paper >> 3) & 1;
280
         if (r0) r0 += br0;
281
         if (g0) g0 += br0;
282
         if (b0) b0 += br0;
283
 
284
         // palette index: gg0rr0bb
285
         t.attrtab[a+0x100]  = (g1 << 6) + (r1 << 3) + b1;
286
         t.attrtab[a]        = (g0 << 6) + (r0 << 3) + b0;
287
      }
288
      else //------------------------------------ all others
289
      {
290
         // palette index: ygrbYGRB
291
         if (flashcolor && (a & 0x80))
292
         {
293
             t.attrtab[a] = 0;
294
             t.attrtab[a+0x100] = ink+(paper<<4);
295
         }
296
         else
297
         {
298
             t.attrtab[a] = paper * 0x11;
299
             t.attrtab[a+0x100] = ink * 0x11;
300
         }
301
      }
302
   }
303
}
304
 
305
void p4bpp_tables()
306
{
307
   for (unsigned pass = 0; pass < 2; pass++) {
308
      for (unsigned bt = 0; bt < 0x100; bt++) {
309
         unsigned lf = ((bt >> 3) & 7) + ((bt >> 4) & 8);
310
         unsigned rt = (bt & 7) + ((bt >> 3) & 8);
311
         if (temp.obpp == 8) {
312
            t.p4bpp8[pass][bt] = (t.sctab8[pass][0x0F+0x10*rt] & 0xFFFF) +
313
                                   (t.sctab8[pass][0x0F+0x10*lf] & 0xFFFF0000);
314
         } else if (temp.obpp == 16) {
315
            t.p4bpp16[pass][bt*2+0] = t.sctab16[pass][0x03+4*rt],
316
            t.p4bpp16[pass][bt*2+1] = t.sctab16[pass][0x03+4*lf];
317
         } else /* if (temp.obpp == 32) */ {
318
            t.p4bpp32[pass][bt*2+0] = t.sctab32[pass][0x100+rt],
319
            t.p4bpp32[pass][bt*2+1] = t.sctab32[pass][0x100+lf];
320
         }
321
      }
322
   }
323
}
324
 
325
void atm_zc_tables() // atm,profi screens (use normal zx-flash)
326
{
327
   for (unsigned pass = 0; pass < 2; pass++) {
328
      for (unsigned at = 0; at < 0x100; at++) {
329
         unsigned pc_attr = colortab[at];
330
         if (temp.obpp == 8)
331
            for (unsigned j = 0; j < 4; j++)
332
               t.zctab8ad[pass][at*4+j] = t.sctab8d[pass][pc_attr*4+j];
333
         else if (temp.obpp == 16)
334
            t.zctab16ad[pass][at] = t.sctab16d[pass][pc_attr],
335
            t.zctab16ad[pass][at+0x100] = t.sctab16d[pass][pc_attr+0x100];
336
         else /* if (temp.obpp == 32) */
337
            t.zctab32ad[pass][at] = t.sctab32[pass][pc_attr],
338
            t.zctab32ad[pass][at+0x100] = t.sctab32[pass][pc_attr+0x100];
339
      }
340
   }
341
 
342
   // atm palette mapping (port out to palette index)
343
   for (unsigned i = 0; i < 0x100; i++) {
344
      unsigned v = i ^ 0xFF, dst;
345
      if (conf.mem_model == MM_ATM450)
346
         dst = // ATM1: --grbGRB => Gg0Rr0Bb
347
               ((v & 0x20) << 1) | // g
348
               ((v & 0x10) >> 1) | // r
349
               ((v & 0x08) >> 3) | // b
350
               ((v & 0x04) << 5) | // G
351
               ((v & 0x02) << 3) | // R
352
               ((v & 0x01) << 1);  // B
353
      else
354
         dst = // ATM2: grbG--RB => Gg0Rr0Bb
355
               ((v & 0x80) >> 1) | // g
356
               ((v & 0x40) >> 3) | // r
357
               ((v & 0x20) >> 5) | // b
358
               ((v & 0x10) << 3) | // G
359
               ((v & 0x02) << 3) | // R
360
               ((v & 0x01) << 1);  // B
361
      t.atm_pal_map[i] = dst;
362
   }
363
}
364
 
365
void hires_sc_tables()  // atm,profi screens (use zx-attributes & flash -> paper_bright)
366
{
367
   for (unsigned pass = 0; pass < 2; pass++) {
368
      for (unsigned at = 0; at < 0x100; at++) {
369
         unsigned pc_attr = (at & 0x80) + (at & 0x38)*2 + (at & 0x40)/8 + (at & 7);
370
         if (temp.obpp == 8)
371
            for (unsigned j = 0; j < 16; j++)
372
               t.zctab8[pass][at*0x10+j] = t.sctab8[pass][pc_attr*0x10+j];
373
         else if (temp.obpp == 16)
374
            for (unsigned j = 0; j < 4; j++)
375
               t.zctab16[pass][at*4+j] = t.sctab16[pass][pc_attr*4+j];
376
         else /* if (temp.obpp == 32) */
377
            for (unsigned j = 0; j < 2; j++)
378
               t.zctab32[pass][at+0x100*j] = t.sctab32[pass][pc_attr+0x100*j];
379
      }
380
   }
381
}
382
 
383
void calc_noflic_16_32()
384
{
385
   unsigned at, pass;
386
   if (temp.obpp == 16) {
387
      for (pass = 0; pass < 2; pass++) {
388
         for (at = 0; at < 2*0x100; at++)
389
            t.sctab16d_nf[pass][at] = (t.sctab16d[pass][at] & temp.shift_mask)/2;
390
         for (at = 0; at < 4*0x100; at++)
391
            t.sctab16_nf[pass][at] = (t.sctab16[pass][at] & temp.shift_mask)/2;
392
         for (at = 0; at < 2*0x100; at++)
393
            t.p4bpp16_nf[pass][at] = (t.p4bpp16[pass][at] & temp.shift_mask)/2;
394
      }
395
   }
396
   if (temp.obpp == 32) {
397
      unsigned shift_mask = 0xFEFEFEFE;
398
      for (pass = 0; pass < 2; pass++) {
399
         for (at = 0; at < 2*0x100; at++)
400
            t.sctab32_nf[pass][at] = (t.sctab32[pass][at] & shift_mask)/2;
401
         for (at = 0; at < 2*0x100; at++)
402
            t.p4bpp32_nf[pass][at] = (t.p4bpp32[pass][at] & shift_mask)/2;
403
      }
404
   }
405
}
406
 
407
// pal.index => raw video data, shadowed with current scanline pass
408
unsigned raw_data(unsigned index, unsigned pass, unsigned bpp)
409
{
410
   if (bpp == 8)
411
   {
412
 
413
      if (pass)
414
      {
415
         if (!conf.scanbright)
416
             return 0;
417
         // palette too small to realize noflic/atari with shaded scanlines
418
         if (conf.scanbright < 100 && !conf.noflic && !conf.atariset[0])
419
         {
420
            if (temp.rflags & RF_PALB)
421
                index = (index & (index << 1) & 0x92) | ((index ^ 0xFF) & (index >> 1) & 0x49);
422
            else
423
                index &= 0x0F;
424
         }
425
      }
426
      return index * 0x01010101;
427
   }
428
 
429
   unsigned r = pal0[index].peRed, g = pal0[index].peGreen, b = pal0[index].peBlue;
430
   if (pass)
431
   {
432
       r = r * conf.scanbright / 100;
433
       g = g * conf.scanbright / 100;
434
       b = b * conf.scanbright / 100;
435
   }
436
 
437
   if (bpp == 32)
438
       return WORD4(b,g,r,0);
439
 
440
   // else (bpp == 16)
441
   if (temp.hi15==0)
442
       return ((b/8) + ((g/4)<<5) + ((r/8)<<11)) * 0x10001;
443
   if (temp.hi15==1)
444
       return ((b/8) + ((g/8)<<5) + ((r/8)<<10)) * 0x10001;
445
   if (temp.hi15==2)
446
       return getYUY2(r,g,b);
447
   return 0;
448
}
449
 
450
unsigned atari_to_raw(unsigned at, unsigned pass)
451
{
452
   unsigned c1 = at/0x10, c2 = at & 0x0F;
453
   unsigned raw0 = raw_data(t.attrtab[c1+0x100], pass, temp.obpp);
454
   unsigned raw1 = raw_data(t.attrtab[c2+0x100], pass, temp.obpp);
455
   if (raw0 == raw1) return raw1;
456
 
457
   if (temp.obpp == 8)
458
      return (temp.rflags & RF_PALB)? (0x49494949 & ((raw0&raw1)^((raw0^raw1)>>1))) |
459
                                      (0x92929292 & ((raw0&raw1)|((raw0|raw1)&((raw0&raw1)<<1))))
460
                                    : (0x0F0F0F0F & raw0) | (0xF0F0F0F0 & raw1);
461
 
462
   return (raw0 & temp.shift_mask)/2 + (raw1 & temp.shift_mask)/2;
463
}
464
 
465
void pixel_tables()
466
{
467
   attr_tables();
468
   for (unsigned pass = 0; pass < 2; pass++)
469
   {
470
      for (unsigned at = 0; at < 0x100; at++)
471
      {
472
         unsigned px0 = t.attrtab[at];
473
         unsigned px1 = t.attrtab[at+0x100];
474
         unsigned p0 = raw_data(px0, pass, temp.obpp);
475
         unsigned p1 = raw_data(px1, pass, temp.obpp);
476
 
477
         // sctab32 required for frame resampler in 16-bit mode, so temp.obpp=16 here
478
         t.sctab32[pass][at] = raw_data(px0, pass, 32);
479
         t.sctab32[pass][at+0x100] = raw_data(px1, pass, 32);
480
 
481
         // 8 bit
482
         unsigned j;
483
         for (j = 0; j < 0x10; j++)
484
         {
485
            unsigned mask = (j >> 3)*0xFF + (j & 0x04)*(0xFF00/4) +
486
                            (j & 0x02)*(0xFF0000/2) + (j & 1)*0xFF000000;
487
            t.sctab8[pass][j + at*0x10] = (mask & p1) + (~mask & p0);
488
         }
489
         for (j = 0; j < 4; j++)
490
         {
491
            unsigned mask = (j >> 1)*0xFFFF + (j & 1)*0xFFFF0000;
492
            t.sctab8d[pass][j+at*4] = (mask & p1) + (~mask & p0);
493
         }
494
         t.sctab8q[at] = p0, t.sctab8q[at+0x100] = p1;
495
 
496
         // 16 bit
497
         for (j = 0; j < 4; j++)
498
         {
499
            unsigned mask = (j >> 1)*0xFFFF + (j & 1)*0xFFFF0000;
500
            t.sctab16[pass][j+at*4] = (mask & p1) + (~mask & p0);
501
         }
502
         t.sctab16d[pass][at] = p0, t.sctab16d[pass][at+0x100] = p1;
503
 
504
         unsigned atarimode;
505
         if (!(temp.rflags & RF_MON) && (atarimode = temp.ataricolors[at]))
506
         {
507
            unsigned rawdata[4], i;
508
            for (i = 0; i < 4; i++) rawdata[i] = atari_to_raw((atarimode >> (8*i)) & 0xFF, pass);
509
            for (i = 0; i < 16; i++) t.sctab8[pass][at*0x10+i] = rawdata[i/4] + 16*rawdata[i & 3];
510
            for (i = 0; i < 4; i++) t.sctab8d[pass][at*4+i] = rawdata[i];
511
            for (i = 0; i < 4; i++) t.sctab16[pass][at*4+i] = rawdata[i];
512
 
513
         }
514
      }
515
   }
516
 
517
   p4bpp_tables(); // used for ATM2+ mode0 and Pentagon-4bpp
518
 
519
   if (temp.obpp > 8 && conf.noflic) calc_noflic_16_32();
520
 
521
   if ((temp.rflags & (RF_DRIVER|RF_2X|RF_USEFONT))==(RF_DRIVER|RF_2X) && // render="double"
522
       (conf.mem_model == MM_ATM450 || conf.mem_model == MM_ATM710 || conf.mem_model == MM_ATM3 || conf.mem_model == MM_PROFI))
523
      hires_sc_tables();
524
}
525
 
526
void video_color_tables()
527
{
528
   temp.shift_mask = 0xFEFEFEFE; // 32bit, 16bit YUY2
529
   if (temp.obpp == 16 && temp.hi15==0) temp.shift_mask = 0xF7DEF7DE;
530
   if (temp.obpp == 16 && temp.hi15==1) temp.shift_mask = 0x7BDE7BDE;
531
 
532
   create_palette();
533
   pixel_tables();
534
   make_colortab(0);
535
 
536
   if (temp.rflags & (RF_USEC32 | RF_USE32AS16)) {
537
      for (unsigned at = 0; at < 0x100; at++) {
538
         for (unsigned vl = 0; vl <= 0x10; vl++) {
539
            unsigned br = (at & 0x40) ? 0xFF : 0xBF;
540
            unsigned c1, c2, res;
541
            c1 = (at & 1) >> 0, c2 = (at & 0x08) >> 3;
542
            unsigned b = (c1*vl + c2*(0x10-vl))*br/0x10;
543
            c1 = (at & 2) >> 1, c2 = (at & 0x10) >> 4;
544
            unsigned r = (c1*vl + c2*(0x10-vl))*br/0x10;
545
            c1 = (at & 4) >> 2, c2 = (at & 0x20) >> 5;
546
            unsigned g = (c1*vl + c2*(0x10-vl))*br/0x10;
547
            if (temp.rflags & RF_USE32AS16) {
548
               if (temp.hi15==0) res = (b/8) + ((g/4)<<5) + ((r/8)<<11);
549
               if (temp.hi15==1) res = (b/8) + ((g/8)<<5) + ((r/8)<<10);
550
               if (temp.hi15==2) res = getYUY2(r,g,b);
551
               else res *= 0x10001; // for hi15=0,1
552
            } else res =  WORD4(b,g,r,0);
553
            t.c32tab[at][vl] = res;
554
         }
555
      }
556
   }
557
   setpal(0);
558
}
559
 
560
void video_timing_tables()
561
{
562
   if (conf.frame < 2000)
563
   {
564
       conf.frame = 2000;
565
       cpu.SetTpi(conf.frame);
566
   }
567
   if (conf.t_line < 128) conf.t_line = 128;
568
   conf.nopaper &= 1;
569
   atrtab = (comp.pEFF7 & EFF7_HWMC) ? t.atrtab_hwmc : t.atrtab;
570
 
571
//   conf.bordersize=2;
572
//   temp.scx = 384, temp.scy = 300;
573
   #define p2cc(p) ((p)/4) // Перевод величины в пикселях в число знакомест с учетом атрибутов (каждое знакоместо занимает 2 байта, байт данных и байт атрибутов)
574
   const unsigned width = p2cc(temp.scx); // Ширина экрана в знакоместах * 2 (т.к. используются пиксели и атрибуты на 1 знакоместо)
575
   //temp.vidbufsize = temp.scx*temp.scy/4;
576
 
577
   // make video table
578
   unsigned mid_lines = 192; // Число строк в центральной части экрана (без бордюра)
579
   const unsigned buf_mid = 256; // Число пикселей в центральной части экрана (без бордюра)
580
 
581
   // Расчет размер бордюра в пикселях (1 пиксель = 2 такта)
582
   temp.b_bottom = temp.b_top = conf.b_top_small, temp.b_left = conf.b_left_small; // border small
583
   if (conf.bordersize==0) temp.b_top = temp.b_left = 0; // border none
584
   if (conf.bordersize==2) { temp.b_top = conf.b_top_full; temp.b_left = conf.b_left_full; } // border full
585
 
586
   // temp.scx - число точек в мультиколоре по горизонтали
587
   // temp.scy - число строк в мультиколоре
588
   // 256x192 - border none
589
   // 320x240 - border small
590
   // 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)))
591
   temp.b_right = temp.scx - buf_mid - temp.b_left; // Расчет размера правой части бордюра в пикселях (1 пиксель = 1/2 такта)
592
   temp.b_bottom = temp.scy - mid_lines - temp.b_top; // Расчет размера нижней части бордюра в пикселях (1 пиксель = 1/2 такта)
593
 
594
   if (conf.nopaper) temp.b_bottom += mid_lines, mid_lines=0; // Режим nopaper (растр в середине экрана отсутствует)
595
   int inx = 0;
596
 
597
   unsigned i;
598
   #define ts(t) (((int)(t) < 0) ? 0 : t)
599
   #define p2t(p) ((p)/2) // Перевод пикселей в такты
600
   // conf.paper - Число тактов от начала растра до центральной части spectrum экрана
601
   // (включает невидимую часть + полностью верхний бордюр + начало строки шириной hblank + левый бордюр)
602
   // Для pentagon 128: (16+64)*(32+36+128+28)+32+36 = 17988 тактов
603
   // 16 строк над верхним бордюром
604
   // 64 строки - верхний бордюр
605
   // каждая строка 224 такта:
606
   // 32 такта hblank
607
   // 36 тактов - левый бордюр
608
   // 128 тактов - центр экрана
609
   // 28 тактов - правый бордюр
610
   unsigned t = conf.paper - temp.b_top*conf.t_line; // Число тактов до начала верхнего бордюра (включая hblank + левый бордюр в первой строке paper)
611
   const unsigned hblank = conf.t_line - p2t(temp.scx); // Число тактов в hblank
612
   video[inx++].next_t = ts(t - p2t(temp.b_left)); // Исключение левого бордюра (next_t - такт начала первой строки верхнего бордюра)
613
//   printf("btop: temp.b_top=%u, conf.b_top_full=%u\n", temp.b_top, conf.b_top_full);
614
   for (i = 0; i < temp.b_top; i++)
615
   { // верхний бордюр
616
      video[inx].next_t = ts(t + p2t(buf_mid+temp.b_right)); // Конец правого бордюра (такт конца текущей строки)
617
      video[inx].screen_ptr = rbuf+width*i; // Указатель на на чало текущей строки в буфере отрисовки
618
      video[inx].nextvmode = 0; // hblank (переход к новой строке)
619
//      printf("%3u: b=%u, e=%u, o=%u\n", i, video[inx-1].next_t, video[inx].next_t, width*i);
620
 
621
       // Переход к следующей строке (t - такт начала paper следующей строки hblank + левый бордюр)
622
      inx++; t += conf.t_line;
623
      video[inx++].next_t = ts(t - p2t(temp.b_left)); // Исключение левого бордюра (такт начала левого бордюра на следующей строке)
624
   }
625
//   printf("paper:\n");
626
   for (i = 0; i < mid_lines; i++)
627
   { // hblank + левый бордюр + экран + правый бордюр
628
      video[inx].next_t = ts(t); // Конец левого бордюра (такт начала paper на текущей строке)
629
      video[inx].screen_ptr = rbuf+width*(i+temp.b_top); // Указатель на начало iй строки левого бордюра в буфере отрисовки
630
      video[inx].nextvmode = 2; // Далее прорисовывается paper
631
//      printf("%3u: b=%u ", i, video[inx-1].next_t);
632
 
633
      inx++;
634
      video[inx].next_t = ts(t + p2t(buf_mid)); // Конец paper (такт начала правого бордюра на текущей строке)
635
      video[inx].screen_ptr = rbuf+width*(i+temp.b_top)+p2cc(temp.b_left);// Указатель на начало iй строки paper в буфере отрисовки
636
      video[inx].scr_offs = ::t.scrtab[i]; // Смещение от начала zx экрана (пиксели)
637
      video[inx].atr_offs = atrtab[i]; // Смещение от начала зоны атрибутов zx экрана
638
 
639
      inx++;
640
      video[inx].next_t = ts(t + p2t(buf_mid+temp.b_right));  // Конец правого бордюра (такт конца текущей строки)
641
      video[inx].screen_ptr = rbuf+width*(i+temp.b_top)+p2cc(buf_mid+temp.b_left); // Указатель на начало iй строки правого бордюра в буфере отрисовки
642
      video[inx].nextvmode = 0; // hblank (переход к новой строке)
643
 
644
//      printf("e=%u\n", video[inx].next_t);
645
       // Переход к следующей строке (t - такт начала paper следующей строки hblank + левый бордюр)
646
      inx++; t += conf.t_line;
647
      video[inx++].next_t = ts(t - p2t(temp.b_left)); // Исключение левого бордюра (такт начала следующей строки)
648
   }
649
//   printf("bbot:\n");
650
   for (i = 0; i < temp.b_bottom; i++)
651
   { // нижний бордюр
652
      video[inx].next_t = ts(t + p2t(buf_mid+temp.b_right)); // Конец правого бордюра (такт конца текущей строки)
653
      video[inx].screen_ptr = rbuf+width*(i+temp.b_top+mid_lines); // Указатель на на чало iй строки нижнего бордюра в буфере отрисовки
654
      video[inx].nextvmode = 0; // hblank (переход к новой строке)
655
//      printf("%3u: b=%u, e=%u\n", i, video[inx-1].next_t, video[inx].next_t);
656
 
657
       // Переход к следующей строке (t - такт начала paper следующей строки hblank + левый бордюр)
658
      inx++; t += conf.t_line;
659
      video[inx++].next_t = ts(t - p2t(temp.b_left)); // Исключение левого бордюра (такт начала следующей строки)
660
   }
661
   video[inx-1].next_t = 0x7FFFFFFF; // Признак последней строки
662
//   exit(0);
663
 
664
   temp.evenM1_C0 = conf.even_M1 ? 0xC0 : 0x00;
665
   temp.border_add = conf.border_4T ? 6 : 0;
666
   temp.border_and = conf.border_4T ? 0xFFFFFFFC : 0xFFFFFFFF;
667
 
668
   for (i = 0; i < NUM_LEDS; i++)
669
   {
670
      unsigned z = *(&conf.led.ay + i);
671
      int x = (signed short)(z & 0xFFFF);
672
      int y = (signed short)(((z >> 16) & 0x7FFF) + ((z >> 15) & 0x8000));
673
      if (x < 0) x += width*8;
674
      if (y < 0) y += temp.scy;
675
      *(&temp.led.ay+i) = (z & 0x80000000) ? rbuf + ((x>>2)&0xFE) + y*width : 0;
676
   }
677
 
678
   if (temp.rflags & RF_USEFONT)
679
       create_font_tables();
680
 
681
   needclr = 2;
682
}
683
 
684
void set_video()
685
{
686
//   printf("%s\n", __FUNCTION__);
687
   set_vidmode();
688
   video_color_tables();
689
}
690
 
691
void apply_video()
692
{
693
//   printf("%s\n", __FUNCTION__);
694
   load_ula_preset();
695
 
696
   if(conf.mem_model == MM_ATM710 || conf.mem_model == MM_ATM3 || conf.mem_model == MM_ATM450 || conf.mem_model == MM_PROFI)
697
   {
698
       conf.render = 1; // Для моделей с экраном 640x200 поддерживается только redner = double (640x480)
699
   }
700
 
701
   temp.rflags = renders[conf.render].flags;
702
   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))
703
   {
704
      temp.rflags |= RF_COMPPAL | RF_PALB;
705
      // disable palette noflic, only if it is really used
706
      if (temp.obpp == 8 && (temp.rflags & (RF_DRIVER | RF_USEFONT | RF_8BPCH)) == RF_DRIVER)
707
      conf.noflic = 0;
708
   }
709
 
710
   if (renders[conf.render].func == render_rsm)
711
       conf.flip = 1; // todo: revert back after returning from frame resampler //Alone Coder
712
 
713
   if (renders[conf.render].func == render_advmame)
714
   {
715
      if (conf.videoscale == 2)
716
          temp.rflags |= RF_2X;
717
      if (conf.videoscale == 3)
718
          temp.rflags |= RF_3X;
719
      if (conf.videoscale == 4)
720
          temp.rflags |= RF_4X;
721
   } //Alone Coder
722
 
723
   set_video();
724
   calc_rsm_tables();
725
   video_timing_tables();
726
}
727
 
728
__inline unsigned char *raypointer()
729
{
730
   if (prev_t > conf.frame)
731
       return rbuf + rb2_offs;
732
   if (!vmode)
733
       return vcurr[1].screen_ptr;
734
   unsigned offs = (prev_t - vcurr[-1].next_t) / 4;
735
   return vcurr->screen_ptr + (offs+1) * 2;
736
}
737
 
738
__inline void clear_until_ray()
739
{
740
   unsigned char *dst = raypointer();
741
   while (dst < rbuf + rb2_offs) *dst++ = 0, *dst++ = 0x55;
742
}
743
 
744
void paint_scr(char alt) // alt=0/1 - main/alt screen, alt=2 - ray-painted
745
{
746
   if (alt == 2) {
747
      update_screen();
748
      clear_until_ray();
749
   } else {
750
      if (alt) comp.p7FFD ^= 8, set_banks();
751
      draw_screen();
752
      if (alt) comp.p7FFD ^= 8, set_banks();
753
   }
754
}
755
 
756
// Вызывается при записи в видеопамять/(порты FE/7FFD) нового значения
757
// Производит отрисовку бордюра/экрана в промежуточный буфер с использованием pc атрибутов
758
void update_screen()
759
{
760
   unsigned last_t = (cpu.t + temp.border_add) & temp.border_and;
761
   unsigned t = prev_t;
762
//   printf("upd_scr: t=%u, lt=%u, vm=%u\n", t, last_t, vmode);
763
   if (t >= last_t) // Невидимая часть строки (hblank либо невидимые строки верхнего бордюра)
764
       return;
765
 
766
   unsigned char b = comp.border_attr;
767
   b |= (b<<4); // Атрибуты бордюра дублируются в формате pc атрибутов ink=paper
768
 
769
   if (vmode == 1)
770
       goto mode1;
771
 
772
   if (vmode == 2)
773
       goto mode2;
774
 
775
mode0: // not visible
776
   {
777
      vmode = 1;
778
      t = vcurr->next_t; // Такт начала строки
779
      vcurr++; // Переход к концу строки
780
      if (t >= last_t)
781
      {
782
done:
783
          prev_t = t;
784
          return;
785
      }
786
   }
787
mode1: // border
788
   {
789
      unsigned offs = (t - vcurr[-1].next_t); // Смещение в тактах от начала строки (1 такт = 2 пикселя)
790
      unsigned char *ptr = vcurr->screen_ptr + offs/2; // Указатель на адрес точки в промежуточном буфере
791
//      u8 *pp =ptr;
792
      ptr = (unsigned char*)(ULONG_PTR(ptr) & ~ULONG_PTR(1)); // Выравание до четного адреса
793
      if(offs & 3)
794
      { // Есть пиксели не попадающие на границу знакоместа
795
         *ptr++ = ((unsigned)0xFF00 >> ((offs & 3)*2)); // Маска пикселей
796
         t += 4 -(offs & 3);
797
         *ptr = (*ptr & 0x0F) + (b & 0xF0); // Атрибуты
798
         ptr++;
799
      }
800
      unsigned end = min(vcurr->next_t, last_t);
801
//      printf("upd_scr_m1: o=%uT, p=%u, t=%uT, end=%uT\n", offs, pp - rbuf, t, end);
802
      for (; t < end; t+=4) // Обработка пикселей по знакоместам (по 8 точек)
803
      {
804
         *ptr++ = 0; // Пиксели не используются
805
         *ptr++ = b; // Атрибуты
806
      }
807
      t = end;
808
      if (t == vcurr->next_t)
809
      { // Строка закончилась,  переход к следующей точке
810
          vmode = vcurr->nextvmode;
811
          vcurr++;
812
      }
813
      if (t == last_t) // Отрисовка закончена, выход
814
          goto done;
815
 
816
      if (!vmode) // Начало следующей строки
817
          goto mode0;
818
   }
819
mode2: // screen
820
   {
821
      unsigned offs = (t - vcurr[-1].next_t)/4; // Смещение в знакоместах от начала строки (1 знакоместо = 4 такта = 8 пикселей)
822
      unsigned char *scr = temp.base + vcurr->scr_offs + offs; // spectrum пиксели
823
      unsigned char *atr = temp.base + vcurr->atr_offs + offs; // spectrum атрибуты
824
      unsigned char *ptr = vcurr->screen_ptr + offs*2; // Структура буфера 8pix:attr
825
      unsigned end = min(last_t, vcurr->next_t);
826
      for (int i = 0; t < end; t += 4, i++)
827
      {
828
         ptr[2*i] = scr[i]; // Копирование spectrum пикселей
829
         ptr[2*i+1] = colortab[atr[i]]; // Конвертирование spectrum атрибутов в pc атрибуты
830
      }
831
      t = end;
832
      if (t == vcurr->next_t)
833
      { // Центральная часть экрана закончилась, отрисовка правого бордюра
834
          vmode = 1; // border
835
          vcurr++;
836
      }
837
      if (t == last_t) // Отрисовка закончена, выход
838
          goto done;
839
      goto mode1; // Отрисовка правого бордюра
840
   }
841
}
842
 
843
void init_frame()
844
{
845
   // recreate colors with flash attribute
846
   unsigned char frame = (unsigned char)comp.frame_counter;
847
   if (!(frame & 15) /* && !conf.flashcolor */ )
848
       make_colortab(frame & 16);
849
 
850
   prev_t = -1; // block MCR
851
   temp.base_2 = 0; // block paper trace
852
 
853
   if (temp.vidblock)
854
       return;
855
 
856
/* [vv] Отключен, т.к. этот бит используется для DDp scroll
857
   // AlCo384 - no border/paper rendering
858
   if (comp.pEFF7 & EFF7_384)
859
       return;
860
*/
861
   // GIGASCREEN - no paper rendering
862
//   if (comp.pEFF7 & EFF7_GIGASCREEN) goto allow_border; //Alone Coder
863
 
864
   // disable multicolors, border still works
865
   if ((temp.rflags & RF_BORDER) || // chunk/etc filter
866
       (conf.mem_model == MM_PROFI && (comp.pDFFD & 0x80)) ||   // profi hires screen
867
       ((conf.mem_model == MM_ATM710 || conf.mem_model == MM_ATM3)&& (comp.pFF77 & 7) != 3) ||  // ATM-2 hires screen
868
       (conf.mem_model == MM_ATM450 && (comp.aFE & 0x60) != 0x60)) // ATM-1 hires screen
869
   {
870
       if ((conf.mem_model == MM_ATM710 || conf.mem_model == MM_ATM3))
871
       {
872
           // ATM2, один из расширенных видеорежимов
873
           AtmVideoCtrl.PrepareFrameATM2(comp.pFF77 & 7);
874
       }
875
 
876
       if (conf.mem_model == MM_ATM450)
877
       {
878
           // ATM1, один из расширенных видеорежимов
879
           AtmVideoCtrl.PrepareFrameATM1( (comp.aFE >> 5) & 3 );
880
 
881
       }
882
 
883
      // if border update disabled, dont show anything on zx-screen
884
      if (!conf.updateb)
885
          return;
886
   }
887
 
888
   // paper + border
889
   temp.base_2 = temp.base;
890
//allow_border:
891
   prev_t = vmode = 0;
892
   vcurr = video;
893
}
894
 
895
void flush_frame()
896
{
897
   if (temp.vidblock)
898
       return;
899
   if (prev_t != -1)
900
   { // MCR on
901
      if (prev_t)
902
      {  // paint until end of frame
903
         // paint until screen bottom, even if n_lines*t_line < cpu.t (=t_frame)
904
         unsigned t = cpu.t;
905
         cpu.t = 0x7FFF0000;
906
         update_screen();
907
         cpu.t = t;
908
//         if (comp.pEFF7 & EFF7_GIGASCREEN) draw_gigascreen_no_border(); //Alone Coder
909
      }
910
      else
911
      { // MCR on, but no screen updates in last frame - use fast painter
912
         if (temp.base_2 /*|| (comp.pEFF7 & EFF7_GIGASCREEN)*/ /*Alone Coder*/)
913
             draw_screen();
914
         else
915
             draw_border();
916
      }
917
      return;
918
   }
919
   if (comp.pEFF7 & EFF7_384)
920
       draw_alco();
921
}
922
 
923
void load_spec_colors()
924
{
925
   // spectrum colors -> palette indexes (RF_PALB - gg0rr0bb format)
926
   static unsigned char comp_pal[16] =
927
      { 0x00, 0x02, 0x10, 0x12, 0x80, 0x82, 0x90, 0x92,
928
        0x00, 0x03, 0x18, 0x1B, 0xC0, 0xC3, 0xD8, 0xDB };
929
   memcpy(comp.comp_pal, comp_pal, sizeof comp.comp_pal);
930
   temp.comp_pal_changed = 1;
931
}