added cycle accurate sample generation

This commit is contained in:
ekeeke31 2007-08-20 19:44:24 +00:00
parent 015710f3e0
commit 16cdbc33d2
7 changed files with 58 additions and 43 deletions

View File

@ -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 */
@ -676,10 +676,10 @@ void m68k_write_memory_16 (unsigned int address, unsigned int value)
}
}
else if (address <= 0xA1001F) /* I/O */
{
io_write ((address >> 1) & 0x0F, value & 0x00FF);
return;
}
{
io_write ((address >> 1) & 0x0F, value & 0x00FF);
return;
}
else if (address <= 0xA1FFFF) /* CONTROL */
{
switch ((address >> 8) & 0xFF)

View File

@ -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 */

View File

@ -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 */

View File

@ -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;
@ -141,8 +141,12 @@ void fm_write(int address, int data)
fm_latch[a1] = data;
}
if(snd.enabled)
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;

View File

@ -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_ */

View File

@ -24,18 +24,19 @@
t_bitmap bitmap;
t_snd snd;
uint32 aim_m68k = 0;
uint32 aim_m68k = 0;
uint32 count_m68k = 0;
uint32 dma_m68k = 0;
uint32 aim_z80 = 0;
uint32 count_z80 = 0;
uint16 misc68Kcycles = 488;
uint16 miscZ80cycles = 228;
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;
double Master_Clock = (double)CLOCK_NTSC;
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);
}
@ -158,7 +164,7 @@ void system_init (void)
void system_reset (void)
{
aim_m68k = 0;
aim_m68k = 0;
count_m68k = 0;
dma_m68k = 0;
aim_z80 = 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 ();

View File

@ -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 */