(MESS) odyssey2, videopac: Updated drivers to use the i8244/i8245 device implementation. [Wilbert Pol]

This commit is contained in:
Wilbert Pol 2013-01-12 12:09:44 +00:00
parent 9cb42d805f
commit bd391081b7
4 changed files with 150 additions and 820 deletions

View File

@ -47,7 +47,7 @@ static ADDRESS_MAP_START( g7400_io , AS_IO, 8, odyssey2_state )
AM_RANGE(MCS48_PORT_P2, MCS48_PORT_P2) AM_READWRITE(p2_read, p2_write)
AM_RANGE(MCS48_PORT_BUS, MCS48_PORT_BUS) AM_READWRITE(bus_read, bus_write)
AM_RANGE(MCS48_PORT_T0, MCS48_PORT_T0) AM_READ(t0_read)
AM_RANGE(MCS48_PORT_T1, MCS48_PORT_T1) AM_READ(t1_read_g7400)
AM_RANGE(MCS48_PORT_T1, MCS48_PORT_T1) AM_READ(t1_read)
AM_RANGE(MCS48_PORT_PROG, MCS48_PORT_PROG) AM_DEVWRITE("i8243", i8243_device, i8243_prog_w);
ADDRESS_MAP_END
@ -137,12 +137,6 @@ WRITE_LINE_MEMBER(odyssey2_state::irq_callback)
}
WRITE8_MEMBER(odyssey2_state::lum_write)
{
m_lum = ( data & 0x01 ) << 3;
}
WRITE16_MEMBER(odyssey2_state::scanline_postprocess)
{
int vpos = data;
@ -156,7 +150,7 @@ WRITE16_MEMBER(odyssey2_state::scanline_postprocess)
}
READ8_MEMBER(odyssey2_state::t1_read_g7400)
READ8_MEMBER(odyssey2_state::t1_read)
{
if ( m_i8244->vblank() || m_i8244->hblank() )
{
@ -166,6 +160,143 @@ READ8_MEMBER(odyssey2_state::t1_read_g7400)
}
READ8_MEMBER(odyssey2_state::p1_read)
{
UINT8 data = m_p1;
logerror("%.9f p1 read %.2x\n", machine().time().as_double(), data);
return data;
}
WRITE8_MEMBER(odyssey2_state::p1_write)
{
m_p1 = data;
m_lum = ( data & 0x80 ) >> 4;
switch_banks();
logerror("%.6f p1 written %.2x\n", machine().time().as_double(), data);
}
READ8_MEMBER(odyssey2_state::p2_read)
{
UINT8 h = 0xFF;
int i, j;
static const char *const keynames[] = { "KEY0", "KEY1", "KEY2", "KEY3", "KEY4", "KEY5" };
if (!(m_p1 & P1_KEYBOARD_SCAN_ENABLE))
{
if ((m_p2 & P2_KEYBOARD_SELECT_MASK) <= 5) /* read keyboard */
{
h &= ioport(keynames[m_p2 & P2_KEYBOARD_SELECT_MASK])->read();
}
for (i= 0x80, j = 0; i > 0; i >>= 1, j++)
{
if (!(h & i))
{
m_p2 &= ~0x10; /* set key was pressed indicator */
m_p2 = (m_p2 & ~0xE0) | (j << 5); /* column that was pressed */
break;
}
}
if (h == 0xFF) /* active low inputs, so no keypresses */
{
m_p2 = m_p2 | 0xF0;
}
}
else
{
m_p2 = m_p2 | 0xF0;
}
logerror("%.6f p2 read %.2x\n", machine().time().as_double(), m_p2);
return m_p2;
}
WRITE8_MEMBER(odyssey2_state::p2_write)
{
m_p2 = data;
if ( m_i8243 )
{
m_i8243->i8243_p2_w( space, 0, m_p2 & 0x0f );
}
logerror("%.6f p2 written %.2x\n", machine().time().as_double(), data);
}
READ8_MEMBER(odyssey2_state::bus_read)
{
UINT8 data = 0xff;
if ((m_p2 & P2_KEYBOARD_SELECT_MASK) == 1)
{
data &= ioport("JOY0")->read(); /* read joystick 1 */
}
if ((m_p2 & P2_KEYBOARD_SELECT_MASK) == 0)
{
data &= ioport("JOY1")->read(); /* read joystick 2 */
}
logerror("%.6f bus read %.2x\n", machine().time().as_double(), data);
return data;
}
WRITE8_MEMBER(odyssey2_state::bus_write)
{
logerror("%.6f bus written %.2x\n", machine().time().as_double(), data);
}
/*
i8243 in the g7400
*/
WRITE8_MEMBER(odyssey2_state::i8243_port_w)
{
switch ( offset & 3 )
{
case 0: // "port 4"
m_g7400_ic674_decode[4] = BIT(data,0);
m_g7400_ic674_decode[5] = BIT(data,1);
m_g7400_ic674_decode[6] = BIT(data,2);
m_g7400_ic674_decode[7] = BIT(data,3);
break;
case 1: // "port 5"
m_g7400_ic674_decode[0] = BIT(data,0);
m_g7400_ic674_decode[1] = BIT(data,1);
m_g7400_ic674_decode[2] = BIT(data,2);
m_g7400_ic674_decode[3] = BIT(data,3);
break;
case 2: // "port 6"
m_g7400_ic678_decode[4] = BIT(data,0);
m_g7400_ic678_decode[5] = BIT(data,1);
m_g7400_ic678_decode[6] = BIT(data,2);
m_g7400_ic678_decode[7] = BIT(data,3);
break;
case 3: // "port 7"
m_g7400_ic678_decode[0] = BIT(data,0);
m_g7400_ic678_decode[1] = BIT(data,1);
m_g7400_ic678_decode[2] = BIT(data,2);
m_g7400_ic678_decode[3] = BIT(data,3);
break;
}
}
static const gfx_layout odyssey2_graphicslayout =
{
8,1,
@ -234,7 +365,7 @@ static MACHINE_CONFIG_START( odyssey2, odyssey2_state )
/* video hardware */
MCFG_SCREEN_ADD("screen", RASTER)
MCFG_SCREEN_RAW_PARAMS( XTAL_7_15909MHz/2, I824X_LINE_CLOCKS, I824X_START_ACTIVE_SCAN, I824X_END_ACTIVE_SCAN, 262, I824X_START_Y, I824X_START_Y + I824X_SCREEN_HEIGHT )
MCFG_SCREEN_RAW_PARAMS( XTAL_7_15909MHz/2, i8244_device::LINE_CLOCKS, i8244_device::START_ACTIVE_SCAN, i8244_device::END_ACTIVE_SCAN, i8244_device::LINES, i8244_device::START_Y, i8244_device::START_Y + i8244_device::SCREEN_HEIGHT )
MCFG_SCREEN_UPDATE_DRIVER(odyssey2_state, screen_update_odyssey2)
MCFG_GFXDECODE( odyssey2 )
@ -242,7 +373,7 @@ static MACHINE_CONFIG_START( odyssey2, odyssey2_state )
/* sound hardware */
MCFG_SPEAKER_STANDARD_MONO("mono")
MCFG_SOUND_ADD("custom", ODYSSEY2, XTAL_7_15909MHz/2)
MCFG_I8244_ADD( "i8244", XTAL_17_73447MHz/5, "screen", WRITELINE( odyssey2_state, irq_callback ), WRITE16( odyssey2_state, scanline_postprocess ) )
MCFG_SOUND_ROUTE(ALL_OUTPUTS, "mono", 0.40)
MCFG_SOUND_ADD("sp0256_speech", SP0256, 3120000)
@ -263,7 +394,7 @@ static MACHINE_CONFIG_START( videopac, odyssey2_state )
/* video hardware */
MCFG_SCREEN_ADD("screen", RASTER)
MCFG_SCREEN_RAW_PARAMS( XTAL_17_73447MHz/5, I824X_LINE_CLOCKS, I824X_START_ACTIVE_SCAN, I824X_END_ACTIVE_SCAN, 312, I824X_START_Y, I824X_START_Y + I824X_SCREEN_HEIGHT )
MCFG_SCREEN_RAW_PARAMS( XTAL_17_73447MHz/5, i8244_device::LINE_CLOCKS, i8244_device::START_ACTIVE_SCAN, i8244_device::END_ACTIVE_SCAN, i8245_device::LINES, i8244_device::START_Y, i8244_device::START_Y + i8244_device::SCREEN_HEIGHT )
MCFG_SCREEN_UPDATE_DRIVER(odyssey2_state, screen_update_odyssey2)
MCFG_GFXDECODE( odyssey2 )
@ -271,7 +402,7 @@ static MACHINE_CONFIG_START( videopac, odyssey2_state )
/* sound hardware */
MCFG_SPEAKER_STANDARD_MONO("mono")
MCFG_SOUND_ADD("custom", ODYSSEY2, XTAL_17_73447MHz/5)
MCFG_I8245_ADD( "i8244", XTAL_17_73447MHz/5, "screen", WRITELINE( odyssey2_state, irq_callback ), WRITE16( odyssey2_state, scanline_postprocess ) )
MCFG_SOUND_ROUTE(ALL_OUTPUTS, "mono", 0.40)
MCFG_SOUND_ADD("sp0256_speech", SP0256, 3120000)
@ -302,7 +433,7 @@ static MACHINE_CONFIG_START( g7400, odyssey2_state )
MCFG_I8243_ADD( "i8243", NOOP, WRITE8(odyssey2_state,i8243_port_w))
MCFG_SPEAKER_STANDARD_MONO("mono")
MCFG_I8244_ADD( "i8244", 3540000, "screen", WRITELINE( odyssey2_state, irq_callback ), WRITE16( odyssey2_state, scanline_postprocess ) )
MCFG_I8245_ADD( "i8244", 3540000, "screen", WRITELINE( odyssey2_state, irq_callback ), WRITE16( odyssey2_state, scanline_postprocess ) )
MCFG_SOUND_ROUTE(ALL_OUTPUTS, "mono", 0.40)
MCFG_FRAGMENT_ADD(odyssey2_cartslot)

View File

@ -20,44 +20,12 @@
#define P2_KEYBOARD_SELECT_MASK (0x07) /* select row to scan */
#define OLD_VDC_CONTROL_REG_STROBE_XY (0x02)
#define I824X_START_ACTIVE_SCAN 6
#define I824X_END_ACTIVE_SCAN (6 + 160)
#define I824X_START_Y 1
#define I824X_SCREEN_HEIGHT 243
#define I824X_LINE_CLOCKS 228
union o2_vdc_t {
UINT8 reg[0x100];
struct {
struct {
UINT8 y,x,color,res;
} sprites[4];
struct {
UINT8 y,x,ptr,color;
} foreground[12];
struct {
struct {
UINT8 y,x,ptr,color;
} single[4];
} quad[4];
UINT8 shape[4][8];
UINT8 control;
UINT8 status;
UINT8 collision;
UINT8 color;
UINT8 y;
UINT8 x;
UINT8 res;
UINT8 shift1,shift2,shift3;
UINT8 sound;
UINT8 res2[5+0x10];
UINT8 hgrid[2][0x10];
UINT8 vgrid[0x10];
} s;
};
struct ef9341_t
{
UINT8 TA;
@ -89,26 +57,17 @@ public:
required_device<cpu_device> m_maincpu;
required_device<screen_device> m_screen;
optional_device<i8243_device> m_i8243;
optional_device<i8244_device> m_i8244;
required_device<i8244_device> m_i8244;
int m_the_voice_lrq_state;
UINT8 *m_ram;
UINT8 m_p1;
UINT8 m_p2;
size_t m_cart_size;
o2_vdc_t m_o2_vdc;
UINT32 m_o2_snd_shift[2];
UINT8 m_x_beam_pos;
UINT8 m_y_beam_pos;
UINT8 m_control_status;
UINT8 m_collision_status;
int m_iff;
bitmap_ind16 m_tmp_bitmap;
int m_start_vpos;
int m_start_vblank;
UINT8 m_lum;
sound_stream *m_sh_channel;
UINT16 m_sh_count;
DECLARE_READ8_MEMBER(t0_read);
DECLARE_READ8_MEMBER(io_read);
DECLARE_WRITE8_MEMBER(io_write);
@ -120,11 +79,7 @@ public:
DECLARE_WRITE8_MEMBER(p1_write);
DECLARE_READ8_MEMBER(p2_read);
DECLARE_WRITE8_MEMBER(p2_write);
DECLARE_READ8_MEMBER(video_read);
DECLARE_WRITE8_MEMBER(video_write);
DECLARE_WRITE8_MEMBER(lum_write);
DECLARE_READ8_MEMBER(t1_read);
DECLARE_READ8_MEMBER(t1_read_g7400);
DECLARE_DRIVER_INIT(odyssey2);
virtual void machine_start();
virtual void machine_reset();
@ -156,7 +111,6 @@ protected:
// Calculate the external chargen address for a character and slice
inline UINT16 external_chargen_address(UINT8 b, UINT8 slice);
void i824x_scanline(int vpos);
void ef9340_scanline(int vpos);
/* timers */
@ -171,29 +125,4 @@ protected:
void switch_banks();
};
/*----------- defined in video/odyssey2.c -----------*/
STREAM_UPDATE( odyssey2_sh_update );
class odyssey2_sound_device : public device_t,
public device_sound_interface
{
public:
odyssey2_sound_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock);
protected:
// device-level overrides
virtual void device_config_complete();
virtual void device_start();
// sound stream update overrides
virtual void sound_stream_update(sound_stream &stream, stream_sample_t **inputs, stream_sample_t **outputs, int samples);
private:
// internal state
};
extern const device_type ODYSSEY2;
#endif /* ODYSSEY2_H_ */

View File

@ -97,6 +97,8 @@ void odyssey2_state::machine_start()
void odyssey2_state::machine_reset()
{
m_lum = 0;
/* jump to "last" bank, will work for all sizes due to being mirrored */
m_p1 = 0xFF;
m_p2 = 0xFF;
@ -115,7 +117,7 @@ READ8_MEMBER(odyssey2_state::io_read)
{
if ((m_p1 & (P1_VDC_COPY_MODE_ENABLE | P1_VDC_ENABLE)) == 0)
{
return video_read(space, offset); /* seems to have higher priority than ram??? */
return m_i8244->read(space, offset); /* seems to have higher priority than ram??? */
}
if (!(m_p1 & P1_EXT_RAM_ENABLE))
{
@ -146,7 +148,7 @@ WRITE8_MEMBER(odyssey2_state::io_write)
}
else if (!(m_p1 & P1_VDC_ENABLE))
{
video_write(space, offset, data);
m_i8244->write(space, offset, data);
}
}
@ -186,101 +188,3 @@ WRITE8_MEMBER(odyssey2_state::g7400_io_write)
}
}
/***** 8048 Ports ************************/
READ8_MEMBER(odyssey2_state::p1_read)
{
UINT8 data = m_p1;
logerror("%.9f p1 read %.2x\n", machine().time().as_double(), data);
return data;
}
WRITE8_MEMBER(odyssey2_state::p1_write)
{
m_p1 = data;
switch_banks();
lum_write(space, 0, m_p1 >> 7);
logerror("%.6f p1 written %.2x\n", machine().time().as_double(), data);
}
READ8_MEMBER(odyssey2_state::p2_read)
{
UINT8 h = 0xFF;
int i, j;
static const char *const keynames[] = { "KEY0", "KEY1", "KEY2", "KEY3", "KEY4", "KEY5" };
if (!(m_p1 & P1_KEYBOARD_SCAN_ENABLE))
{
if ((m_p2 & P2_KEYBOARD_SELECT_MASK) <= 5) /* read keyboard */
{
h &= ioport(keynames[m_p2 & P2_KEYBOARD_SELECT_MASK])->read();
}
for (i= 0x80, j = 0; i > 0; i >>= 1, j++)
{
if (!(h & i))
{
m_p2 &= ~0x10; /* set key was pressed indicator */
m_p2 = (m_p2 & ~0xE0) | (j << 5); /* column that was pressed */
break;
}
}
if (h == 0xFF) /* active low inputs, so no keypresses */
{
m_p2 = m_p2 | 0xF0;
}
}
else
{
m_p2 = m_p2 | 0xF0;
}
logerror("%.6f p2 read %.2x\n", machine().time().as_double(), m_p2);
return m_p2;
}
WRITE8_MEMBER(odyssey2_state::p2_write)
{
m_p2 = data;
if ( m_i8243 )
{
m_i8243->i8243_p2_w( space, 0, m_p2 & 0x0f );
}
logerror("%.6f p2 written %.2x\n", machine().time().as_double(), data);
}
READ8_MEMBER(odyssey2_state::bus_read)
{
UINT8 data = 0xff;
if ((m_p2 & P2_KEYBOARD_SELECT_MASK) == 1)
{
data &= ioport("JOY0")->read(); /* read joystick 1 */
}
if ((m_p2 & P2_KEYBOARD_SELECT_MASK) == 0)
{
data &= ioport("JOY1")->read(); /* read joystick 2 */
}
logerror("%.6f bus read %.2x\n", machine().time().as_double(), data);
return data;
}
WRITE8_MEMBER(odyssey2_state::bus_write)
{
logerror("%.6f bus written %.2x\n", machine().time().as_double(), data);
}

View File

@ -74,72 +74,6 @@ const UINT8 odyssey2_colors[] =
0xFF, 0xFF, 0xFF
};
static const UINT8 o2_shape[0x40][8]={
{ 0x7C,0xC6,0xC6,0xC6,0xC6,0xC6,0x7C,0x00 }, // 0
{ 0x18,0x38,0x18,0x18,0x18,0x18,0x3C,0x00 },
{ 0x3C,0x66,0x0C,0x18,0x30,0x60,0x7E,0x00 },
{ 0x7C,0xC6,0x06,0x3C,0x06,0xC6,0x7C,0x00 },
{ 0xCC,0xCC,0xCC,0xFE,0x0C,0x0C,0x0C,0x00 },
{ 0xFE,0xC0,0xC0,0x7C,0x06,0xC6,0x7C,0x00 },
{ 0x7C,0xC6,0xC0,0xFC,0xC6,0xC6,0x7C,0x00 },
{ 0xFE,0x06,0x0C,0x18,0x30,0x60,0xC0,0x00 },
{ 0x7C,0xC6,0xC6,0x7C,0xC6,0xC6,0x7C,0x00 },
{ 0x7C,0xC6,0xC6,0x7E,0x06,0xC6,0x7C,0x00 },
{ 0x00,0x18,0x18,0x00,0x18,0x18,0x00,0x00 },
{ 0x18,0x7E,0x58,0x7E,0x1A,0x7E,0x18,0x00 },
{ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 },
{ 0x3C,0x66,0x0C,0x18,0x18,0x00,0x18,0x00 },
{ 0xC0,0xC0,0xC0,0xC0,0xC0,0xC0,0xFE,0x00 },
{ 0xFC,0xC6,0xC6,0xFC,0xC0,0xC0,0xC0,0x00 },
{ 0x00,0x18,0x18,0x7E,0x18,0x18,0x00,0x00 },
{ 0xC6,0xC6,0xC6,0xD6,0xFE,0xEE,0xC6,0x00 },
{ 0xFE,0xC0,0xC0,0xF8,0xC0,0xC0,0xFE,0x00 },
{ 0xFC,0xC6,0xC6,0xFC,0xD8,0xCC,0xC6,0x00 },
{ 0x7E,0x18,0x18,0x18,0x18,0x18,0x18,0x00 },
{ 0xC6,0xC6,0xC6,0xC6,0xC6,0xC6,0x7C,0x00 },
{ 0x3C,0x18,0x18,0x18,0x18,0x18,0x3C,0x00 },
{ 0x7C,0xC6,0xC6,0xC6,0xC6,0xC6,0x7C,0x00 },
{ 0x7C,0xC6,0xC6,0xC6,0xDE,0xCC,0x76,0x00 },
{ 0x7C,0xC6,0xC0,0x7C,0x06,0xC6,0x7C,0x00 },
{ 0xFC,0xC6,0xC6,0xC6,0xC6,0xC6,0xFC,0x00 },
{ 0xFE,0xC0,0xC0,0xF8,0xC0,0xC0,0xC0,0x00 },
{ 0x7C,0xC6,0xC0,0xC0,0xCE,0xC6,0x7E,0x00 },
{ 0xC6,0xC6,0xC6,0xFE,0xC6,0xC6,0xC6,0x00 },
{ 0x06,0x06,0x06,0x06,0x06,0xC6,0x7C,0x00 },
{ 0xC6,0xCC,0xD8,0xF0,0xD8,0xCC,0xC6,0x00 },
{ 0x38,0x6C,0xC6,0xC6,0xFE,0xC6,0xC6,0x00 },
{ 0x7E,0x06,0x0C,0x18,0x30,0x60,0x7E,0x00 },
{ 0xC6,0xC6,0x6C,0x38,0x6C,0xC6,0xC6,0x00 },
{ 0x7C,0xC6,0xC0,0xC0,0xC0,0xC6,0x7C,0x00 },
{ 0xC6,0xC6,0xC6,0xC6,0xC6,0x6C,0x38,0x00 },
{ 0xFC,0xC6,0xC6,0xFC,0xC6,0xC6,0xFC,0x00 },
{ 0xC6,0xEE,0xFE,0xD6,0xC6,0xC6,0xC6,0x00 },
{ 0x00,0x00,0x00,0x00,0x00,0x18,0x18,0x00 },
{ 0x00,0x00,0x00,0x7E,0x00,0x00,0x00,0x00 },
{ 0x00,0x66,0x3C,0x18,0x3C,0x66,0x00,0x00 },
{ 0x00,0x18,0x00,0x7E,0x00,0x18,0x00,0x00 },
{ 0x00,0x00,0x7E,0x00,0x7E,0x00,0x00,0x00 },
{ 0x66,0x66,0x66,0x3C,0x18,0x18,0x18,0x00 },
{ 0xC6,0xE6,0xF6,0xFE,0xDE,0xCE,0xC6,0x00 },
{ 0x03,0x06,0x0C,0x18,0x30,0x60,0xC0,0x00 },
{ 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0x00 },
{ 0xCE,0xDB,0xDB,0xDB,0xDB,0xDB,0xCE,0x00 },
{ 0x00,0x00,0x3C,0x7E,0x7E,0x7E,0x3C,0x00 },
{ 0x1C,0x1C,0x18,0x1E,0x18,0x18,0x1C,0x00 },
{ 0x1C,0x1C,0x18,0x1E,0x18,0x34,0x26,0x00 },
{ 0x38,0x38,0x18,0x78,0x18,0x2C,0x64,0x00 },
{ 0x38,0x38,0x18,0x78,0x18,0x18,0x38,0x00 },
{ 0x00,0x18,0x0C,0xFE,0x0C,0x18,0x00,0x00 },
{ 0x18,0x3C,0x7E,0xFF,0xFF,0x18,0x18,0x00 },
{ 0x03,0x07,0x0F,0x1F,0x3F,0x7F,0xFF,0x00 },
{ 0xC0,0xE0,0xF0,0xF8,0xFC,0xFE,0xFF,0x00 },
{ 0x38,0x38,0x12,0xFE,0xB8,0x28,0x6C,0x00 },
{ 0xC0,0x60,0x30,0x18,0x0C,0x06,0x03,0x00 },
{ 0x00,0x00,0x0C,0x08,0x08,0x7F,0x3E,0x00 },
{ 0x00,0x03,0x63,0xFF,0xFF,0x18,0x08,0x00 },
{ 0x00,0x00,0x00,0x10,0x38,0xFF,0x7E,0x00 }
};
void odyssey2_state::palette_init()
{
@ -152,399 +86,6 @@ void odyssey2_state::palette_init()
}
READ8_MEMBER(odyssey2_state::video_read)
{
UINT8 data = 0;
switch (offset)
{
case 0xa1:
data = m_control_status;
m_iff = 0;
m_maincpu->set_input_line(0, CLEAR_LINE);
m_control_status &= ~ 0x08;
if ( m_screen->hpos() < I824X_START_ACTIVE_SCAN || m_screen->hpos() > I824X_END_ACTIVE_SCAN )
{
data |= 1;
}
break;
case 0xa2:
data = m_collision_status;
m_collision_status = 0;
break;
case 0xa4:
if (m_o2_vdc.s.control & OLD_VDC_CONTROL_REG_STROBE_XY)
{
m_y_beam_pos = m_screen->vpos() - m_start_vpos;
}
data = m_y_beam_pos;
break;
case 0xa5:
if ((m_o2_vdc.s.control & OLD_VDC_CONTROL_REG_STROBE_XY))
{
m_x_beam_pos = m_screen->hpos();
if ( m_x_beam_pos < I824X_START_ACTIVE_SCAN )
{
m_x_beam_pos = m_x_beam_pos - I824X_START_ACTIVE_SCAN + I824X_LINE_CLOCKS;
}
else
{
m_x_beam_pos = m_x_beam_pos - I824X_START_ACTIVE_SCAN;
}
}
data = m_x_beam_pos;
break;
default:
data = m_o2_vdc.reg[offset];
}
return data;
}
WRITE8_MEMBER(odyssey2_state::video_write)
{
/* Update the sound */
if( offset >= 0xa7 && offset <= 0xaa )
m_sh_channel->update();
if (offset == 0xa0) {
if ( m_o2_vdc.s.control & OLD_VDC_CONTROL_REG_STROBE_XY
&& !(data & OLD_VDC_CONTROL_REG_STROBE_XY))
{
/* Toggling strobe bit, tuck away values */
m_x_beam_pos = m_screen->hpos();
if ( m_x_beam_pos < I824X_START_ACTIVE_SCAN )
{
m_x_beam_pos = m_x_beam_pos - I824X_START_ACTIVE_SCAN + 228;
}
else
{
m_x_beam_pos = m_x_beam_pos - I824X_START_ACTIVE_SCAN;
}
m_y_beam_pos = m_screen->vpos() - m_start_vpos;
}
}
m_o2_vdc.reg[offset] = data;
}
READ8_MEMBER(odyssey2_state::t1_read)
{
if ( m_screen->vpos() > m_start_vpos && m_screen->vpos() < m_start_vblank )
{
if ( m_screen->hpos() >= I824X_START_ACTIVE_SCAN && m_screen->hpos() < I824X_END_ACTIVE_SCAN )
{
return 1;
}
}
return 0;
}
void odyssey2_state::i824x_scanline(int vpos)
{
UINT8 collision_map[160];
if ( vpos < m_start_vpos )
return;
if ( vpos == m_start_vpos )
{
m_control_status &= ~0x08;
}
if ( vpos < m_start_vblank )
{
rectangle rect;
//static const int sprite_width[4] = { 8, 8, 8, 8 };
int i;
m_control_status &= ~ 0x01;
/* Draw a line */
rect.set(I824X_START_ACTIVE_SCAN, I824X_END_ACTIVE_SCAN - 1, vpos, vpos);
m_tmp_bitmap.fill(( (m_o2_vdc.s.color >> 3) & 0x7 ) | ( ( m_lum << 3 ) ^ 0x08 ), rect );
/* Clear collision map */
memset( collision_map, 0, sizeof( collision_map ) );
/* Display grid if enabled */
if ( m_o2_vdc.s.control & 0x08 )
{
UINT16 color = ( m_o2_vdc.s.color & 7 ) | ( ( m_o2_vdc.s.color >> 3 ) & 0x08 ) | ( ( m_lum << 3 ) ^ 0x08 );
int x_grid_offset = 8;
int y_grid_offset = 24;
int width = 16;
int height = 24;
int w = ( m_o2_vdc.s.control & 0x80 ) ? width : 2;
int j, k, y;
/* Draw horizontal part of grid */
for ( j = 1, y = 0; y < 9; y++, j <<= 1 )
{
if ( y_grid_offset + y * height <= ( vpos - m_start_vpos ) && ( vpos - m_start_vpos ) < y_grid_offset + y * height + 3 )
{
for ( i = 0; i < 9; i++ )
{
if ( ( m_o2_vdc.s.hgrid[0][i] & j ) || ( m_o2_vdc.s.hgrid[1][i] & ( j >> 8 ) ) )
{
for ( k = 0; k < width + 2; k++ )
{
int px = x_grid_offset + i * width + k;
collision_map[ px ] |= COLLISION_HORIZ_GRID_DOTS;
m_tmp_bitmap.pix16(vpos, I824X_START_ACTIVE_SCAN + px ) = color;
}
}
}
}
}
/* Draw vertical part of grid */
for( j = 1, y = 0; y < 8; y++, j <<= 1 )
{
if ( y_grid_offset + y * height <= ( vpos - m_start_vpos ) && ( vpos - m_start_vpos ) < y_grid_offset + ( y + 1 ) * height )
{
for ( i = 0; i < 10; i++ )
{
if ( m_o2_vdc.s.vgrid[i] & j )
{
for ( k = 0; k < w; k++ )
{
int px = x_grid_offset + i * width + k;
/* Check if we collide with an already drawn source object */
if ( collision_map[ px ] & m_o2_vdc.s.collision )
{
m_collision_status |= COLLISION_VERTICAL_GRID;
}
/* Check if an already drawn object would collide with us */
if ( COLLISION_VERTICAL_GRID & m_o2_vdc.s.collision && collision_map[ px ] )
{
m_collision_status |= collision_map[ px ];
}
collision_map[ px ] |= COLLISION_VERTICAL_GRID;
m_tmp_bitmap.pix16(vpos, I824X_START_ACTIVE_SCAN + px ) = color;
}
}
}
}
}
}
/* Display objects if enabled */
if ( m_o2_vdc.s.control & 0x20 )
{
/* Regular foreground objects */
for ( i = 0; i < ARRAY_LENGTH( m_o2_vdc.s.foreground ); i++ )
{
int y = m_o2_vdc.s.foreground[i].y;
int height = 8 - ( ( ( y >> 1 ) + m_o2_vdc.s.foreground[i].ptr ) & 7 );
if ( y <= ( vpos - m_start_vpos ) && ( vpos - m_start_vpos ) < y + height * 2 )
{
UINT16 color = 16 + ( ( m_o2_vdc.s.foreground[i].color & 0x0E ) >> 1 );
int offset = ( m_o2_vdc.s.foreground[i].ptr | ( ( m_o2_vdc.s.foreground[i].color & 0x01 ) << 8 ) ) + ( y >> 1 ) + ( ( vpos - m_start_vpos - y ) >> 1 );
UINT8 chr = ((char*)o2_shape)[ offset & 0x1FF ];
int x = m_o2_vdc.s.foreground[i].x;
UINT8 m;
for ( m = 0x80; m > 0; m >>= 1, x++ )
{
if ( chr & m )
{
if ( x >= 0 && x < 160 )
{
/* Check if we collide with an already drawn source object */
if ( collision_map[ x ] & m_o2_vdc.s.collision )
{
m_collision_status |= COLLISION_CHARACTERS;
}
/* Check if an already drawn object would collide with us */
if ( COLLISION_CHARACTERS & m_o2_vdc.s.collision && collision_map[ x ] )
{
m_collision_status |= collision_map[ x ];
}
collision_map[ x ] |= COLLISION_CHARACTERS;
m_tmp_bitmap.pix16(vpos, I824X_START_ACTIVE_SCAN + x ) = color;
}
}
}
}
}
/* Quad objects */
for ( i = 0; i < ARRAY_LENGTH( m_o2_vdc.s.quad ); i++ )
{
int y = m_o2_vdc.s.quad[i].single[0].y;
int height = 8;
if ( y <= ( vpos - m_start_vpos ) && ( vpos - m_start_vpos ) < y + height * 2 )
{
int x = m_o2_vdc.s.quad[i].single[0].x;
int j;
// Charaecter height is always determined by the height of the 4th character
int char_height = 8 - ( ( ( y >> 1 ) + m_o2_vdc.s.quad[i].single[3].ptr ) & 7 );
for ( j = 0; j < ARRAY_LENGTH( m_o2_vdc.s.quad[0].single ); j++, x += 8 )
{
if ( y <= ( vpos - m_start_vpos ) && ( vpos - m_start_vpos ) < y + char_height * 2 )
{
UINT16 color = 16 + ( ( m_o2_vdc.s.quad[i].single[j].color & 0x0E ) >> 1 );
int offset = ( m_o2_vdc.s.quad[i].single[j].ptr | ( ( m_o2_vdc.s.quad[i].single[j].color & 0x01 ) << 8 ) ) + ( y >> 1 ) + ( ( vpos - m_start_vpos - y ) >> 1 );
UINT8 chr = ((char*)o2_shape)[ offset & 0x1FF ];
UINT8 m;
for ( m = 0x80; m > 0; m >>= 1, x++ )
{
if ( chr & m )
{
if ( x >= 0 && x < 160 )
{
/* Check if we collide with an already drawn source object */
if ( collision_map[ x ] & m_o2_vdc.s.collision )
{
m_collision_status |= COLLISION_CHARACTERS;
}
/* Check if an already drawn object would collide with us */
if ( COLLISION_CHARACTERS & m_o2_vdc.s.collision && collision_map[ x ] )
{
m_collision_status |= collision_map[ x ];
}
collision_map[ x ] |= COLLISION_CHARACTERS;
m_tmp_bitmap.pix16(vpos, I824X_START_ACTIVE_SCAN + x ) = color;
}
}
}
}
else
{
x += 8;
}
}
}
}
/* Sprites */
for ( i = 0; i < ARRAY_LENGTH( m_o2_vdc.s.sprites ); i++ )
{
int y = m_o2_vdc.s.sprites[i].y;
int height = 8;
if ( m_o2_vdc.s.sprites[i].color & 4 )
{
/* Zoomed sprite */
//sprite_width[i] = 16;
if ( y <= ( vpos - m_start_vpos ) && ( vpos - m_start_vpos ) < y + height * 4 )
{
UINT16 color = 16 + ( ( m_o2_vdc.s.sprites[i].color >> 3 ) & 0x07 );
UINT8 chr = m_o2_vdc.s.shape[i][ ( ( vpos - m_start_vpos - y ) >> 2 ) ];
int x = m_o2_vdc.s.sprites[i].x;
UINT8 m;
for ( m = 0x01; m > 0; m <<= 1, x += 2 )
{
if ( chr & m )
{
if ( x >= 0 && x < 160 )
{
/* Check if we collide with an already drawn source object */
if ( collision_map[ x ] & m_o2_vdc.s.collision )
{
m_collision_status |= ( 1 << i );
}
/* Check if an already drawn object would collide with us */
if ( ( 1 << i ) & m_o2_vdc.s.collision && collision_map[ x ] )
{
m_collision_status |= collision_map[ x ];
}
collision_map[ x ] |= ( 1 << i );
m_tmp_bitmap.pix16(vpos, I824X_START_ACTIVE_SCAN + x ) = color;
}
if ( x >= -1 && x < 159 )
{
/* Check if we collide with an already drawn source object */
if ( collision_map[ x ] & m_o2_vdc.s.collision )
{
m_collision_status |= ( 1 << i );
}
/* Check if an already drawn object would collide with us */
if ( ( 1 << i ) & m_o2_vdc.s.collision && collision_map[ x ] )
{
m_collision_status |= collision_map[ x ];
}
collision_map[ x ] |= ( 1 << i );
m_tmp_bitmap.pix16(vpos, I824X_START_ACTIVE_SCAN + x + 1 ) = color;
}
}
}
}
}
else
{
/* Regular sprite */
if ( y <= ( vpos - m_start_vpos ) && ( vpos - m_start_vpos ) < y + height * 2 )
{
UINT16 color = 16 + ( ( m_o2_vdc.s.sprites[i].color >> 3 ) & 0x07 );
UINT8 chr = m_o2_vdc.s.shape[i][ ( ( vpos - m_start_vpos - y ) >> 1 ) ];
int x = m_o2_vdc.s.sprites[i].x;
UINT8 m;
for ( m = 0x01; m > 0; m <<= 1, x++ )
{
if ( chr & m )
{
if ( x >= 0 && x < 160 )
{
/* Check if we collide with an already drawn source object */
if ( collision_map[ x ] & m_o2_vdc.s.collision )
{
m_collision_status |= ( 1 << i );
}
/* Check if an already drawn object would collide with us */
if ( ( 1 << i ) & m_o2_vdc.s.collision && collision_map[ x ] )
{
m_collision_status |= collision_map[ x ];
}
collision_map[ x ] |= ( 1 << i );
m_tmp_bitmap.pix16(vpos, I824X_START_ACTIVE_SCAN + x ) = color;
}
}
}
}
}
}
}
}
/* Check for start of VBlank */
if ( vpos == m_start_vblank )
{
m_control_status |= 0x08;
if ( ! m_iff )
{
m_maincpu->set_input_line(0, ASSERT_LINE);
m_iff = 1;
}
}
}
void odyssey2_state::device_timer(emu_timer &timer, device_timer_id id, int param, void *ptr)
{
int vpos = m_screen->vpos();
@ -552,8 +93,6 @@ void odyssey2_state::device_timer(emu_timer &timer, device_timer_id id, int para
switch ( id )
{
case TIMER_LINE:
// handle i824x line timer
i824x_scanline(vpos);
if ( m_g7400 )
{
ef9340_scanline(vpos);
@ -561,16 +100,6 @@ void odyssey2_state::device_timer(emu_timer &timer, device_timer_id id, int para
break;
case TIMER_HBLANK:
// handle i824x HBlank timer
if ( vpos < m_start_vpos - 1 )
{
return;
}
if ( vpos < m_start_vblank - 1 )
{
m_control_status |= 0x01;
}
break;
}
}
@ -584,25 +113,8 @@ void odyssey2_state::device_timer(emu_timer &timer, device_timer_id id, int para
void odyssey2_state::video_start()
{
memset(m_o2_vdc.reg, 0, 0x100);
m_o2_snd_shift[0] = m_o2_snd_shift[1] = 0;
m_x_beam_pos = 0;
m_y_beam_pos = 0;
m_control_status = 0;
m_collision_status = 0;
m_iff = 0;
m_start_vpos = 0;
m_start_vblank = 0;
m_lum = 0;
m_o2_snd_shift[0] = machine().sample_rate() / 983;
m_o2_snd_shift[1] = machine().sample_rate() / 3933;
m_start_vpos = I824X_START_Y;
m_start_vblank = I824X_START_Y + I824X_SCREEN_HEIGHT;
m_control_status = 0;
m_iff = 0;
m_screen->register_screen_bitmap(m_tmp_bitmap);
@ -639,116 +151,7 @@ void odyssey2_state::video_start_g7400()
UINT32 odyssey2_state::screen_update_odyssey2(screen_device &screen, bitmap_ind16 &bitmap, const rectangle &cliprect)
{
copybitmap( bitmap, m_tmp_bitmap, 0, 0, 0, 0, cliprect );
if ( m_i8244 )
{
return m_i8244->screen_update(screen, bitmap, cliprect);
}
return 0;
}
static DEVICE_START( odyssey2_sound )
{
odyssey2_state *state = device->machine().driver_data<odyssey2_state>();
state->m_sh_channel = device->machine().sound().stream_alloc(*device, 0, 1, device->clock()/(I824X_LINE_CLOCKS*4), 0, odyssey2_sh_update );
}
STREAM_UPDATE( odyssey2_sh_update )
{
odyssey2_state *state = device->machine().driver_data<odyssey2_state>();
UINT32 old_signal, signal;
int ii;
int period;
stream_sample_t *buffer = outputs[0];
/* Generate the signal */
old_signal = signal = state->m_o2_vdc.s.shift3 | (state->m_o2_vdc.s.shift2 << 8) | (state->m_o2_vdc.s.shift1 << 16);
if( state->m_o2_vdc.s.sound & 0x80 ) /* Sound is enabled */
{
for( ii = 0; ii < samples; ii++, buffer++ )
{
*buffer = 0;
*buffer = signal & 0x1;
period = (state->m_o2_vdc.s.sound & 0x20) ? 1 : 4;
if( ++state->m_sh_count >= period )
{
state->m_sh_count = 0;
signal >>= 1;
/* Loop sound */
signal |= *buffer << 23;
/* Check if noise should be applied */
if ( state->m_o2_vdc.s.sound & 0x10 )
{
/* Noise tap is on bits 0 and 5 and fed back to bits 15 (and 23!) */
UINT32 new_bit = ( ( old_signal ) ^ ( old_signal >> 5 ) ) & 0x01;
signal = ( old_signal & 0xFF0000 ) | ( ( old_signal & 0xFFFF ) >> 1 ) | ( new_bit << 15 ) | ( new_bit << 23 );
}
state->m_o2_vdc.s.shift3 = signal & 0xFF;
state->m_o2_vdc.s.shift2 = ( signal >> 8 ) & 0xFF;
state->m_o2_vdc.s.shift1 = ( signal >> 16 ) & 0xFF;
old_signal = signal;
}
/* Throw an interrupt if enabled */
if( state->m_o2_vdc.s.control & 0x4 )
{
state->m_maincpu->set_input_line(1, HOLD_LINE); /* Is this right? */
}
/* Adjust volume */
*buffer *= state->m_o2_vdc.s.sound & 0xf;
/* Pump the volume up */
*buffer <<= 10;
}
}
else
{
/* Sound disabled, so clear the buffer */
for( ii = 0; ii < samples; ii++, buffer++ )
*buffer = 0;
}
}
/*
i8243 in the g7400
*/
WRITE8_MEMBER(odyssey2_state::i8243_port_w)
{
switch ( offset & 3 )
{
case 0: // "port 4"
m_g7400_ic674_decode[4] = BIT(data,0);
m_g7400_ic674_decode[5] = BIT(data,1);
m_g7400_ic674_decode[6] = BIT(data,2);
m_g7400_ic674_decode[7] = BIT(data,3);
break;
case 1: // "port 5"
m_g7400_ic674_decode[0] = BIT(data,0);
m_g7400_ic674_decode[1] = BIT(data,1);
m_g7400_ic674_decode[2] = BIT(data,2);
m_g7400_ic674_decode[3] = BIT(data,3);
break;
case 2: // "port 6"
m_g7400_ic678_decode[4] = BIT(data,0);
m_g7400_ic678_decode[5] = BIT(data,1);
m_g7400_ic678_decode[6] = BIT(data,2);
m_g7400_ic678_decode[7] = BIT(data,3);
break;
case 3: // "port 7"
m_g7400_ic678_decode[0] = BIT(data,0);
m_g7400_ic678_decode[1] = BIT(data,1);
m_g7400_ic678_decode[2] = BIT(data,2);
m_g7400_ic678_decode[3] = BIT(data,3);
break;
}
return m_i8244->screen_update(screen, bitmap, cliprect);
}
@ -1007,40 +410,3 @@ void odyssey2_state::ef9340_scanline(int vpos)
}
}
const device_type ODYSSEY2 = &device_creator<odyssey2_sound_device>;
odyssey2_sound_device::odyssey2_sound_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock)
: device_t(mconfig, ODYSSEY2, "P8244/P8245", tag, owner, clock),
device_sound_interface(mconfig, *this)
{
}
//-------------------------------------------------
// device_config_complete - perform any
// operations now that the configuration is
// complete
//-------------------------------------------------
void odyssey2_sound_device::device_config_complete()
{
}
//-------------------------------------------------
// device_start - device-specific startup
//-------------------------------------------------
void odyssey2_sound_device::device_start()
{
DEVICE_START_NAME( odyssey2_sound )(this);
}
//-------------------------------------------------
// sound_stream_update - handle a stream update
//-------------------------------------------------
void odyssey2_sound_device::sound_stream_update(sound_stream &stream, stream_sample_t **inputs, stream_sample_t **outputs, int samples)
{
// should never get here
fatalerror("sound_stream_update called; not applicable to legacy sound devices\n");
}