2008-08-07 14:26:07 +02:00
|
|
|
/***************************************************************************************
|
2009-05-13 16:26:55 +02:00
|
|
|
* Genesis Plus
|
2008-08-07 14:26:07 +02:00
|
|
|
* Main Emulation
|
|
|
|
*
|
|
|
|
* Copyright (C) 1998, 1999, 2000, 2001, 2002, 2003 Charles Mac Donald (original code)
|
2009-05-13 16:26:55 +02:00
|
|
|
* Eke-Eke (2007,2008,2009), additional code & fixes for the GCN/Wii port
|
|
|
|
*
|
2008-08-07 14:26:07 +02:00
|
|
|
* This program is free software; you can redistribute it and/or modify
|
|
|
|
* it under the terms of the GNU General Public License as published by
|
|
|
|
* the Free Software Foundation; either version 2 of the License, or
|
|
|
|
* (at your option) any later version.
|
|
|
|
*
|
|
|
|
* This program is distributed in the hope that it will be useful,
|
|
|
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
|
|
* GNU General Public License for more details.
|
|
|
|
*
|
|
|
|
* You should have received a copy of the GNU General Public License
|
|
|
|
* along with this program; if not, write to the Free Software
|
|
|
|
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
|
|
|
*
|
|
|
|
****************************************************************************************/
|
2007-08-10 22:34:06 +02:00
|
|
|
|
|
|
|
#include "shared.h"
|
2009-07-22 19:25:41 +02:00
|
|
|
#include "Fir_Resampler.h"
|
2009-05-26 18:40:35 +02:00
|
|
|
#include "eq.h"
|
2007-08-10 22:34:06 +02:00
|
|
|
|
|
|
|
#define SND_SIZE (snd.buffer_size * sizeof(int16))
|
|
|
|
|
2008-08-07 14:26:07 +02:00
|
|
|
/* Global variables */
|
2007-08-10 22:34:06 +02:00
|
|
|
t_bitmap bitmap;
|
|
|
|
t_snd snd;
|
2010-01-24 12:41:53 +01:00
|
|
|
uint32 mcycles_vdp;
|
|
|
|
uint32 mcycles_z80;
|
|
|
|
uint32 mcycles_68k;
|
|
|
|
uint32 hint_68k;
|
2008-08-07 14:26:07 +02:00
|
|
|
uint8 system_hw;
|
|
|
|
|
2009-05-26 18:40:35 +02:00
|
|
|
/****************************************************************
|
|
|
|
* AUDIO equalizer
|
|
|
|
****************************************************************/
|
|
|
|
static EQSTATE eq;
|
2009-02-22 20:57:41 +01:00
|
|
|
|
2009-05-26 18:40:35 +02:00
|
|
|
void audio_set_equalizer(void)
|
|
|
|
{
|
2009-07-30 09:15:54 +02:00
|
|
|
init_3band_state(&eq,config.low_freq,config.high_freq,snd.sample_rate);
|
2009-05-26 18:40:35 +02:00
|
|
|
eq.lg = (double)(config.lg);
|
|
|
|
eq.mg = (double)(config.mg);
|
|
|
|
eq.hg = (double)(config.hg);
|
|
|
|
}
|
2009-02-22 20:57:41 +01:00
|
|
|
|
|
|
|
/****************************************************************
|
|
|
|
* AUDIO stream update
|
|
|
|
****************************************************************/
|
2009-08-11 10:18:46 +02:00
|
|
|
static int llp,rrp;
|
|
|
|
|
2010-01-24 12:41:53 +01:00
|
|
|
int audio_update (void)
|
2009-02-22 20:57:41 +01:00
|
|
|
{
|
2009-08-11 10:18:46 +02:00
|
|
|
int i, l, r;
|
|
|
|
int ll = llp;
|
|
|
|
int rr = rrp;
|
|
|
|
|
|
|
|
int psg_preamp = config.psg_preamp;
|
|
|
|
int fm_preamp = config.fm_preamp;
|
|
|
|
int filter = config.filter;
|
|
|
|
uint32 factora = (config.lp_range << 16) / 100;
|
|
|
|
uint32 factorb = 0x10000 - factora;
|
2009-02-22 20:57:41 +01:00
|
|
|
|
2010-01-24 12:41:53 +01:00
|
|
|
int16 *fm = snd.fm.buffer;
|
|
|
|
int16 *psg = snd.psg.buffer;
|
2009-07-22 19:25:41 +02:00
|
|
|
|
2009-06-02 20:12:31 +02:00
|
|
|
#ifdef NGC
|
2009-02-22 20:57:41 +01:00
|
|
|
int16 *sb = (int16 *) soundbuffer[mixbuffer];
|
|
|
|
#endif
|
|
|
|
|
2010-01-24 12:41:53 +01:00
|
|
|
/* get number of available samples */
|
|
|
|
int size = sound_update(mcycles_vdp);
|
|
|
|
|
|
|
|
/* return an aligned number of samples */
|
|
|
|
size &= ~7;
|
|
|
|
|
2009-07-22 19:25:41 +02:00
|
|
|
if (config.hq_fm)
|
2009-02-22 20:57:41 +01:00
|
|
|
{
|
2010-01-24 12:41:53 +01:00
|
|
|
/* resample into FM output buffer */
|
2009-07-22 19:25:41 +02:00
|
|
|
Fir_Resampler_read(fm,size);
|
2010-01-24 12:41:53 +01:00
|
|
|
|
2010-01-27 08:20:44 +01:00
|
|
|
#ifdef LOGSOUND
|
2010-01-24 12:41:53 +01:00
|
|
|
error("%d FM samples remaining\n",Fir_Resampler_written() >> 1);
|
|
|
|
#endif
|
2009-07-22 19:25:41 +02:00
|
|
|
}
|
|
|
|
else
|
2010-01-24 12:41:53 +01:00
|
|
|
{
|
|
|
|
/* adjust remaining samples in FM output buffer*/
|
|
|
|
snd.fm.pos -= (size << 1);
|
|
|
|
|
2010-01-27 08:20:44 +01:00
|
|
|
#ifdef LOGSOUND
|
2010-01-24 12:41:53 +01:00
|
|
|
error("%d FM samples remaining\n",(snd.fm.pos - snd.fm.buffer)>>1);
|
|
|
|
#endif
|
2009-02-22 20:57:41 +01:00
|
|
|
}
|
|
|
|
|
2010-01-24 12:41:53 +01:00
|
|
|
/* adjust remaining samples in PSG output buffer*/
|
|
|
|
snd.psg.pos -= size;
|
|
|
|
|
2010-01-27 08:20:44 +01:00
|
|
|
#ifdef LOGSOUND
|
2010-01-24 12:41:53 +01:00
|
|
|
error("%d PSG samples remaining\n",snd.psg.pos - snd.psg.buffer);
|
|
|
|
#endif
|
|
|
|
|
2009-02-22 20:57:41 +01:00
|
|
|
/* mix samples */
|
|
|
|
for (i = 0; i < size; i ++)
|
|
|
|
{
|
|
|
|
/* PSG samples (mono) */
|
2009-08-05 09:02:09 +02:00
|
|
|
l = r = ((*psg++) * psg_preamp)/100;
|
2009-02-22 20:57:41 +01:00
|
|
|
|
|
|
|
/* FM samples (stereo) */
|
2010-01-24 12:41:53 +01:00
|
|
|
l += (*fm++ * fm_preamp)/100;
|
|
|
|
r += (*fm++ * fm_preamp)/100;
|
2009-02-22 20:57:41 +01:00
|
|
|
|
2009-05-26 18:40:35 +02:00
|
|
|
/* filtering */
|
|
|
|
if (filter & 1)
|
2009-02-22 20:57:41 +01:00
|
|
|
{
|
2009-05-26 18:40:35 +02:00
|
|
|
/* single-pole low-pass filter (6 dB/octave) */
|
2009-08-11 19:25:38 +02:00
|
|
|
ll = (ll>>16)*factora + l*factorb;
|
|
|
|
rr = (rr>>16)*factora + r*factorb;
|
2009-08-11 10:18:46 +02:00
|
|
|
l = ll >> 16;
|
|
|
|
r = rr >> 16;
|
2009-02-22 20:57:41 +01:00
|
|
|
}
|
2009-05-26 18:40:35 +02:00
|
|
|
else if (filter & 2)
|
|
|
|
{
|
|
|
|
/* 3 Band EQ */
|
|
|
|
l = do_3band(&eq,l);
|
|
|
|
r = do_3band(&eq,r);
|
|
|
|
}
|
2009-02-22 20:57:41 +01:00
|
|
|
|
|
|
|
/* clipping */
|
|
|
|
if (l > 32767) l = 32767;
|
|
|
|
else if (l < -32768) l = -32768;
|
|
|
|
if (r > 32767) r = 32767;
|
|
|
|
else if (r < -32768) r = -32768;
|
|
|
|
|
|
|
|
/* update sound buffer */
|
2009-06-02 20:12:31 +02:00
|
|
|
#ifndef NGC
|
2009-02-22 20:57:41 +01:00
|
|
|
snd.buffer[0][i] = l;
|
|
|
|
snd.buffer[1][i] = r;
|
|
|
|
#else
|
|
|
|
*sb++ = r;
|
|
|
|
*sb++ = l;
|
|
|
|
#endif
|
|
|
|
}
|
2009-08-11 10:18:46 +02:00
|
|
|
|
2010-01-24 12:41:53 +01:00
|
|
|
/* save delayed samples for next frame */
|
2009-08-11 10:18:46 +02:00
|
|
|
llp = ll;
|
|
|
|
rrp = rr;
|
2010-01-24 12:41:53 +01:00
|
|
|
|
|
|
|
/* save remaining samples for next frame */
|
|
|
|
memcpy(snd.fm.buffer, fm, (snd.fm.pos - snd.fm.buffer) << 1);
|
|
|
|
memcpy(snd.psg.buffer, psg, (snd.psg.pos - snd.psg.buffer) << 1);
|
|
|
|
|
2010-01-27 08:20:44 +01:00
|
|
|
#ifdef LOGSOUND
|
2010-01-24 12:41:53 +01:00
|
|
|
error("%d samples returned\n\n",size);
|
|
|
|
#endif
|
|
|
|
|
|
|
|
return size;
|
2009-02-22 20:57:41 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
/****************************************************************
|
|
|
|
* AUDIO System initialization
|
|
|
|
****************************************************************/
|
2010-01-24 12:41:53 +01:00
|
|
|
int audio_init (int samplerate, float framerate)
|
2009-02-22 20:57:41 +01:00
|
|
|
{
|
|
|
|
/* Shutdown first */
|
|
|
|
audio_shutdown();
|
|
|
|
|
|
|
|
/* Clear the sound data context */
|
|
|
|
memset(&snd, 0, sizeof (snd));
|
|
|
|
|
2010-01-24 12:41:53 +01:00
|
|
|
/* Default settings */
|
|
|
|
snd.sample_rate = samplerate;
|
|
|
|
snd.frame_rate = framerate;
|
2009-02-22 20:57:41 +01:00
|
|
|
|
|
|
|
/* Calculate the sound buffer size (for one frame) */
|
2010-01-24 12:41:53 +01:00
|
|
|
snd.buffer_size = (int)(samplerate / framerate) + 32;
|
2009-02-22 20:57:41 +01:00
|
|
|
|
2010-01-24 12:41:53 +01:00
|
|
|
#ifndef NGC
|
2009-07-22 19:25:41 +02:00
|
|
|
/* Output buffers */
|
2009-02-22 20:57:41 +01:00
|
|
|
snd.buffer[0] = (int16 *) malloc(SND_SIZE);
|
|
|
|
snd.buffer[1] = (int16 *) malloc(SND_SIZE);
|
2010-01-24 12:41:53 +01:00
|
|
|
if (!snd.buffer[0] || !snd.buffer[1])
|
|
|
|
return (-1);
|
2009-02-22 20:57:41 +01:00
|
|
|
#endif
|
|
|
|
|
2009-07-22 19:25:41 +02:00
|
|
|
/* SN76489 stream buffers */
|
2010-01-24 12:41:53 +01:00
|
|
|
snd.psg.buffer = (int16 *) malloc(SND_SIZE);
|
|
|
|
if (!snd.psg.buffer)
|
|
|
|
return (-1);
|
2009-02-22 20:57:41 +01:00
|
|
|
|
2009-07-22 19:25:41 +02:00
|
|
|
/* YM2612 stream buffers */
|
2010-01-24 12:41:53 +01:00
|
|
|
snd.fm.buffer = (int16 *) malloc(SND_SIZE * 2);
|
|
|
|
if (!snd.fm.buffer)
|
|
|
|
return (-1);
|
2009-02-22 20:57:41 +01:00
|
|
|
|
2009-07-22 19:25:41 +02:00
|
|
|
/* Resampling buffer */
|
|
|
|
if (config.hq_fm)
|
2009-02-22 20:57:41 +01:00
|
|
|
{
|
2010-01-24 12:41:53 +01:00
|
|
|
if (!Fir_Resampler_initialize(4096))
|
|
|
|
return (-1);
|
2009-02-22 20:57:41 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
/* Set audio enable flag */
|
|
|
|
snd.enabled = 1;
|
|
|
|
|
2010-01-24 12:41:53 +01:00
|
|
|
/* Reset audio */
|
|
|
|
audio_reset();
|
2009-02-22 20:57:41 +01:00
|
|
|
|
|
|
|
return (0);
|
|
|
|
}
|
|
|
|
|
2010-01-24 12:41:53 +01:00
|
|
|
/****************************************************************
|
|
|
|
* AUDIO System reset
|
|
|
|
****************************************************************/
|
|
|
|
void audio_reset(void)
|
|
|
|
{
|
|
|
|
/* Low-Pass filter */
|
|
|
|
llp = 0;
|
|
|
|
rrp = 0;
|
|
|
|
|
|
|
|
/* 3 band EQ */
|
|
|
|
audio_set_equalizer();
|
|
|
|
|
|
|
|
/* audio buffers */
|
|
|
|
Fir_Resampler_clear();
|
|
|
|
snd.psg.pos = snd.psg.buffer;
|
|
|
|
snd.fm.pos = snd.fm.buffer;
|
|
|
|
#ifndef NGC
|
|
|
|
if (snd.buffer[0])
|
|
|
|
memset (snd.buffer[0], 0, SND_SIZE);
|
|
|
|
if (snd.buffer[1])
|
|
|
|
memset (snd.buffer[1], 0, SND_SIZE);
|
|
|
|
#endif
|
|
|
|
if (snd.psg.buffer)
|
|
|
|
memset (snd.psg.buffer, 0, SND_SIZE);
|
|
|
|
if (snd.fm.buffer)
|
|
|
|
memset (snd.fm.buffer, 0, SND_SIZE * 2);
|
|
|
|
}
|
|
|
|
|
2009-02-22 20:57:41 +01:00
|
|
|
/****************************************************************
|
|
|
|
* AUDIO System shutdown
|
|
|
|
****************************************************************/
|
|
|
|
void audio_shutdown(void)
|
|
|
|
{
|
2009-07-22 19:25:41 +02:00
|
|
|
/* Sound buffers */
|
2010-01-24 12:41:53 +01:00
|
|
|
#ifndef NGC
|
|
|
|
if (snd.buffer[0])
|
|
|
|
free(snd.buffer[0]);
|
|
|
|
if (snd.buffer[1])
|
|
|
|
free(snd.buffer[1]);
|
|
|
|
#endif
|
|
|
|
if (snd.fm.buffer)
|
|
|
|
free(snd.fm.buffer);
|
|
|
|
if (snd.psg.buffer)
|
|
|
|
free(snd.psg.buffer);
|
2009-02-22 20:57:41 +01:00
|
|
|
|
2009-07-22 19:25:41 +02:00
|
|
|
/* Resampling buffer */
|
|
|
|
Fir_Resampler_shutdown();
|
2009-02-22 20:57:41 +01:00
|
|
|
}
|
2007-08-10 22:34:06 +02:00
|
|
|
|
2008-08-07 14:26:07 +02:00
|
|
|
/****************************************************************
|
|
|
|
* Virtual Genesis initialization
|
|
|
|
****************************************************************/
|
2007-08-10 22:34:06 +02:00
|
|
|
void system_init (void)
|
|
|
|
{
|
2009-08-06 20:31:05 +02:00
|
|
|
/* Genesis hardware */
|
2009-08-14 18:46:19 +02:00
|
|
|
gen_init();
|
2009-10-16 13:32:55 +02:00
|
|
|
io_init();
|
2009-08-14 18:46:19 +02:00
|
|
|
vdp_init();
|
|
|
|
render_init();
|
2009-08-09 11:33:48 +02:00
|
|
|
|
|
|
|
/* Cartridge hardware */
|
|
|
|
cart_hw_init();
|
2010-01-24 12:41:53 +01:00
|
|
|
|
|
|
|
/* Sound Chips hardware */
|
|
|
|
sound_init();
|
2007-08-10 22:34:06 +02:00
|
|
|
}
|
|
|
|
|
2008-08-07 14:26:07 +02:00
|
|
|
/****************************************************************
|
2009-01-07 18:12:03 +01:00
|
|
|
* Virtual Genesis Hard Reset
|
2008-08-07 14:26:07 +02:00
|
|
|
****************************************************************/
|
2007-08-10 22:34:06 +02:00
|
|
|
void system_reset (void)
|
|
|
|
{
|
2009-08-09 11:33:48 +02:00
|
|
|
/* Cartridge Hardware */
|
2008-12-10 19:16:30 +01:00
|
|
|
cart_hw_reset();
|
|
|
|
|
2009-08-06 20:31:05 +02:00
|
|
|
/* Genesis hardware */
|
2009-08-14 18:46:19 +02:00
|
|
|
gen_reset(1);
|
2009-10-16 13:32:55 +02:00
|
|
|
io_reset();
|
2009-08-14 18:46:19 +02:00
|
|
|
vdp_reset();
|
|
|
|
render_reset();
|
2008-12-10 19:16:30 +01:00
|
|
|
|
2010-01-24 12:41:53 +01:00
|
|
|
/* Sound chips */
|
|
|
|
sound_reset();
|
|
|
|
|
|
|
|
/* Audio System */
|
|
|
|
audio_reset();
|
2007-08-10 22:34:06 +02:00
|
|
|
}
|
|
|
|
|
2008-08-07 14:26:07 +02:00
|
|
|
/****************************************************************
|
|
|
|
* Virtual Genesis shutdown
|
|
|
|
****************************************************************/
|
2007-08-10 22:34:06 +02:00
|
|
|
void system_shutdown (void)
|
|
|
|
{
|
2008-12-10 19:16:30 +01:00
|
|
|
gen_shutdown ();
|
|
|
|
vdp_shutdown ();
|
|
|
|
render_shutdown ();
|
2007-08-10 22:34:06 +02:00
|
|
|
}
|
|
|
|
|
2008-08-07 14:26:07 +02:00
|
|
|
/****************************************************************
|
|
|
|
* Virtual Genesis Frame emulation
|
|
|
|
****************************************************************/
|
2007-08-10 22:34:06 +02:00
|
|
|
int system_frame (int do_skip)
|
|
|
|
{
|
2008-12-10 19:16:30 +01:00
|
|
|
if (!gen_running)
|
2008-12-04 20:32:22 +01:00
|
|
|
{
|
2009-09-30 19:11:24 +02:00
|
|
|
osd_input_Update();
|
2008-12-04 20:32:22 +01:00
|
|
|
return 0;
|
2008-12-10 19:16:30 +01:00
|
|
|
}
|
|
|
|
|
2008-12-04 20:32:22 +01:00
|
|
|
/* update display settings */
|
|
|
|
int line;
|
|
|
|
int reset = resetline;
|
|
|
|
int vdp_height = bitmap.viewport.h;
|
|
|
|
int end_line = vdp_height + bitmap.viewport.y;
|
|
|
|
int start_line = lines_per_frame - bitmap.viewport.y;
|
2008-12-10 19:16:30 +01:00
|
|
|
int old_interlaced = interlaced;
|
2008-12-07 20:31:50 +01:00
|
|
|
interlaced = (reg[12] & 2) >> 1;
|
2008-12-10 19:16:30 +01:00
|
|
|
if (old_interlaced != interlaced)
|
2008-08-07 14:26:07 +02:00
|
|
|
{
|
2009-08-14 15:54:15 +02:00
|
|
|
bitmap.viewport.changed = 1;
|
2008-12-07 20:31:50 +01:00
|
|
|
im2_flag = ((reg[12] & 6) == 6);
|
2008-12-10 19:16:30 +01:00
|
|
|
odd_frame = 1;
|
|
|
|
}
|
2008-08-07 14:26:07 +02:00
|
|
|
odd_frame ^= 1;
|
2008-12-04 20:32:22 +01:00
|
|
|
|
2008-12-05 17:26:57 +01:00
|
|
|
/* clear VBLANK and DMA flags */
|
2010-01-24 12:41:53 +01:00
|
|
|
status &= 0xFFE5;
|
2008-12-10 19:16:30 +01:00
|
|
|
|
2008-12-05 17:26:57 +01:00
|
|
|
/* even/odd field flag (interlaced modes only) */
|
2010-01-24 12:41:53 +01:00
|
|
|
if (odd_frame && interlaced)
|
|
|
|
status |= 0x0010;
|
2007-08-10 22:34:06 +02:00
|
|
|
|
2008-12-10 19:16:30 +01:00
|
|
|
/* reload HCounter */
|
|
|
|
int h_counter = reg[10];
|
2007-08-10 22:34:06 +02:00
|
|
|
|
2010-01-24 12:41:53 +01:00
|
|
|
/* reset VDP FIFO */
|
|
|
|
fifo_write_cnt = 0;
|
|
|
|
fifo_lastwrite = 0;
|
|
|
|
|
|
|
|
/* reset line cycle count */
|
|
|
|
mcycles_vdp = 0;
|
2007-08-10 22:34:06 +02:00
|
|
|
|
2009-01-13 21:02:06 +01:00
|
|
|
/* process scanlines */
|
2008-12-10 19:16:30 +01:00
|
|
|
for (line = 0; line < lines_per_frame; line ++)
|
|
|
|
{
|
2008-12-05 17:26:57 +01:00
|
|
|
/* update VCounter */
|
2008-12-10 19:16:30 +01:00
|
|
|
v_counter = line;
|
2007-08-10 22:34:06 +02:00
|
|
|
|
2008-12-10 19:16:30 +01:00
|
|
|
/* update 6-Buttons or Menacer */
|
|
|
|
input_update();
|
2007-08-10 22:34:06 +02:00
|
|
|
|
2010-01-24 12:41:53 +01:00
|
|
|
/* 68k line cycle count */
|
|
|
|
hint_68k = mcycles_68k;
|
2007-08-10 22:34:06 +02:00
|
|
|
|
2010-01-24 12:41:53 +01:00
|
|
|
/* Soft Reset line */
|
2008-12-10 19:16:30 +01:00
|
|
|
if (line == reset)
|
2008-11-13 08:24:30 +01:00
|
|
|
{
|
2009-08-14 18:46:19 +02:00
|
|
|
/* Pro Action Replay (switch at "Trainer" position) */
|
|
|
|
if (config.lock_on == TYPE_AR)
|
|
|
|
datel_reset(0);
|
|
|
|
|
2008-11-13 08:24:30 +01:00
|
|
|
gen_reset(0);
|
|
|
|
}
|
2008-08-07 14:26:07 +02:00
|
|
|
|
2010-01-24 12:41:53 +01:00
|
|
|
/* update VDP DMA */
|
|
|
|
if (dma_length)
|
|
|
|
vdp_update_dma();
|
|
|
|
|
2008-12-05 17:26:57 +01:00
|
|
|
/* active display */
|
2008-12-04 20:32:22 +01:00
|
|
|
if (line <= vdp_height)
|
2008-12-10 19:16:30 +01:00
|
|
|
{
|
|
|
|
/* H Interrupt */
|
2008-12-05 17:26:57 +01:00
|
|
|
if(--h_counter < 0)
|
2008-12-10 19:16:30 +01:00
|
|
|
{
|
|
|
|
h_counter = reg[10];
|
|
|
|
hint_pending = 1;
|
2010-01-24 12:41:53 +01:00
|
|
|
if (reg[0] & 0x10)
|
|
|
|
irq_status = (irq_status & ~0x40) | 0x14;
|
2008-09-13 17:42:24 +02:00
|
|
|
}
|
2008-08-07 14:26:07 +02:00
|
|
|
|
2008-12-10 19:16:30 +01:00
|
|
|
/* vertical retrace */
|
2008-12-04 20:32:22 +01:00
|
|
|
if (line == vdp_height)
|
2008-12-10 19:16:30 +01:00
|
|
|
{
|
2008-12-04 20:32:22 +01:00
|
|
|
/* render overscan */
|
2010-01-27 08:20:44 +01:00
|
|
|
if (!do_skip && (line < end_line))
|
2010-01-24 12:41:53 +01:00
|
|
|
render_line(line, 1);
|
2008-12-04 20:32:22 +01:00
|
|
|
|
2008-12-05 17:26:57 +01:00
|
|
|
/* update inputs (doing this here fix Warriors of Eternal Sun) */
|
2009-09-30 19:11:24 +02:00
|
|
|
osd_input_Update();
|
2008-08-07 14:26:07 +02:00
|
|
|
|
2008-12-05 17:26:57 +01:00
|
|
|
/* set VBLANK flag */
|
|
|
|
status |= 0x08;
|
2008-08-07 14:26:07 +02:00
|
|
|
|
2008-12-05 17:26:57 +01:00
|
|
|
/* Z80 interrupt is 16ms period (one frame) and 64us length (one scanline) */
|
2008-12-10 19:16:30 +01:00
|
|
|
zirq = 1;
|
2010-01-24 12:41:53 +01:00
|
|
|
z80_set_irq_line(0, ASSERT_LINE);
|
2008-12-10 19:16:30 +01:00
|
|
|
|
2010-01-24 12:41:53 +01:00
|
|
|
/* delay between VINT flag & V Interrupt (Ex-Mutants, Tyrant) */
|
|
|
|
m68k_run(mcycles_vdp + 588);
|
2008-12-05 17:26:57 +01:00
|
|
|
status |= 0x80;
|
|
|
|
|
2010-01-24 12:41:53 +01:00
|
|
|
/* delay between VBLANK flag & V Interrupt (Dracula, OutRunners, VR Troopers) */
|
|
|
|
m68k_run(mcycles_vdp + 788);
|
|
|
|
if (zstate == 1)
|
|
|
|
z80_run(mcycles_vdp + 788);
|
|
|
|
else
|
|
|
|
mcycles_z80 = mcycles_vdp + 788;
|
|
|
|
|
|
|
|
/* V Interrupt */
|
2009-06-05 19:31:46 +02:00
|
|
|
vint_pending = 1;
|
2010-01-24 12:41:53 +01:00
|
|
|
if (reg[1] & 0x20)
|
|
|
|
irq_status = (irq_status & ~0x40) | 0x36;
|
2008-12-04 20:32:22 +01:00
|
|
|
}
|
|
|
|
else if (!do_skip)
|
|
|
|
{
|
2010-01-24 12:41:53 +01:00
|
|
|
/* sprites are processed during horizontal blanking */
|
|
|
|
parse_satb(0x80 + line);
|
|
|
|
|
|
|
|
/* render scanline */
|
2008-12-04 20:32:22 +01:00
|
|
|
render_line(line, 0);
|
2008-12-10 19:16:30 +01:00
|
|
|
}
|
2008-12-04 20:32:22 +01:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
/* render overscan */
|
2010-01-27 08:20:44 +01:00
|
|
|
if (!do_skip && ((line < end_line) || (line >= start_line)))
|
2010-01-24 12:41:53 +01:00
|
|
|
render_line(line, 1);
|
2008-12-04 20:32:22 +01:00
|
|
|
|
2008-08-07 14:26:07 +02:00
|
|
|
/* clear any pending Z80 interrupt */
|
2008-12-04 20:32:22 +01:00
|
|
|
if (zirq)
|
|
|
|
{
|
2008-12-05 17:26:57 +01:00
|
|
|
zirq = 0;
|
|
|
|
z80_set_irq_line(0, CLEAR_LINE);
|
|
|
|
}
|
2008-08-07 14:26:07 +02:00
|
|
|
}
|
|
|
|
|
2008-12-10 19:16:30 +01:00
|
|
|
/* process line */
|
2010-01-24 12:41:53 +01:00
|
|
|
m68k_run(mcycles_vdp + MCYCLES_PER_LINE);
|
|
|
|
if (zstate == 1)
|
|
|
|
z80_run(mcycles_vdp + MCYCLES_PER_LINE);
|
|
|
|
else
|
|
|
|
mcycles_z80 = mcycles_vdp + MCYCLES_PER_LINE;
|
2008-12-10 19:16:30 +01:00
|
|
|
|
|
|
|
/* SVP chip */
|
2010-01-24 12:41:53 +01:00
|
|
|
if (svp)
|
|
|
|
ssp1601_run(SVP_cycles);
|
|
|
|
|
|
|
|
/* update line cycle count */
|
|
|
|
mcycles_vdp += MCYCLES_PER_LINE;
|
2008-12-10 19:16:30 +01:00
|
|
|
}
|
|
|
|
|
2010-01-24 12:41:53 +01:00
|
|
|
/* adjust cpu cycle count for next frame */
|
|
|
|
mcycles_68k -= mcycles_vdp;
|
|
|
|
mcycles_z80 -= mcycles_vdp;
|
|
|
|
|
2008-12-10 19:16:30 +01:00
|
|
|
return gen_running;
|
2007-08-10 22:34:06 +02:00
|
|
|
}
|