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 "vars.h"
  5. #include "gs.h"
  6. #include "gsz80.h"
  7. #include "vs1001.h"
  8. #include "sdcard.h"
  9. #include "debug.h"
  10.  
  11. #include "z80/op_noprefix.h"
  12.  
  13. #ifdef MOD_GSZ80
  14. namespace z80gs
  15. {
  16. unsigned __int64 gs_t_states; // inc'ed with GSCPUINT every gs int
  17. static unsigned __int64 gscpu_t_at_frame_start; // gs_t_states+gscpu.t when spectrum frame begins
  18.  
  19. Z80INLINE unsigned char rm(unsigned addr);
  20. u8 __fastcall dbgrm(u32 addr);
  21. Z80INLINE void wm(unsigned addr, unsigned char val);
  22. void __fastcall dbgwm(u32 addr, u8 val);
  23. Z80INLINE u8 *am_r(u32 addr);
  24. Z80INLINE unsigned char m1_cycle(Z80 *cpu);
  25. unsigned char in(unsigned port);
  26. void out(unsigned port, unsigned char val);
  27. // FIXME: ╤фхырЄ№ яхЁхъы■ўрхь√щ шэЄхЁЇхщё т чртшёшьюёЄш юЄ Їырур gscpu.dbgchk
  28. namespace z80fast
  29. {
  30. Z80INLINE unsigned char xm(unsigned addr);
  31. Z80INLINE unsigned char rm(unsigned addr);
  32. Z80INLINE void wm(unsigned addr, unsigned char val);
  33. }
  34.  
  35. namespace z80dbg
  36. {
  37. Z80INLINE unsigned char xm(unsigned addr);
  38. Z80INLINE unsigned char rm(unsigned addr);
  39. Z80INLINE void wm(unsigned addr, unsigned char val);
  40. }
  41.  
  42. u8 __fastcall Xm(u32 addr)
  43. {
  44.     return z80gs::z80fast::xm(addr);
  45. }
  46.  
  47. u8 __fastcall Rm(u32 addr)
  48. {
  49.     return z80gs::z80fast::rm(addr);
  50. }
  51.  
  52. void __fastcall Wm(u32 addr, u8 val)
  53. {
  54.     z80gs::z80fast::wm(addr, val);
  55. }
  56.  
  57. u8 __fastcall DbgXm(u32 addr)
  58. {
  59.     return z80gs::z80dbg::xm(addr);
  60. }
  61.  
  62. u8 __fastcall DbgRm(u32 addr)
  63. {
  64.     return z80gs::z80dbg::rm(addr);
  65. }
  66.  
  67. void __fastcall DbgWm(u32 addr, u8 val)
  68. {
  69.     z80gs::z80dbg::wm(addr, val);
  70. }
  71. }
  72.  
  73. u8 *TGsZ80::DirectMem(unsigned addr) const
  74. {
  75.     return z80gs::am_r(addr);
  76. }
  77.  
  78. unsigned char TGsZ80::m1_cycle()
  79. {
  80.     return z80gs::m1_cycle(this);
  81. }
  82.  
  83. unsigned char TGsZ80::in(unsigned port)
  84. {
  85.     return z80gs::in(port);
  86. }
  87.  
  88. void TGsZ80::out(unsigned port, unsigned char val)
  89. {
  90.     z80gs::out(port, val);
  91. }
  92.  
  93. void TGsZ80::retn()
  94. {
  95.     nmi_in_progress = false;
  96. }
  97.  
  98. namespace z80gs
  99. {
  100. #include "z80/op_system.h"
  101.  
  102. const u8 MPAG   = 0x00;
  103. const u8 MPAGEX = 0x10;
  104.  
  105. const u8 DMA_MOD= 0x1b;
  106. const u8 DMA_HAD= 0x1c;
  107. const u8 DMA_MAD= 0x1d;
  108. const u8 DMA_LAD= 0x1e;
  109. const u8 DMA_CST= 0x1f;
  110.  
  111. const u8 GSCFG0 = 0x0F;
  112.  
  113. const u8 M_NOROM = 1;
  114. const u8 M_RAMRO = 2;
  115. const u8 M_EXPAG = 8;
  116.  
  117. static u8 *gsbankr[4] = { ROM_GS_M, GSRAM_M + 3 * PAGE, ROM_GS_M, ROM_GS_M + PAGE }; // bank pointers for read
  118. static u8 *gsbankw[4] = { TRASH_M, GSRAM_M + 3 * PAGE, TRASH_M, TRASH_M }; // bank pointers for write
  119.  
  120. static unsigned gs_v[4];
  121. static unsigned char gsvol[4], gsbyte[4];
  122. static unsigned led_gssum[4], led_gscnt[4];
  123. static unsigned char gsdata_in, gsdata_out, gspage = 0;
  124. static unsigned char gscmd, gsstat;
  125.  
  126. static unsigned long long mult_gs, mult_gs2;
  127.  
  128. // ngs
  129. static u8 ngs_mode_pg1; // page ex number
  130. static u8 ngs_cfg0;
  131. static u8 ngs_s_ctrl;
  132. static u8 ngs_s_stat;
  133. static u8 SdRdVal, SdRdValNew;
  134. static u8 ngs_dmamod;
  135.  
  136.  
  137. static bool SdDataAvail = false;
  138.  
  139. const unsigned GSINTFQ = 37500; // hz
  140. static unsigned GSCPUFQI;
  141. const unsigned GSCPUINT = GSCPUFQ/GSINTFQ;
  142. const int MULT_GS_SHIFT = 12; // cpu tick -> gscpu tick precision
  143. void flush_gs_z80();
  144. void reset();
  145. void nmi();
  146.  
  147. void apply_gs()
  148. {
  149.    GSCPUFQI = GSCPUFQ / conf.intfq;
  150.    mult_gs = (temp.snd_frame_ticks << MULT_C)/GSCPUFQI;
  151.    mult_gs2 = (GSCPUFQI<<MULT_GS_SHIFT)/conf.frame;
  152.  
  153.    make_gs_volume();
  154. }
  155.  
  156. static inline void flush_gs_sound()
  157. {
  158.    if (temp.sndblock)
  159.        return;
  160.  
  161.   unsigned l,r;         //!psb
  162.   l = gs_v[0] + gs_v[1];    //!psb
  163.   r = gs_v[2] + gs_v[3];    //!psb
  164.  
  165. //   sound.update(gscpu.t + (unsigned) (gs_t_states - gscpu_t_at_frame_start), gs_v[0] + gs_v[1], gs_v[2] + gs_v[3]);
  166.    unsigned lv, rv;
  167.    lv = (l + r/2) / 2;
  168.    rv = (r + l/2) / 2;
  169.  
  170. /*
  171.    if(gs_t_states < gscpu_t_at_frame_start)
  172.    {
  173.        printf("err: gs_t_states = %lld, gscpu_t_at_frame_start=%lld, gscpu.t = %u, t = %lld\n",
  174.            gs_t_states, gscpu_t_at_frame_start, gscpu.t, ((gs_t_states + gscpu.t)  - gscpu_t_at_frame_start));
  175.        fflush(stdout);
  176.    }
  177. */
  178.  
  179. //   assert(gs_t_states >= gscpu_t_at_frame_start);
  180.  
  181.    sound.update(unsigned((gs_t_states + gscpu.t) - gscpu_t_at_frame_start), lv, rv);     //!psb
  182.  
  183.    for (int ch = 0; ch < 4; ch++)
  184.    {
  185.       gsleds[ch].level = led_gssum[ch] * gsvol[ch] / (led_gscnt[ch]*(0x100*0x40/16)+1);
  186.       led_gssum[ch] = led_gscnt[ch] = 0;
  187.       gsleds[ch].attrib = 0x0F;
  188.    }
  189. }
  190.  
  191. void init_gs_frame()
  192. {
  193. //   printf("%s, gs_t_states = %lld, gscpu.t = %u\n", __FUNCTION__, gs_t_states, gscpu.t);
  194.    assert(gscpu.t < LONG_MAX);
  195.    gscpu_t_at_frame_start = gs_t_states + gscpu.t;
  196.    sound.start_frame();
  197. }
  198.  
  199. void flush_gs_frame()
  200. {
  201.    flush_gs_z80();
  202.  
  203. /*   printf("%s, gs_t_states = %lld, gscpu_t_at_frame_start = %lld, gscpu.t = %u, t = %lld\n",
  204.        __FUNCTION__, gs_t_states, gscpu_t_at_frame_start, gscpu.t,
  205.        ((gs_t_states + gscpu.t)  - gscpu_t_at_frame_start));
  206. */
  207.    sound.end_frame(unsigned((gs_t_states + gscpu.t) - gscpu_t_at_frame_start));
  208. }
  209.  
  210. void out_gs(unsigned port, u8 val)
  211. {
  212.    port &= 0xFF;
  213.  
  214.    switch(port)
  215.    {
  216.    case 0x33: // GSCTR
  217.        if(val & 0x80) // reset
  218.        {
  219.            reset();
  220.            flush_gs_z80();
  221.            return;
  222.        }
  223.        if(val & 0x40) // nmi
  224.        {
  225.            nmi();
  226.            flush_gs_z80();
  227.            return;
  228.        }
  229.        return;
  230.    }
  231.  
  232.    flush_gs_z80();
  233.    switch(port)
  234.    {
  235.    case 0xB3: // GSDAT
  236.         gsdata_out = val;
  237.         gsstat |= 0x80;
  238.    break;
  239.    case 0xBB: // GSCOM
  240.        gscmd = val;
  241.        gsstat |= 0x01;
  242.    break;
  243.    }
  244. }
  245.  
  246. u8 in_gs(unsigned port)
  247. {
  248.    flush_gs_z80();
  249.    port &= 0xFF;
  250.    switch(port)
  251.    {
  252.    case 0xB3: gsstat &= 0x7F; return gsdata_in;
  253.    case 0xBB: return gsstat | 0x7E;
  254.    }
  255.    return 0xFF;
  256. }
  257.  
  258. static void gs_byte_to_dac(unsigned addr, unsigned char byte)
  259. {
  260.    flush_gs_sound();
  261.    unsigned chan = (addr>>8) & 3;
  262.    gsbyte[chan] = byte;
  263. //   gs_v[chan] = (gsbyte[chan] * gs_vfx[gsvol[chan]]) >> 8;
  264.    gs_v[chan] = unsigned(((signed char)(gsbyte[chan]-0x80) * (signed)gs_vfx[gsvol[chan]]) /256 + int(gs_vfx[33])); //!psb
  265.    led_gssum[chan] += byte;
  266.    led_gscnt[chan]++;
  267. }
  268.  
  269. static inline void stepi();
  270.  
  271. Z80INLINE u8 *am_r(u32 addr)
  272. {
  273.    return &gsbankr[(addr >> 14U) & 3][addr & (PAGE-1)];
  274. }
  275.  
  276. namespace z80fast
  277. {
  278.    #include "gsz80.inl"
  279. }
  280. namespace z80dbg
  281. {
  282.    #define Z80_DBG
  283.    #include "gsz80.inl"
  284.    #undef Z80_DBG
  285. }
  286.  
  287. u8 *__fastcall MemDbg(u32 addr);
  288.  
  289. u8 *__fastcall MemDbg(u32 addr)
  290. {
  291.     return am_r(addr);
  292. }
  293.  
  294. u8 __fastcall dbgrm(u32 addr)
  295. {
  296.     return z80dbg::rm(addr);
  297. }
  298.  
  299. void __fastcall dbgwm(u32 addr, u8 val)
  300. {
  301.     *am_r(addr) = val;
  302. }
  303.  
  304. void __cdecl BankNames(int i, char *Name)
  305. {
  306.     if(gsbankr[i] < GSRAM_M + MAX_GSRAM_PAGES*PAGE)
  307.         sprintf(Name, "RAM%2lX", ULONG((gsbankr[i] - GSRAM_M) / PAGE));
  308.     if((gsbankr[i] - ROM_GS_M) < PAGE*MAX_GSROM_PAGES)
  309.         sprintf(Name, "ROM%2lX", ULONG((gsbankr[i] - ROM_GS_M) / PAGE));
  310. }
  311.  
  312.  
  313. Z80INLINE unsigned char m1_cycle(Z80 *cpu)
  314. {
  315.    cpu->r_low++; cpu->t += 4;
  316.    return cpu->MemIf->xm(cpu->pc++);
  317. }
  318.  
  319. static inline void UpdateMemMapping()
  320. {
  321.     bool RamRo = (ngs_cfg0 & M_RAMRO) != 0;
  322.     bool NoRom = (ngs_cfg0 & M_NOROM) != 0;
  323.     if(NoRom)
  324.     {
  325.         gsbankr[0] = gsbankw[0] = GSRAM_M;
  326.         gsbankr[1] = gsbankw[1] = GSRAM_M + 3 * PAGE;
  327.         gsbankr[2] = gsbankw[2] = GSRAM_M + gspage * PAGE;
  328.         gsbankr[3] = gsbankw[3] = GSRAM_M + ngs_mode_pg1 * PAGE;
  329.  
  330.         if(RamRo)
  331.         {
  332.             if(gspage == 0 || gspage == 1) // RAM0 or RAM1 in PG2
  333.                gsbankw[2] = TRASH_M;
  334.             if(ngs_mode_pg1 == 0 || ngs_mode_pg1 == 1) // RAM0 or RAM1 in PG3
  335.                gsbankw[3] = TRASH_M;
  336.         }
  337.     }
  338.     else
  339.     {
  340.         gsbankw[0] = gsbankw[2] = gsbankw[3] = TRASH_M;
  341.         gsbankr[0] = ROM_GS_M;                                  // ROM0
  342.         gsbankr[1] = gsbankw[1] = GSRAM_M + 3 * PAGE;           // RAM3
  343.         gsbankr[2] = ROM_GS_M +  (gspage & 0x1F) * PAGE;        // ROMn
  344.         gsbankr[3] = ROM_GS_M +  (ngs_mode_pg1 & 0x1F) * PAGE;  // ROMm
  345.     }
  346. }
  347.  
  348. void out(unsigned port, unsigned char val)
  349. {
  350. //   printf(__FUNCTION__" port=0x%X, val=0x%X\n", (port & 0xFF), val);
  351.    switch (port & 0xFF)
  352.    {
  353.       case MPAG:
  354.       {
  355.          bool ExtMem = (ngs_cfg0 & M_EXPAG) != 0;
  356.  
  357.          gspage = rol8(val, 1) & temp.gs_ram_mask & (ExtMem ? 0xFF : 0xFE);
  358.  
  359.          if(!ExtMem)
  360.              ngs_mode_pg1 = (rol8(val, 1) & temp.gs_ram_mask) | 1;
  361. //         printf(__FUNCTION__"->GSPG, %X, Ro=%d, NoRom=%d, Ext=%d\n", gspage, RamRo, NoRom, ExtMem);
  362.          UpdateMemMapping();
  363.          return;
  364.       }
  365.       case 0x02: gsstat &= 0x7F; return;
  366.       case 0x03: gsstat |= 0x80; gsdata_in = val; return;
  367.       case 0x05: gsstat &= 0xFE; return;
  368.       case 0x06: case 0x07: case 0x08: case 0x09:
  369.       {
  370.          flush_gs_sound();
  371.          unsigned chan = (port & 0x0F)-6; val &= 0x3F;
  372.          gsvol[chan] = val;
  373. //         gs_v[chan] = (gsbyte[chan] * gs_vfx[gsvol[chan]]) >> 8;
  374.          gs_v[chan] = unsigned(((signed char)(gsbyte[chan]-0x80) * (signed)gs_vfx[gsvol[chan]]) /256 + int(gs_vfx[33])); //!psb
  375.          return;
  376.       }
  377.       case 0x0A: gsstat = u8((gsstat & 0x7F) | (gspage << 7)); return;
  378.       case 0x0B: gsstat = u8((gsstat & 0xFE) | ((gsvol[0] >> 5) & 1)); return;
  379.  
  380.    }
  381.  
  382. //   printf(__FUNCTION__" port=0x%X, val=0x%X\n", (port & 0xFF), val);
  383.    // ngs
  384.    switch (port & 0xFF)
  385.    {
  386.       case GSCFG0:
  387.       {
  388.           ngs_cfg0 = val & 0x3F;
  389. //          printf(__FUNCTION__"->GSCFG0, %X, Ro=%d, NoRom=%d, Ext=%d\n", ngs_cfg0, RamRo, NoRom, ExtMem);
  390.           UpdateMemMapping();
  391.       }
  392.       break;
  393.  
  394.       case MPAGEX:
  395.       {
  396. //          assert((ngs_cfg0 & M_EXPAG) != 0);
  397.           ngs_mode_pg1 = rol8(val, 1) & temp.gs_ram_mask;
  398.           UpdateMemMapping();
  399.       }
  400.       break;
  401.  
  402.       case S_CTRL:
  403. //          printf(__FUNCTION__"->S_CTRL\n");
  404.           if(val & 0x80)
  405.               ngs_s_ctrl |= (val & 0xF);
  406.           else
  407.               ngs_s_ctrl &= ~(val & 0xF);
  408.  
  409.           if(!(ngs_s_ctrl & _MPXRS))
  410.               Vs1001.Reset();
  411.  
  412.           Vs1001.SetNcs((ngs_s_ctrl & _MPNCS) != false);
  413.       break;
  414.  
  415.       case MC_SEND:
  416.           Vs1001.WrCmd(val);
  417.       break;
  418.  
  419.       case MD_SEND:
  420.           Vs1001.Wr(val);
  421.       break;
  422.  
  423.       case SD_SEND:
  424.           SdCard.Wr(val);
  425.           SdRdValNew = SdCard.Rd();
  426.           SdDataAvail = true;
  427.       break;
  428.  
  429.       case DMA_MOD:
  430.           ngs_dmamod = val;
  431.       break;
  432.  
  433.       case DMA_HAD:
  434.           if (ngs_dmamod == 1)
  435.               temp.gsdmaaddr = (temp.gsdmaaddr&0x0000ffff)|(unsigned(val & 0x1F)<<16); // 5bit only
  436.       break;
  437.  
  438.       case DMA_MAD:
  439.           if (ngs_dmamod == 1)
  440.               temp.gsdmaaddr = (temp.gsdmaaddr&0x001f00ff)|(unsigned(val)<<8);
  441.       break;
  442.  
  443.       case DMA_LAD:
  444.           if (ngs_dmamod == 1)
  445.               temp.gsdmaaddr = (temp.gsdmaaddr&0x001fff00)|val;
  446.       break;
  447.  
  448.       case DMA_CST:
  449.           if (ngs_dmamod == 1)
  450.               temp.gsdmaon = val;
  451.       break;
  452.    }
  453. }
  454.  
  455. unsigned char in(unsigned port)
  456. {
  457.    switch (port & 0xFF)
  458.    {
  459.       case 0x01: return gscmd;
  460.       case 0x02: gsstat &= 0x7F; return gsdata_out;
  461.       case 0x03: gsstat |= 0x80; gsdata_in = 0xFF; return 0xFF;
  462.       case 0x04: return gsstat;
  463.       case 0x05: gsstat &= 0xFE; return 0xFF;
  464.       case 0x0A: gsstat = u8((gsstat & 0x7F) | (gspage << 7)); return 0xFF;
  465.       case 0x0B: gsstat = u8((gsstat & 0xFE) | (gsvol[0] >> 5)); return 0xFF;
  466.  
  467.  
  468.       // ngs
  469.       case GSCFG0:
  470.           return ngs_cfg0;
  471.       case S_CTRL:
  472.           return ngs_s_ctrl;
  473.  
  474.       case S_STAT:
  475.           if(Vs1001.GetDreq())
  476.               ngs_s_stat |= _MPDRQ;
  477.           else
  478.               ngs_s_stat &= ~_MPDRQ;
  479.           return ngs_s_stat;
  480.  
  481.       case MC_READ:
  482.           return Vs1001.Rd();
  483.  
  484.       case SD_READ:
  485.       {
  486.           u8 Tmp = SdRdVal;
  487.           SdRdVal = SdRdValNew;
  488.           return Tmp;
  489.       }
  490.       case SD_RSTR:
  491.           if(SdDataAvail)
  492.           {
  493.               SdDataAvail = false;
  494.               return SdRdValNew;
  495.           }
  496.           return SdCard.Rd();
  497.  
  498.       case DMA_MOD:
  499.           return ngs_dmamod;
  500.  
  501.       case DMA_HAD:
  502.           if (ngs_dmamod == 1)
  503.               return (temp.gsdmaaddr>>16) & 0x1F; // 5bit only
  504.       break;
  505.  
  506.       case DMA_MAD:
  507.           if (ngs_dmamod == 1)
  508.               return (temp.gsdmaaddr>>8) & 0xFF;
  509.       break;
  510.  
  511.       case DMA_LAD:
  512.           if (ngs_dmamod == 1)
  513.               return temp.gsdmaaddr & 0xFF;
  514.       break;
  515.  
  516.       case DMA_CST:
  517.           if (ngs_dmamod == 1)
  518.               return temp.gsdmaon;
  519.       break;
  520.    }
  521.    return 0xFF;
  522. }
  523.  
  524. //#include "z80/cmd.cpp"
  525.  
  526. static inline void stepi()
  527. {
  528.    u8 opcode = m1_cycle(&gscpu);
  529.    (::normal_opcode[opcode])(&gscpu);
  530. }
  531.  
  532. void Z80FAST step();
  533.  
  534. void Z80FAST step()
  535. {
  536.     stepi();
  537. }
  538.  
  539. void flush_gs_z80()
  540. {
  541.    if(gscpu.dbgchk)
  542.    {
  543.        gscpu.SetDbgMemIf();
  544.        z80gs::z80dbg::z80loop();
  545.    }
  546.    else
  547.    {
  548.        gscpu.SetFastMemIf();
  549.        z80gs::z80fast::z80loop();
  550.    }
  551. }
  552.  
  553. __int64 __cdecl delta()
  554. {
  555.     return i64(gs_t_states) + gscpu.t - gscpu.debug_last_t;
  556. }
  557.  
  558. void __cdecl SetLastT()
  559. {
  560.    gscpu.debug_last_t = i64(gs_t_states + gscpu.t);
  561. }
  562.  
  563. void nmi()
  564. {
  565.    gscpu.sp -= 2;
  566.    z80fast::wm(gscpu.sp, gscpu.pcl);
  567.    z80fast::wm(gscpu.sp+1, gscpu.pch);
  568.    gscpu.pc = 0x66;
  569.    gscpu.iff1 = gscpu.halted = 0;
  570. }
  571.  
  572. void reset()
  573. {
  574.    gscpu.reset();
  575.    gsbankr[0] = ROM_GS_M; gsbankr[1] = GSRAM_M + 3 * PAGE; gsbankr[2] = ROM_GS_M; gsbankr[3] = ROM_GS_M + PAGE;
  576.    gsbankw[0] = TRASH_M; gsbankw[1] = GSRAM_M + 3 * PAGE; gsbankw[2] = TRASH_M; gsbankw[3] = TRASH_M;
  577.  
  578.    gscpu.t = 0;
  579.    gs_t_states = 0;
  580.    gscpu_t_at_frame_start = 0;
  581.    ngs_cfg0 = 0;
  582.    ngs_s_stat = u8(u8(rdtsc() & ~7U) | _SDDET | _MPDRQ);
  583.    ngs_s_ctrl = u8(u8(rdtsc() & ~0xFU) | _SDNCS);
  584.    SdRdVal = SdRdValNew = 0xFF;
  585.    SdDataAvail = false;
  586.    Vs1001.Reset();
  587.  
  588.    ngs_mode_pg1 = 1;
  589.    ngs_dmamod = 0;
  590.    temp.gsdmaaddr = 0;
  591.    temp.gsdmaon = 0;
  592.    SdCard.Reset();
  593. }
  594.  
  595. } // end of z80gs namespace
  596. #endif
  597.