Subversion Repositories pentevo

Rev

Rev 796 | Blame | Compare with Previous | Last modification | View Log | Download | RSS feed | ?url?

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