Subversion Repositories pentevo

Rev

Rev 716 | Blame | Last modification | View Log | Download | RSS feed

  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
  978.