Subversion Repositories pentevo

Rev

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

Rev Author Line No. Line
716 lvd 1
#include "std.h"
2
 
3
#include "resource.h"
4
#include "emul.h"
5
#include "vars.h"
6
#include "snapshot.h"
7
#include "tape.h"
8
#include "memory.h"
9
#include "opendlg.h"
10
#include "draw.h"
11
#include "config.h"
12
#include "z80.h"
13
#include "sshot_png.h"
796 DimkaM 14
#include "funcs.h"
716 lvd 15
 
16
#include "util.h"
17
 
18
int readSP();
19
int readSNA48();
20
int readSNA128();
21
int readZ80();
22
int writeSNA(FILE*);
23
 
24
int load_arc(char *fname);
25
 
796 DimkaM 26
SNAP what_is(char *filename)
716 lvd 27
{
28
   FILE *ff = fopen(filename, "rb");
29
   if (!ff) return snNOFILE;
796 DimkaM 30
   snapsize = unsigned(fread(snbuf, 1, sizeof snbuf, ff));
716 lvd 31
   fclose(ff);
32
   if (snapsize == sizeof snbuf) return snTOOLARGE;
796 DimkaM 33
   SNAP type = snUNKNOWN;
716 lvd 34
   char *ptr = strrchr(filename, '.');
796 DimkaM 35
   unsigned ext = ptr? (*(unsigned*)(ptr+1) | 0x20202020U) : 0;
716 lvd 36
   if (snapsize < 32) return type;
37
 
38
   if (snapsize == 131103 || snapsize == 147487) type = snSNA_128;
39
   if (snapsize == 49179) type = snSNA_48;
40
   if (ext == WORD4('t','a','p',' ')) type = snTAP;
41
   if (ext == WORD4('z','8','0',' ')) type = snZ80;
796 DimkaM 42
   if(ext == WORD4('p', 'a', 'l', ' ') && (snapsize == sizeof(comp.comp_pal)))
43
   {
44
       type = snPAL;
45
       return type;
46
   }
716 lvd 47
   if (conf.trdos_present)
48
   {
49
      if (!snbuf[13] && snbuf[14] && (int)snapsize == snbuf[14]*256+17) type = snHOB;
50
      if (snapsize >= 8192 && !(snapsize & 0xFF) && ext == WORD4('t','r','d',' ')) type = snTRD;
51
 
52
      if (snapsize >= 8192 && ext == WORD4('i','s','d',' '))
53
          type = snISD;
54
 
55
      if (snapsize >= 8192 && ext == WORD4('p','r','o',' '))
56
          type = snPRO;
57
 
800 DimkaM 58
      if(snapsize >= 8192 && ext == WORD4('d', 's', 'k', ' '))
59
          type = snDSK;
60
 
61
      if(snapsize >= 8192 && ext == WORD4('i', 'p', 'f', ' '))
62
          type = snIPF;
63
 
716 lvd 64
      if (!memcmp(snbuf, "SINCLAIR", 8))
65
      {
66
          unsigned nfiles = snbuf[8];
67
          unsigned nsec = 0;
68
          for(unsigned i = 0; i < nfiles; i++)
69
          {
70
              nsec += snbuf[9+14*i+13];
71
          }
72
 
73
          if(snapsize >= 9 + nfiles * 14 + nsec * 0x100)
74
              type = snSCL;
75
      }
76
      if (!memcmp(snbuf, "FDI", 3) && *(unsigned short*)(snbuf+4) <= MAX_CYLS && *(unsigned short*)(snbuf+6) <= 2) type = snFDI;
77
      if (((*(short*)snbuf|0x2020) == WORD2('t','d')) && snbuf[4] >= 10 && snbuf[4] <= 21 && snbuf[9] <= 2) type = snTD0;
78
      if (*(unsigned*)snbuf == WORD4('U','D','I','!') && *(unsigned*)(snbuf+4)==snapsize-4 && snbuf[9] < MAX_CYLS && snbuf[10]<2 && !snbuf[8]) type = snUDI;
79
   }
80
   if (snapsize > 10 && !memcmp(snbuf, "ZXTape!\x1A", 8))
81
   {
82
       type = snTZX;
83
   }
84
   if (snapsize > 0x22 && !memcmp(snbuf, "Compressed Square Wave\x1A", 23)) type = snCSW;
85
   if (*(unsigned short*)snbuf == WORD2('S','P') && *(unsigned short*)(snbuf+2)+0x26 == (int)snapsize) type = snSP;
86
   return type;
87
}
88
 
796 DimkaM 89
static int readPAL();
90
 
716 lvd 91
int loadsnap(char *filename)
92
{
93
   if (load_arc(filename))
94
       return 1;
796 DimkaM 95
   SNAP type = what_is(filename);
716 lvd 96
 
97
   if (type >= snHOB)
98
   {
99
 
796 DimkaM 100
      if (trd_toload == -1U)
716 lvd 101
      {
796 DimkaM 102
         unsigned last = -1U;
103
         for (unsigned i = 0; i < 4; i++) if (trd_loaded[i]) last = i;
104
         trd_toload = (last == -1U)? 0 : ((type == snHOB)? last : (last+1) & 3);
716 lvd 105
      }
106
 
107
      for (unsigned k = 0; k < 4; k++)
108
      {
800 DimkaM 109
         if (k != trd_toload && !stricmp(comp.fdd[k].name, filename))
716 lvd 110
         {
111
            static char err[] = "This disk image is already loaded to drive X:\n"
112
                                "Do you still want to load it to drive Y:?";
796 DimkaM 113
            err[43] = char(k+'A');
114
            err[84] = char(trd_toload+'A');
716 lvd 115
            if (MessageBox(GetForegroundWindow(), err, "Warning", MB_YESNO | MB_ICONWARNING) == IDNO) return 1;
116
         }
117
      }
118
 
800 DimkaM 119
      FDD *drive = comp.fdd + trd_toload;
716 lvd 120
      if (!drive->test())
121
          return 0;
796 DimkaM 122
      comp.wd.Eject(trd_toload);
716 lvd 123
      int ok = drive->read(type);
124
      if (ok)
125
      {
126
         if (*conf.appendboot)
127
             drive->addboot();
128
         strcpy(drive->name, filename);
129
         if (GetFileAttributes(filename) & FILE_ATTRIBUTE_READONLY)
130
            conf.trdos_wp[trd_toload] = 1;
131
         drive->snaptype = (type == snHOB || type == snSCL)? snTRD : type;
132
         trd_loaded[trd_toload] = 1;
133
//---------Alone Coder
134
         char *name = filename;
135
         for (char *x = name; *x; x++)
136
             if (*x == '\\') name = x+1;
137
         strcpy(temp.LastSnapName, name);
138
         char *p = strrchr(temp.LastSnapName, '.');
139
         if(p)
140
         {
141
             *p = 0;
142
         }
143
         char wintitle[0x200];
144
         strcpy(wintitle,name);
145
         strcat(wintitle," - UnrealSpeccy");
146
         SetWindowText(wnd, wintitle);
147
//~---------Alone Coder
148
      }
149
      return ok;
150
   }
151
 
152
   if (type == snSP) return readSP();
153
   if (type == snSNA_48) return readSNA48();
154
   if (type == snSNA_128) return readSNA128();
155
   if (type == snZ80) return readZ80();
156
   if (type == snTAP) return readTAP();
157
   if (type == snTZX) return readTZX();
158
   if (type == snCSW) return readCSW();
796 DimkaM 159
   if(type == snPAL)
160
   {
161
       return readPAL();
162
   }
716 lvd 163
 
164
   return 0;
165
}
166
 
167
int readSNA128()
168
{
169
   if(conf.mem_model == MM_PENTAGON && conf.Sna128Lock)
170
   {
171
       conf.ramsize = 128;
796 DimkaM 172
       temp.ram_mask = u8((conf.ramsize-1) >> 4);
716 lvd 173
   }
174
 
175
   hdrSNA128 *hdr = (hdrSNA128*)snbuf;
176
   reset(hdr->trdos? RM_DOS : RM_SOS);
177
   cpu.alt.af = hdr->altaf;
178
   cpu.alt.bc = hdr->altbc;
179
   cpu.alt.de = hdr->altde;
180
   cpu.alt.hl = hdr->althl;
181
   cpu.af = hdr->af;
182
   cpu.bc = hdr->bc;
183
   cpu.de = hdr->de;
184
   cpu.hl = hdr->hl;
185
   cpu.ix = hdr->ix;
186
   cpu.iy = hdr->iy;
187
   cpu.sp = hdr->sp;
188
   cpu.pc = hdr->pc;
189
   cpu.i = hdr->i;
190
   cpu.r_low = hdr->r;
191
   cpu.r_hi = hdr->r & 0x80;
192
   cpu.im = hdr->im;
193
   cpu.iff1 = cpu.iff2 = (hdr->iff >> 2) & 1;
194
   comp.p7FFD = hdr->p7FFD;
195
   comp.pFE = hdr->pFE;
196
   comp.border_attr = comp.pFE & 7;
197
   memcpy(memory+PAGE*5, hdr->page5, PAGE);
198
   memcpy(memory+PAGE*2, hdr->page2, PAGE);
199
   memcpy(memory+PAGE*(hdr->p7FFD & 7), hdr->active_page, PAGE);
200
   unsigned char *newpage = snbuf+0xC01F;
796 DimkaM 201
   unsigned char mapped = u8(0x24U | (1 << (hdr->p7FFD & 7)));
716 lvd 202
   for (unsigned char i = 0; i < 8; i++)
203
   {
204
      if (!(mapped & (1 << i)))
205
      {
206
         memcpy(memory + PAGE*i, newpage, PAGE);
207
         newpage += PAGE;
208
      }
209
   }
210
   set_banks();
211
   return 1;
212
}
213
 
214
int readSNA48()
215
{
216
   //conf.mem_model = MM_PENTAGON; conf.ramsize = 128;  // molodcov_alex
217
   reset(RM_SOS);
218
   hdrSNA128 *hdr = (hdrSNA128*)snbuf;
219
   cpu.alt.af = hdr->altaf; cpu.alt.bc = hdr->altbc;
220
   cpu.alt.de = hdr->altde; cpu.alt.hl = hdr->althl;
221
   cpu.af = hdr->af; cpu.bc = hdr->bc; cpu.de = hdr->de; cpu.hl = hdr->hl;
222
   cpu.ix = hdr->ix; cpu.iy = hdr->iy; cpu.sp = hdr->sp;
223
   cpu.i = hdr->i; cpu.r_low = hdr->r; cpu.r_hi = hdr->r & 0x80; cpu.im = hdr->im;
224
   cpu.iff1 = cpu.iff2 = (hdr->iff >> 2) & 1; comp.p7FFD = 0x30;
225
   comp.pEFF7 |= EFF7_LOCKMEM; //Alone Coder
226
   comp.pFE = hdr->pFE; comp.border_attr = comp.pFE & 7;
227
   memcpy(memory+PAGE*5, hdr->page5, PAGE);
228
   memcpy(memory+PAGE*2, hdr->page2, PAGE);
229
   memcpy(memory+PAGE*0, hdr->active_page, PAGE);
230
   cpu.pc = cpu.DirectRm(cpu.sp)+0x100*cpu.DirectRm(cpu.sp+1); cpu.sp += 2;
231
   set_banks(); return 1;
232
}
233
 
234
int readSP()
235
{
236
   //conf.mem_model = MM_PENTAGON; conf.ramsize = 128;  // molodcov_alex
237
   reset(RM_SOS);
238
   hdrSP *hdr = (hdrSP*)snbuf;
239
   cpu.alt.af = hdr->altaf; cpu.alt.bc = hdr->altbc;
240
   cpu.alt.de = hdr->altde; cpu.alt.hl = hdr->althl;
241
   cpu.af = hdr->af; cpu.bc = hdr->bc; cpu.de = hdr->de; cpu.hl = hdr->hl;
242
   cpu.ix = hdr->ix; cpu.iy = hdr->iy; cpu.sp = hdr->sp; cpu.pc = hdr->pc;
243
   cpu.i = hdr->i; cpu.r_low = hdr->r; cpu.r_hi = hdr->r & 0x80;
244
   cpu.iff1 = (hdr->flags & 1);
245
   cpu.im = 1 + ((hdr->flags >> 1) & 1);
246
   cpu.iff2 = (hdr->flags >> 2) & 1;
247
   comp.p7FFD = 0x30;
248
   comp.pEFF7 |= EFF7_LOCKMEM; //Alone Coder
249
   comp.pFE = hdr->pFE; comp.border_attr = comp.pFE & 7;
250
   for (unsigned i = 0; i < hdr->len; i++)
251
      cpu.DirectWm(hdr->start + i, snbuf[i + 0x26]);
252
   set_banks(); return 1;
253
}
254
 
255
int writeSNA(FILE *ff)
256
{
257
/*   if (conf.ramsize != 128) {
258
      MessageBox(GetForegroundWindow(), "SNA format can hold only\r\n128kb memory models", "Save", MB_ICONERROR);
259
      return 0;
260
   }*/ //Alone Coder
261
   hdrSNA128 *hdr = (hdrSNA128*)snbuf;
262
   hdr->trdos = (comp.flags & CF_TRDOS)? 1 : 0;
796 DimkaM 263
   hdr->altaf = u16(cpu.alt.af); hdr->altbc = u16(cpu.alt.bc);
264
   hdr->altde = u16(cpu.alt.de); hdr->althl = u16(cpu.alt.hl);
265
   hdr->af = u16(cpu.af); hdr->bc = u16(cpu.bc); hdr->de = u16(cpu.de); hdr->hl = u16(cpu.hl);
266
   hdr->ix = u16(cpu.ix); hdr->iy = u16(cpu.iy); hdr->sp = u16(cpu.sp); hdr->pc = u16(cpu.pc);
716 lvd 267
   hdr->i = cpu.i; hdr->r = (cpu.r_low & 0x7F)+cpu.r_hi; hdr->im = cpu.im;
268
   hdr->iff = cpu.iff2 ? 4 : 0;
269
   hdr->p7FFD = comp.p7FFD;
270
   hdr->pFE = comp.pFE; comp.border_attr = comp.pFE & 7;
271
   unsigned savesize = sizeof(hdrSNA128);
796 DimkaM 272
   unsigned char mapped = u8(0x24U | (1 << (comp.p7FFD & 7)));
716 lvd 273
   if (comp.p7FFD == 0x30)
274
   { // save 48k
275
      mapped = 0xFF;
276
      savesize = 0xC01B;
277
      hdr->sp -= 2;
278
      cpu.DirectWm(hdr->sp, cpu.pcl);
279
      cpu.DirectWm(hdr->sp+1, cpu.pch);
280
   }
281
   memcpy(hdr->page5, memory+PAGE*5, PAGE);
282
   memcpy(hdr->page2, memory+PAGE*2, PAGE);
283
   memcpy(hdr->active_page, memory+PAGE*(comp.p7FFD & 7), PAGE);
284
   if (fwrite(hdr, 1, savesize, ff) != savesize) return 0;
285
   for (unsigned char i = 0; i < 8; i++)
286
      if (!(mapped & (1 << i))) {
287
         if (fwrite(memory + PAGE*i, 1, PAGE, ff) != PAGE) return 0;
288
      }
289
   return 1;
290
}
291
 
796 DimkaM 292
static void unpack_page(unsigned char *dst, unsigned dstlen, unsigned char *src, unsigned srclen)
716 lvd 293
{
294
   memset(dst, 0, dstlen);
796 DimkaM 295
   while (srclen > 0 && dstlen > 0)
296
   {
297
      if (srclen >= 4 && src[0] == 0xED && src[1] == 0xED)
298
      {
299
         size_t len = src[2];
300
         memset(dst, src[3], len);
301
         dstlen -= len;
302
         srclen -= 4;
303
         src += 4;
304
         dst += len;
305
      }
306
      else
307
      {
308
          *dst++ = *src++;
309
          dstlen--;
310
          srclen--;
311
      }
716 lvd 312
   }
313
}
314
 
315
int readZ80()
316
{
317
   //conf.mem_model = MM_PENTAGON; conf.ramsize = 128;  // molodcov_alex
318
   hdrZ80 *hdr = (hdrZ80*)snbuf;
319
   unsigned char *ptr = snbuf + 30;
320
   unsigned char model48k = (hdr->model < 3);
321
   reset((model48k|(hdr->p7FFD & 0x10)) ? RM_SOS : RM_128);
322
   if (hdr->flags == 0xFF)
323
       hdr->flags = 1;
324
   if (hdr->pc == 0)
325
   { // 2.01
326
      ptr += 2 + hdr->len;
327
      hdr->pc = hdr->newpc;
328
      memset(RAM_BASE_M, 0, PAGE*8); // clear 128k - first 8 pages
329
 
796 DimkaM 330
      unsigned char * const p48[] =
331
      {
332
             base_sos_rom, nullptr, nullptr, nullptr,
333
             RAM_BASE_M+2*PAGE, RAM_BASE_M+0*PAGE, nullptr, nullptr,
334
             RAM_BASE_M+5*PAGE, nullptr, nullptr, nullptr
335
      };
336
      unsigned char * const p128[] =
337
      {
338
             base_sos_rom, base_dos_rom, base_128_rom, RAM_BASE_M+0*PAGE,
339
             RAM_BASE_M+1*PAGE, RAM_BASE_M+2*PAGE, RAM_BASE_M+3*PAGE, RAM_BASE_M+4*PAGE,
340
             RAM_BASE_M+5*PAGE, RAM_BASE_M+6*PAGE, RAM_BASE_M+7*PAGE, nullptr
341
      };
342
 
716 lvd 343
      while (ptr < snbuf+snapsize)
344
      {
345
         unsigned len = *(unsigned short*)ptr;
346
         if (ptr[2] > 11)
347
             return 0;
348
         unsigned char *dstpage = model48k ? p48[ptr[2]] : p128[ptr[2]];
349
         if (!dstpage)
350
             return 0;
351
         ptr += 3;
352
         if (len == 0xFFFF)
796 DimkaM 353
         {
354
             len = PAGE;
355
             memcpy(dstpage, ptr, len);
356
         }
716 lvd 357
         else
358
             unpack_page(dstpage, PAGE, ptr, len);
359
         ptr += len;
360
      }
361
   }
362
   else
363
   {
796 DimkaM 364
      unsigned len = snapsize - 30;
716 lvd 365
      unsigned char *mem48 = ptr;
366
      if (hdr->flags & 0x20)
367
         unpack_page(mem48 = snbuf + 4*PAGE, 3*PAGE, ptr, len);
368
      memcpy(memory + PAGE*5, mem48, PAGE);
369
      memcpy(memory + PAGE*2, mem48 + PAGE, PAGE);
370
      memcpy(memory + PAGE*0, mem48 + 2*PAGE, PAGE);
371
      model48k = 1;
372
   }
796 DimkaM 373
   cpu.a = hdr->a; cpu.f = hdr->f;
374
   cpu.bc = hdr->bc; cpu.de = hdr->de; cpu.hl = hdr->hl;
375
   cpu.alt.bc = hdr->bc1; cpu.alt.de = hdr->de1; cpu.alt.hl = hdr->hl1;
376
   cpu.alt.a = hdr->a1; cpu.alt.f = hdr->f1;
377
   cpu.pc = hdr->pc; cpu.sp = hdr->sp; cpu.ix = hdr->ix; cpu.iy = hdr->iy;
378
   cpu.i = hdr->i; cpu.r_low = hdr->r & 0x7F;
379
   cpu.r_hi = u8((hdr->flags & 1U) << 7U);
716 lvd 380
   comp.pFE = (hdr->flags >> 1) & 7;
381
   comp.border_attr = comp.pFE;
796 DimkaM 382
   cpu.iff1 = hdr->iff1; cpu.iff2 = hdr->iff2; cpu.im = (hdr->im & 3);
716 lvd 383
   comp.p7FFD = (model48k) ? 0x30 : hdr->p7FFD;
384
 
385
   if(hdr->len == 55) // version 3.0 (with 1ffd)
386
       comp.p1FFD = hdr->p1FFD;
387
 
388
   if (model48k)
389
       comp.pEFF7 |= EFF7_LOCKMEM; //Alone Coder
796 DimkaM 390
 
716 lvd 391
   set_banks();
392
 
393
   return 1;
394
}
395
 
796 DimkaM 396
static int readPAL()
397
{
398
    memcpy(comp.comp_pal, snbuf, snapsize);
399
    temp.comp_pal_changed = 1;
400
    if(conf.ula_plus)
401
    {
402
        comp.ula_plus_en = true; // ���� ������������ ULA+, �� ����� � ���������� �� (����� ��������� ������� ���� �����)
403
    }
404
    return 1;
405
}
406
 
407
static int writePAL(FILE *ff)
408
{
409
    if(fwrite(comp.comp_pal, 1, sizeof(comp.comp_pal), ff) != sizeof(comp.comp_pal))
410
    {
411
        return 0;
412
    }
413
    return 1;
414
}
415
 
716 lvd 416
#define arctmp ((char*)rbuf)
796 DimkaM 417
static char *arc_fname;
418
static INT_PTR CALLBACK ArcDlg(HWND dlg, UINT msg, WPARAM wp, LPARAM lp)
716 lvd 419
{
796 DimkaM 420
   (void)lp;
421
 
716 lvd 422
   if (msg == WM_INITDIALOG) {
423
      for (char *dst = arctmp; *dst; dst += strlen(dst)+1)
424
         SendDlgItemMessage(dlg, IDC_ARCLIST, LB_ADDSTRING, 0, (LPARAM)dst);
425
      SendDlgItemMessage(dlg, IDC_ARCLIST, LB_SETCURSEL, 0, 0);
426
      return 1;
427
   }
428
   if ((msg == WM_COMMAND && wp == IDCANCEL) ||
429
       (msg == WM_SYSCOMMAND && (wp & 0xFFF0) == SC_CLOSE)) EndDialog(dlg, 0);
430
   if (msg == WM_COMMAND && (LOWORD(wp) == IDOK || (HIWORD(wp)==LBN_DBLCLK && LOWORD(wp) == IDC_ARCLIST)))
431
   {
796 DimkaM 432
      int n = int(SendDlgItemMessage(dlg, IDC_ARCLIST, LB_GETCURSEL, 0, 0));
716 lvd 433
      char *dst = arctmp;
434
      for (int q = 0; q < n; q++) dst += strlen(dst)+1;
435
      arc_fname = dst;
436
      EndDialog(dlg, 0);
437
   }
438
   return 0;
439
}
440
 
796 DimkaM 441
static bool filename_ok(char *fname)
716 lvd 442
{
443
   for (char *wc = skiparc; *wc; wc += strlen(wc)+1)
444
      if (wcmatch(fname, wc)) return 0;
445
   return 1;
446
}
447
 
448
int load_arc(char *fname)
449
{
450
   char *ext = strrchr(fname, '.'); if (!ext) return 0;
451
   ext++;
796 DimkaM 452
   char *cmdtmp;
453
   char done = 0;
716 lvd 454
   for (char *x = arcbuffer; *x; x = cmdtmp + strlen(cmdtmp)+1) {
455
      cmdtmp = x + strlen(x)+1;
456
      if (stricmp(ext, x)) continue;
457
 
458
      char dir[0x200]; GetCurrentDirectory(sizeof dir, dir);
459
      char tmp[0x200]; GetTempPath(sizeof tmp, tmp);
460
      char d1[0x20]; sprintf(d1, "us%08lX", GetTickCount());
461
      SetCurrentDirectory(tmp);
796 DimkaM 462
      CreateDirectory(d1, nullptr);
716 lvd 463
      SetCurrentDirectory(d1);
464
 
465
      color();
466
      char cmdln[0x200]; sprintf(cmdln, cmdtmp, fname);
467
      STARTUPINFO si = { sizeof si };
468
      si.dwFlags = STARTF_USESHOWWINDOW; si.wShowWindow = SW_HIDE;
469
      PROCESS_INFORMATION pi;
470
      unsigned flags = CREATE_NEW_CONSOLE;
796 DimkaM 471
      HANDLE hc = CreateFile("CONOUT$", GENERIC_WRITE, FILE_SHARE_READ|FILE_SHARE_WRITE, nullptr, OPEN_EXISTING, 0, nullptr);
472
      if(hc != INVALID_HANDLE_VALUE)
473
      {
474
          CloseHandle(hc);
475
          flags = 0;
476
      }
477
      if (CreateProcess(nullptr, cmdln, nullptr, nullptr, 0, flags, nullptr, nullptr, &si, &pi)) {
716 lvd 478
         WaitForSingleObject(pi.hProcess, INFINITE);
479
         DWORD code; GetExitCodeProcess(pi.hProcess, &code);
480
         CloseHandle(pi.hThread);
481
         CloseHandle(pi.hProcess);
796 DimkaM 482
         if (!code || MessageBox(GetForegroundWindow(), "Broken archive", nullptr, MB_ICONERROR | MB_OKCANCEL) == IDOK) {
716 lvd 483
            WIN32_FIND_DATA fd; HANDLE h;
484
            char *dst = arctmp; unsigned nfiles = 0;
485
            if ((h = FindFirstFile("*.*", &fd)) != INVALID_HANDLE_VALUE) {
486
               do {
487
                  if (!(fd.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) && filename_ok(fd.cFileName)) {
488
                     strcpy(dst, fd.cFileName); dst += strlen(dst)+1;
489
                     nfiles++;
490
                  }
491
               } while (FindNextFile(h, &fd));
492
               FindClose(h);
493
            }
796 DimkaM 494
            *dst = 0; arc_fname = nullptr;
716 lvd 495
            if (nfiles == 1) arc_fname = arctmp;
496
            if (nfiles > 1)
497
                DialogBox(hIn, MAKEINTRESOURCE(IDD_ARC), GetForegroundWindow(), ArcDlg);
796 DimkaM 498
            if (!nfiles) MessageBox(GetForegroundWindow(), "Empty archive!", nullptr, MB_ICONERROR | MB_OK);
716 lvd 499
            char buf[0x200]; strcpy(buf, tmp); strcat(buf, "\\");
796 DimkaM 500
            strcat(buf, d1);
501
            strcat(buf, "\\");
502
            if(arc_fname)
503
            {
504
                strcat(buf, arc_fname);
505
                arc_fname = buf;
506
            }
507
            if (arc_fname && !(done = (char)loadsnap(arc_fname))) MessageBox(GetForegroundWindow(), "loading error", arc_fname, MB_ICONERROR);
716 lvd 508
            if (!done) done = -1;
509
         }
510
         // delete junk
511
         SetCurrentDirectory(tmp);
512
         SetCurrentDirectory(d1);
513
         WIN32_FIND_DATA fd; HANDLE h;
514
         if ((h = FindFirstFile("*.*", &fd)) != INVALID_HANDLE_VALUE) {
515
            do { DeleteFile(fd.cFileName); } while (FindNextFile(h, &fd));
516
            FindClose(h);
517
         }
518
      }
519
      SetCurrentDirectory(tmp);
520
      RemoveDirectory(d1);
521
      SetCurrentDirectory(dir);
522
      eat(); if (done) return done > 0 ? 1 : 0;
523
   }
524
   eat(); return 0;
525
}
526
 
796 DimkaM 527
void opensnap(unsigned index)
716 lvd 528
{
529
   char mask[0x200]; *mask = 0;
796 DimkaM 530
   for(char *x = arcbuffer; *x; )
531
   {
532
       strcat(mask, ";*.");
533
       strcat(mask, x);
534
       x += strlen(x) + 1;
535
       x += strlen(x) + 1;
536
   }
716 lvd 537
 
538
   char fline[0x400];
800 DimkaM 539
   const char *src = "all (sna,z80,sp,tap,tzx,csw,trd,scl,fdi,td0,udi,isd,pro,dsk,ipf,hobeta,pal)\0"
540
               "*.sna;*.z80;*.sp;*.tap;*.tzx;*.csw;*.trd;*.scl;*.td0;*.udi;*.fdi;*.isd;*.pro;*.dsk;*.ipf;*.$?;*.!?;*.pal<\0"
541
               "Disk B (trd,scl,fdi,td0,udi,isd,pro,dsk,ipf,hobeta)\0*.trd;*.scl;*.fdi;*.udi;*.td0;*.isd;*.pro;*.dsk;*.ipf;*.$?<\0"
542
               "Disk C (trd,scl,fdi,td0,udi,isd,pro,dsk,ipf,hobeta)\0*.trd;*.scl;*.fdi;*.udi;*.td0;*.isd;*.pro;*.dsk;*.ipf;*.$?<\0"
543
               "Disk D (trd,scl,fdi,td0,udi,isd,pro,dsk,ipf,hobeta)\0*.trd;*.scl;*.fdi;*.udi;*.td0;*.isd;*.pro;*.dsk;*.ipf;*.$?<\0\0>";
716 lvd 544
   if (!conf.trdos_present)
796 DimkaM 545
      src = "ZX files (sna,z80,tap,tzx,csw,pal)\0*.sna;*.z80;*.tap;*.tzx;*.csw;*.pal<\0\0>";
546
   for(char *dst = fline; *src != '>'; src++)
547
   {
548
       if(*src == '<')
549
       {
550
           strcpy(dst, mask);
551
           dst += strlen(dst);
552
       }
553
       else
554
       {
555
           *dst++ = *src;
556
       }
557
   }
716 lvd 558
 
796 DimkaM 559
   OPENFILENAME ofn = { };
716 lvd 560
   char fname[0x200]; *fname = 0;
561
   char dir[0x200]; GetCurrentDirectory(sizeof dir, dir);
562
 
563
   ofn.lStructSize = (WinVerMajor < 5) ? OPENFILENAME_SIZE_VERSION_400 : sizeof(OPENFILENAME);
564
   ofn.hwndOwner = GetForegroundWindow();
565
   ofn.lpstrFilter = fline;
566
   ofn.lpstrFile = fname; ofn.nMaxFile = sizeof fname;
567
   ofn.lpstrTitle = "Load Snapshot / Disk / Tape";
568
   ofn.Flags = OFN_FILEMUSTEXIST | OFN_HIDEREADONLY;
796 DimkaM 569
   ofn.nFilterIndex = DWORD(index);
716 lvd 570
   ofn.lpstrInitialDir = dir;
571
//   __debugbreak();
572
   if (GetSnapshotFileName(&ofn, 0))
573
   {
574
      trd_toload = ofn.nFilterIndex-1;
575
      if (!loadsnap(fname))
576
          MessageBox(GetForegroundWindow(), fname, "loading error", MB_ICONERROR);
577
   }
578
   eat();
579
}
580
 
796 DimkaM 581
static const int mx_typs = (1+4*6);
582
static unsigned char snaps[mx_typs];
583
static unsigned exts[mx_typs];
584
static unsigned drvs[mx_typs];
585
static unsigned snp;
716 lvd 586
static void addref(LPSTR &ptr, unsigned char sntype, const char *ref, unsigned drv, unsigned ext)
587
{
588
   strcpy(ptr, ref); ptr += strlen(ptr)+1;
589
   strcpy(ptr, ref+strlen(ref)+1); ptr += strlen(ptr)+1;
590
   drvs[snp] = drv; exts[snp] = ext; snaps[snp++] = sntype;
591
}
592
 
593
void savesnap(int diskindex)
594
{
595
again:
796 DimkaM 596
   OPENFILENAME ofn = { };
716 lvd 597
   char fname[0x200]; *fname = 0;
598
   if (diskindex >= 0) {
800 DimkaM 599
      strcpy(fname, comp.fdd[diskindex].name);
796 DimkaM 600
      size_t ln = strlen(fname);
716 lvd 601
      if (ln > 4 && (*(unsigned*)(fname+ln-4) | WORD4(0,0x20,0x20,0x20)) == WORD4('.','s','c','l'))
602
         *(unsigned*)(fname+ln-4) = WORD4('.','t','r','d');
603
   }
604
 
605
   snp = 1; char types[600], *ptr = types;
606
 
607
   if (diskindex < 0)
608
   {
609
      exts[snp] = WORD4('s','n','a',0); snaps[snp] = snSNA_128; // default
796 DimkaM 610
      addref(ptr, snSNA_128, "ZX-Spectrum 128K snapshot (SNA)\0*.sna", -1U, WORD4('s','n','a',0));
611
 
612
      exts[snp] = WORD4('p', 'a', 'l', 0); snaps[snp] = snPAL;
613
      addref(ptr, snPAL, "Palette (ULA+)\0*.pal", -1U, WORD4('p', 'a', 'l', 0));
716 lvd 614
   }
615
 
616
   ofn.lStructSize = (WinVerMajor < 5) ? OPENFILENAME_SIZE_VERSION_400 : sizeof(OPENFILENAME);
617
   ofn.nFilterIndex = 1;
618
 
619
   if (conf.trdos_present)
620
   {
621
      static char mask[] = "Disk A (TRD)\0*.trd";
622
      static const char ex[][3] = { {'T','R','D'}, {'F','D','I'},{'T','D','0'},{'U','D','I'},{'I','S','D'},{'P','R','O'}};
623
      static const unsigned ex2[] = { snTRD, snFDI, snTD0, snUDI, snISD, snPRO };
624
 
796 DimkaM 625
      for (unsigned n = 0; n < 4; n++)
716 lvd 626
      {
800 DimkaM 627
         if (!comp.fdd[n].rawdata)
716 lvd 628
             continue;
796 DimkaM 629
         if (diskindex >= 0 && unsigned(diskindex) != n)
716 lvd 630
             continue;
796 DimkaM 631
         mask[5] = char('A'+n);
716 lvd 632
 
796 DimkaM 633
         for (size_t i = 0; i < sizeof ex/sizeof(ex[0]); i++)
716 lvd 634
         {
800 DimkaM 635
            if (unsigned(diskindex) == n && ex2[i] == comp.fdd[n].snaptype)
716 lvd 636
                ofn.nFilterIndex = snp;
637
            memcpy(mask+8, ex[i], 3);
638
            memcpy(mask+15, ex[i], 3);
796 DimkaM 639
            addref(ptr, u8(ex2[i]), mask, n, (*(const unsigned*)ex[i] & 0xFFFFFF) | 0x202020);
716 lvd 640
         }
641
      }
642
   }
643
   ofn.lpstrFilter = types; *ptr = 0;
644
   ofn.lpstrFile = fname; ofn.nMaxFile = sizeof fname;
645
   ofn.Flags = OFN_PATHMUSTEXIST | OFN_HIDEREADONLY;
646
   ofn.hwndOwner = GetForegroundWindow();
647
   char *path = strrchr(fname, '\\');
648
   if (path)
649
   { // check if directory exists (for files opened from archive)
650
      char x = *path; *path = 0;
651
      unsigned atr = GetFileAttributes(fname); *path = x;
796 DimkaM 652
      if (atr == -1U || !(atr & FILE_ATTRIBUTE_DIRECTORY)) *fname = 0;
716 lvd 653
   } else path = fname;
654
   path = strrchr(path, '.'); if (path) *path = 0; // delete extension
655
 
656
   if (GetSnapshotFileName(&ofn, 1))
657
   {
658
      char *fn = strrchr(ofn.lpstrFile, '\\');
659
      fn = fn? fn+1 : ofn.lpstrFile;
660
      char *extpos = strrchr(fn, '.');
661
      if (!extpos || stricmp(extpos+1, (char*)&exts[ofn.nFilterIndex]))
662
      {
663
         char *dst = fn + strlen(fn); *dst++ = '.';
664
         *(unsigned*)dst = exts[ofn.nFilterIndex];
665
      }
796 DimkaM 666
      if (GetFileAttributes(ofn.lpstrFile) != INVALID_FILE_ATTRIBUTES &&
716 lvd 667
            IDNO == MessageBox(GetForegroundWindow(), "File exists. Overwrite ?", "Save", MB_ICONQUESTION | MB_YESNO))
668
         goto again;
669
 
670
      FILE *ff = fopen(ofn.lpstrFile, "wb");
671
      if (ff)
672
      {
673
         int res = 0;
800 DimkaM 674
         FDD *saveto = comp.fdd + drvs[ofn.nFilterIndex];
716 lvd 675
         switch (snaps[ofn.nFilterIndex])
676
         {
677
            case snSNA_128: res = writeSNA(ff); break;
796 DimkaM 678
            case snPAL: res = writePAL(ff); break;
716 lvd 679
            case snTRD: res = saveto->write_trd(ff); break;
680
            case snUDI: res = saveto->write_udi(ff); break;
681
            case snFDI: res = saveto->write_fdi(ff); break;
682
            case snTD0: res = saveto->write_td0(ff); break;
683
            case snISD: res = saveto->write_isd(ff); break;
684
            case snPRO: res = saveto->write_pro(ff); break;
685
         }
686
         fclose(ff);
687
         if (!res)
688
             MessageBox(GetForegroundWindow(), "write error", "Save", MB_ICONERROR);
796 DimkaM 689
         else if (drvs[ofn.nFilterIndex]!=-1U)
716 lvd 690
         {
800 DimkaM 691
             comp.fdd[drvs[ofn.nFilterIndex]].optype=0;
692
             strcpy(comp.fdd[drvs[ofn.nFilterIndex]].name, ofn.lpstrFile);
716 lvd 693
 
694
             //---------Alone Coder
695
             char *name = ofn.lpstrFile;
696
             for (char *x = name; *x; x++)
697
             {
698
                 if (*x == '\\')
699
                     name = x+1;
700
             }
701
             char wintitle[0x200];
702
             strcpy(wintitle,name);
703
             strcat(wintitle," - UnrealSpeccy");
704
             SetWindowText(wnd, wintitle);
705
             //~---------Alone Coder
706
         }
707
      }
708
      else
709
          MessageBox(GetForegroundWindow(), "Can't open file for writing", "Save", MB_ICONERROR);
710
   }
711
   eat();
712
}
713
 
714
void ConvPal8ToBgr24(u8 *dst, u8 *scrbuf, int dx)
715
{
716
    u8 *ds = dst;
717
    for(unsigned i = 0; i < temp.oy; i++) // convert to BGR24 format
718
    {
796 DimkaM 719
       unsigned char *src = scrbuf + int(i)*dx;
716 lvd 720
       for (unsigned y = 0; y < temp.ox; y++)
721
       {
722
          ds[0] = pal0[src[y]].peBlue;
723
          ds[1] = pal0[src[y]].peGreen;
724
          ds[2] = pal0[src[y]].peRed;
725
          ds += 3;
726
       }
727
       ds = (PBYTE)(ULONG_PTR(ds + 3) & ~ULONG_PTR(3)); // ������ ������ ��������� �� 4
728
    }
729
}
730
 
731
void ConvRgb15ToBgr24(u8 *dst, u8 *scrbuf, int dx)
732
{
733
    u8 *ds = dst;
734
    for(unsigned i = 0; i < temp.oy; i++) // convert to BGR24 format
735
    {
796 DimkaM 736
       unsigned char *src = scrbuf + int(i)*dx;
716 lvd 737
       for (unsigned y = 0; y < temp.ox; y++)
738
       {
739
          unsigned xx;
740
          xx = *(unsigned*)(src + y*2);
741
 
796 DimkaM 742
          ds[0] = u8((xx & 0x1F)<<3);
743
          ds[1] = u8((xx & 0x03E0)>>2);
744
          ds[2] = u8((xx & 0x7C00)>>7);
716 lvd 745
          ds += 3;
746
       }
747
       ds = (PBYTE)(ULONG_PTR(ds + 3) & ~ULONG_PTR(3)); // ������ ������ ��������� �� 4
748
    }
749
}
750
 
751
void ConvRgb16ToBgr24(u8 *dst, u8 *scrbuf, int dx)
752
{
753
    u8 *ds = dst;
754
    for(unsigned i = 0; i < temp.oy; i++) // convert to BGR24 format
755
    {
796 DimkaM 756
       unsigned char *src = scrbuf + int(i)*dx;
716 lvd 757
       for (unsigned y = 0; y < temp.ox; y++)
758
       {
759
          unsigned xx;
760
          xx = *(unsigned*)(src + y*2);
761
 
796 DimkaM 762
          ds[0] = u8((xx&0x1F)<<3);
763
          ds[1] = u8((xx&0x07E0)>>3);
764
          ds[2] = u8((xx&0xF800)>>8);
716 lvd 765
          ds += 3;
766
       }
767
       ds = (PBYTE)(ULONG_PTR(ds + 3) & ~ULONG_PTR(3)); // ������ ������ ��������� �� 4
768
    }
769
}
770
 
771
void ConvYuy2ToBgr24(u8 *dst, u8 *scrbuf, int dx)
772
{
773
    u8 *ds = dst;
774
    for(unsigned i = 0; i < temp.oy; i++) // convert to BGR24 format
775
    {
796 DimkaM 776
        unsigned char *src = scrbuf + int(i)*dx;
716 lvd 777
        for (unsigned y = 0; y < temp.ox; y++)
778
        {
779
            unsigned xx;
780
            xx = *(unsigned*)(src + y*2);
781
 
782
            int u = src[y/2*4+1], v = src[y/2*4+3], Y = src[y*2];
783
            int r = (int)(.4732927654e-2*u-255.3076403+1.989858012*v+.9803921569*Y);
784
            int g = (int)(-.9756592292*v+186.0716700-.4780256930*u+.9803921569*Y);
785
            int b = (int)(.9803921569*Y+2.004732928*u-255.3076403-.1014198783e-1*v); // mapple rulez!
786
            if (r < 0) r = 0; if (r > 255) r = 255;
787
            if (g < 0) g = 0; if (g > 255) g = 255;
788
            if (b < 0) b = 0; if (b > 255) b = 255;
789
 
796 DimkaM 790
            ds[0] = u8(b);
791
            ds[1] = u8(g);
792
            ds[2] = u8(r);
716 lvd 793
            ds += 3;
794
        }
795
        ds = (PBYTE)(ULONG_PTR(ds + 3) & ~ULONG_PTR(3)); // ������ ������ ��������� �� 4
796
    }
797
}
798
 
799
void ConvBgr32ToBgr24(u8 *dst, u8 *scrbuf, int dx)
800
{
801
    u8 *ds = dst;
802
    for(unsigned i = 0; i < temp.oy; i++) // convert to BGR24 format
803
    {
796 DimkaM 804
       unsigned char *src = scrbuf + int(i)*dx;
716 lvd 805
       for (unsigned x = 0; x < temp.ox; x++)
806
       {
807
          ds[0] = src[0];
808
          ds[1] = src[1];
809
          ds[2] = src[2];
810
          src += 4;
811
          ds += 3;
812
       }
813
       ds = (PBYTE)(ULONG_PTR(ds + 3) & ~ULONG_PTR(3)); // ������ ������ ��������� �� 4
814
    }
815
}
816
 
817
 
796 DimkaM 818
TColorConverter ConvBgr24 = nullptr;
716 lvd 819
 
796 DimkaM 820
static void SaveBmp(FILE *File, u8 *ds)
716 lvd 821
{
822
     static u8 bmpheader32[]=
823
     {
824
            // BITMAPFILEHEADER
825
            0x42,0x4d,           // Type
826
            0x36,0x10,0x0e,0x00, // Size
827
            0x00,0x00,           // Reserved1
828
            0x00,0x00,           // Reserved2
829
            0x36,0x00,0x00,0x00, // OffBits
830
            // BITMAPINFOHEADER
831
            0x28,0x00,0x00,0x00, // Size
832
            0x80,0x02,0x00,0x00, // Width
833
            0xe0,0x01,0x00,0x00, // Height
834
            0x01,0x00,           // Planes
835
            0x18,0x00,           // BitCount
836
            0x00,0x00,0x00,0x00, // Compression
837
            0x00,0x10,0x0e,0x00, // SizeImage
838
            0x00,0x00,0x00,0x00, // XPixelsPerMeter
839
            0x00,0x00,0x00,0x00, // YPixelsPerMeter
840
            0x00,0x00,0x00,0x00, // ClrUsed
841
            0x00,0x00,0x00,0x00  // ClrImportant
842
     };
843
 
844
    *(unsigned*)(bmpheader32 + 2) = temp.ox * temp.oy * 3 + sizeof(bmpheader32); // filesize
845
    *(unsigned*)(bmpheader32 + 0x12) = temp.ox;
846
    *(unsigned*)(bmpheader32 + 0x16) = temp.oy;
847
    fwrite(bmpheader32, 1, sizeof(bmpheader32), File);
848
 
796 DimkaM 849
    for(int y = int(temp.oy - 1); y >= 0 ; y--)
716 lvd 850
    {
796 DimkaM 851
        fwrite(ds + ((unsigned(y) * temp.ox * 3 + 3) & ~3U), 1, temp.ox * 3, File);
716 lvd 852
    }
853
}
854
 
796 DimkaM 855
static void SavePng(FILE *File, u8 *ds)
716 lvd 856
{
857
    static png_color bkgColor = {127, 127, 127};
858
 
859
    if(!temp.PngSupport)
860
        return;
861
 
796 DimkaM 862
    PngSaveImage(File, ds, int(temp.ox), int(temp.oy), bkgColor);
716 lvd 863
}
864
 
865
#define MAKE_RGBQUAD(r,g,b) (ULONG) (u32(b) | (u32(g)<<8) | (u32(r)<<16))
866
 
867
static void SaveBmp16c(FILE *File, const u8 *ds)
868
{
869
     static u8 bmpheader32[]=
870
     {
871
            // BITMAPFILEHEADER
872
            0x42,0x4d,           // Type
873
            0x36,0x10,0x0e,0x00, // Size = 320*200/2 + sizeof(bmpheader32)
874
            0x00,0x00,           // Reserved1
875
            0x00,0x00,           // Reserved2
876
            0x76,0x00,0x00,0x00, // OffBits
877
            // BITMAPINFOHEADER
878
            0x28,0x00,0x00,0x00, // Size
879
            0x40,0x01,0x00,0x00, // Width = 320
880
            0xc8,0x00,0x00,0x00, // Height = 200
881
            0x01,0x00,           // Planes
882
            0x04,0x00,           // BitCount = 4
883
            0x00,0x00,0x00,0x00, // Compression = BI_RGB
884
            0x00,0x10,0x0e,0x00, // SizeImage
885
            0x00,0x00,0x00,0x00, // XPixelsPerMeter
886
            0x00,0x00,0x00,0x00, // YPixelsPerMeter
887
            0x00,0x00,0x00,0x00, // ClrUsed
888
            0x00,0x00,0x00,0x00, // ClrImportant
889
            // PALETTE
890
            0,0,0,0,             //  0 bgra
891
            0,0,0,0,             //  1 bgra
892
            0,0,0,0,             //  2 bgra
893
            0,0,0,0,             //  3 bgra
894
            0,0,0,0,             //  4 bgra
895
            0,0,0,0,             //  5 bgra
896
            0,0,0,0,             //  6 bgra
897
            0,0,0,0,             //  7 bgra
898
            0,0,0,0,             //  8 bgra
899
            0,0,0,0,             //  9 bgra
900
            0,0,0,0,             // 10 bgra
901
            0,0,0,0,             // 11 bgra
902
            0,0,0,0,             // 12 bgra
903
            0,0,0,0,             // 13 bgra
904
            0,0,0,0,             // 14 bgra
905
            0,0,0,0              // 15 bgra
906
     };
907
 
908
    *(unsigned*)(bmpheader32 + 2) = 320 * 200 / 2 + sizeof(bmpheader32); // filesize
909
    for(unsigned i = 0; i < 16; i++)
910
    {
796 DimkaM 911
        // ������ ������ ������� Gg0Rr0Bb
912
        // ��������� ������� ��������� - ULA+
913
        unsigned PalIdx = ((i & 8) << 1) | (i & 7);
914
        u8 r = u8(u32((comp.comp_pal[PalIdx] >> 3) & 3) * 255 / 3);
915
        u8 g = u8(u32((comp.comp_pal[PalIdx] >> 6) & 3) * 255 / 3);
916
        u8 b = u8(u32(comp.comp_pal[PalIdx] & 3) * 255 / 3);
716 lvd 917
 
918
        *(PULONG)(bmpheader32 + 54 + 4*i) = MAKE_RGBQUAD(r,g,b);
919
    }
920
    fwrite(bmpheader32, 1, sizeof(bmpheader32), File);
921
    fwrite(ds, 1, 320 * 200 / 2, File);
922
}
923
 
924
static void ConvPal16cAtm1(u8 *Buf)
925
{
926
    static const int ega0_ofs = -4*PAGE;
927
    static const int ega1_ofs = 0;
928
    static const int ega2_ofs = -4*PAGE+0x2000;
929
    static const int ega3_ofs = 0x2000;
930
 
931
   for (int y = 200 - 1; y >= 0; y--)
932
   {
933
      const u8 *src = temp.base + y*40;
934
 
935
      for(unsigned x = 0; x < 320; x += 8)
936
      {
937
          u8 v0 = src[ega0_ofs];
938
          u8 v1 = src[ega1_ofs];
939
          u8 v2 = src[ega2_ofs];
940
          u8 v3 = src[ega3_ofs];
796 DimkaM 941
          Buf[0] = u8(((((v0 >> 3) & 8) | (v0 & 0x7)) << 4) |
942
                   (((v0 & 0x80) | ((v0 << 1) & 0x70)) >> 4));
943
          Buf[1] = u8(((((v1 >> 3) & 8) | (v1 & 0x7)) << 4) |
944
                   (((v1 & 0x80) | ((v1 << 1) & 0x70)) >> 4));
945
          Buf[2] = u8(((((v2 >> 3) & 8) | (v2 & 0x7)) << 4) |
946
                   (((v2 & 0x80) | ((v2 << 1) & 0x70)) >> 4));
947
          Buf[3] = u8(((((v3 >> 3) & 8) | (v3 & 0x7)) << 4) |
948
                   (((v3 & 0x80) | ((v3 << 1) & 0x70)) >> 4));
716 lvd 949
 
950
          src++;
951
          Buf += 4;
952
      }
953
   }
954
 
955
}
956
 
957
#define ConvPal16cAtm2 ConvPal16cAtm1
958
 
959
typedef void (*TSaver)(FILE *File, u8 *ds);
960
 
961
void main_scrshot()
962
{
963
   char fname[FILENAME_MAX];
964
   static unsigned sshot = 0;
965
   static const char *Format[] = { "scr", "bmp", "png" };
966
   static const TSaver Saver[] = { SaveBmp, SavePng };
967
 
968
   const char *Ext = Format[conf.scrshot];
969
 
970
   if (conf.scrshot == 0 &&
971
       (
972
        ((conf.mem_model == MM_ATM710 || conf.mem_model == MM_ATM3) && ((comp.pFF77 & 7) == 0)) ||
973
        ((conf.mem_model == MM_ATM450) && (((comp.aFE >> 5) & 3) == 0))
974
       )
975
      )
976
   {
977
       Ext = Format[1];
978
   }
979
 
796 DimkaM 980
   snprintf(fname, _countof(fname), "%s\\%s_%06u.%s", conf.scrshot_dir,
716 lvd 981
       temp.LastSnapName[0] ? temp.LastSnapName : "sshot", sshot, Ext);
982
   fname[FILENAME_MAX-1] = 0;
983
 
984
   FILE *fileShot = fopen(fname, "wb");
985
   if (!fileShot)
986
      return;
987
 
988
   if (conf.scrshot == 0)
989
   {
990
      switch(conf.mem_model)
991
      {
992
      case MM_ATM710:
993
      case MM_ATM3:
994
          {
995
              switch(comp.pFF77 & 7)
996
              {
997
              case 0: // EGA 320x200 16c
998
                  {
999
                      u8 *Buf = (u8 *)malloc(320*200/2);
1000
                      ConvPal16cAtm2(Buf);
1001
                      SaveBmp16c(fileShot, Buf);
1002
                      free(Buf);
1003
                  }
1004
              break;
1005
              case 3:
1006
                  goto standard_zx_mode;
1007
              }
1008
          }
1009
      break;
1010
 
1011
      case MM_ATM450:
1012
          switch((comp.aFE >> 5) & 3)
1013
          {
1014
          case 0: // EGA 320x200 16c
1015
              {
1016
                  u8 *Buf = (u8 *)malloc(320*200/2);
1017
                  ConvPal16cAtm1(Buf);
1018
                  SaveBmp16c(fileShot, Buf);
1019
                  free(Buf);
1020
              }
1021
          break;
1022
 
1023
          case 3:
1024
              goto standard_zx_mode;
1025
          }
1026
      break;
1027
 
1028
      default:
1029
standard_zx_mode:;
1030
          fwrite(temp.base, 1, 6912, fileShot);
1031
      }
1032
   }
1033
   else
1034
   {
1035
      unsigned dx = temp.ox * temp.obpp / 8;
1036
      unsigned char *scrbuf_unaligned = (unsigned char*)malloc(dx * temp.oy + CACHE_LINE);
1037
      unsigned char *scrbuf = (unsigned char*)align_by(scrbuf_unaligned, CACHE_LINE);
1038
      memset(scrbuf, 0, dx * temp.oy);
1039
      renders[conf.render].func(scrbuf, dx); // render to memory buffer (PAL8, YUY2, RGB15, RGB16, RGB32)
1040
 
796 DimkaM 1041
      u8 *ds = (u8 *)malloc(((temp.ox * 3 + 3) & ~3U) * temp.oy);
1042
      ConvBgr24(ds, scrbuf, int(dx));
716 lvd 1043
 
1044
      Saver[conf.scrshot - 1](fileShot, ds);
1045
 
1046
      free(ds);
1047
      free(scrbuf_unaligned);
1048
   }
1049
   fclose(fileShot);
1050
   sprintf(statusline, "saving %s", strrchr(fname, '\\') + 1);
1051
   statcnt = 30;
1052
   sshot++;
1053
}
1054
/*
1055
static void VideoFrameSaver()
1056
{
1057
   char fname[FILENAME_MAX];
1058
   static unsigned FrameNum = 0;
1059
   static const char *Format[] = { "scr", "bmp", "png" };
1060
   static const TSaver Saver[] = { SaveBmp, SavePng };
1061
 
1062
   sprintf(fname, "video%06u.%s", FrameNum, Format[conf.scrshot]);
1063
   addpath(fname);
1064
 
1065
   FILE *fileShot = fopen(fname, "wb");
1066
   if (!fileShot)
1067
      return;
1068
 
1069
   if (conf.scrshot == 0)
1070
   {
1071
      fwrite(temp.base, 1, 6912, fileShot);
1072
   }
1073
   else
1074
   {
1075
       unsigned dx = temp.ox * temp.obpp / 8;
1076
       unsigned char *scrbuf_unaligned = (unsigned char*)malloc(dx * temp.oy + CACHE_LINE);
1077
       unsigned char *scrbuf = (unsigned char*)align_by(scrbuf_unaligned, CACHE_LINE);
1078
       memset(scrbuf, 0, dx * temp.oy);
1079
       renders[conf.render].func(scrbuf, dx); // render to memory buffer (PAL8, YUY2, RGB15, RGB16, RGB32)
1080
 
1081
       u8 *ds = (u8 *)malloc(((temp.ox * 3 + 3) & ~3) * temp.oy);
1082
       ConvBgr24(ds, scrbuf, dx);
1083
 
1084
       Saver[conf.scrshot - 1](fileShot, ds);
1085
 
1086
       free(ds);
1087
       free(scrbuf_unaligned);
1088
   }
1089
   fclose(fileShot);
1090
   FrameNum++;
1091
}
1092
 
1093
static void VideoNullSaver()
1094
{
1095
 
1096
}
1097
 
1098
TVideoSaver VideoSaver = VideoNullSaver;
1099
 
1100
void main_savevideo()
1101
{
1102
   static bool StartSave = false;
1103
 
1104
   if(!StartSave)
1105
   {
1106
       sprintf(statusline, "start saving video");
1107
       StartSave = true;
1108
       VideoSaver = VideoFrameSaver;
1109
   }
1110
   else
1111
   {
1112
       sprintf(statusline, "stop saving video");
1113
       StartSave = false;
1114
       VideoSaver = VideoNullSaver;
1115
   }
1116
 
1117
   statcnt = 30;
1118
}
1119
*/
1120