Subversion Repositories pentevo

Rev

Details | Last modification | View Log | RSS feed

Rev Author Line No. Line
716 lvd 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