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 "memory.h"
6
#include "util.h"
7
 
8
// input: ports 7FFD,1FFD,DFFD,FFF7,FF77,EFF7, flags CF_TRDOS,CF_CACHEON
9
void set_banks()
10
{
11
   bankw[1] = bankr[1] = RAM_BASE_M + 5*PAGE;
12
   bankw[2] = bankr[2] = RAM_BASE_M + 2*PAGE;
13
 
14
   // screen begining
15
   temp.base = memory + ((comp.p7FFD & 8) ? 7*PAGE : 5*PAGE);
16
/*
17
   if(conf.mem_model == MM_QUORUM)
18
       temp.base = memory + (comp.p80FD & 7) * 0x2000 + 5*PAGE;
19
*/
20
 
21
   if (temp.base_2)
22
       temp.base_2 = temp.base;
23
 
24
   // these flags will be re-calculated
25
   comp.flags &= ~(CF_DOSPORTS | CF_Z80FBUS | CF_LEAVEDOSRAM | CF_LEAVEDOSADR | CF_SETDOSROM);
26
 
27
   unsigned char *bank0, *bank3;
28
 
29
   if (comp.flags & CF_TRDOS)
30
   {
31
       if(comp.p7FFD & 0x10)
32
       {
33
           bank0 = base_dos_rom;
34
       }
35
       else
36
       {
37
           bank0 = base_sys_rom;
38
       }
39
   }
40
   else
41
       bank0 = (comp.p7FFD & 0x10)? base_sos_rom : base_128_rom;
42
 
43
   unsigned bank = (comp.p7FFD & 7);
44
 
45
   switch (conf.mem_model)
46
   {
47
      case MM_PENTAGON:
48
         if(!(comp.pEFF7 & EFF7_LOCKMEM))
49
         {
50
             // 7FFD bits
51
             //    210 - 128
52
             //   6210 - 256
53
             //  76210 - 512
54
             // 576210 - 1024
55
             bank |= (comp.p7FFD & 0xC0) >> 3;
56
             bank |= (comp.p7FFD & 0x20);
57
         }
58
 
59
         bank3 = RAM_BASE_M + (bank & temp.ram_mask)*PAGE;
60
 
61
         if (comp.pEFF7 & EFF7_ROCACHE)
62
             bank0 = RAM_BASE_M + 0*PAGE; //Alone Coder 0.36.4
63
         break;
64
 
65
      case MM_PROFSCORP:
66
         membits[0x0100] &= ~MEMBITS_R;
67
         membits[0x0104] &= ~MEMBITS_R;
68
         membits[0x0108] &= ~MEMBITS_R;
69
         membits[0x010C] &= ~MEMBITS_R;
70
      case MM_SCORP:
71
         bank += ((comp.p1FFD & 0x10) >> 1) + ((comp.p1FFD & 0xC0) >> 2);
72
         bank3 = RAM_BASE_M + (bank & temp.ram_mask) * PAGE;
73
 
74
/*
75
         // обработка памяти gmx (конфликтует со стандартным profrom)
76
         // нужно сделать флаг записи в порт 7EFD, и если была хоть одна запись
77
         // то обрабатывать rom по стандарту gmx
78
         comp.profrom_bank = ((comp.p7EFD >> 4) & 3) & temp.profrom_mask;
79
         {
80
             unsigned char *base = ROM_BASE_M + (comp.profrom_bank * 64*1024);
81
             base_128_rom = base + 0*PAGE;
82
             base_sos_rom = base + 1*PAGE;
83
             base_sys_rom = base + 2*PAGE;
84
             base_dos_rom = base + 3*PAGE;
85
         }
86
*/
87
 
88
         // Доработка из книжки gmx (включение портов dos из ОЗУ, сделано немного не так как в реальной схеме)
89
         if(comp.p1FFD & 4)
90
             comp.flags |= CF_TRDOS;
91
         if(comp.p1FFD & 2)
92
            bank0 = base_sys_rom;
93
         if(comp.p1FFD & 1)
94
            bank0 = RAM_BASE_M + 0 * PAGE;
95
         if(conf.mem_model == MM_PROFSCORP)
96
         {
97
             if (bank0 == base_sys_rom)
98
                 comp.flags |= CF_PROFROM;
99
             else
100
                 comp.flags &= ~CF_PROFROM;
101
         }
102
         break;
103
 
104
      case MM_KAY:
105
      {
106
         bank += ((comp.p1FFD & 0x10) >> 1) + ((comp.p1FFD & 0x80) >> 3) + ((comp.p7FFD & 0x80) >> 2);
107
         bank3 = RAM_BASE_M + (bank & temp.ram_mask)*PAGE;
108
         unsigned char rom1 = (comp.p1FFD >> 2) & 2;
109
         if (comp.flags & CF_TRDOS) rom1 ^= 2;
110
         switch (rom1+((comp.p7FFD & 0x10) >> 4))
111
         {
112
            case 0: bank0 = base_128_rom; break;
113
            case 1: bank0 = base_sos_rom; break;
114
            case 2: bank0 = base_sys_rom; break;
115
            case 3: bank0 = base_dos_rom; break;
116
            default: __assume(0);
117
         }
118
         if (comp.p1FFD & 1) bank0 = RAM_BASE_M + 0*PAGE;
119
         break;
120
      }
121
 
122
      case MM_PROFI:
123
         bank += ((comp.pDFFD & 0x07) << 3); bank3 = RAM_BASE_M + (bank & temp.ram_mask)*PAGE;
124
         if (comp.pDFFD & 0x08) bankr[1] = bankw[1] = bank3, bank3 = RAM_BASE_M+7*PAGE;
125
         if (comp.pDFFD & 0x10) bank0 = RAM_BASE_M+0*PAGE;
126
         if (comp.pDFFD & 0x20) comp.flags |= CF_DOSPORTS;
127
         if (comp.pDFFD & 0x40) bankr[2] = bankw[2] = RAM_BASE_M + 6*PAGE;
128
         break;
129
 
130
      case MM_ATM450:
131
      {
132
         // RAM
133
         // original ATM uses D2 as ROM address extension, not RAM
134
         bank += ((comp.pFDFD & 0x07) << 3);
135
         bank3 = RAM_BASE_M + (bank & temp.ram_mask)*PAGE;
136
         if (!(comp.aFE & 0x80))
137
         {
138
            bankw[1] = bankr[1] = RAM_BASE_M + 4*PAGE;
139
            bank0 = RAM_BASE_M;
140
            break;
141
         }
142
 
143
         // ROM
144
         if (comp.p7FFD & 0x20)
145
             comp.aFB &= ~0x80;
146
         if ((comp.flags & CF_TRDOS) && (comp.pFDFD & 8))
147
             comp.aFB |= 0x80; // more priority, then 7FFD
148
 
149
         if (comp.aFB & 0x80) // CPSYS signal
150
         {
151
             bank0 = base_sys_rom;
152
             break;
153
         }
154
         // system rom not used on 7FFD.4=0 and DOS=1
155
         if (comp.flags & CF_TRDOS)
156
             bank0 = base_dos_rom;
157
         break;
158
      }
159
 
160
      case MM_ATM3:
161
         if (comp.pBF & 1) // shaden
162
            comp.flags |= CF_DOSPORTS;
163
 
164
      case MM_ATM710:
165
      {
166
         if (!(comp.aFF77 & 0x200)) // ~cpm=0
167
            comp.flags |= CF_TRDOS;
168
 
169
         if (!(comp.aFF77 & 0x100))
170
         { // pen=0
171
            bankr[1] = bankr[2] = bank3 = bank0 = ROM_BASE_M + PAGE * temp.rom_mask;
172
            break;
173
         }
174
 
175
         unsigned i = ((comp.p7FFD & 0x10) >> 2);
176
         for (unsigned bank = 0; bank < 4; bank++)
177
         {
178
            switch (comp.pFFF7[i+bank] & 0x300)
179
            {
180
               case 0x000: // RAM from 7FFD
181
                  bankr[bank] = bankw[bank] = RAM_BASE_M + PAGE * ((comp.p7FFD & 7) | (comp.pFFF7[i+bank] & 0xF8 & temp.ram_mask));
182
                  break;
183
               case 0x100: // ROM from 7FFD
184
                  bankr[bank] = ROM_BASE_M + PAGE*((comp.pFFF7[i+bank] & 0xFE & temp.rom_mask) + ((comp.flags & CF_TRDOS)?1:0));
185
                  break;
186
               case 0x200: // RAM from FFF7
187
                  bankr[bank] = bankw[bank] = RAM_BASE_M + PAGE*(comp.pFFF7[i+bank] & 0xFF & temp.ram_mask);
188
                  break;
189
               case 0x300: // ROM from FFF7
190
                  bankr[bank] = ROM_BASE_M + PAGE*(comp.pFFF7[i+bank] & 0xFF & temp.rom_mask);
191
                  break;
192
            }
193
         }
194
         bank0 = bankr[0]; bank3 = bankr[3];
195
 
196
         if(conf.mem_model == MM_ATM3 && cpu.nmi_in_progress)
197
             bank0 = RAM_BASE_M + PAGE * 0xFF;
198
         break;
199
      }
200
 
201
      case MM_PLUS3:
202
      {
203
          if(comp.p7FFD & 0x20) // paging disabled (48k mode)
204
          {
205
              bank3 = RAM_BASE_M + (bank & temp.ram_mask)*PAGE;
206
              break;
207
          }
208
 
209
          if(!(comp.p1FFD & 1))
210
          {
211
              unsigned RomBank = ((comp.p1FFD & 4) >> 1) | ((comp.p7FFD & 0x10) >> 4);
212
              switch(RomBank)
213
              {
214
                 case 0: bank0 = base_128_rom; break;
215
                 case 1: bank0 = base_sys_rom; break;
216
                 case 2: bank0 = base_dos_rom; break;
217
                 case 3: bank0 = base_sos_rom; break;
218
              }
219
              bank3 = RAM_BASE_M + (bank & temp.ram_mask)*PAGE;
220
          }
221
          else
222
          {
223
              unsigned RamPage = (comp.p1FFD >> 1) & 3; // d2,d1
224
              static const unsigned RamDecoder[4][4] =
225
              { {0, 1, 2, 3}, {4, 5, 6, 7}, {4, 5, 6, 3}, {4, 7, 6, 3} };
226
              for(unsigned i = 0; i < 4; i++)
227
                  bankw[i] = bankr[i] = RAM_BASE_M + PAGE * RamDecoder[RamPage][i];
228
              bank0 = bankr[0];
229
              bank3 = bankr[3];
230
          }
231
          break;
232
      }
233
 
234
      case MM_QUORUM:
235
      {
236
          if(!(comp.p00 & Q_TR_DOS))
237
              comp.flags |= CF_DOSPORTS;
238
 
239
          if(comp.p00 & Q_B_ROM)
240
          {
241
              if (comp.flags & CF_TRDOS)
242
                  bank0 = base_dos_rom;
243
              else
244
                  bank0 = (comp.p7FFD & 0x10) ? base_sos_rom : base_128_rom;
245
          }
246
          else
247
          {
248
              bank0 = base_sys_rom;
249
          }
250
 
251
          if(comp.p00 & Q_F_RAM)
252
          {
253
              unsigned bnk0 = (comp.p00 & Q_RAM_8) ? 8 : 0;
254
              bank0 = RAM_BASE_M + (bnk0 & temp.ram_mask) * PAGE;
255
          }
256
 
257
          bank |= ((comp.p7FFD & 0xC0) >> 3) | (comp.p7FFD & 0x20);
258
          bank3 = RAM_BASE_M + (bank & temp.ram_mask) * PAGE;
259
          break;
260
      }
261
 
262
      default: bank3 = RAM_BASE_M + 0*PAGE;
263
   }
264
 
265
   bankw[0] = bankr[0] = bank0;
266
   bankw[3] = bankr[3] = bank3;
267
 
268
   if (bankr[0] >= ROM_BASE_M) bankw[0] = TRASH_M;
269
   if (bankr[1] >= ROM_BASE_M) bankw[1] = TRASH_M;
270
   if (bankr[2] >= ROM_BASE_M) bankw[2] = TRASH_M;
271
   if (bankr[3] >= ROM_BASE_M) bankw[3] = TRASH_M;
272
 
273
 
274
   unsigned char dosflags = CF_LEAVEDOSRAM;
275
   if (conf.mem_model == MM_PENTAGON || conf.mem_model == MM_PROFI)
276
       dosflags = CF_LEAVEDOSADR;
277
 
278
   if (comp.flags & CF_TRDOS)
279
   {
280
       comp.flags |= dosflags | CF_DOSPORTS;
281
   }
282
   else if ((comp.p7FFD & 0x10) && conf.trdos_present)
283
   { // B-48, inactive DOS, DOS present
284
      // for Scorp, ATM-1/2 and KAY, TR-DOS not started on executing RAM 3Dxx
285
      if (!((dosflags & CF_LEAVEDOSRAM) && bankr[0] < RAM_BASE_M+PAGE*MAX_RAM_PAGES))
286
         comp.flags |= CF_SETDOSROM;
287
   }
288
 
289
   if (comp.flags & CF_CACHEON)
290
   {
291
      unsigned char *cpage = CACHE_M;
292
      if (conf.cache == 32 && !(comp.p7FFD & 0x10)) cpage += PAGE;
293
      bankr[0] = bankw[0] = cpage;
294
      // if (comp.pEFF7 & EFF7_ROCACHE) bankw[0] = TRASH_M; //Alone Coder 0.36.4
295
   }
296
 
297
   if ((comp.flags & CF_DOSPORTS)? conf.floatdos : conf.floatbus)
298
       comp.flags |= CF_Z80FBUS;
299
 
300
   if (temp.led.osw && (trace_rom | trace_ram))
301
   {
302
      for (unsigned i = 0; i < 4; i++) {
303
         unsigned bank = (bankr[i] - RAM_BASE_M) / PAGE;
304
         if (bank < MAX_PAGES) used_banks[bank] = 1;
305
      }
306
   }
307
 
308
/*
309
    if ((unsigned)(bankr[0] - ROM_BASE_M) < PAGE*MAX_ROM_PAGES)
310
    {
311
        printf("ROM%2X\n", (bankr[0] - ROM_BASE_M)/PAGE);
312
        printf("DOS=%p\n",  base_dos_rom);
313
        printf("SVM=%p\n",  base_sys_rom);
314
        printf("SOS=%p\n",  base_sos_rom);
315
        printf("128=%p\n",  base_128_rom);
316
    }
317
*/
318
}
319
 
320
void set_scorp_profrom(unsigned read_address)
321
{
322
   static unsigned char switch_table[] =
323
   {
324
      0,1,2,3,
325
      3,3,3,2,
326
      2,2,0,1,
327
      1,0,1,0
328
   };
329
   comp.profrom_bank = switch_table[read_address*4 + comp.profrom_bank] & temp.profrom_mask;
330
   unsigned char *base = ROM_BASE_M + (comp.profrom_bank * 64*1024);
331
   base_128_rom = base + 0*PAGE;
332
   base_sos_rom = base + 1*PAGE;
333
   base_sys_rom = base + 2*PAGE;
334
   base_dos_rom = base + 3*PAGE;
335
   set_banks();
336
}
337
 
338
/*
339
u8 *__fastcall MemDbg(u32 addr)
340
{
341
    return am_r(addr);
342
}
343
 
344
void __fastcall wmdbg(u32 addr, u8 val)
345
{
346
   *am_r(addr) = val;
347
}
348
 
349
u8 __fastcall rmdbg(u32 addr)
350
{
351
   return *am_r(addr);
352
}
353
*/
354
 
355
void set_mode(ROM_MODE mode)
356
{
357
   if (mode == RM_NOCHANGE)
358
       return;
359
 
360
   if (mode == RM_CACHE)
361
   {
362
       comp.flags |= CF_CACHEON;
363
       set_banks();
364
       return;
365
   }
366
 
367
   // no RAM/cache/SERVICE
368
   comp.p1FFD &= ~7;
369
   comp.pDFFD &= ~0x10;
370
   comp.flags &= ~CF_CACHEON;
371
 
372
   // comp.aFF77 |= 0x100; // enable ATM memory
373
 
374
   switch (mode)
375
   {
376
      case RM_128:
377
         comp.flags &= ~CF_TRDOS;
378
         comp.p7FFD &= ~0x10;
379
         break;
380
      case RM_SOS:
381
         comp.flags &= ~CF_TRDOS;
382
         comp.p7FFD |= 0x10;
383
 
384
         if(conf.mem_model == MM_PLUS3) // disable paging
385
            comp.p7FFD |= 0x20;
386
         break;
387
      case RM_SYS:
388
         comp.flags |= CF_TRDOS;
389
         comp.p7FFD &= ~0x10;
390
         break;
391
      case RM_DOS:
392
         comp.flags |= CF_TRDOS;
393
         comp.p7FFD |=  0x10;
394
         if(conf.mem_model == MM_ATM710 || conf.mem_model == MM_ATM3)
395
             comp.p7FFD &=  ~0x10;
396
         break;
397
   }
398
   set_banks();
399
}
400
 
401
unsigned char cmosBCD(unsigned char binary)
402
{
403
   if (!(cmos[11] & 4)) binary = (binary % 10) + 0x10*((binary/10)%10);
404
   return binary;
405
}
406
 
407
unsigned char cmos_read()
408
{
409
   static SYSTEMTIME st;
410
   static bool UF = false;
411
   static unsigned Seconds = 0;
412
   static unsigned long long last_tsc = 0ULL;
413
   unsigned char reg = comp.cmos_addr;
414
   unsigned char rv;
415
   if (conf.cmos == 2)
416
       reg &= 0x3F;
417
 
418
   if ((1 << reg) & ((1<<0)|(1<<2)|(1<<4)|(1<<6)|(1<<7)|(1<<8)|(1<<9)|(1<<12)))
419
   {
420
      unsigned long long tsc = rdtsc();
421
      // [vv] Часы читаются не чаще двух раз в секунду
422
      if ((tsc-last_tsc) >= 25 * temp.ticks_frame)
423
      {
424
          GetLocalTime(&st);
425
          if(st.wSecond != Seconds)
426
          {
427
              UF = true;
428
              Seconds = st.wSecond;
429
          }
430
      }
431
   }
432
 
433
   switch (reg)
434
   {
435
      case 0:     return cmosBCD((BYTE)st.wSecond);
436
      case 2:     return cmosBCD((BYTE)st.wMinute);
437
      case 4:     return cmosBCD((BYTE)st.wHour);
438
      case 6:     return 1+(((BYTE)st.wDayOfWeek+8-conf.cmos) % 7);
439
      case 7:     return cmosBCD((BYTE)st.wDay);
440
      case 8:     return cmosBCD((BYTE)st.wMonth);
441
      case 9:     return cmosBCD(st.wYear % 100);
442
      case 10:    return 0x20 | (cmos [10] & 0xF); // molodcov_alex
443
      case 11:    return (cmos[11] & 4) | 2;
444
      case 12:  // [vv] UF
445
          rv = UF ? 0x10 : 0;
446
          UF = false;
447
          return rv;
448
      case 13:    return 0x80;
449
   }
450
   return cmos[reg];
451
}
452
 
453
void cmos_write(unsigned char val)
454
{
455
   if (conf.cmos == 2) comp.cmos_addr &= 0x3F;
456
   cmos[comp.cmos_addr] = val;
457
}
458
 
459
void NVRAM::write(unsigned char val)
460
{
461
   const int SCL = 0x40, SDA = 0x10, WP = 0x20,
462
             SDA_1 = 0xFF, SDA_0 = 0xBF,
463
             SDA_SHIFT_IN = 4;
464
 
465
   if ((val ^ prev) & SCL) // clock edge, data in/out
466
   {
467
      if (val & SCL) // nvram reads SDA
468
      {
469
         if (state == RD_ACK)
470
         {
471
            if (val & SDA) goto idle; // no ACK, stop
472
            // move next byte to host
473
            state = SEND_DATA;
474
            dataout = nvram[address];
475
            address = (address+1) & 0x7FF;
476
            bitsout = 0; goto exit; // out_z==1;
477
         }
478
 
479
         if ((1<<state) & ((1<<RCV_ADDR)|(1<<RCV_CMD)|(1<<RCV_DATA))) {
480
            if (out_z) // skip nvram ACK before reading
481
               datain = 2*datain + ((val >> SDA_SHIFT_IN) & 1), bitsin++;
482
         }
483
 
484
      } else { // nvram sets SDA
485
 
486
         if (bitsin == 8) // byte received
487
         {
488
            bitsin = 0;
489
            if (state == RCV_CMD) {
490
               if ((datain & 0xF0) != 0xA0) goto idle;
491
               address = (address & 0xFF) + ((datain << 7) & 0x700);
492
               if (datain & 1) { // read from current address
493
                  dataout = nvram[address];
494
                  address = (address+1) & 0x7FF;
495
                  bitsout = 0;
496
                  state = SEND_DATA;
497
               } else
498
                  state = RCV_ADDR;
499
            } else if (state == RCV_ADDR) {
500
               address = (address & 0x700) + datain;
501
               state = RCV_DATA; bitsin = 0;
502
            } else if (state == RCV_DATA) {
503
               nvram[address] = datain;
504
               address = (address & 0x7F0) + ((address+1) & 0x0F);
505
               // state unchanged
506
            }
507
 
508
            // EEPROM always acknowledges
509
            out = SDA_0; out_z = 0; goto exit;
510
         }
511
 
512
         if (state == SEND_DATA) {
513
            if (bitsout == 8) { state = RD_ACK; out_z = 1; goto exit; }
514
            out = (dataout & 0x80)? SDA_1 : SDA_0; dataout *= 2;
515
            bitsout++; out_z = 0; goto exit;
516
         }
517
 
518
         out_z = 1; // no ACK, reading
519
      }
520
      goto exit;
521
   }
522
 
523
   if ((val & SCL) && ((val ^ prev) & SDA)) // start/stop
524
   {
525
      if (val & SDA) { idle: state = IDLE; } // stop
526
      else state = RCV_CMD, bitsin = 0; // start
527
      out_z = 1;
528
   }
529
 
530
   // else SDA changed on low SCL
531
 
532
 
533
 exit:
534
   if (out_z) out = (val & SDA)? SDA_1 : SDA_0;
535
   prev = val;
536
}