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 "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. 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. u8 *gsbankr[4] = { ROM_GS_M, GSRAM_M + 3 * PAGE, ROM_GS_M, ROM_GS_M + PAGE }; // bank pointers for read
  118. u8 *gsbankw[4] = { TRASH_M, GSRAM_M + 3 * PAGE, TRASH_M, TRASH_M }; // bank pointers for write
  119.  
  120. unsigned gs_v[4];
  121. unsigned char gsvol[4], gsbyte[4];
  122. unsigned led_gssum[4], led_gscnt[4];
  123. unsigned char gsdata_in, gsdata_out, gspage = 0;
  124. unsigned char gscmd, gsstat;
  125.  
  126. unsigned long long mult_gs, mult_gs2;
  127.  
  128. // ngs
  129. u8 ngs_mode_pg1; // page ex number
  130. u8 ngs_cfg0;
  131. u8 ngs_s_ctrl;
  132. u8 ngs_s_stat;
  133. u8 SdRdVal, SdRdValNew;
  134. u8 ngs_dmamod;
  135.  
  136.  
  137. bool SdDataAvail = false;
  138.  
  139. const int GSINTFQ = 37500; // hz
  140. static int 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.  
  154. static inline void flush_gs_sound()
  155. {
  156.    if (temp.sndblock)
  157.        return;
  158.  
  159.   unsigned l,r;         //!psb
  160.   l = gs_v[0] + gs_v[1];    //!psb
  161.   r = gs_v[2] + gs_v[3];    //!psb
  162.  
  163. //   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]);
  164.    unsigned lv, rv;
  165.    lv = (l + r/2) / 2;
  166.    rv = (r + l/2) / 2;
  167.  
  168. /*
  169.    if(gs_t_states < gscpu_t_at_frame_start)
  170.    {
  171.        printf("err: gs_t_states = %lld, gscpu_t_at_frame_start=%lld, gscpu.t = %u, t = %lld\n",
  172.            gs_t_states, gscpu_t_at_frame_start, gscpu.t, ((gs_t_states + gscpu.t)  - gscpu_t_at_frame_start));
  173.        fflush(stdout);
  174.    }
  175. */
  176.  
  177. //   assert(gs_t_states >= gscpu_t_at_frame_start);
  178.  
  179.    sound.update(unsigned((gs_t_states + gscpu.t) - gscpu_t_at_frame_start), lv, rv);     //!psb
  180.  
  181.    for (int ch = 0; ch < 4; ch++)
  182.    {
  183.       gsleds[ch].level = led_gssum[ch] * gsvol[ch] / (led_gscnt[ch]*(0x100*0x40/16)+1);
  184.       led_gssum[ch] = led_gscnt[ch] = 0;
  185.       gsleds[ch].attrib = 0x0F;
  186.    }
  187. }
  188.  
  189. void init_gs_frame()
  190. {
  191. //   printf("%s, gs_t_states = %lld, gscpu.t = %u\n", __FUNCTION__, gs_t_states, gscpu.t);
  192.    assert(gscpu.t < LONG_MAX);
  193.    gscpu_t_at_frame_start = gs_t_states + gscpu.t;
  194.    sound.start_frame();
  195. }
  196.  
  197. void flush_gs_frame()
  198. {
  199.    flush_gs_z80();
  200.  
  201. /*   printf("%s, gs_t_states = %lld, gscpu_t_at_frame_start = %lld, gscpu.t = %u, t = %lld\n",
  202.        __FUNCTION__, gs_t_states, gscpu_t_at_frame_start, gscpu.t,
  203.        ((gs_t_states + gscpu.t)  - gscpu_t_at_frame_start));
  204. */
  205.    sound.end_frame(unsigned((gs_t_states + gscpu.t) - gscpu_t_at_frame_start));
  206. }
  207.  
  208. void out_gs(unsigned port, u8 val)
  209. {
  210.    port &= 0xFF;
  211.  
  212.    switch(port)
  213.    {
  214.    case 0x33: // GSCTR
  215.        if(val & 0x80) // reset
  216.        {
  217.            reset();
  218.            flush_gs_z80();
  219.            return;
  220.        }
  221.        if(val & 0x40) // nmi
  222.        {
  223.            nmi();
  224.            flush_gs_z80();
  225.            return;
  226.        }
  227.        return;
  228.    break;
  229.    }
  230.  
  231.    flush_gs_z80();
  232.    switch(port)
  233.    {
  234.    case 0xB3: // GSDAT
  235.         gsdata_out = val;
  236.         gsstat |= 0x80;
  237.    break;
  238.    case 0xBB: // GSCOM
  239.        gscmd = val;
  240.        gsstat |= 0x01;
  241.    break;
  242.    }
  243. }
  244.  
  245. u8 in_gs(unsigned port)
  246. {
  247.    flush_gs_z80();
  248.    port &= 0xFF;
  249.    switch(port)
  250.    {
  251.    case 0xB3: gsstat &= 0x7F; return gsdata_in;
  252.    case 0xBB: return gsstat | 0x7E;
  253.    }
  254.    return 0xFF;
  255. }
  256.  
  257. static void gs_byte_to_dac(unsigned addr, unsigned char byte)
  258. {
  259.    flush_gs_sound();
  260.    unsigned chan = (addr>>8) & 3;
  261.    gsbyte[chan] = byte;
  262. //   gs_v[chan] = (gsbyte[chan] * gs_vfx[gsvol[chan]]) >> 8;
  263.    gs_v[chan] = ((signed char)(gsbyte[chan]-0x80) * (signed)gs_vfx[gsvol[chan]]) /256 + gs_vfx[33]; //!psb
  264.    led_gssum[chan] += byte;
  265.    led_gscnt[chan]++;
  266. }
  267.  
  268. static inline void stepi();
  269.  
  270. Z80INLINE u8 *am_r(u32 addr)
  271. {
  272.    return &gsbankr[(addr >> 14U) & 3][addr & (PAGE-1)];
  273. }
  274.  
  275. namespace z80fast
  276. {
  277.    #include "gsz80.inl"
  278. }
  279. namespace z80dbg
  280. {
  281.    #define Z80_DBG
  282.    #include "gsz80.inl"
  283.    #undef Z80_DBG
  284. }
  285.  
  286. u8 *__fastcall MemDbg(u32 addr)
  287. {
  288.     return am_r(addr);
  289. }
  290.  
  291. u8 __fastcall dbgrm(u32 addr)
  292. {
  293.     return z80dbg::rm(addr);
  294. }
  295.  
  296. void __fastcall dbgwm(u32 addr, u8 val)
  297. {
  298.     *am_r(addr) = val;
  299. }
  300.  
  301. void __cdecl BankNames(int i, char *Name)
  302. {
  303.     if(gsbankr[i] < GSRAM_M + MAX_GSRAM_PAGES*PAGE)
  304.         sprintf(Name, "RAM%2lX", ULONG((gsbankr[i] - GSRAM_M) / PAGE));
  305.     if((gsbankr[i] - ROM_GS_M) < PAGE*MAX_GSROM_PAGES)
  306.         sprintf(Name, "ROM%2lX", ULONG((gsbankr[i] - ROM_GS_M) / PAGE));
  307. }
  308.  
  309.  
  310. Z80INLINE unsigned char m1_cycle(Z80 *cpu)
  311. {
  312.    cpu->r_low++; cpu->t += 4;
  313.    return cpu->MemIf->xm(cpu->pc++);
  314. }
  315.  
  316. static inline void UpdateMemMapping()
  317. {
  318.     bool RamRo = (ngs_cfg0 & M_RAMRO) != 0;
  319.     bool NoRom = (ngs_cfg0 & M_NOROM) != 0;
  320.     if(NoRom)
  321.     {
  322.         gsbankr[0] = gsbankw[0] = GSRAM_M;
  323.         gsbankr[1] = gsbankw[1] = GSRAM_M + 3 * PAGE;
  324.         gsbankr[2] = gsbankw[2] = GSRAM_M + gspage * PAGE;
  325.         gsbankr[3] = gsbankw[3] = GSRAM_M + ngs_mode_pg1 * PAGE;
  326.  
  327.         if(RamRo)
  328.         {
  329.             if(gspage == 0 || gspage == 1) // RAM0 or RAM1 in PG2
  330.                gsbankw[2] = TRASH_M;
  331.             if(ngs_mode_pg1 == 0 || ngs_mode_pg1 == 1) // RAM0 or RAM1 in PG3
  332.                gsbankw[3] = TRASH_M;
  333.         }
  334.     }
  335.     else
  336.     {
  337.         gsbankw[0] = gsbankw[2] = gsbankw[3] = TRASH_M;
  338.         gsbankr[0] = ROM_GS_M;                                  // ROM0
  339.         gsbankr[1] = gsbankw[1] = GSRAM_M + 3 * PAGE;           // RAM3
  340.         gsbankr[2] = ROM_GS_M +  (gspage & 0x1F) * PAGE;        // ROMn
  341.         gsbankr[3] = ROM_GS_M +  (ngs_mode_pg1 & 0x1F) * PAGE;  // ROMm
  342.     }
  343. }
  344.  
  345. void out(unsigned port, unsigned char val)
  346. {
  347. //   printf(__FUNCTION__" port=0x%X, val=0x%X\n", (port & 0xFF), val);
  348.    switch (port & 0xFF)
  349.    {
  350.       case MPAG:
  351.       {
  352.          bool ExtMem = (ngs_cfg0 & M_EXPAG) != 0;
  353.  
  354.          gspage = rol8(val, 1) & temp.gs_ram_mask & (ExtMem ? 0xFF : 0xFE);
  355.  
  356.          if(!ExtMem)
  357.              ngs_mode_pg1 = (rol8(val, 1) & temp.gs_ram_mask) | 1;
  358. //         printf(__FUNCTION__"->GSPG, %X, Ro=%d, NoRom=%d, Ext=%d\n", gspage, RamRo, NoRom, ExtMem);
  359.          UpdateMemMapping();
  360.          return;
  361.       }
  362.       case 0x02: gsstat &= 0x7F; return;
  363.       case 0x03: gsstat |= 0x80; gsdata_in = val; return;
  364.       case 0x05: gsstat &= 0xFE; return;
  365.       case 0x06: case 0x07: case 0x08: case 0x09:
  366.       {
  367.          flush_gs_sound();
  368.          unsigned chan = (port & 0x0F)-6; val &= 0x3F;
  369.          gsvol[chan] = val;
  370. //         gs_v[chan] = (gsbyte[chan] * gs_vfx[gsvol[chan]]) >> 8;
  371.          gs_v[chan] = ((signed char)(gsbyte[chan]-0x80) * (signed)gs_vfx[gsvol[chan]]) /256 + gs_vfx[33]; //!psb
  372.          return;
  373.       }
  374.       case 0x0A: gsstat = (gsstat & 0x7F) | (gspage << 7); return;
  375.       case 0x0B: gsstat = (gsstat & 0xFE) | ((gsvol[0] >> 5) & 1); return;
  376.  
  377.    }
  378.  
  379. //   printf(__FUNCTION__" port=0x%X, val=0x%X\n", (port & 0xFF), val);
  380.    // ngs
  381.    switch (port & 0xFF)
  382.    {
  383.       case GSCFG0:
  384.       {
  385.           ngs_cfg0 = val & 0x3F;
  386. //          printf(__FUNCTION__"->GSCFG0, %X, Ro=%d, NoRom=%d, Ext=%d\n", ngs_cfg0, RamRo, NoRom, ExtMem);
  387.           UpdateMemMapping();
  388.       }
  389.       break;
  390.  
  391.       case MPAGEX:
  392.       {
  393. //          assert((ngs_cfg0 & M_EXPAG) != 0);
  394.           ngs_mode_pg1 = rol8(val, 1) & temp.gs_ram_mask;
  395.           UpdateMemMapping();
  396.       }
  397.       break;
  398.  
  399.       case S_CTRL:
  400. //          printf(__FUNCTION__"->S_CTRL\n");
  401.           if(val & 0x80)
  402.               ngs_s_ctrl |= (val & 0xF);
  403.           else
  404.               ngs_s_ctrl &= ~(val & 0xF);
  405.  
  406.           if(!(ngs_s_ctrl & _MPXRS))
  407.               Vs1001.Reset();
  408.  
  409.           Vs1001.SetNcs((ngs_s_ctrl & _MPNCS) != false);
  410.       break;
  411.  
  412.       case MC_SEND:
  413.           Vs1001.WrCmd(val);
  414.       break;
  415.  
  416.       case MD_SEND:
  417.           Vs1001.Wr(val);
  418.       break;
  419.  
  420.       case SD_SEND:
  421.           SdCard.Wr(val);
  422.           SdRdValNew = SdCard.Rd();
  423.           SdDataAvail = true;
  424.       break;
  425.  
  426.       case DMA_MOD:
  427.           ngs_dmamod = val;
  428.       break;
  429.  
  430.       case DMA_HAD:
  431.           if (ngs_dmamod == 1)
  432.               temp.gsdmaaddr = (temp.gsdmaaddr&0x0000ffff)|(unsigned(val & 0x1F)<<16); // 5bit only
  433.       break;
  434.  
  435.       case DMA_MAD:
  436.           if (ngs_dmamod == 1)
  437.               temp.gsdmaaddr = (temp.gsdmaaddr&0x001f00ff)|(unsigned(val)<<8);
  438.       break;
  439.  
  440.       case DMA_LAD:
  441.           if (ngs_dmamod == 1)
  442.               temp.gsdmaaddr = (temp.gsdmaaddr&0x001fff00)|val;
  443.       break;
  444.  
  445.       case DMA_CST:
  446.           if (ngs_dmamod == 1)
  447.               temp.gsdmaon = val;
  448.       break;
  449.    }
  450. }
  451.  
  452. unsigned char in(unsigned port)
  453. {
  454.    switch (port & 0xFF)
  455.    {
  456.       case 0x01: return gscmd;
  457.       case 0x02: gsstat &= 0x7F; return gsdata_out;
  458.       case 0x03: gsstat |= 0x80; gsdata_in = 0xFF; return 0xFF;
  459.       case 0x04: return gsstat;
  460.       case 0x05: gsstat &= 0xFE; return 0xFF;
  461.       case 0x0A: gsstat = (gsstat & 0x7F) | (gspage << 7); return 0xFF;
  462.       case 0x0B: gsstat = (gsstat & 0xFE) | (gsvol[0] >> 5); return 0xFF;
  463.  
  464.  
  465.       // ngs
  466.       case GSCFG0:
  467.           return ngs_cfg0;
  468.       case S_CTRL:
  469.           return ngs_s_ctrl;
  470.  
  471.       case S_STAT:
  472.           if(Vs1001.GetDreq())
  473.               ngs_s_stat |= _MPDRQ;
  474.           else
  475.               ngs_s_stat &= ~_MPDRQ;
  476.           return ngs_s_stat;
  477.  
  478.       case MC_READ:
  479.           return Vs1001.Rd();
  480.  
  481.       case SD_READ:
  482.       {
  483.           u8 Tmp = SdRdVal;
  484.           SdRdVal = SdRdValNew;
  485.           return Tmp;
  486.       }
  487.       case SD_RSTR:
  488.           if(SdDataAvail)
  489.           {
  490.               SdDataAvail = false;
  491.               return SdRdValNew;
  492.           }
  493.           return SdCard.Rd();
  494.  
  495.       case DMA_MOD:
  496.           return ngs_dmamod;
  497.  
  498.       case DMA_HAD:
  499.           if (ngs_dmamod == 1)
  500.               return (temp.gsdmaaddr>>16) & 0x1F; // 5bit only
  501.       break;
  502.  
  503.       case DMA_MAD:
  504.           if (ngs_dmamod == 1)
  505.               return (temp.gsdmaaddr>>8) & 0xFF;
  506.       break;
  507.  
  508.       case DMA_LAD:
  509.           if (ngs_dmamod == 1)
  510.               return temp.gsdmaaddr & 0xFF;
  511.       break;
  512.  
  513.       case DMA_CST:
  514.           if (ngs_dmamod == 1)
  515.               return temp.gsdmaon;
  516.       break;
  517.    }
  518.    return 0xFF;
  519. }
  520.  
  521. //#include "z80/cmd.cpp"
  522.  
  523. static inline void stepi()
  524. {
  525.    u8 opcode = m1_cycle(&gscpu);
  526.    (::normal_opcode[opcode])(&gscpu);
  527. }
  528.  
  529. void Z80FAST step()
  530. {
  531.     stepi();
  532. }
  533.  
  534. void flush_gs_z80()
  535. {
  536.    if(gscpu.dbgchk)
  537.    {
  538.        gscpu.SetDbgMemIf();
  539.        z80gs::z80dbg::z80loop();
  540.    }
  541.    else
  542.    {
  543.        gscpu.SetFastMemIf();
  544.        z80gs::z80fast::z80loop();
  545.    }
  546. }
  547.  
  548. __int64 __cdecl delta()
  549. {
  550.     return gs_t_states + gscpu.t - gscpu.debug_last_t;
  551. }
  552.  
  553. void __cdecl SetLastT()
  554. {
  555.    gscpu.debug_last_t = gs_t_states + gscpu.t;
  556. }
  557.  
  558. void nmi()
  559. {
  560.    gscpu.sp -= 2;
  561.    z80fast::wm(gscpu.sp, gscpu.pcl);
  562.    z80fast::wm(gscpu.sp+1, gscpu.pch);
  563.    gscpu.pc = 0x66;
  564.    gscpu.iff1 = gscpu.halted = 0;
  565. }
  566.  
  567. void reset()
  568. {
  569.    gscpu.reset();
  570.    gsbankr[0] = ROM_GS_M; gsbankr[1] = GSRAM_M + 3 * PAGE; gsbankr[2] = ROM_GS_M; gsbankr[3] = ROM_GS_M + PAGE;
  571.    gsbankw[0] = TRASH_M; gsbankw[1] = GSRAM_M + 3 * PAGE; gsbankw[2] = TRASH_M, gsbankw[3] = TRASH_M;
  572.  
  573.    gscpu.t = 0;
  574.    gs_t_states = 0;
  575.    gscpu_t_at_frame_start = 0;
  576.    ngs_cfg0 = 0;
  577.    ngs_s_stat = u8(rdtsc() & ~7) | _SDDET | _MPDRQ;
  578.    ngs_s_ctrl = u8(rdtsc() & ~0xF) | _SDNCS;
  579.    SdRdVal = SdRdValNew = 0xFF;
  580.    SdDataAvail = false;
  581.    Vs1001.Reset();
  582.  
  583.    ngs_mode_pg1 = 1;
  584.    ngs_dmamod = 0;
  585.    temp.gsdmaaddr = 0;
  586.    temp.gsdmaon = 0;
  587.    SdCard.Reset();
  588. }
  589.  
  590. } // end of z80gs namespace
  591. #endif
  592.