improved Pro Action Replay emulation (still not working completely)

added cycle-accurate YM2612 reset handler
some fixes in FIR resampler
This commit is contained in:
ekeeke31 2009-08-14 16:46:19 +00:00
parent 0d58ff65e0
commit a2ece6f81b
13 changed files with 147 additions and 151 deletions

View File

@ -472,7 +472,7 @@ void cart_hw_reset()
break;
case TYPE_AR:
datel_reset();
datel_reset(1);
break;
case TYPE_SK:

View File

@ -64,7 +64,7 @@ void datel_init(void)
{
case TYPE_AR:
{
/* internal registers mapped at $0000-$ffff */
/* internal registers mapped at $010000-$01ffff */
m68k_memory_map[0x01].write16 = ar_write_regs;
/* $0000-$7fff mirrored into $8000-$ffff */
@ -74,18 +74,15 @@ void datel_init(void)
case TYPE_PRO1:
{
/* internal registers mapped at $0000-$ffff */
/* internal registers mapped at $010000-$01ffff */
m68k_memory_map[0x01].write16 = ar_write_regs;
/* RAM (64k) mapped at $400000-$7fffff */
for (i=0x40; i<0x80; i++)
{
m68k_memory_map[i].base = action_replay.ram;
m68k_memory_map[i].read8 = NULL;
m68k_memory_map[i].read16 = NULL;
m68k_memory_map[i].write8 = NULL;
m68k_memory_map[i].write16 = NULL;
}
/* RAM (64k) mapped at $420000-$42ffff */
m68k_memory_map[0x42].base = action_replay.ram;
m68k_memory_map[0x42].read8 = NULL;
m68k_memory_map[0x42].read16 = NULL;
m68k_memory_map[0x42].write8 = NULL;
m68k_memory_map[0x42].write16 = NULL;
break;
}
@ -94,15 +91,12 @@ void datel_init(void)
/* internal registers mapped at $100000-$10ffff */
m68k_memory_map[0x10].write16 = ar_write_regs_pro2;
/* RAM (64k) mapped at $400000-$7fffff */
for (i=0x40; i<0x80; i++)
{
m68k_memory_map[i].base = action_replay.ram;
m68k_memory_map[i].read8 = NULL;
m68k_memory_map[i].read16 = NULL;
m68k_memory_map[i].write8 = NULL;
m68k_memory_map[i].write16 = NULL;
}
/* RAM (64k) mapped at $600000-$60ffff */
m68k_memory_map[0x60].base = action_replay.ram;
m68k_memory_map[0x60].read8 = NULL;
m68k_memory_map[0x60].read16 = NULL;
m68k_memory_map[0x60].write8 = NULL;
m68k_memory_map[0x60].write16 = NULL;
break;
}
}
@ -119,10 +113,16 @@ void datel_init(void)
#endif
}
void datel_reset(void)
void datel_reset(int hard_reset)
{
if (action_replay.enabled)
{
if (hard_reset)
{
/* clear RAM */
memset(action_replay.ram,0,sizeof(action_replay.ram));
}
/* reset codes */
datel_switch(0);
@ -133,33 +133,26 @@ void datel_reset(void)
memset(action_replay.addr,0,sizeof(action_replay.addr));
/* ROM mapped at $000000-$3fffff */
int i;
switch (action_replay.enabled)
{
case TYPE_AR: /* 32k ROM */
case TYPE_PRO2: /* 64k ROM */
{
for (i=0x00; i<0x40; i++)
{
m68k_memory_map[i].base = action_replay.rom;
}
m68k_memory_map[0].base = action_replay.rom;
break;
}
case TYPE_PRO1: /* 128k ROM */
{
for (i=0x00; i<0x40; i+=2)
{
m68k_memory_map[i].base = action_replay.rom;
m68k_memory_map[i+1].base = action_replay.rom + 0x10000;
}
m68k_memory_map[0].base = action_replay.rom;
m68k_memory_map[1].base = action_replay.rom + 0x10000;
break;
}
}
}
}
void datel_switch(uint8 enable)
void datel_switch(int enable)
{
int i;
if (enable)
@ -214,6 +207,13 @@ void datel_switch(uint8 enable)
*(uint16 *)(work_ram + (action_replay.addr[i]&0xffff)) = action_replay.old[i];
}
}
/* set default Work RAM write handlers */
for (i=0xe0; i<0x100; i++)
{
m68k_memory_map[i].write8 = NULL;
m68k_memory_map[i].write16 = NULL;
}
}
}
@ -280,18 +280,17 @@ static void ar_write_regs(uint32 address, uint32 data)
action_replay.addr[2] = (action_replay.regs[8] | ((action_replay.regs[9] & 0x7f00) << 8)) << 1;
action_replay.addr[3] = (action_replay.regs[11] | ((action_replay.regs[12] & 0x7f00) << 8)) << 1;
/* Cartridge ROM mapped to $000000-$3fffff */
/* Enable Cartridge ROM */
/* NOTE: codes should be disabled on startup */
int i;
for (i=0x00; i<0x40; i++)
{
m68k_memory_map[i].base = cart.rom + ((i<<16) & cart.mask);
}
m68k_memory_map[0].base = cart.rom;
m68k_memory_map[1].base = cart.rom + ((1<<16) & cart.mask);
}
}
static void ar_write_regs_pro2(uint32 address, uint32 data)
{
/* TODO */
/* Enable Cartridge ROM */
if (((address & 0xff) == 0x78) && (data == 0xffff))
m68k_memory_map[0].base = cart.rom;
}

View File

@ -23,7 +23,7 @@
#define _DATEL_H_
extern void datel_init(void);
extern void datel_reset(void);
extern void datel_switch(uint8 enable);
extern void datel_reset(int hard_reset);
extern void datel_switch(int enable);
#endif

View File

@ -42,12 +42,12 @@ void set_softreset(void)
resetline = (int) ((double) (lines_per_frame - 1) * rand() / (RAND_MAX + 1.0));
}
void gen_init (void)
void gen_init(void)
{
int i;
/* initialize CPUs */
m68k_set_cpu_type (M68K_CPU_TYPE_68000);
m68k_set_cpu_type(M68K_CPU_TYPE_68000);
m68k_init();
z80_init(0,0,0,z80_irq_callback);
@ -113,33 +113,18 @@ void gen_init (void)
}
/* VDP */
m68k_memory_map[0xc0].read8 = vdp_read_byte;
m68k_memory_map[0xc0].read16 = vdp_read_word;
m68k_memory_map[0xc0].write8 = vdp_write_byte;
m68k_memory_map[0xc0].write16 = vdp_write_word;
m68k_memory_map[0xc8].read8 = vdp_read_byte;
m68k_memory_map[0xc8].read16 = vdp_read_word;
m68k_memory_map[0xc8].write8 = vdp_write_byte;
m68k_memory_map[0xc8].write16 = vdp_write_word;
m68k_memory_map[0xd0].read8 = vdp_read_byte;
m68k_memory_map[0xd0].read16 = vdp_read_word;
m68k_memory_map[0xd0].write8 = vdp_write_byte;
m68k_memory_map[0xd0].write16 = vdp_write_word;
m68k_memory_map[0xd8].read8 = vdp_read_byte;
m68k_memory_map[0xd8].read16 = vdp_read_word;
m68k_memory_map[0xd8].write8 = vdp_write_byte;
m68k_memory_map[0xd8].write16 = vdp_write_word;
zbank_memory_map[0xc0].read = zbank_read_vdp;
zbank_memory_map[0xc0].write = zbank_write_vdp;
zbank_memory_map[0xc8].read = zbank_read_vdp;
zbank_memory_map[0xc8].write = zbank_write_vdp;
zbank_memory_map[0xd0].read = zbank_read_vdp;
zbank_memory_map[0xd0].write = zbank_write_vdp;
zbank_memory_map[0xd8].read = zbank_read_vdp;
zbank_memory_map[0xd8].write = zbank_write_vdp;
for (i=0xc0; i<0xe0; i+=8)
{
m68k_memory_map[i].read8 = vdp_read_byte;
m68k_memory_map[i].read16 = vdp_read_word;
m68k_memory_map[i].write8 = vdp_write_byte;
m68k_memory_map[i].write16 = vdp_write_word;
zbank_memory_map[i].read = zbank_read_vdp;
zbank_memory_map[i].write = zbank_write_vdp;
}
}
void gen_reset (uint32 hard_reset)
void gen_reset(uint32 hard_reset)
{
if (hard_reset)
{
@ -152,30 +137,30 @@ void gen_reset (uint32 hard_reset)
{
m68k_memory_map[0].base = bios_rom;
}
count_m68k = 0;
count_z80 = 0;
gen_running = 1; /* System is running */
zreset = 0; /* Z80 is reset */
zbusreq = 0; /* Z80 has control of the Z bus */
zbusack = 1; /* Z80 is busy using the Z bus */
zirq = 0; /* No interrupts occuring */
zbank = 0; /* Assume default bank is $000000-$007FFF */
}
gen_running = 1;
resetline = -1;
#ifdef NGC
/* register SOFTRESET */
SYS_SetResetCallback(set_softreset);
#endif
zreset = 0; /* Z80 is reset */
zbusreq = 0; /* Z80 has control of the Z bus */
zbusack = 1; /* Z80 is busy using the Z bus */
zirq = 0; /* No interrupts occuring */
zbank = 0; /* Assume default bank is 000000-007FFF */
/* Reset CPUs */
m68k_pulse_reset ();
z80_reset ();
YM2612ResetChip();
SN76489_Reset();
/* reset CPUs */
m68k_pulse_reset();
z80_reset();
fm_reset();
}
void gen_shutdown (void)
void gen_shutdown(void)
{
z80_exit();
}
@ -183,7 +168,7 @@ void gen_shutdown (void)
/*-----------------------------------------------------------------------
Bus controller chip functions
-----------------------------------------------------------------------*/
void gen_busreq_w (uint32 state)
void gen_busreq_w(uint32 state)
{
uint32 z80_cycles_to_run;
@ -217,7 +202,7 @@ void gen_busreq_w (uint32 state)
zbusack = 1 ^ (zbusreq & zreset);
}
void gen_reset_w (uint32 state)
void gen_reset_w(uint32 state)
{
uint32 z80_cycles_to_run;
@ -247,8 +232,8 @@ void gen_reset_w (uint32 state)
}
/* Reset Z80 & YM2612 */
z80_reset ();
YM2612ResetChip();
z80_reset();
fm_reset();
}
zreset = state;

View File

@ -160,6 +160,14 @@
#define M68K_EMULATE_ADDRESS_ERROR OPT_ON
/* If ON, branch instructions will check for infinite loop and
* freeze current CPU execution .
* Unnecessary checking might be disabled to improve instruction
* emulation speed since infinite loops are going to "lock" the CPU
* execution anyway.
*/
#define M68K_CHECK_INFINITE_LOOP OPT_OFF
/* Turn ON to enable logging of illegal instruction calls.
* M68K_LOG_FILEHANDLE must be #defined to a stdio file stream.
* Turn on M68K_LOG_1010_1111 to log all 1010 and 1111 calls.

View File

@ -854,6 +854,7 @@ void m68k_run (int cyc)
if(CPU_STOPPED)
{
count_m68k = cyc;
REG_PPC = REG_PC;
return;
}

View File

@ -304,7 +304,7 @@ extern unsigned int count_m68k;
#define REG_DA m68ki_cpu.dar /* easy access to data and address regs */
#define REG_D m68ki_cpu.dar
#define REG_A (m68ki_cpu.dar+8)
#define REG_PPC m68ki_cpu.ppc
#define REG_PPC m68ki_cpu.ppc
#define REG_PC m68ki_cpu.pc
#define REG_SP_BASE m68ki_cpu.sp
#define REG_USP m68ki_cpu.sp[0]
@ -606,6 +606,12 @@ extern unsigned int count_m68k;
#define M68K_DO_LOG_EMU(A)
#endif
#if M68K_CHECK_INFINITE_LOOP
#define m68ki_check_infinite_loop() if(REG_PC == REG_PPC) USE_ALL_CYCLES()
#else
#define m68ki_check_infinite_loop()
#endif /* M68K_CHECK_INFINITE_LOOP */
/* -------------------------- EA / Operand Access ------------------------- */

View File

@ -8067,8 +8067,7 @@ static void m68k_op_bra_8(void)
{
m68ki_trace_t0(); /* auto-disable (see m68kcpu.h) */
m68ki_branch_8(MASK_OUT_ABOVE_8(REG_IR));
if(REG_PC == REG_PPC)
USE_ALL_CYCLES();
m68ki_check_infinite_loop(); /* auto-disable (see m68kcpu.h) */
}
@ -8078,8 +8077,7 @@ static void m68k_op_bra_16(void)
REG_PC -= 2;
m68ki_trace_t0(); /* auto-disable (see m68kcpu.h) */
m68ki_branch_16(offset);
if(REG_PC == REG_PPC)
USE_ALL_CYCLES();
m68ki_check_infinite_loop(); /* auto-disable (see m68kcpu.h) */
}
@ -8091,16 +8089,14 @@ static void m68k_op_bra_32(void)
REG_PC -= 4;
m68ki_trace_t0(); /* auto-disable (see m68kcpu.h) */
m68ki_branch_32(offset);
if(REG_PC == REG_PPC)
USE_ALL_CYCLES();
m68ki_check_infinite_loop(); /* auto-disable (see m68kcpu.h) */
return;
}
else
{
m68ki_trace_t0(); /* auto-disable (see m68kcpu.h) */
m68ki_branch_8(MASK_OUT_ABOVE_8(REG_IR));
if(REG_PC == REG_PPC)
USE_ALL_CYCLES();
m68ki_check_infinite_loop(); /* auto-disable (see m68kcpu.h) */
}
}
@ -16542,8 +16538,7 @@ static void m68k_op_jmp_32_ai(void)
{
m68ki_jump(EA_AY_AI_32());
m68ki_trace_t0(); /* auto-disable (see m68kcpu.h) */
if(REG_PC == REG_PPC)
USE_ALL_CYCLES();
m68ki_check_infinite_loop(); /* auto-disable (see m68kcpu.h) */
}
@ -16551,8 +16546,7 @@ static void m68k_op_jmp_32_di(void)
{
m68ki_jump(EA_AY_DI_32());
m68ki_trace_t0(); /* auto-disable (see m68kcpu.h) */
if(REG_PC == REG_PPC)
USE_ALL_CYCLES();
m68ki_check_infinite_loop(); /* auto-disable (see m68kcpu.h) */
}
@ -16560,8 +16554,7 @@ static void m68k_op_jmp_32_ix(void)
{
m68ki_jump(EA_AY_IX_32());
m68ki_trace_t0(); /* auto-disable (see m68kcpu.h) */
if(REG_PC == REG_PPC)
USE_ALL_CYCLES();
m68ki_check_infinite_loop(); /* auto-disable (see m68kcpu.h) */
}
@ -16569,8 +16562,7 @@ static void m68k_op_jmp_32_aw(void)
{
m68ki_jump(EA_AW_32());
m68ki_trace_t0(); /* auto-disable (see m68kcpu.h) */
if(REG_PC == REG_PPC)
USE_ALL_CYCLES();
m68ki_check_infinite_loop(); /* auto-disable (see m68kcpu.h) */
}
@ -16578,8 +16570,7 @@ static void m68k_op_jmp_32_al(void)
{
m68ki_jump(EA_AL_32());
m68ki_trace_t0(); /* auto-disable (see m68kcpu.h) */
if(REG_PC == REG_PPC)
USE_ALL_CYCLES();
m68ki_check_infinite_loop(); /* auto-disable (see m68kcpu.h) */
}
@ -16587,8 +16578,7 @@ static void m68k_op_jmp_32_pcdi(void)
{
m68ki_jump(EA_PCDI_32());
m68ki_trace_t0(); /* auto-disable (see m68kcpu.h) */
if(REG_PC == REG_PPC)
USE_ALL_CYCLES();
m68ki_check_infinite_loop(); /* auto-disable (see m68kcpu.h) */
}
@ -16596,8 +16586,7 @@ static void m68k_op_jmp_32_pcix(void)
{
m68ki_jump(EA_PCIX_32());
m68ki_trace_t0(); /* auto-disable (see m68kcpu.h) */
if(REG_PC == REG_PPC)
USE_ALL_CYCLES();
m68ki_check_infinite_loop(); /* auto-disable (see m68kcpu.h) */
}

View File

@ -76,11 +76,10 @@ static int available( unsigned long input_count )
int Fir_Resampler_initialize( int new_size )
{
buffer = (sample_t *) realloc( buffer, (new_size + WRITE_OFFSET) * sizeof (sample_t) );
write_pos = 0;
if ( !buffer && new_size ) return 0;
buffer_size = new_size + WRITE_OFFSET;
write_pos = 0;
res = 1;
imp_phase = 0;
skip_bits = 0;
step = STEREO;
ratio = 1.0;
@ -206,28 +205,27 @@ int Fir_Resampler_read( sample_t** out, unsigned long count )
sample_t const* imp = impulses [imp_phase];
int remain = res - imp_phase;
int n;
int pt0,pt1;
sample_t* i;
unsigned long l,r;
if ( end_pos - in >= WIDTH * STEREO )
{
end_pos -= WIDTH * STEREO;
do
{
count--;
/* accumulate in extended precision */
unsigned long l = 0;
unsigned long r = 0;
l = 0;
r = 0;
const sample_t* i = in;
if ( count < 0 )
break;
i = in;
for ( n = WIDTH / 2; n; --n )
{
int pt0 = imp [0];
pt0 = imp [0];
l += pt0 * i [0];
r += pt0 * i [1];
int pt1 = imp [1];
pt1 = imp [1];
imp += 2;
l += pt1 * i [2];
r += pt1 * i [3];
@ -253,7 +251,7 @@ int Fir_Resampler_read( sample_t** out, unsigned long count )
*out_l++ = (sample_t) l;
*out_r++ = (sample_t) r;
}
while ( in <= end_pos );
while ( (in <= end_pos) && (--count > 0) );
}
imp_phase = res - remain;

View File

@ -40,7 +40,7 @@ static inline int psg_sample_cnt(uint8 z80)
else return ((count_m68k / m68cycles_per_sample[1]) - snd.psg.pos);
}
/* update FM samples */
/* run FM chip for n samples */
static inline void fm_update(int cnt)
{
if (cnt > 0)
@ -50,7 +50,7 @@ static inline void fm_update(int cnt)
}
}
/* update PSG samples */
/* run PSG chip for n samples */
static inline void psg_update(int cnt)
{
if (cnt > 0)
@ -60,6 +60,7 @@ static inline void psg_update(int cnt)
}
}
/* initialize sound chips emulation */
void sound_init(int rate)
{
double vclk = (vdp_pal ? (double)CLOCK_PAL : (double)CLOCK_NTSC) / 7.0; /* 68000 and YM2612 clock */
@ -96,6 +97,13 @@ void sound_update(int fm_len, int psg_len)
snd.psg.pos = 0;
}
/* reset FM chip */
void fm_reset(void)
{
fm_update(fm_sample_cnt(0));
YM2612ResetChip();
}
/* write FM chip */
void fm_write(unsigned int cpu, unsigned int address, unsigned int data)
{
@ -110,8 +118,7 @@ unsigned int fm_read(unsigned int cpu, unsigned int address)
return YM2612Read();
}
/* PSG write */
/* write PSG chip */
void psg_write(unsigned int cpu, unsigned int data)
{
psg_update(psg_sample_cnt(cpu));

View File

@ -27,6 +27,7 @@
/* Function prototypes */
extern void sound_init(int rate);
extern void sound_update(int fm_len, int psg_len);
extern void fm_reset(void);
extern void fm_write(unsigned int cpu, unsigned int address, unsigned int data);
extern unsigned int fm_read(unsigned int cpu, unsigned int address);
extern void psg_write(unsigned int cpu, unsigned int data);

View File

@ -78,7 +78,7 @@ void audio_update (int size)
/* resampling */
if (config.hq_fm)
{
int len = Fir_Resampler_input_needed(size * 2);
int len = Fir_Resampler_input_needed(size << 1);
sound_update(len >> 1,size);
Fir_Resampler_write(len);
Fir_Resampler_read(fm,size);
@ -209,9 +209,9 @@ void audio_shutdown(void)
void system_init (void)
{
/* Genesis hardware */
gen_init ();
vdp_init ();
render_init ();
gen_init();
vdp_init();
render_init();
io_init();
/* Cartridge hardware */
@ -227,9 +227,10 @@ void system_reset (void)
cart_hw_reset();
/* Genesis hardware */
gen_reset (1);
vdp_reset ();
render_reset ();
gen_reset(1);
SN76489_Reset();
vdp_reset();
render_reset();
io_reset();
/* Clear Sound Buffers */
@ -321,6 +322,10 @@ int system_frame (int do_skip)
/* wait for RESET button to be released */
while (SYS_ResetButtonDown());
#endif
/* Pro Action Replay (switch at "Trainer" position) */
if (config.lock_on == TYPE_AR)
datel_reset(0);
gen_reset(0);
}

View File

@ -211,7 +211,7 @@ void vdp_reset(void)
bitmap.viewport.ow = 224;
/* reset border area */
bitmap.viewport.x = (reg[12] & 1) ? 16 : 12;
bitmap.viewport.x = config.overscan ? ((reg[12] & 1) ? 16 : 12) : 0;
bitmap.viewport.y = config.overscan ? (vdp_pal ? 32 : 8) : 0;
bitmap.viewport.changed = 1;
@ -245,7 +245,7 @@ void vdp_restore(uint8 *vdp_regs)
hctab = (reg[12] & 1) ? cycle2hc40 : cycle2hc32;
/* reinitialize overscan area */
bitmap.viewport.x = (reg[12] & 1) ? 16 : 12;
bitmap.viewport.x = config.overscan ? ((reg[12] & 1) ? 16 : 12) : 0;
bitmap.viewport.y = config.overscan ? (((reg[1] & 8) ? 0 : 8) + (vdp_pal ? 24 : 0)) : 0;
bitmap.viewport.changed = 1;
@ -685,10 +685,7 @@ static inline void reg_w(unsigned int r, unsigned int d)
/* update viewport */
bitmap.viewport.changed = 1;
bitmap.viewport.h = (d & 8) ? 240 : 224;
if (config.overscan)
{
bitmap.viewport.y = ((vdp_pal ? 288 : 240) - bitmap.viewport.h) / 2;
}
if (config.overscan) bitmap.viewport.y = ((vdp_pal ? 288 : 240) - bitmap.viewport.h) / 2;
/* update VC table */
if (vdp_pal) vctab = (d & 8) ? vc_pal_240 : vc_pal_224;