Top secrets sources NedoPC pentevo

Rev

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

#include "std.h"

#include "emul.h"
#include "vars.h"
#include "memory.h"
#include "util.h"

// input: ports 7FFD,1FFD,DFFD,FFF7,FF77,EFF7, flags CF_TRDOS,CF_CACHEON
void set_banks()
{
   bankw[1] = bankr[1] = RAM_BASE_M + 5*PAGE;
   bankw[2] = bankr[2] = RAM_BASE_M + 2*PAGE;

   // screen begining
   temp.base = memory + ((comp.p7FFD & 8) ? 7*PAGE : 5*PAGE);
/*
   if(conf.mem_model == MM_QUORUM)
       temp.base = memory + (comp.p80FD & 7) * 0x2000 + 5*PAGE;
*/


   if (temp.base_2)
       temp.base_2 = temp.base;

   // these flags will be re-calculated
   comp.flags &= ~(CF_DOSPORTS | CF_Z80FBUS | CF_LEAVEDOSRAM | CF_LEAVEDOSADR | CF_SETDOSROM);

   unsigned char *bank0, *bank3;

   if (comp.flags & CF_TRDOS)
   {
       if(comp.p7FFD & 0x10)
       {
           bank0 = base_dos_rom;
       }
       else
       {
           bank0 = base_sys_rom;
       }
   }
   else
       bank0 = (comp.p7FFD & 0x10)? base_sos_rom : base_128_rom;

   unsigned bank = (comp.p7FFD & 7);

   switch (conf.mem_model)
   {
      case MM_PENTAGON:
         if(!(comp.pEFF7 & EFF7_LOCKMEM))
         {
             // 7FFD bits
             //    210 - 128
             //   6210 - 256
             //  76210 - 512
             // 576210 - 1024
             bank |= (comp.p7FFD & 0xC0) >> 3;
             bank |= (comp.p7FFD & 0x20);
         }

         bank3 = RAM_BASE_M + (bank & temp.ram_mask)*PAGE;

         if (comp.pEFF7 & EFF7_ROCACHE)
             bank0 = RAM_BASE_M + 0*PAGE; //Alone Coder 0.36.4
         break;

      case MM_PROFSCORP:
         membits[0x0100] &= ~MEMBITS_R;
         membits[0x0104] &= ~MEMBITS_R;
         membits[0x0108] &= ~MEMBITS_R;
         membits[0x010C] &= ~MEMBITS_R;
      case MM_SCORP:
         bank += ((comp.p1FFD & 0x10) >> 1) + ((comp.p1FFD & 0xC0) >> 2);
         bank3 = RAM_BASE_M + (bank & temp.ram_mask) * PAGE;

/*
         // îáðàáîòêà ïàìÿòè gmx (êîíôëèêòóåò ñî ñòàíäàðòíûì profrom)
         // íóæíî ñäåëàòü ôëàã çàïèñè â ïîðò 7EFD, è åñëè áûëà õîòü îäíà çàïèñü
         // òî îáðàáàòûâàòü rom ïî ñòàíäàðòó gmx
         comp.profrom_bank = ((comp.p7EFD >> 4) & 3) & temp.profrom_mask;
         {
             unsigned char *base = ROM_BASE_M + (comp.profrom_bank * 64*1024);
             base_128_rom = base + 0*PAGE;
             base_sos_rom = base + 1*PAGE;
             base_sys_rom = base + 2*PAGE;
             base_dos_rom = base + 3*PAGE;
         }
*/


         // Äîðàáîòêà èç êíèæêè gmx (âêëþ÷åíèå ïîðòîâ dos èç ÎÇÓ, ñäåëàíî íåìíîãî íå òàê êàê â ðåàëüíîé ñõåìå)
         if(comp.p1FFD & 4)
             comp.flags |= CF_TRDOS;
         if(comp.p1FFD & 2)
            bank0 = base_sys_rom;
         if(comp.p1FFD & 1)
            bank0 = RAM_BASE_M + 0 * PAGE;
         if(conf.mem_model == MM_PROFSCORP)
         {
             if (bank0 == base_sys_rom)
                 comp.flags |= CF_PROFROM;
             else
                 comp.flags &= ~CF_PROFROM;
         }
         break;

      case MM_KAY:
      {
         bank += ((comp.p1FFD & 0x10) >> 1) + ((comp.p1FFD & 0x80) >> 3) + ((comp.p7FFD & 0x80) >> 2);
         bank3 = RAM_BASE_M + (bank & temp.ram_mask)*PAGE;
         unsigned char rom1 = (comp.p1FFD >> 2) & 2;
         if (comp.flags & CF_TRDOS) rom1 ^= 2;
         switch (rom1+((comp.p7FFD & 0x10) >> 4))
         {
            case 0: bank0 = base_128_rom; break;
            case 1: bank0 = base_sos_rom; break;
            case 2: bank0 = base_sys_rom; break;
            case 3: bank0 = base_dos_rom; break;
            default: __assume(0);
         }
         if (comp.p1FFD & 1) bank0 = RAM_BASE_M + 0*PAGE;
         break;
      }

      case MM_PROFI:
         bank += ((comp.pDFFD & 0x07U) << 3U); bank3 = RAM_BASE_M + (bank & temp.ram_mask)*PAGE;
         if(comp.pDFFD & 0x08)
         {
             bankr[1] = bankw[1] = bank3;
             bank3 = RAM_BASE_M + 7 * PAGE;
         }
         if (comp.pDFFD & 0x10) bank0 = RAM_BASE_M+0*PAGE;
         if (comp.pDFFD & 0x20) comp.flags |= CF_DOSPORTS;
         if (comp.pDFFD & 0x40) bankr[2] = bankw[2] = RAM_BASE_M + 6*PAGE;
         break;

      case MM_ATM450:
      {
         // RAM
         // original ATM uses D2 as ROM address extension, not RAM
         bank += ((comp.pFDFD & 0x07U) << 3U);
         bank3 = RAM_BASE_M + (bank & temp.ram_mask)*PAGE;
         if (!(comp.aFE & 0x80))
         {
            bankw[1] = bankr[1] = RAM_BASE_M + 4*PAGE;
            bank0 = RAM_BASE_M;
            break;
         }

         // ROM
         if (comp.p7FFD & 0x20)
             comp.aFB &= ~0x80;
         if ((comp.flags & CF_TRDOS) && (comp.pFDFD & 8))
             comp.aFB |= 0x80; // more priority, then 7FFD

         if (comp.aFB & 0x80) // CPSYS signal
         {
             bank0 = base_sys_rom;
             break;
         }
         // system rom not used on 7FFD.4=0 and DOS=1
         if (comp.flags & CF_TRDOS)
             bank0 = base_dos_rom;
         break;
      }

      case MM_ATM3:
         if (comp.pBF & 1) // shaden
            comp.flags |= CF_DOSPORTS;

      case MM_ATM710:
      {
         if (!(comp.aFF77 & 0x200)) // ~cpm=0
            comp.flags |= CF_TRDOS;

         if (!(comp.aFF77 & 0x100))
         { // pen=0
            bankr[1] = bankr[2] = bank3 = bank0 = ROM_BASE_M + PAGE * temp.rom_mask;
            break;
         }

         unsigned i = ((comp.p7FFD & 0x10) >> 2);
         for (unsigned bank = 0; bank < 4; bank++)
         {
            switch (comp.pFFF7[i+bank] & 0x300)
            {
               case 0x000: // RAM from 7FFD
                  bankr[bank] = bankw[bank] = RAM_BASE_M + PAGE * ((comp.p7FFD & 7) | (comp.pFFF7[i+bank] & 0xF8 & temp.ram_mask));
                  break;
               case 0x100: // ROM from 7FFD
                  bankr[bank] = ROM_BASE_M + PAGE*((comp.pFFF7[i+bank] & 0xFE & temp.rom_mask) + ((comp.flags & CF_TRDOS)?1:0));
                  break;
               case 0x200: // RAM from FFF7
                  bankr[bank] = bankw[bank] = RAM_BASE_M + PAGE*(comp.pFFF7[i+bank] & 0xFF & temp.ram_mask);
                  break;
               case 0x300: // ROM from FFF7
                  bankr[bank] = ROM_BASE_M + PAGE*(comp.pFFF7[i+bank] & 0xFF & temp.rom_mask);
                  break;
            }
         }
         bank0 = bankr[0]; bank3 = bankr[3];

         if(conf.mem_model == MM_ATM3 && cpu.nmi_in_progress)
             bank0 = RAM_BASE_M + PAGE * 0xFF;
         break;
      }

      case MM_PLUS3:
      {
          if(comp.p7FFD & 0x20) // paging disabled (48k mode)
          {
              bank3 = RAM_BASE_M + (bank & temp.ram_mask)*PAGE;
              break;
          }

          if(!(comp.p1FFD & 1))
          {
              unsigned RomBank = ((comp.p1FFD & 4) >> 1) | ((comp.p7FFD & 0x10) >> 4);
              switch(RomBank)
              {
                 case 0: bank0 = base_128_rom; break;
                 case 1: bank0 = base_sys_rom; break;
                 case 2: bank0 = base_dos_rom; break;
                 case 3: bank0 = base_sos_rom; break;
              }
              bank3 = RAM_BASE_M + (bank & temp.ram_mask)*PAGE;
          }
          else
          {
              unsigned RamPage = (comp.p1FFD >> 1) & 3; // d2,d1
              static const unsigned RamDecoder[4][4] =
              { {0, 1, 2, 3}, {4, 5, 6, 7}, {4, 5, 6, 3}, {4, 7, 6, 3} };
              for(unsigned i = 0; i < 4; i++)
                  bankw[i] = bankr[i] = RAM_BASE_M + PAGE * RamDecoder[RamPage][i];
              bank0 = bankr[0];
              bank3 = bankr[3];
          }
          break;
      }

      case MM_QUORUM:
      {
          if(!(comp.p00 & Q_TR_DOS))
              comp.flags |= CF_DOSPORTS;

          if(comp.p00 & Q_B_ROM)
          {
              if (comp.flags & CF_TRDOS)
                  bank0 = base_dos_rom;
              else
                  bank0 = (comp.p7FFD & 0x10) ? base_sos_rom : base_128_rom;
          }
          else
          {
              bank0 = base_sys_rom;
          }

          if(comp.p00 & Q_F_RAM)
          {
              unsigned bnk0 = (comp.p00 & Q_RAM_8) ? 8 : 0;
              bank0 = RAM_BASE_M + (bnk0 & temp.ram_mask) * PAGE;
          }

          bank |= ((comp.p7FFD & 0xC0) >> 3) | (comp.p7FFD & 0x20);
          bank3 = RAM_BASE_M + (bank & temp.ram_mask) * PAGE;
          break;
      }

      default: bank3 = RAM_BASE_M + 0*PAGE;
   }

   bankw[0] = bankr[0] = bank0;
   bankw[3] = bankr[3] = bank3;

   if (bankr[0] >= ROM_BASE_M) bankw[0] = TRASH_M;
   if (bankr[1] >= ROM_BASE_M) bankw[1] = TRASH_M;
   if (bankr[2] >= ROM_BASE_M) bankw[2] = TRASH_M;
   if (bankr[3] >= ROM_BASE_M) bankw[3] = TRASH_M;


   unsigned char dosflags = CF_LEAVEDOSRAM;
   if (conf.mem_model == MM_PENTAGON || conf.mem_model == MM_PROFI)
       dosflags = CF_LEAVEDOSADR;

   if (comp.flags & CF_TRDOS)
   {
       comp.flags |= dosflags | CF_DOSPORTS;
   }
   else if ((comp.p7FFD & 0x10) && conf.trdos_present)
   { // B-48, inactive DOS, DOS present
      // for Scorp, ATM-1/2 and KAY, TR-DOS not started on executing RAM 3Dxx
      if (!((dosflags & CF_LEAVEDOSRAM) && bankr[0] < RAM_BASE_M+PAGE*MAX_RAM_PAGES))
         comp.flags |= CF_SETDOSROM;
   }

   if (comp.flags & CF_CACHEON)
   {
      unsigned char *cpage = CACHE_M;
      if (conf.cache == 32 && !(comp.p7FFD & 0x10)) cpage += PAGE;
      bankr[0] = bankw[0] = cpage;
      // if (comp.pEFF7 & EFF7_ROCACHE) bankw[0] = TRASH_M; //Alone Coder 0.36.4
   }

   if ((comp.flags & CF_DOSPORTS)? conf.floatdos : conf.floatbus)
       comp.flags |= CF_Z80FBUS;

   if (temp.led.osw && (trace_rom | trace_ram))
   {
      for (unsigned i = 0; i < 4; i++) {
         unsigned bank = unsigned((bankr[i] - RAM_BASE_M) / PAGE);
         if (bank < MAX_PAGES) used_banks[bank] = 1;
      }
   }

/*
    if ((unsigned)(bankr[0] - ROM_BASE_M) < PAGE*MAX_ROM_PAGES)
    {
        printf("ROM%2X\n", (bankr[0] - ROM_BASE_M)/PAGE);
        printf("DOS=%p\n",  base_dos_rom);
        printf("SVM=%p\n",  base_sys_rom);
        printf("SOS=%p\n",  base_sos_rom);
        printf("128=%p\n",  base_128_rom);
    }
*/

}

void set_scorp_profrom(unsigned read_address)
{
   static unsigned char switch_table[] =
   {
      0,1,2,3,
      3,3,3,2,
      2,2,0,1,
      1,0,1,0
   };
   comp.profrom_bank = switch_table[read_address*4 + comp.profrom_bank] & temp.profrom_mask;
   unsigned char *base = ROM_BASE_M + (comp.profrom_bank * 64*1024);
   base_128_rom = base + 0*PAGE;
   base_sos_rom = base + 1*PAGE;
   base_sys_rom = base + 2*PAGE;
   base_dos_rom = base + 3*PAGE;
   set_banks();
}

/*
u8 *__fastcall MemDbg(u32 addr)
{
    return am_r(addr);
}

void __fastcall wmdbg(u32 addr, u8 val)
{
   *am_r(addr) = val;
}

u8 __fastcall rmdbg(u32 addr)
{
   return *am_r(addr);
}
*/


void set_mode(ROM_MODE mode)
{
   if (mode == RM_NOCHANGE)
       return;

   if (mode == RM_CACHE)
   {
       comp.flags |= CF_CACHEON;
       set_banks();
       return;
   }

   // no RAM/cache/SERVICE
   comp.p1FFD &= ~7;
   comp.pDFFD &= ~0x10;
   comp.flags &= ~CF_CACHEON;

   // comp.aFF77 |= 0x100; // enable ATM memory

   switch (mode)
   {
      case RM_128:
         comp.flags &= ~CF_TRDOS;
         comp.p7FFD &= ~0x10;
         break;
      case RM_SOS:
         comp.flags &= ~CF_TRDOS;
         comp.p7FFD |= 0x10;

         if(conf.mem_model == MM_PLUS3) // disable paging
            comp.p7FFD |= 0x20;
         break;
      case RM_SYS:
         comp.flags |= CF_TRDOS;
         comp.p7FFD &= ~0x10;
         break;
      case RM_DOS:
         comp.flags |= CF_TRDOS;
         comp.p7FFD |=  0x10;
         if(conf.mem_model == MM_ATM710 || conf.mem_model == MM_ATM3)
             comp.p7FFD &=  ~0x10;
         break;
   }
   set_banks();
}

static unsigned char cmosBCD(unsigned char binary)
{
   if (!(cmos[11] & 4)) binary = (binary % 10) + 0x10*((binary/10)%10);
   return binary;
}

unsigned char cmos_read()
{
   static SYSTEMTIME st;
   static bool UF = false;
   static unsigned Seconds = 0;
   static unsigned long long last_tsc = 0ULL;
   unsigned char reg = comp.cmos_addr;
   unsigned char rv;
   if (conf.cmos == 2)
       reg &= 0x3F;

   if ((1 << reg) & ((1<<0)|(1<<2)|(1<<4)|(1<<6)|(1<<7)|(1<<8)|(1<<9)|(1<<12)))
   {
      unsigned long long tsc = rdtsc();
      // [vv] ×àñû ÷èòàþòñÿ íå ÷àùå äâóõ ðàç â ñåêóíäó
      if ((tsc-last_tsc) >= 25 * temp.ticks_frame)
      {
          GetLocalTime(&st);
          if(st.wSecond != Seconds)
          {
              UF = true;
              Seconds = st.wSecond;
          }
      }
   }

   switch (reg)
   {
      case 0:     return cmosBCD((BYTE)st.wSecond);
      case 2:     return cmosBCD((BYTE)st.wMinute);
      case 4:     return cmosBCD((BYTE)st.wHour);
      case 6:     return 1+(((BYTE)st.wDayOfWeek+8-conf.cmos) % 7);
      case 7:     return cmosBCD((BYTE)st.wDay);
      case 8:     return cmosBCD((BYTE)st.wMonth);
      case 9:     return cmosBCD(st.wYear % 100);
      case 10:    return 0x20 | (cmos [10] & 0xF); // molodcov_alex
      case 11:    return (cmos[11] & 4) | 2;
      case 12:  // [vv] UF
          rv = UF ? 0x10 : 0;
          UF = false;
          return rv;
      case 13:    return 0x80;
   }
   return cmos[reg];
}

void cmos_write(unsigned char val)
{
   if (conf.cmos == 2) comp.cmos_addr &= 0x3F;
   cmos[comp.cmos_addr] = val;
}

void NVRAM::write(unsigned char val)
{
   const int SCL = 0x40, SDA = 0x10, //WP = 0x20,
             SDA_1 = 0xFF, SDA_0 = 0xBF,
             SDA_SHIFT_IN = 4;

   if ((val ^ prev) & SCL) // clock edge, data in/out
   {
      if (val & SCL) // nvram reads SDA
      {
         if (state == RD_ACK)
         {
            if (val & SDA) goto idle; // no ACK, stop
            // move next byte to host
            state = SEND_DATA;
            dataout = nvram[address];
            address = (address+1) & 0x7FF;
            bitsout = 0; goto exit; // out_z==1;
         }

         if ((1<<state) & ((1<<RCV_ADDR)|(1<<RCV_CMD)|(1<<RCV_DATA))) {
             if(out_z) // skip nvram ACK before reading
             {
                 datain = 2 * datain + ((val >> SDA_SHIFT_IN) & 1);
                 bitsin++;
             }
         }

      } else { // nvram sets SDA

         if (bitsin == 8) // byte received
         {
            bitsin = 0;
            if (state == RCV_CMD) {
               if ((datain & 0xF0) != 0xA0) goto idle;
               address = (address & 0xFF) + ((datain << 7) & 0x700);
               if (datain & 1) { // read from current address
                  dataout = nvram[address];
                  address = (address+1) & 0x7FF;
                  bitsout = 0;
                  state = SEND_DATA;
               } else
                  state = RCV_ADDR;
            } else if (state == RCV_ADDR) {
               address = (address & 0x700) + datain;
               state = RCV_DATA; bitsin = 0;
            } else if (state == RCV_DATA) {
               nvram[address] = datain;
               address = (address & 0x7F0) + ((address+1) & 0x0F);
               // state unchanged
            }

            // EEPROM always acknowledges
            out = SDA_0; out_z = 0; goto exit;
         }

         if (state == SEND_DATA) {
            if (bitsout == 8) { state = RD_ACK; out_z = 1; goto exit; }
            out = (dataout & 0x80)? SDA_1 : SDA_0; dataout *= 2;
            bitsout++; out_z = 0; goto exit;
         }

         out_z = 1; // no ACK, reading
      }
      goto exit;
   }

   if ((val & SCL) && ((val ^ prev) & SDA)) // start/stop
   {
      if (val & SDA) { idle: state = IDLE; } // stop
      else // start
      {
          state = RCV_CMD;
          bitsin = 0;
      }
      out_z = 1;
   }

   // else SDA changed on low SCL


 exit:
   if (out_z) out = (val & SDA)? SDA_1 : SDA_0;
   prev = val;
}