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