mirror of
https://github.com/ekeeke/Genesis-Plus-GX.git
synced 2025-01-23 16:41:11 +01:00
added cycle accurate sample generation
This commit is contained in:
parent
015710f3e0
commit
16cdbc33d2
@ -442,7 +442,7 @@ void m68k_write_memory_8 (unsigned int address, unsigned int value)
|
||||
case 0x13:
|
||||
case 0x15:
|
||||
case 0x17:
|
||||
psg_write (value);
|
||||
psg_write (0, value);
|
||||
return;
|
||||
|
||||
case 0x18: /* Unused */
|
||||
@ -481,7 +481,7 @@ void m68k_write_memory_8 (unsigned int address, unsigned int value)
|
||||
return;
|
||||
|
||||
case 0x4000:
|
||||
fm_write (address & 3, value);
|
||||
fm_write (0, address & 3, value);
|
||||
return;
|
||||
|
||||
case 0x6000:
|
||||
@ -619,7 +619,7 @@ void m68k_write_memory_16 (unsigned int address, unsigned int value)
|
||||
|
||||
case 0x10: /* PSG */
|
||||
case 0x14: /* PSG */
|
||||
psg_write (value & 0xFF);
|
||||
psg_write (0, value & 0xFF);
|
||||
return;
|
||||
|
||||
case 0x18: /* Unused */
|
||||
@ -654,7 +654,7 @@ void m68k_write_memory_16 (unsigned int address, unsigned int value)
|
||||
return;
|
||||
|
||||
case 0x4000: /* YM2612 */
|
||||
fm_write (address & 3, (value >> 8) & 0xFF);
|
||||
fm_write (0, address & 3, (value >> 8) & 0xFF);
|
||||
return;
|
||||
|
||||
case 0x6000: /* Bank register and VDP */
|
||||
|
@ -171,7 +171,7 @@ void z80bank_vdp_w(int address, int data)
|
||||
case 0x13:
|
||||
case 0x15:
|
||||
case 0x17:
|
||||
psg_write(data);
|
||||
psg_write(1, data);
|
||||
return;
|
||||
|
||||
case 0x18: /* Unused */
|
||||
|
@ -42,7 +42,7 @@ void cpu_writemem16(unsigned int address, unsigned int data)
|
||||
return;
|
||||
|
||||
case 2: /* YM2612 */
|
||||
fm_write(address & 3, data);
|
||||
fm_write(1, address & 3, data);
|
||||
return;
|
||||
|
||||
case 3: /* Bank register and VDP */
|
||||
@ -164,7 +164,7 @@ void z80_vdp_w(int address, int data)
|
||||
case 0x13:
|
||||
case 0x15:
|
||||
case 0x17:
|
||||
psg_write(data);
|
||||
psg_write(1, data);
|
||||
return;
|
||||
|
||||
case 0x10: /* Unused */
|
||||
|
@ -1,6 +1,6 @@
|
||||
/*
|
||||
sound.c
|
||||
YM2612 and SN76489 handler
|
||||
YM2612 and SN76489 emulation
|
||||
*/
|
||||
|
||||
#include "shared.h"
|
||||
@ -84,7 +84,7 @@ void fm_reset(void)
|
||||
fm_status = 0;
|
||||
}
|
||||
|
||||
void fm_write(int address, int data)
|
||||
void fm_write(uint8 cpu, int address, int data)
|
||||
{
|
||||
int a0 = (address & 1);
|
||||
int a1 = (address >> 1) & 1;
|
||||
@ -143,6 +143,10 @@ void fm_write(int address, int data)
|
||||
|
||||
if (snd.enabled)
|
||||
{
|
||||
|
||||
if (cpu) snd.fm.curStage = (count_z80 + current_z80 - z80_ICount) / z80cyc_per_sample; /* write from Z80 */
|
||||
else snd.fm.curStage = (count_m68k + m68k_cycles_run()) / m68cyc_per_sample; /* write from 68000 */
|
||||
|
||||
if(snd.fm.curStage - snd.fm.lastStage > 0)
|
||||
{
|
||||
if (FM_GENS)
|
||||
@ -159,6 +163,7 @@ void fm_write(int address, int data)
|
||||
tempBuffer[1] = snd.fm.buffer[1] + snd.fm.lastStage;
|
||||
YM2612UpdateOne(myFM, tempBuffer, snd.fm.curStage - snd.fm.lastStage);
|
||||
}
|
||||
|
||||
snd.fm.lastStage = snd.fm.curStage;
|
||||
}
|
||||
|
||||
@ -205,10 +210,13 @@ void fm_update_timers(int inc)
|
||||
}
|
||||
}
|
||||
|
||||
void psg_write(int data)
|
||||
void psg_write(uint8 cpu, int data)
|
||||
{
|
||||
if(snd.enabled)
|
||||
{
|
||||
if (cpu) snd.psg.curStage = (count_z80 + current_z80 - z80_ICount) / z80cyc_per_sample; /* write from Z80 */
|
||||
else snd.psg.curStage = (count_m68k + m68k_cycles_run()) / m68cyc_per_sample; /* write from 68000 */
|
||||
|
||||
if(snd.psg.curStage - snd.psg.lastStage > 0)
|
||||
{
|
||||
int16 *tempBuffer;
|
||||
|
@ -21,9 +21,9 @@ extern t_timer timer[2];
|
||||
void sound_init (void);
|
||||
void fm_reset (void);
|
||||
void fm_restore(void);
|
||||
void fm_write (int address, int data);
|
||||
void fm_write (uint8 cpu, int address, int data);
|
||||
int fm_read (int address);
|
||||
void fm_update_timers (int inc);
|
||||
void psg_write (int data);
|
||||
void psg_write (uint8 cpu, int data);
|
||||
|
||||
#endif /* _SOUND_H_ */
|
||||
|
@ -29,13 +29,14 @@ uint32 count_m68k = 0;
|
||||
uint32 dma_m68k = 0;
|
||||
uint32 aim_z80 = 0;
|
||||
uint32 count_z80 = 0;
|
||||
int32 current_z80 = 0;
|
||||
uint16 misc68Kcycles = 488;
|
||||
uint16 miscZ80cycles = 228;
|
||||
uint16 lines_per_frame = 262;
|
||||
uint16 m68cyc_per_sample = 160;
|
||||
uint16 z80cyc_per_sample = 75;
|
||||
double Master_Clock = (double)CLOCK_NTSC;
|
||||
void *myFM = NULL;
|
||||
static int sound_tbl[312];
|
||||
static int sound_inc[312];
|
||||
uint8 alttiming = 0;
|
||||
|
||||
void m68k_run (int cyc)
|
||||
@ -57,8 +58,8 @@ void m68k_run (int cyc)
|
||||
|
||||
void z80_run (int cyc)
|
||||
{
|
||||
int cyc_do = cyc - count_z80;
|
||||
if (cyc_do > 0) count_z80 += z80_execute(cyc_do);
|
||||
current_z80 = cyc - count_z80;
|
||||
if (current_z80 > 0) count_z80 += z80_execute(current_z80);
|
||||
}
|
||||
|
||||
void m68k_freeze(int cycles)
|
||||
@ -77,12 +78,12 @@ void m68k_freeze(int cycles)
|
||||
else m68ki_remaining_cycles -= cycles; /* we burn some 68k cycles */
|
||||
}
|
||||
|
||||
extern uint8 hq_fm;
|
||||
int audio_init (int rate)
|
||||
{
|
||||
int i;
|
||||
double sample_cyc;
|
||||
int vclk = (int)(Master_Clock / 7.0); /* 68000 and YM2612 clock */
|
||||
int zclk = (int)(Master_Clock / 15.0); /* Z80 and SN76489 clock */
|
||||
extern uint8 hq_fm;
|
||||
|
||||
/* Clear the sound data context */
|
||||
memset (&snd, 0, sizeof (snd));
|
||||
@ -130,14 +131,19 @@ int audio_init (int rate)
|
||||
if (FM_GENS) YM2612_Init(vclk, rate, hq_fm);
|
||||
else if (!myFM) myFM = YM2612Init (0, 0, vclk, rate, 0, 0);
|
||||
|
||||
/* Make sound table */
|
||||
for (i = 0; i < lines_per_frame; i++)
|
||||
{
|
||||
float p = (snd.buffer_size * i) / lines_per_frame;
|
||||
float q = (snd.buffer_size * (i+1)) / lines_per_frame;
|
||||
sound_tbl[i] = p;
|
||||
sound_inc[i] = ((q - p) * 1000000) / snd.sample_rate;
|
||||
}
|
||||
/*
|
||||
CYCLE-ACCURATE SAMPLES GENERATION:
|
||||
|
||||
We calculate number of cpu cycles between each new sound sample generation.
|
||||
Since both 68000 and Z80 can write to the sound chips, we need the cycles step for both CPU:
|
||||
At 48kHz, one sample is produced each 160 (NTSC) or 158 (PAL) 68k cycles
|
||||
which is equivalent to 75 (NTSC) or 74 (PAL) Z80 cycles
|
||||
*/
|
||||
sample_cyc = Master_Clock / 7.0 / ((double) rate);
|
||||
m68cyc_per_sample = (sample_cyc - (double)(int)sample_cyc) > 0.5 ? (int)(sample_cyc + 1) : (int)(sample_cyc);
|
||||
sample_cyc = Master_Clock / 15.0 / ((double) rate);
|
||||
z80cyc_per_sample = (sample_cyc - (double)(int)sample_cyc) > 0.5 ? (int)(sample_cyc + 1) : (int)(sample_cyc);
|
||||
|
||||
return (0);
|
||||
}
|
||||
|
||||
@ -296,10 +302,8 @@ int system_frame (int do_skip)
|
||||
if (zreset == 1 && zbusreq == 0) z80_run(aim_z80);
|
||||
else count_z80 = aim_z80;
|
||||
|
||||
/* Update sound buffers and timers */
|
||||
fm_update_timers (sound_inc[v_counter]);
|
||||
snd.fm.curStage = sound_tbl[v_counter];
|
||||
snd.psg.curStage = sound_tbl[v_counter];
|
||||
/* Update FM timers (one raster takes approx. 63.7 us) */
|
||||
fm_update_timers (64);
|
||||
}
|
||||
|
||||
if (snd.enabled) audio_update ();
|
||||
|
@ -54,9 +54,12 @@ extern uint32 count_m68k;
|
||||
extern uint32 dma_m68k;
|
||||
extern uint32 aim_z80;
|
||||
extern uint32 count_z80;
|
||||
extern int32 current_z80;
|
||||
extern uint16 misc68Kcycles;
|
||||
extern uint16 miscZ80cycles;
|
||||
extern uint16 lines_per_frame;
|
||||
extern uint16 m68cyc_per_sample;
|
||||
extern uint16 z80cyc_per_sample;
|
||||
extern double Master_Clock;
|
||||
|
||||
/* Function prototypes */
|
||||
|
Loading…
x
Reference in New Issue
Block a user