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 "memory.h"
7
#include "atm.h"
8
#include "sound.h"
9
#include "gs.h"
10
#include "sdcard.h"
11
#include "zc.h"
12
#include "tape.h"
13
 
14
void out(unsigned port, unsigned char val)
15
{
16
   port &= 0xFFFF;
17
   u8 p1 = (port & 0xFF);
18
   brk_port_out = port; brk_port_val = val;
19
 
20
   // В начале дешифрация портов по полным 8бит
21
   #ifdef MOD_GS
22
   // 10111011 | BB
23
   // 10110011 | B3
24
   // 00110011 | 33
25
   if ((port & 0xFF) == 0x33 && conf.gs_type) // 33
26
   {
27
       out_gs(port, val);
28
       return;
29
   }
30
   if ((port & 0xF7) == 0xB3 && conf.gs_type) // BB, B3
31
   {
32
       out_gs(port, val);
33
       return;
34
   }
35
   #endif
36
 
37
   // z-controller
38
   if (conf.zc && (port & 0xFF) == 0x57)
39
   {
40
       Zc.Wr(port, val);
41
       return;
42
   }
43
 
44
   // divide на nemo портах
45
   if(conf.ide_scheme == IDE_NEMO_DIVIDE)
46
   {
47
       if((port & 0x1E) == 0x10) // rrr1000x
48
       {
49
           if((port & 0xFF) == 0x11)
50
           {
51
               comp.ide_write = val;
52
               comp.ide_hi_byte_w = 0;
53
               comp.ide_hi_byte_w1 = 1;
54
               return;
55
           }
56
 
57
           if((port & 0xFE) == 0x10)
58
           {
59
               comp.ide_hi_byte_w ^= 1;
60
 
61
               if(comp.ide_hi_byte_w1) // Была запись в порт 0x11 (старший байт уже запомнен)
62
               {
63
                   comp.ide_hi_byte_w1 = 0;
64
               }
65
               else
66
               {
67
                   if(comp.ide_hi_byte_w) // Запоминаем младший байт
68
                   {
69
                       comp.ide_write = val;
70
                       return;
71
                   }
72
                   else // Меняем старший и младший байты местами (как этого ожидает write_hdd_5)
73
                   {
74
                       u8 tmp = comp.ide_write;
75
                       comp.ide_write = val;
76
                       val = tmp;
77
                   }
78
               }
79
           }
80
           else
81
           {
82
               comp.ide_hi_byte_w = 0;
83
           }
84
           goto write_hdd_5;
85
       }
86
       else if((port & 0xFF) == 0xC8)
87
       {
88
           return hdd.write(8, val);
89
       }
90
   }
91
 
92
   if(conf.mem_model == MM_ATM3)
93
   {
94
       // Порт расширений АТМ3
95
       if((port & 0xFF) == 0xBF)
96
       {
97
           if((comp.pBF ^ val) & comp.pBF & 8) // D3: 1->0
98
               nmi_pending  = 1;
99
           comp.pBF = val;
100
           set_banks();
101
           return;
102
       }
103
 
104
       // Порт разблокировки RAM0 АТМ3
105
       if((port & 0xFF) == 0xBE)
106
       {
107
           comp.pBE = 2; // счетчик для выхода из nmi
108
           return;
109
       }
110
   }
111
 
112
   if (comp.flags & CF_DOSPORTS)
113
   {
114
      if(conf.mem_model == MM_ATM3 && (p1 & 0x1F) == 0x0F && (((p1 >> 5) - 1) < 5))
115
      {
116
          // 2F = 001|01111b
117
          // 4F = 010|01111b
118
          // 6F = 011|01111b
119
          // 8F = 100|01111b
120
          // AF = 101|01111b
121
          comp.wd_shadow[(p1 >> 5) - 1] = val;
122
      }
123
 
124
      if (conf.ide_scheme == IDE_ATM && (port & 0x1F) == 0x0F)
125
      {
126
         if (port & 0x100) { comp.ide_write = val; return; }
127
      write_hdd_5:
128
         port >>= 5;
129
      write_hdd:
130
         port &= 7;
131
         if (port)
132
             hdd.write(port, val);
133
         else
134
             hdd.write_data(val | (comp.ide_write << 8));
135
         return;
136
      }
137
 
138
      if ((port & 0x18A3) == (0xFFFE & 0x18A3))
139
      { // SMUC
140
         if (conf.smuc)
141
         {
142
            if ((port & 0xA044) == (0xDFBA & 0xA044))
143
            { // clock
144
               if (comp.pFFBA & 0x80)
145
                   cmos_write(val);
146
               else
147
                   comp.cmos_addr = val;
148
               return;
149
            }
150
            if ((port & 0xA044) == (0xFFBA & 0xA044))
151
            { // SMUC system port
152
               if ((val & 1) && (conf.ide_scheme == IDE_SMUC))
153
                   hdd.reset();
154
               comp.nvram.write(val);
155
               comp.pFFBA = val;
156
               return;
157
            }
158
            if ((port & 0xA044) == (0x7FBA & 0xA044))
159
            {
160
                comp.p7FBA = val;
161
                return;
162
            }
163
         }
164
         if ((port & 0x8044) == (0xFFBE & 0x8044) && conf.ide_scheme == IDE_SMUC)
165
         { // FFBE, FEBE
166
            if(comp.pFFBA & 0x80)
167
            {
168
                if(!(port & 0x100))
169
                    hdd.write(8, val); // control register
170
                return;
171
            }
172
 
173
            if (!(port & 0x2000))
174
            {
175
                comp.ide_write = val;
176
                return;
177
            }
178
            port >>= 8;
179
                goto write_hdd;
180
         }
181
      }
182
 
183
      if (conf.mem_model == MM_ATM710 || conf.mem_model == MM_ATM3)
184
      {
185
         if ((conf.mem_model == MM_ATM3) && ((port & 0x3FFF) == 0x37F7)) // x7f7 ATM3 4Mb memory manager
186
         {
187
             unsigned idx = ((comp.p7FFD & 0x10) >> 2) | ((port >> 14) & 3);
188
             comp.pFFF7[idx] = (comp.pFFF7[idx] & ~0x1FF) | (val ^ 0xFF); // always ram
189
             set_banks();
190
             return;
191
         }
192
 
193
         if (p1 == 0x77) // xx77
194
         {
195
             set_atm_FF77(port, val);
196
             return;
197
         }
198
 
199
         u32 mask = (conf.mem_model == MM_ATM3) ? 0x3FFF : 0x00FF;
200
         if ((port & mask) == (0x3FF7 & mask)) // xff7
201
         {
202
             comp.pFFF7[((comp.p7FFD & 0x10) >> 2) | ((port >> 14) & 3)] = (((val & 0xC0) << 2) | (val & 0x3F)) ^ 0x33F;
203
             set_banks();
204
             return;
205
         }
206
 
207
         if ((p1 & 0x9F) == 0x9F && !(comp.aFF77 & 0x4000))
208
             atm_writepal(val); // don't return - write to TR-DOS system port
209
      }
210
 
211
      if(conf.mem_model == MM_PROFI)
212
      {
213
          if((comp.p7FFD & 0x10) && (comp.pDFFD & 0x20)) // modified ports
214
          {
215
              // BDI ports
216
              if((p1 & 0x9F) == 0x83) // WD93 ports
217
              {
218
                  comp.wd.out((p1 & 0x60) | 0x1F, val);
219
                  return;
220
              }
221
 
222
              if((p1 & 0xE3) == 0x23) // port FF
223
              {
224
                  comp.wd.out(0xFF, val);
225
                  return;
226
              }
227
 
228
              // RTC
229
              if((port & 0x9F) == 0x9F && conf.cmos)
230
              {
231
                if(port & 0x20)
232
                {
233
                    comp.cmos_addr = val;
234
                    return;
235
                }
236
                cmos_write(val);
237
                return;
238
              }
239
 
240
              // IDE (AB=10101011, CB=11001011, EB=11101011)
241
              if ((p1 & 0x9F) == 0x8B && (conf.ide_scheme == IDE_PROFI))
242
              {
243
                  if(p1 & 0x40)
244
                  {    // cs1
245
                      if (!(p1 & 0x20))
246
                      {
247
                          comp.ide_write = val;
248
                          return;
249
                      }
250
                      port >>= 8;
251
                      goto write_hdd;
252
                  }
253
 
254
                  // cs3
255
                  if(p1 & 0x20)
256
                  {
257
                      if(((port>>8) & 7) == 6)
258
                          hdd.write(8, val);
259
                      return;
260
                  }
261
              }
262
          }
263
          else
264
          {
265
              // BDI ports
266
              if((p1 & 0x83) == 0x03)  // WD93 ports 1F, 3F, 5F, 7F
267
              {
268
                  comp.wd.out((p1 & 0x60) | 0x1F,val);
269
                  return;
270
              }
271
 
272
              if((p1 & 0xE3) == ((comp.pDFFD & 0x20) ? 0xA3 : 0xE3)) // port FF
273
              {
274
                  comp.wd.out(0xFF,val);
275
                  return;
276
              }
277
          }
278
      } // profi
279
 
280
      if(conf.mem_model == MM_QUORUM /* && !(comp.p00 & Q_TR_DOS)*/) // cpm ports
281
      {
282
          if((p1 & 0xFC) == 0x80) // 80, 81, 82, 83
283
          {
284
              p1 = ((p1 & 3) << 5) | 0x1F;
285
 
286
              comp.wd.out(p1, val);
287
              return;
288
          }
289
 
290
          if(p1 == 0x85) // 85
291
          {
292
//            01 -> 00 A
293
//            10 -> 01 B
294
//            00 -> 11 D (unused)
295
//            11 -> 11 D (unused)
296
              static const u8 drv_decode[] = { 3, 0, 1, 3 };
297
              u8 drv = drv_decode[val & 3];
298
              comp.wd.out(0xFF, ((val & ~3) ^ 0x10) | 0xCC | 8 | drv);
299
              return;
300
          }
301
      } // quorum
302
      else if ((p1 & 0x1F) == 0x1F) // 1F, 3F, 5F, 7F, FF
303
      {
304
          comp.wd.out(p1, val);
305
          return;
306
      }
307
      // don't return - out to port #FE works in trdos!
308
   }
309
   else // не dos
310
   {
311
         if(((port & 0xA3) == 0xA3) && (conf.ide_scheme == IDE_DIVIDE))
312
         {
313
             if((port & 0xFF) == 0xA3)
314
             {
315
                 comp.ide_hi_byte_w ^= 1;
316
                 if(comp.ide_hi_byte_w)
317
                 {
318
                     comp.ide_write = val;
319
                     return;
320
                 }
321
                 u8 tmp = comp.ide_write;
322
                 comp.ide_write = val;
323
                 val = tmp;
324
             }
325
             else
326
             {
327
                 comp.ide_hi_byte_w = 0;
328
             }
329
             port >>= 2;
330
             goto write_hdd;
331
         }
332
 
333
         if ((unsigned char)port == 0x1F && conf.sound.ay_scheme == AY_SCHEME_POS)
334
         {
335
             comp.active_ay = val & 1;
336
             return;
337
         }
338
 
339
         if (!(port & 6) && (conf.ide_scheme == IDE_NEMO || conf.ide_scheme == IDE_NEMO_A8))
340
         {
341
             unsigned hi_byte = (conf.ide_scheme == IDE_NEMO)? (port & 1) : (port & 0x100);
342
             if (hi_byte)
343
             {
344
                 comp.ide_write = val;
345
                 return;
346
             }
347
             if ((port & 0x18) == 0x08)
348
             {
349
                 if ((port & 0xE0) == 0xC0)
350
                     hdd.write(8, val);
351
                 return;
352
             } // CS1=0,CS0=1,reg=6
353
             if ((port & 0x18) != 0x10)
354
                 return; // invalid CS0,CS1
355
             goto write_hdd_5;
356
         }
357
   }
358
 
359
   if((port & 0xFF) == 0x00 && conf.mem_model == MM_QUORUM)
360
   {
361
       comp.p00 = val;
362
       set_banks();
363
       return;
364
   }
365
 
366
   #ifdef MOD_VID_VD
367
   if ((unsigned char)port == 0xDF)
368
   {
369
       comp.pVD = val;
370
       comp.vdbase = (comp.pVD & 4)? vdmem[comp.pVD & 3] : 0;
371
       return;
372
   }
373
   #endif
374
 
375
   // port #FE
376
   bool pFE;
377
 
378
   // scorp  xx1xxx10 /dos=1 (sc16 green)
379
   if((conf.mem_model == MM_SCORP || conf.mem_model == MM_PROFSCORP) && !(comp.flags & CF_DOSPORTS))
380
       pFE = ((port & 0x23) == (0xFE & 0x23));
381
   else if(conf.mem_model == MM_QUORUM) // 1xx11xx0
382
       pFE = ((port & 0x99) == (0xFE & 0x99));
383
   else // others xxxxxxx0
384
       pFE = !(port & 1);
385
 
386
   if (pFE)
387
   {
388
//[vv]      assert(!(val & 0x08));
389
 
390
      spkr_dig = (val & 0x10) ? conf.sound.beeper_vol : 0;
391
      mic_dig = (val & 0x08) ? conf.sound.micout_vol : 0;
392
 
393
      // speaker & mic
394
      if ((comp.pFE ^ val) & 0x18)
395
      {
396
//          __debugbreak();
397
          flush_dig_snd();
398
      }
399
 
400
 
401
      unsigned char new_border = (val & 7);
402
      if (conf.mem_model == MM_ATM710 || conf.mem_model == MM_ATM3 || conf.mem_model == MM_ATM450)
403
          new_border |= ((port & 8) ^ 8); // port F6, bright border
404
      if (comp.border_attr ^ new_border)
405
          update_screen();
406
      comp.border_attr = new_border;
407
 
408
      if (conf.mem_model == MM_ATM450)
409
          set_atm_aFE((unsigned char)port);
410
 
411
      if (conf.mem_model == MM_PROFI)
412
      {
413
        if(!(port & 0x80) && (comp.pDFFD & 0x80))
414
        {
415
          comp.comp_pal[(~comp.pFE) & 0xF] = ~(port>>8);
416
          temp.comp_pal_changed = 1;
417
        }
418
      }
419
 
420
      comp.pFE = val;
421
      // do not return! intro to navy seals (by rst7) uses out #FC for to both FE and 7FFD
422
   }
423
 
424
   // #xD
425
   if (!(port & 2))
426
   {
427
 
428
      if (conf.sound.covoxDD && (unsigned char)port == 0xDD)
429
      { // port DD - covox
430
//         __debugbreak();
431
         flush_dig_snd();
432
         covDD_vol = val*conf.sound.covoxDD_vol/0x100;
433
         return;
434
      }
435
 
436
      if (!(port & 0x8000)) // zx128 port
437
      {
438
         // 0001xxxxxxxxxx0x (bcig4)
439
         if ((port & 0xF002) == (0x1FFD & 0xF002) && conf.mem_model == MM_PLUS3)
440
             goto set1FFD;
441
 
442
         if ((port & 0xC003) == (0x1FFD & 0xC003) && conf.mem_model == MM_KAY)
443
             goto set1FFD;
444
 
445
         // 00xxxxxxxx1xxx01 (sc16 green)
446
         if ((port & 0xC023) == (0x1FFD & 0xC023) && (conf.mem_model == MM_SCORP || conf.mem_model == MM_PROFSCORP))
447
         {
448
set1FFD:
449
            comp.p1FFD = val;
450
            set_banks();
451
            return;
452
         }
453
 
454
         // gmx
455
         if(port == 0x7EFD && conf.mem_model == MM_PROFSCORP)
456
         {
457
            comp.p7EFD = val;
458
            set_banks();
459
            return;
460
         }
461
 
462
         if (conf.mem_model == MM_ATM450 && (port & 0x8202) == (0x7DFD & 0x8202))
463
         {
464
             atm_writepal(val);
465
             return;
466
         }
467
 
468
         // if (conf.mem_model == MM_ATM710 && (port & 0x8202) != (0x7FFD & 0x8202)) return; // strict 7FFD decoding on ATM-2
469
 
470
         // 01xxxxxxxx1xxx01 (sc16 green)
471
         if ((port & 0xC023) != (0x7FFD & 0xC023) && (conf.mem_model == MM_SCORP || conf.mem_model == MM_PROFSCORP))
472
             return;
473
         // 0xxxxxxxxxx11x0x
474
         if ((port & 0x801A) != (0x7FFD & 0x801A) && (conf.mem_model == MM_QUORUM))
475
             return;
476
 
477
         // 7FFD
478
         if (comp.p7FFD & 0x20)
479
         { // 48k lock
480
            // #EFF7.2 forces lock
481
            if ((comp.pEFF7 & EFF7_LOCKMEM) && conf.mem_model == MM_PENTAGON && conf.ramsize == 1024)
482
                return;
483
 
484
            // if not pentagon-1024 or profi with #DFFD.4 set, apply lock
485
            if (!((conf.ramsize == 1024 && conf.mem_model == MM_PENTAGON) ||
486
                  (conf.mem_model == MM_PROFI && (comp.pDFFD & 0x10)))) // molodcov_alex
487
                return;
488
         }
489
 
490
         if ((comp.p7FFD ^ val) & 0x08)
491
             update_screen();
492
 
493
         comp.p7FFD = val;
494
         set_banks();
495
         return;
496
      }
497
 
498
      // xx0xxxxxxxxxxx0x (3.2) [vv]
499
      if ((port & 0x2002) == (0xDFFD & 0x2002) && conf.mem_model == MM_PROFI)
500
      {
501
          comp.pDFFD = val;
502
          set_banks();
503
          return;
504
      }
505
 
506
      if (conf.mem_model == MM_ATM450 && (port & 0x8202) == (0xFDFD & 0x8202))
507
      {
508
          comp.pFDFD = val;
509
          set_banks();
510
          return;
511
      }
512
 
513
      // 1x0xxxxxxxx11x0x
514
      if ((port & 0xA01A) == (0x80FD & 0xA01A) && conf.mem_model == MM_QUORUM)
515
      {
516
          comp.p80FD = val;
517
          set_banks();
518
          return;
519
      }
520
 
521
      if ((port & 0xC0FF) == 0xC0FD)
522
      { // A15=A14=1, FxFD - AY select register
523
         if ((conf.sound.ay_scheme == AY_SCHEME_CHRV) && ((val & 0xF8) == 0xF8)) //Alone Coder
524
         {
525
             if (conf.sound.ay_chip == (SNDCHIP::CHIP_YM2203))
526
             {
527
                 fmsoundon0 = val & 4;
528
                 tfmstatuson0 = val & 2;
529
             } //Alone Coder 0.36.6
530
             comp.active_ay = val & 1;
531
         };
532
         unsigned n_ay = (conf.sound.ay_scheme == AY_SCHEME_QUADRO)? (port >> 12) & 1 : comp.active_ay;
533
         ay[n_ay].select(val);
534
         return;
535
      }
536
 
537
      if ((port & 0xC000)==0x8000 && conf.sound.ay_scheme)
538
      {  // BFFD - AY data register
539
         unsigned n_ay = (conf.sound.ay_scheme == AY_SCHEME_QUADRO)? (port >> 12) & 1 : comp.active_ay;
540
         ay[n_ay].write(temp.sndblock? 0 : cpu.t, val);
541
         if (conf.input.mouse == 2 && ay[n_ay].get_activereg() == 14)
542
             input.aymouse_wr(val);
543
         return;
544
      }
545
      return;
546
   }
547
 
548
   if (conf.sound.sd && (port & 0xAF) == 0x0F)
549
   { // soundrive
550
//      __debugbreak();
551
      if ((unsigned char)port == 0x0F) comp.p0F = val;
552
      if ((unsigned char)port == 0x1F) comp.p1F = val;
553
      if ((unsigned char)port == 0x4F) comp.p4F = val;
554
      if ((unsigned char)port == 0x5F) comp.p5F = val;
555
      flush_dig_snd();
556
      sd_l = (conf.sound.sd_vol * (comp.p0F+comp.p1F)) >> 8;
557
      sd_r = (conf.sound.sd_vol * (comp.p4F+comp.p5F)) >> 8;
558
      return;
559
   }
560
   if (conf.sound.covoxFB && !(port & 4))
561
   { // port FB - covox
562
//      __debugbreak();
563
      flush_dig_snd();
564
      covFB_vol = val*conf.sound.covoxFB_vol/0x100;
565
      return;
566
   }
567
 
568
   if (conf.sound.saa1099 && ((port & 0xFF) == 0xFF)) // saa1099
569
   {
570
       if(port & 0x100)
571
           Saa1099.WrCtl(val);
572
       else
573
           Saa1099.WrData(temp.sndblock? 0 : cpu.t, val);
574
       return;
575
   }
576
 
577
   if (port == 0xEFF7 && conf.mem_model == MM_PENTAGON)
578
   {
579
      unsigned char oldpEFF7 = comp.pEFF7; //Alone Coder 0.36.4
580
      comp.pEFF7 = (comp.pEFF7 & conf.EFF7_mask) | (val & ~conf.EFF7_mask);
581
      comp.pEFF7 |= EFF7_GIGASCREEN; // [vv] disable turbo
582
//    if ((comp.pEFF7 ^ oldpEFF7) & EFF7_GIGASCREEN) {
583
//      conf.frame = frametime;
584
//      if ((conf.mem_model == MM_PENTAGON)&&(comp.pEFF7 & EFF7_GIGASCREEN))conf.frame = 71680;
585
//      apply_sound();
586
//    } //Alone Coder removed 0.37.1
587
 
588
      if (!(comp.pEFF7 & EFF7_4BPP))
589
      {
590
          temp.offset_vscroll = 0;
591
          temp.offset_vscroll_prev = 0;
592
          temp.offset_hscroll = 0;
593
          temp.offset_hscroll_prev = 0;
594
      }
595
 
596
      if ((comp.pEFF7 ^ oldpEFF7) & (EFF7_ROCACHE | EFF7_LOCKMEM))
597
          set_banks(); //Alone Coder 0.36.4
598
      return;
599
   }
600
   if (conf.cmos && (((comp.pEFF7 & EFF7_CMOS) && conf.mem_model == MM_PENTAGON) || conf.mem_model == MM_ATM3))
601
   {
602
      unsigned mask = (conf.mem_model == MM_ATM3 && (comp.flags & CF_DOSPORTS)) ? ~0x100 : 0xFFFF;
603
 
604
      if (port == (0xDFF7 & mask))
605
      {
606
          comp.cmos_addr = val;
607
          return;
608
      }
609
      if (port == (0xBFF7 & mask))
610
      {
611
          cmos_write(val);
612
          return;
613
      }
614
   }
615
   if ((port & 0xF8FF) == 0xF8EF && modem.open_port)
616
       modem.write((port >> 8) & 7, val);
617
}
618
 
619
__inline unsigned char in1(unsigned port)
620
{
621
   port &= 0xFFFF;
622
   brk_port_in = port;
623
 
624
   u8 p1 = (port & 0xFF);
625
 
626
/*
627
   if((port & 0xFF) == 0xF0)
628
       __debugbreak();
629
 
630
   if((comp.flags & CF_DOSPORTS) && port == 0xFADF)
631
       __debugbreak();
632
*/
633
 
634
   // В начале дешифрация портов по полным 8бит
635
   // ngs
636
   #ifdef MOD_GS
637
   if ((port & 0xF7) == 0xB3 && conf.gs_type)
638
       return in_gs(port);
639
   #endif
640
 
641
   // z-controller
642
   if (conf.zc && (port & 0xDF) == 0x57)
643
       return Zc.Rd(port);
644
 
645
   if(conf.mem_model == MM_ATM3)
646
   {
647
       // Порт расширений АТМ3
648
       if((port & 0xFF) == 0xBF)
649
           return comp.pBF;
650
 
651
       if((port & 0xFF) == 0xBE)
652
       {
653
           u8 port_hi = (port >> 8) & 0xFF;
654
           if((port_hi & ~7) == 0) // Чтение не инвертированного номера страницы
655
           {
656
               unsigned PgIdx = port_hi & 7;
657
               return (comp.pFFF7[PgIdx] & 0xFF) ^ 0xFF;
658
           }
659
 
660
           switch(port_hi)
661
           {
662
           case 0x8: // ram/rom
663
           {
664
               u8 RamRomMask = 0;
665
               for(unsigned i = 0; i < 8; i++)
666
                   RamRomMask |= ((comp.pFFF7[i] >> 8) & 1) << i;
667
               return ~RamRomMask;
668
           }
669
           case 0x9: //dos7ffd
670
           {
671
               u8 RamRomMask = 0;
672
               for(unsigned i = 0; i < 8; i++)
673
                   RamRomMask |= ((comp.pFFF7[i] >> 9) & 1) << i;
674
               return ~RamRomMask;
675
           }
676
           case 0xA: return comp.p7FFD;
677
//           case 0xB:;
678
           case 0xC: return  (((comp.aFF77 >> 14) & 1) << 7) |
679
                             (((comp.aFF77 >> 9) & 1) << 6) |
680
                             (((comp.aFF77 >> 8) & 1) << 5) |
681
                             ((comp.flags & CF_TRDOS) ? 0x10 : 0) |
682
                             (comp.pFF77 & 0xF);
683
           case 0xD: return atm_readpal();
684
           }
685
       }
686
   }
687
 
688
   // divide на nemo портах
689
   if(conf.ide_scheme == IDE_NEMO_DIVIDE)
690
   {
691
       if(((port & 0x1E) == 0x10)) // rrr1000x
692
       {
693
           if((port & 0xFF) == 0x11)
694
           {
695
               comp.ide_hi_byte_r = 0;
696
               return comp.ide_read;
697
           }
698
 
699
           if((port & 0xFE) == 0x10)
700
           {
701
               comp.ide_hi_byte_r ^= 1;
702
               if(!comp.ide_hi_byte_r)
703
               {
704
                   return comp.ide_read;
705
               }
706
           }
707
           else
708
           {
709
               comp.ide_hi_byte_r = 0;
710
           }
711
           goto read_hdd_5;
712
       }
713
       else if((port & 0xFF) == 0xC8)
714
       {
715
        return hdd.read(8);
716
       }
717
   }
718
 
719
   // quorum additional keyboard port
720
   if((conf.mem_model == MM_QUORUM) && ((port & 0xFF) == 0x7E))
721
   {
722
      u8 val = input.read_quorum(port >> 8);
723
      return val;
724
   }
725
 
726
   if (comp.flags & CF_DOSPORTS)
727
   {
728
      if(conf.mem_model == MM_ATM3 && (p1 & 0x1F) == 0x0F && (((p1 >> 5) - 1) < 5))
729
      {
730
          // 2F = 001|01111b
731
          // 4F = 010|01111b
732
          // 6F = 011|01111b
733
          // 8F = 100|01111b
734
          // AF = 101|01111b
735
          return comp.wd_shadow[(p1 >> 5) - 1];
736
      }
737
 
738
      if (conf.ide_scheme == IDE_ATM && (port & 0x1F) == 0x0F)
739
      {
740
         if (port & 0x100)
741
             return comp.ide_read;
742
      read_hdd_5:
743
         port >>= 5;
744
      read_hdd:
745
         port &= 7;
746
         if (port)
747
             return hdd.read(port);
748
         unsigned v = hdd.read_data();
749
         comp.ide_read = (unsigned char)(v >> 8);
750
         return (unsigned char)v;
751
      }
752
 
753
      if ((port & 0x18A3) == (0xFFFE & 0x18A3))
754
      { // SMUC
755
         if (conf.smuc)
756
         {
757
            if ((port & 0xA044) == (0xDFBA & 0xA044)) return cmos_read(); // clock
758
            if ((port & 0xA044) == (0xFFBA & 0xA044)) return comp.nvram.out; // SMUC system port
759
            if ((port & 0xA044) == (0x7FBA & 0xA044)) return comp.p7FBA | 0x3F;
760
            if ((port & 0xA044) == (0x5FBA & 0xA044)) return 0x3F;
761
            if ((port & 0xA044) == (0x5FBE & 0xA044)) return 0x57;
762
            if ((port & 0xA044) == (0x7FBE & 0xA044)) return 0x57;
763
         }
764
         if ((port & 0x8044) == (0xFFBE & 0x8044) && conf.ide_scheme == IDE_SMUC)
765
         { // FFBE, FEBE
766
            if(comp.pFFBA & 0x80)
767
            {
768
                if(!(port & 0x100))
769
                    return hdd.read(8); // alternate status
770
                return 0xFF; // obsolete register
771
            }
772
 
773
            if (!(port & 0x2000))
774
                return comp.ide_read;
775
            port >>= 8;
776
            goto read_hdd;
777
         }
778
      }
779
 
780
      unsigned char p1 = (unsigned char)port;
781
 
782
      if (conf.mem_model == MM_PROFI) // molodcov_alex
783
      {
784
          if((comp.p7FFD & 0x10) && (comp.pDFFD & 0x20))
785
          { // modified ports
786
            // BDI ports
787
            if((p1 & 0x9F) == 0x83)
788
                return comp.wd.in((p1 & 0x60) | 0x1F);  // WD93 ports (1F, 3F, 7F)
789
            if((p1 & 0xE3) == 0x23)
790
                return comp.wd.in(0xFF);                // port FF
791
 
792
            // RTC
793
            if((port & 0x9F) == 0x9F && conf.cmos)
794
            {
795
                if(!(port & 0x20))
796
                    return cmos_read();
797
            }
798
 
799
            // IDE
800
            if((p1 & 0x9F) == 0x8B && (conf.ide_scheme == IDE_PROFI))
801
            {
802
                if(p1 & 0x40) // cs1
803
                {
804
                    if (p1 & 0x20)
805
                        return comp.ide_read;
806
                    port >>= 8;
807
                    goto read_hdd;
808
                }
809
            }
810
          }
811
          else
812
          {
813
              // BDI ports
814
              if((p1 & 0x83) == 0x03)
815
                  return comp.wd.in((p1 & 0x60) | 0x1F);  // WD93 ports
816
              if((p1 & 0xE3) == ((comp.pDFFD & 0x20) ? 0xA3 : 0xE3))
817
                  return comp.wd.in(0xFF);                // port FF
818
          }
819
      }
820
 
821
      if(conf.mem_model == MM_QUORUM /* && !(comp.p00 & Q_TR_DOS) */) // cpm ports
822
      {
823
          if((p1 & 0xFC) == 0x80) // 80, 81, 82, 83
824
          {
825
              p1 = ((p1 & 3) << 5) | 0x1F;
826
              return comp.wd.in(p1);
827
          }
828
      }
829
          // 1F = 0001|1111b
830
          // 3F = 0011|1111b
831
          // 5F = 0101|1111b
832
          // 7F = 0111|1111b
833
          // DF = 1101|1111b порт мыши
834
          // FF = 1111|1111b
835
      else if ((p1 & 0x9F) == 0x1F || p1 == 0xFF) // 1F, 3F, 5F, 7F, FF
836
          return comp.wd.in(p1);
837
   }
838
   else // не dos
839
   {
840
       if(((port & 0xA3) == 0xA3) && (conf.ide_scheme == IDE_DIVIDE))
841
       {
842
           if((port & 0xFF) == 0xA3)
843
           {
844
               comp.ide_hi_byte_r ^= 1;
845
               if(!comp.ide_hi_byte_r)
846
               {
847
                   return comp.ide_read;
848
               }
849
           }
850
           else
851
           {
852
               comp.ide_hi_byte_r = 0;
853
           }
854
           port >>= 2;
855
           goto read_hdd;
856
       }
857
 
858
 
859
       if (!(port & 6) && (conf.ide_scheme == IDE_NEMO || conf.ide_scheme == IDE_NEMO_A8))
860
       {
861
          unsigned hi_byte = (conf.ide_scheme == IDE_NEMO)? (port & 1) : (port & 0x100);
862
          if(hi_byte)
863
              return comp.ide_read;
864
          comp.ide_read = 0xFF;
865
          if((port & 0x18) == 0x08)
866
              return ((port & 0xE0) == 0xC0)? hdd.read(8) : 0xFF; // CS1=0,CS0=1,reg=6
867
          if((port & 0x18) != 0x10)
868
              return 0xFF; // invalid CS0,CS1
869
          goto read_hdd_5;
870
       }
871
   }
872
 
873
 
874
   if ((conf.mem_model != MM_ATM3) && !(port & 0x20) ||
875
       (conf.mem_model == MM_ATM3) && (p1 == 0x1F || p1 == 0xDF))
876
   { // kempstons
877
      port = (port & 0xFFFF) | 0xFA00; // A13,A15 not used in decoding
878
      if ((port == 0xFADF || port == 0xFBDF || port == 0xFFDF) && conf.input.mouse == 1)
879
      { // mouse
880
         input.mouse_joy_led |= 1;
881
         if (port == 0xFBDF)
882
             return input.kempston_mx();
883
         if (port == 0xFFDF)
884
             return input.kempston_my();
885
         return input.mbuttons;
886
      }
887
      input.mouse_joy_led |= 2;
888
      unsigned char res = (conf.input.kjoy)? input.kjoy : 0xFF;
889
      if (conf.mem_model == MM_SCORP || conf.mem_model == MM_PROFSCORP)
890
         res = (res & 0x1F) | (comp.wd.in(0xFF) & 0xE0);
891
      return res;
892
   }
893
 
894
   // port #FE
895
   bool pFE;
896
 
897
   // scorp  xx1xxx10 (sc16)
898
   if((conf.mem_model == MM_SCORP || conf.mem_model == MM_PROFSCORP) && !(comp.flags & CF_DOSPORTS))
899
       pFE = ((port & 0x23) == (0xFE & 0x23));
900
   else if(conf.mem_model == MM_QUORUM) // 1xx11xx0
901
       pFE = ((port & 0x99) == (0xFE & 0x99));
902
   else // others xxxxxxx0
903
       pFE = !(port & 1);
904
 
905
   if (pFE)
906
   {
907
      if ((cpu.pc & 0xFFFF) == 0x0564 && bankr[0][0x0564]==0x1F && conf.tape_autostart && !comp.tape.play_pointer)
908
          start_tape();
909
      u8 val = input.read(port >> 8);
910
      if (conf.mem_model == MM_ATM450)
911
          val = (val & 0x7F) | atm450_z(cpu.t);
912
      return val;
913
   }
914
 
915
   if ((port & 0x8202) == (0x7FFD & 0x8202) && (conf.mem_model == MM_ATM710 || conf.ide_scheme == IDE_ATM))
916
   { // ATM-2 IDE+DAC/ADC
917
      unsigned char irq = 0x40;
918
      if (conf.ide_scheme == IDE_ATM) irq = (hdd.read_intrq() & 0x40);
919
      return irq + 0x3F;
920
   }
921
 
922
   if ((unsigned char)port == 0xFD && conf.sound.ay_scheme)
923
   {
924
      if((conf.sound.ay_scheme == AY_SCHEME_CHRV) && (conf.sound.ay_chip == (SNDCHIP::CHIP_YM2203)) && (tfmstatuson0 == 0))
925
          return 0x7f /*always ready*/; //Alone Coder 0.36.6
926
      if ((port & 0xC0FF) != 0xC0FD) return 0xFF;
927
      unsigned n_ay = (conf.sound.ay_scheme == AY_SCHEME_QUADRO)? (port >> 12) & 1 : comp.active_ay;
928
      // else FxFD - read selected AY register
929
      if (conf.input.mouse == 2 && ay[n_ay].get_activereg() == 14) { input.mouse_joy_led |= 1; return input.aymouse_rd(); }
930
      return ay[n_ay].read();
931
   }
932
 
933
//   if ((port & 0x7F) == 0x7B) { // FB/7B
934
   if ((port & 0x04) == 0x00)
935
   { // FB/7B //Alone Coder 0.36.6 (for MODPLAYi)
936
      if (conf.mem_model == MM_ATM450)
937
      {
938
         comp.aFB = (unsigned char)port;
939
         set_banks();
940
      }
941
      else if (conf.cache)
942
      {
943
         comp.flags &= ~CF_CACHEON;
944
         if (port & 0x80) comp.flags |= CF_CACHEON;
945
         set_banks();
946
      }
947
      return 0xFF;
948
   }
949
 
950
   if (conf.cmos && ((comp.pEFF7 & EFF7_CMOS) || conf.mem_model == MM_ATM3))
951
   {
952
      unsigned mask = (conf.mem_model == MM_ATM3 && (comp.flags & CF_DOSPORTS)) ? ~0x100 : 0xFFFF;
953
      if(port == (0xBFF7 & mask))
954
          return cmos_read();
955
   }
956
 
957
   if ((port & 0xF8FF) == 0xF8EF && modem.open_port)
958
       return modem.read((port >> 8) & 7);
959
 
960
   if (conf.portff && ((port & 0xFF) == 0xFF))
961
   {
962
      update_screen();
963
      if (vmode != 2) return 0xFF; // ray is not in paper
964
      unsigned ula_t = (cpu.t+temp.border_add) & temp.border_and;
965
      return temp.base[vcurr->atr_offs + (ula_t - vcurr[-1].next_t)/4];
966
   }
967
   return 0xFF;
968
}
969
 
970
unsigned char in(unsigned port)
971
{
972
   brk_port_val = in1(port);
973
   return brk_port_val;
974
}
975
 
976
#undef in_trdos
977
#undef out_trdos