Subversion Repositories pentevo

Rev

Rev 796 | Go to most recent revision | Blame | Compare with Previous | Last modification | View Log | Download | RSS feed

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