mirror of
https://github.com/holub/mame
synced 2025-04-24 09:20:02 +03:00
Missed files
This commit is contained in:
parent
a16d106a97
commit
89bf152dae
3
.gitattributes
vendored
3
.gitattributes
vendored
@ -2628,6 +2628,7 @@ src/mame/drivers/vastar.c svneol=native#text/plain
|
||||
src/mame/drivers/vball.c svneol=native#text/plain
|
||||
src/mame/drivers/vcombat.c svneol=native#text/plain
|
||||
src/mame/drivers/vd.c svneol=native#text/plain
|
||||
src/mame/drivers/vectrex.c svneol=native#text/plain
|
||||
src/mame/drivers/vega.c svneol=native#text/plain
|
||||
src/mame/drivers/vegaeo.c svneol=native#text/plain
|
||||
src/mame/drivers/vegas.c svneol=native#text/plain
|
||||
@ -3344,6 +3345,7 @@ src/mame/includes/usgames.h svneol=native#text/plain
|
||||
src/mame/includes/vaportra.h svneol=native#text/plain
|
||||
src/mame/includes/vastar.h svneol=native#text/plain
|
||||
src/mame/includes/vball.h svneol=native#text/plain
|
||||
src/mame/includes/vectrex.h svneol=native#text/plain
|
||||
src/mame/includes/vendetta.h svneol=native#text/plain
|
||||
src/mame/includes/vertigo.h svneol=native#text/plain
|
||||
src/mame/includes/vicdual.h svneol=native#text/plain
|
||||
@ -4460,6 +4462,7 @@ src/mame/video/vastar.c svneol=native#text/plain
|
||||
src/mame/video/vball.c svneol=native#text/plain
|
||||
src/mame/video/vdc.c svneol=native#text/plain
|
||||
src/mame/video/vdc.h svneol=native#text/plain
|
||||
src/mame/video/vectrex.c svneol=native#text/plain
|
||||
src/mame/video/vendetta.c svneol=native#text/plain
|
||||
src/mame/video/vertigo.c svneol=native#text/plain
|
||||
src/mame/video/vicdual.c svneol=native#text/plain
|
||||
|
233
src/mame/drivers/vectrex.c
Normal file
233
src/mame/drivers/vectrex.c
Normal file
@ -0,0 +1,233 @@
|
||||
/*****************************************************************
|
||||
|
||||
GCE Vectrex
|
||||
|
||||
Mathis Rosenhauer
|
||||
Christopher Salomon (technical advice)
|
||||
Bruce Tomlin (hardware info)
|
||||
|
||||
*****************************************************************/
|
||||
|
||||
#include "emu.h"
|
||||
#include "cpu/m6809/m6809.h"
|
||||
#include "video/vector.h"
|
||||
#include "machine/6522via.h"
|
||||
#include "includes/vectrex.h"
|
||||
#include "imagedev/cartslot.h"
|
||||
#include "sound/ay8910.h"
|
||||
#include "sound/dac.h"
|
||||
#include "machine/nvram.h"
|
||||
|
||||
|
||||
static ADDRESS_MAP_START(vectrex_map, AS_PROGRAM, 8)
|
||||
AM_RANGE(0x0000, 0x7fff) AM_ROM
|
||||
AM_RANGE(0xc800, 0xcbff) AM_RAM AM_MIRROR(0x0400) AM_BASE_MEMBER(vectrex_state, m_gce_vectorram) AM_SIZE_MEMBER(vectrex_state, m_gce_vectorram_size)
|
||||
AM_RANGE(0xd000, 0xd7ff) AM_READWRITE(vectrex_via_r, vectrex_via_w)
|
||||
AM_RANGE(0xe000, 0xffff) AM_ROM
|
||||
ADDRESS_MAP_END
|
||||
|
||||
static INPUT_PORTS_START(vectrex)
|
||||
PORT_START("CONTR1X")
|
||||
PORT_BIT(0xff, 0x80, IPT_AD_STICK_X) PORT_MINMAX(0,0xff) PORT_SENSITIVITY(50) PORT_KEYDELTA(30)
|
||||
|
||||
PORT_START("CONTR1Y")
|
||||
PORT_BIT(0xff, 0x80, IPT_AD_STICK_Y) PORT_MINMAX(0,0xff) PORT_SENSITIVITY(50) PORT_KEYDELTA(30) PORT_REVERSE
|
||||
|
||||
PORT_START("CONTR2X")
|
||||
PORT_BIT(0xff, 0x80, IPT_AD_STICK_X) PORT_MINMAX(0,0xff) PORT_SENSITIVITY(50) PORT_KEYDELTA(30) PORT_PLAYER(2)
|
||||
|
||||
PORT_START("CONTR2Y")
|
||||
PORT_BIT(0xff, 0x80, IPT_AD_STICK_Y) PORT_MINMAX(0,0xff) PORT_SENSITIVITY(50) PORT_KEYDELTA(30) PORT_REVERSE PORT_PLAYER(2)
|
||||
|
||||
PORT_START("BUTTONS")
|
||||
PORT_BIT(0x01, IP_ACTIVE_LOW, IPT_BUTTON1) PORT_PLAYER(1)
|
||||
PORT_BIT(0x02, IP_ACTIVE_LOW, IPT_BUTTON2) PORT_PLAYER(1)
|
||||
PORT_BIT(0x04, IP_ACTIVE_LOW, IPT_BUTTON3) PORT_PLAYER(1)
|
||||
PORT_BIT(0x08, IP_ACTIVE_LOW, IPT_BUTTON4) PORT_PLAYER(1)
|
||||
PORT_BIT(0x10, IP_ACTIVE_LOW, IPT_BUTTON1) PORT_PLAYER(2)
|
||||
PORT_BIT(0x20, IP_ACTIVE_LOW, IPT_BUTTON2) PORT_PLAYER(2)
|
||||
PORT_BIT(0x40, IP_ACTIVE_LOW, IPT_BUTTON3) PORT_PLAYER(2)
|
||||
PORT_BIT(0x80, IP_ACTIVE_LOW, IPT_BUTTON4) PORT_PLAYER(2)
|
||||
|
||||
PORT_START("3DCONF")
|
||||
PORT_CONFNAME(0x01, 0x00, "3D Imager")
|
||||
PORT_CONFSETTING(0x00, DEF_STR(Off))
|
||||
PORT_CONFSETTING(0x01, DEF_STR(On))
|
||||
PORT_CONFNAME(0x02, 0x00, "Separate images")
|
||||
PORT_CONFSETTING(0x00, DEF_STR(No))
|
||||
PORT_CONFSETTING(0x02, DEF_STR(Yes))
|
||||
PORT_CONFNAME(0x1c, 0x10, "Left eye")
|
||||
PORT_CONFSETTING(0x00, "Black")
|
||||
PORT_CONFSETTING(0x04, "Red")
|
||||
PORT_CONFSETTING(0x08, "Green")
|
||||
PORT_CONFSETTING(0x0c, "Blue")
|
||||
PORT_CONFSETTING(0x10, "Color")
|
||||
PORT_CONFNAME(0xe0, 0x80, "Right eye")
|
||||
PORT_CONFSETTING(0x00, "Black")
|
||||
PORT_CONFSETTING(0x20, "Red")
|
||||
PORT_CONFSETTING(0x40, "Green")
|
||||
PORT_CONFSETTING(0x60, "Blue")
|
||||
PORT_CONFSETTING(0x80, "Color")
|
||||
|
||||
PORT_START("LPENCONF")
|
||||
PORT_CONFNAME(0x03, 0x00, "Lightpen")
|
||||
PORT_CONFSETTING(0x00, DEF_STR(Off))
|
||||
PORT_CONFSETTING(0x01, "left port")
|
||||
PORT_CONFSETTING(0x02, "right port")
|
||||
PORT_BIT(0x10, IP_ACTIVE_HIGH, IPT_BUTTON5) PORT_CODE(MOUSECODE_BUTTON1)
|
||||
|
||||
PORT_START("LPENY")
|
||||
PORT_BIT(0xff, 0x80, IPT_LIGHTGUN_X) PORT_CROSSHAIR(Y, 1, 0, 0) PORT_MINMAX(0,0xff) PORT_SENSITIVITY(35) PORT_KEYDELTA(1) PORT_PLAYER(1)
|
||||
|
||||
PORT_START("LPENX")
|
||||
PORT_BIT(0xff, 0x80, IPT_LIGHTGUN_Y) PORT_CROSSHAIR(X, 1, 0, 0) PORT_MINMAX(0,0xff) PORT_SENSITIVITY(35) PORT_KEYDELTA(1) PORT_REVERSE PORT_PLAYER(1)
|
||||
|
||||
INPUT_PORTS_END
|
||||
|
||||
|
||||
|
||||
static const ay8910_interface vectrex_ay8910_interface =
|
||||
{
|
||||
AY8910_LEGACY_OUTPUT,
|
||||
AY8910_DEFAULT_LOADS,
|
||||
DEVCB_INPUT_PORT("BUTTONS"),
|
||||
DEVCB_NULL,
|
||||
DEVCB_MEMORY_HANDLER("maincpu", PROGRAM, vectrex_psg_port_w),
|
||||
DEVCB_NULL
|
||||
};
|
||||
|
||||
static MACHINE_CONFIG_START( vectrex, vectrex_state )
|
||||
/* basic machine hardware */
|
||||
MCFG_CPU_ADD("maincpu", M6809, XTAL_6MHz / 4)
|
||||
MCFG_CPU_PROGRAM_MAP(vectrex_map)
|
||||
|
||||
/* video hardware */
|
||||
MCFG_SCREEN_ADD("screen", VECTOR)
|
||||
MCFG_SCREEN_REFRESH_RATE(60)
|
||||
MCFG_SCREEN_FORMAT(BITMAP_FORMAT_RGB32)
|
||||
MCFG_SCREEN_SIZE(400, 300)
|
||||
MCFG_SCREEN_VISIBLE_AREA(0, 399, 0, 299)
|
||||
MCFG_SCREEN_UPDATE(vectrex)
|
||||
|
||||
MCFG_VIDEO_START(vectrex)
|
||||
|
||||
/* sound hardware */
|
||||
MCFG_SPEAKER_STANDARD_MONO("mono")
|
||||
MCFG_SOUND_ADD("dac", DAC, 0)
|
||||
MCFG_SOUND_ROUTE(ALL_OUTPUTS, "mono", 0.50)
|
||||
MCFG_SOUND_ADD("ay8912", AY8912, 1500000)
|
||||
MCFG_SOUND_CONFIG(vectrex_ay8910_interface)
|
||||
MCFG_SOUND_ROUTE(ALL_OUTPUTS, "mono", 0.20)
|
||||
|
||||
/* via */
|
||||
MCFG_VIA6522_ADD("via6522_0", 0, vectrex_via6522_interface)
|
||||
|
||||
/* cartridge */
|
||||
MCFG_CARTSLOT_ADD("cart")
|
||||
MCFG_CARTSLOT_EXTENSION_LIST("bin,gam,vec")
|
||||
MCFG_CARTSLOT_NOT_MANDATORY
|
||||
MCFG_CARTSLOT_LOAD(vectrex_cart)
|
||||
MCFG_CARTSLOT_INTERFACE("vectrex_cart")
|
||||
|
||||
/* software lists */
|
||||
MCFG_SOFTWARE_LIST_ADD("cart_list","vectrex")
|
||||
MACHINE_CONFIG_END
|
||||
|
||||
ROM_START(vectrex)
|
||||
ROM_REGION(0x10000,"maincpu", 0)
|
||||
ROM_LOAD("system.img", 0xe000, 0x2000, CRC(ba13fb57) SHA1(65d07426b520ddd3115d40f255511e0fd2e20ae7))
|
||||
ROM_END
|
||||
|
||||
|
||||
/*****************************************************************
|
||||
|
||||
RA+A Spectrum I+
|
||||
|
||||
The Spectrum I+ was a modified Vectrex. It had a 32K ROM cart
|
||||
and 2K additional battery backed RAM (0x8000 - 0x87ff). PB6
|
||||
was used to signal inserted coins to the VIA. The unit was
|
||||
controlled by 8 buttons (2x4 buttons of controller 1 and 2).
|
||||
Each button had a LED which were mapped to 0xa000.
|
||||
The srvice mode can be accessed by pressing button
|
||||
8 during startup. As soon as all LEDs light up,
|
||||
press 2 and 3 without releasing 8. Then release 8 and
|
||||
after that 2 and 3. You can leave the screen where you enter
|
||||
ads by pressing 8 several times.
|
||||
|
||||
Character matrix is:
|
||||
|
||||
btn| 1 2 3 4 5 6 7 8
|
||||
---+------------------------
|
||||
1 | 0 1 2 3 4 5 6 7
|
||||
2 | 8 9 A B C D E F
|
||||
3 | G H I J K L M N
|
||||
4 | O P Q R S T U V
|
||||
5 | W X Y Z sp ! " #
|
||||
6 | $ % & ' ( ) * +
|
||||
7 | , - _ / : ; ? =
|
||||
8 |bs ret up dn l r hom esc
|
||||
|
||||
The first page of ads is shown with the "result" of the
|
||||
test. Remaining pages are shown in attract mode. If no extra
|
||||
ram is present, the word COLOR is scrolled in big vector!
|
||||
letters in attract mode.
|
||||
|
||||
*****************************************************************/
|
||||
|
||||
static ADDRESS_MAP_START(raaspec_map , AS_PROGRAM, 8)
|
||||
AM_RANGE(0x0000, 0x7fff) AM_ROM
|
||||
AM_RANGE(0x8000, 0x87ff) AM_RAM AM_SHARE("nvram")
|
||||
AM_RANGE(0xa000, 0xa000) AM_WRITE(raaspec_led_w)
|
||||
AM_RANGE(0xc800, 0xcbff) AM_RAM AM_MIRROR(0x0400) AM_BASE_MEMBER(vectrex_state, m_gce_vectorram) AM_SIZE_MEMBER(vectrex_state, m_gce_vectorram_size)
|
||||
AM_RANGE(0xd000, 0xd7ff) AM_READWRITE (vectrex_via_r, vectrex_via_w)
|
||||
AM_RANGE(0xe000, 0xffff) AM_ROM
|
||||
ADDRESS_MAP_END
|
||||
|
||||
static INPUT_PORTS_START(raaspec)
|
||||
PORT_START("LPENCONF")
|
||||
PORT_START("LPENY")
|
||||
PORT_START("LPENX")
|
||||
PORT_START("3DCONF")
|
||||
PORT_START("BUTTONS")
|
||||
PORT_BIT(0x01, IP_ACTIVE_LOW, IPT_BUTTON1)
|
||||
PORT_BIT(0x02, IP_ACTIVE_LOW, IPT_BUTTON2)
|
||||
PORT_BIT(0x04, IP_ACTIVE_LOW, IPT_BUTTON3)
|
||||
PORT_BIT(0x08, IP_ACTIVE_LOW, IPT_BUTTON4)
|
||||
PORT_BIT(0x10, IP_ACTIVE_LOW, IPT_BUTTON5)
|
||||
PORT_BIT(0x20, IP_ACTIVE_LOW, IPT_BUTTON6)
|
||||
PORT_BIT(0x40, IP_ACTIVE_LOW, IPT_BUTTON7)
|
||||
PORT_BIT(0x80, IP_ACTIVE_LOW, IPT_BUTTON8)
|
||||
PORT_START("COIN")
|
||||
PORT_BIT(0x40, IP_ACTIVE_HIGH, IPT_COIN1)
|
||||
INPUT_PORTS_END
|
||||
|
||||
|
||||
static MACHINE_CONFIG_DERIVED( raaspec, vectrex )
|
||||
MCFG_CPU_MODIFY("maincpu")
|
||||
MCFG_CPU_PROGRAM_MAP(raaspec_map)
|
||||
MCFG_NVRAM_ADD_0FILL("nvram")
|
||||
|
||||
MCFG_VIDEO_START(raaspec)
|
||||
|
||||
/* via */
|
||||
MCFG_DEVICE_REMOVE("via6522_0")
|
||||
MCFG_VIA6522_ADD("via6522_0", 0, spectrum1_via6522_interface)
|
||||
|
||||
MCFG_DEVICE_REMOVE("cart")
|
||||
MACHINE_CONFIG_END
|
||||
|
||||
ROM_START(raaspec)
|
||||
ROM_REGION(0x10000,"maincpu", 0)
|
||||
ROM_LOAD("spectrum.bin", 0x0000, 0x8000, CRC(20af7f3f) SHA1(7ce85db8dd32687ad7629631ae113820371faf7c))
|
||||
ROM_LOAD("system.img", 0xe000, 0x2000, CRC(ba13fb57) SHA1(65d07426b520ddd3115d40f255511e0fd2e20ae7))
|
||||
ROM_END
|
||||
|
||||
/***************************************************************************
|
||||
|
||||
Game driver(s)
|
||||
|
||||
***************************************************************************/
|
||||
|
||||
/* YEAR NAME PARENT COMPAT MACHINE INPUT INIT COMPANY FULLNAME */
|
||||
CONS(1982, vectrex, 0, 0, vectrex, vectrex, vectrex, "General Consumer Electronics", "Vectrex" , ROT270)
|
||||
CONS(1984, raaspec, vectrex, 0, raaspec, raaspec, vectrex, "Roy Abel & Associates", "Spectrum I+" , ROT270)
|
103
src/mame/includes/vectrex.h
Normal file
103
src/mame/includes/vectrex.h
Normal file
@ -0,0 +1,103 @@
|
||||
/*****************************************************************************
|
||||
*
|
||||
* includes/vectrex.h
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
#ifndef VECTREX_H_
|
||||
#define VECTREX_H_
|
||||
|
||||
#include "machine/6522via.h"
|
||||
|
||||
#define NVECT 10000
|
||||
|
||||
typedef struct _vectrex_point
|
||||
{
|
||||
int x; int y;
|
||||
rgb_t col;
|
||||
int intensity;
|
||||
} vectrex_point;
|
||||
|
||||
class vectrex_state : public driver_device
|
||||
{
|
||||
public:
|
||||
vectrex_state(const machine_config &mconfig, device_type type, const char *tag)
|
||||
: driver_device(mconfig, type, tag) { }
|
||||
|
||||
UINT8 *m_gce_vectorram;
|
||||
size_t m_gce_vectorram_size;
|
||||
int m_imager_status;
|
||||
UINT32 m_beam_color;
|
||||
unsigned char m_via_out[2];
|
||||
double m_imager_freq;
|
||||
emu_timer *m_imager_timer;
|
||||
int m_lightpen_port;
|
||||
int m_reset_refresh;
|
||||
rgb_t m_imager_colors[6];
|
||||
const double *m_imager_angles;
|
||||
unsigned char m_imager_pinlevel;
|
||||
int m_old_mcontrol;
|
||||
double m_sl;
|
||||
double m_pwl;
|
||||
int m_x_center;
|
||||
int m_y_center;
|
||||
int m_x_max;
|
||||
int m_y_max;
|
||||
int m_x_int;
|
||||
int m_y_int;
|
||||
int m_lightpen_down;
|
||||
int m_pen_x;
|
||||
int m_pen_y;
|
||||
emu_timer *m_lp_t;
|
||||
emu_timer *m_refresh;
|
||||
UINT8 m_blank;
|
||||
UINT8 m_ramp;
|
||||
INT8 m_analog[5];
|
||||
int m_point_index;
|
||||
int m_display_start;
|
||||
int m_display_end;
|
||||
vectrex_point m_points[NVECT];
|
||||
UINT16 m_via_timer2;
|
||||
attotime m_vector_start_time;
|
||||
UINT8 m_cb2;
|
||||
void (*vector_add_point_function) (running_machine &, int, int, rgb_t, int);
|
||||
};
|
||||
|
||||
|
||||
/*----------- defined in machine/vectrex.c -----------*/
|
||||
|
||||
DEVICE_IMAGE_LOAD( vectrex_cart );
|
||||
|
||||
|
||||
TIMER_CALLBACK(vectrex_imager_eye);
|
||||
void vectrex_configuration(running_machine &machine);
|
||||
READ8_DEVICE_HANDLER (vectrex_via_pa_r);
|
||||
READ8_DEVICE_HANDLER(vectrex_via_pb_r );
|
||||
void vectrex_via_irq (device_t *device, int level);
|
||||
WRITE8_HANDLER ( vectrex_psg_port_w );
|
||||
|
||||
DRIVER_INIT( vectrex );
|
||||
|
||||
/* for spectrum 1+ */
|
||||
READ8_DEVICE_HANDLER( vectrex_s1_via_pb_r );
|
||||
|
||||
|
||||
/*----------- defined in video/vectrex.c -----------*/
|
||||
|
||||
extern const via6522_interface vectrex_via6522_interface;
|
||||
extern const via6522_interface spectrum1_via6522_interface;
|
||||
|
||||
VIDEO_START( vectrex );
|
||||
SCREEN_UPDATE( vectrex );
|
||||
|
||||
VIDEO_START( raaspec );
|
||||
|
||||
WRITE8_HANDLER ( raaspec_led_w );
|
||||
|
||||
READ8_HANDLER ( vectrex_via_r );
|
||||
WRITE8_HANDLER ( vectrex_via_w );
|
||||
|
||||
void vectrex_add_point_stereo (running_machine &machine, int x, int y, rgb_t color, int intensity);
|
||||
void vectrex_add_point (running_machine &machine, int x, int y, rgb_t color, int intensity);
|
||||
|
||||
#endif /* VECTREX_H_ */
|
496
src/mame/video/vectrex.c
Normal file
496
src/mame/video/vectrex.c
Normal file
@ -0,0 +1,496 @@
|
||||
#include <math.h>
|
||||
#include "emu.h"
|
||||
#include "includes/vectrex.h"
|
||||
#include "video/vector.h"
|
||||
#include "machine/6522via.h"
|
||||
#include "cpu/m6809/m6809.h"
|
||||
#include "sound/ay8910.h"
|
||||
#include "sound/dac.h"
|
||||
|
||||
|
||||
#define ANALOG_DELAY 7800
|
||||
|
||||
#define INT_PER_CLOCK 550
|
||||
|
||||
#ifndef M_SQRT1_2
|
||||
#define M_SQRT1_2 0.70710678118654752440
|
||||
#endif
|
||||
|
||||
/*********************************************************************
|
||||
|
||||
Enums and typedefs
|
||||
|
||||
*********************************************************************/
|
||||
|
||||
enum {
|
||||
PORTB = 0,
|
||||
PORTA
|
||||
};
|
||||
|
||||
enum {
|
||||
A_X = 0,
|
||||
A_ZR,
|
||||
A_Z,
|
||||
A_AUDIO,
|
||||
A_Y,
|
||||
};
|
||||
|
||||
|
||||
/*********************************************************************
|
||||
|
||||
Prototypes
|
||||
|
||||
*********************************************************************/
|
||||
|
||||
static WRITE8_DEVICE_HANDLER (v_via_pa_w);
|
||||
static WRITE8_DEVICE_HANDLER(v_via_pb_w);
|
||||
static WRITE8_DEVICE_HANDLER (v_via_ca2_w);
|
||||
static WRITE8_DEVICE_HANDLER (v_via_cb2_w);
|
||||
|
||||
|
||||
/*********************************************************************
|
||||
|
||||
Local variables
|
||||
|
||||
*********************************************************************/
|
||||
|
||||
const via6522_interface vectrex_via6522_interface =
|
||||
{
|
||||
DEVCB_HANDLER(vectrex_via_pa_r), DEVCB_HANDLER(vectrex_via_pb_r), /* read PA/B */
|
||||
DEVCB_NULL, DEVCB_NULL, DEVCB_NULL, DEVCB_NULL, /* read ca1, cb1, ca2, cb2 */
|
||||
DEVCB_HANDLER(v_via_pa_w), DEVCB_HANDLER(v_via_pb_w), /* write PA/B */
|
||||
DEVCB_NULL, DEVCB_NULL, DEVCB_HANDLER(v_via_ca2_w), DEVCB_HANDLER(v_via_cb2_w), /* write ca1, cb1, ca2, cb2 */
|
||||
DEVCB_LINE(vectrex_via_irq), /* IRQ */
|
||||
};
|
||||
|
||||
|
||||
|
||||
/*********************************************************************
|
||||
|
||||
Lightpen
|
||||
|
||||
*********************************************************************/
|
||||
|
||||
static TIMER_CALLBACK(lightpen_trigger)
|
||||
{
|
||||
vectrex_state *state = machine.driver_data<vectrex_state>();
|
||||
if (state->m_lightpen_port & 1)
|
||||
{
|
||||
via6522_device *via_0 = machine.device<via6522_device>("via6522_0");
|
||||
via_0->write_ca1(1);
|
||||
via_0->write_ca1(0);
|
||||
}
|
||||
|
||||
if (state->m_lightpen_port & 2)
|
||||
{
|
||||
cputag_set_input_line(machine, "maincpu", M6809_FIRQ_LINE, PULSE_LINE);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/*********************************************************************
|
||||
|
||||
VIA T2 configuration
|
||||
|
||||
We need to snoop the frequency of VIA timer 2 here since most
|
||||
vectrex games use that timer for steady screen refresh. Even if the
|
||||
game stops T2 we continue refreshing the screen with the last known
|
||||
frequency. Note that we quickly get out of sync in this case and the
|
||||
screen will start flickering (see cut scenes in Spike).
|
||||
|
||||
Note that the timer can be adjusted to the full period each time T2
|
||||
is restarted. This behaviour avoids flicker in most games. Some
|
||||
games like mine 3d don't work well with this scheme though and show
|
||||
severe jerking. So the second option is to leave the current period
|
||||
alone (if the new period isn't shorter) and change only the next
|
||||
full period.
|
||||
|
||||
*********************************************************************/
|
||||
|
||||
READ8_HANDLER(vectrex_via_r)
|
||||
{
|
||||
via6522_device *via = space->machine().device<via6522_device>("via6522_0");
|
||||
return via->read(*space, offset);
|
||||
}
|
||||
|
||||
WRITE8_HANDLER(vectrex_via_w)
|
||||
{
|
||||
vectrex_state *state = space->machine().driver_data<vectrex_state>();
|
||||
via6522_device *via = space->machine().device<via6522_device>("via6522_0");
|
||||
attotime period;
|
||||
|
||||
switch (offset)
|
||||
{
|
||||
case 8:
|
||||
state->m_via_timer2 = (state->m_via_timer2 & 0xff00) | data;
|
||||
break;
|
||||
|
||||
case 9:
|
||||
state->m_via_timer2 = (state->m_via_timer2 & 0x00ff) | (data << 8);
|
||||
|
||||
period = (attotime::from_hz(space->machine().device("maincpu")->unscaled_clock()) * state->m_via_timer2);
|
||||
|
||||
if (state->m_reset_refresh)
|
||||
state->m_refresh->adjust(period, 0, period);
|
||||
else
|
||||
state->m_refresh->adjust(
|
||||
min(period, state->m_refresh->remaining()),
|
||||
0,
|
||||
period);
|
||||
break;
|
||||
}
|
||||
via->write(*space, offset, data);
|
||||
}
|
||||
|
||||
|
||||
/*********************************************************************
|
||||
|
||||
Screen refresh
|
||||
|
||||
*********************************************************************/
|
||||
|
||||
static TIMER_CALLBACK(vectrex_refresh)
|
||||
{
|
||||
vectrex_state *state = machine.driver_data<vectrex_state>();
|
||||
/* Refresh only marks the range of vectors which will be drawn
|
||||
* during the next SCREEN_UPDATE. */
|
||||
state->m_display_start = state->m_display_end;
|
||||
state->m_display_end = state->m_point_index;
|
||||
}
|
||||
|
||||
|
||||
SCREEN_UPDATE(vectrex)
|
||||
{
|
||||
vectrex_state *state = screen->machine().driver_data<vectrex_state>();
|
||||
int i;
|
||||
|
||||
vectrex_configuration(screen->machine());
|
||||
|
||||
/* start black */
|
||||
vector_add_point(screen->machine(),
|
||||
state->m_points[state->m_display_start].x,
|
||||
state->m_points[state->m_display_start].y,
|
||||
state->m_points[state->m_display_start].col,
|
||||
0);
|
||||
|
||||
for (i = state->m_display_start; i != state->m_display_end; i = (i + 1) % NVECT)
|
||||
{
|
||||
vector_add_point(screen->machine(),
|
||||
state->m_points[i].x,
|
||||
state->m_points[i].y,
|
||||
state->m_points[i].col,
|
||||
state->m_points[i].intensity);
|
||||
}
|
||||
|
||||
SCREEN_UPDATE_CALL(vector);
|
||||
vector_clear_list();
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
/*********************************************************************
|
||||
|
||||
Vector functions
|
||||
|
||||
*********************************************************************/
|
||||
|
||||
void vectrex_add_point(running_machine &machine, int x, int y, rgb_t color, int intensity)
|
||||
{
|
||||
vectrex_state *state = machine.driver_data<vectrex_state>();
|
||||
vectrex_point *newpoint;
|
||||
|
||||
state->m_point_index = (state->m_point_index+1) % NVECT;
|
||||
newpoint = &state->m_points[state->m_point_index];
|
||||
|
||||
newpoint->x = x;
|
||||
newpoint->y = y;
|
||||
newpoint->col = color;
|
||||
newpoint->intensity = intensity;
|
||||
}
|
||||
|
||||
|
||||
void vectrex_add_point_stereo(running_machine &machine, int x, int y, rgb_t color, int intensity)
|
||||
{
|
||||
vectrex_state *state = machine.driver_data<vectrex_state>();
|
||||
if (state->m_imager_status == 2) /* left = 1, right = 2 */
|
||||
vectrex_add_point(machine, (int)(y * M_SQRT1_2)+ state->m_x_center,
|
||||
(int)(((state->m_x_max - x) * M_SQRT1_2)),
|
||||
color,
|
||||
intensity);
|
||||
else
|
||||
vectrex_add_point(machine, (int)(y * M_SQRT1_2),
|
||||
(int)((state->m_x_max - x) * M_SQRT1_2),
|
||||
color,
|
||||
intensity);
|
||||
}
|
||||
|
||||
|
||||
static TIMER_CALLBACK(vectrex_zero_integrators)
|
||||
{
|
||||
vectrex_state *state = machine.driver_data<vectrex_state>();
|
||||
state->m_x_int = state->m_x_center + (state->m_analog[A_ZR] * INT_PER_CLOCK);
|
||||
state->m_y_int = state->m_y_center + (state->m_analog[A_ZR] * INT_PER_CLOCK);
|
||||
(*state->vector_add_point_function)(machine, state->m_x_int, state->m_y_int, state->m_beam_color, 0);
|
||||
}
|
||||
|
||||
|
||||
/*********************************************************************
|
||||
|
||||
Delayed signals
|
||||
|
||||
The RAMP signal is delayed wrt. beam blanking. Getting this right
|
||||
is important for text placement, the maze in Clean Sweep and many
|
||||
other games.
|
||||
|
||||
*********************************************************************/
|
||||
|
||||
static TIMER_CALLBACK(update_signal)
|
||||
{
|
||||
vectrex_state *state = machine.driver_data<vectrex_state>();
|
||||
int length;
|
||||
|
||||
if (!state->m_ramp)
|
||||
{
|
||||
length = machine.device("maincpu")->unscaled_clock() * INT_PER_CLOCK
|
||||
* (machine.time() - state->m_vector_start_time).as_double();
|
||||
|
||||
state->m_x_int += length * (state->m_analog[A_X] + state->m_analog[A_ZR]);
|
||||
state->m_y_int += length * (state->m_analog[A_Y] + state->m_analog[A_ZR]);
|
||||
|
||||
(*state->vector_add_point_function)(machine, state->m_x_int, state->m_y_int, state->m_beam_color, 2 * state->m_analog[A_Z] * state->m_blank);
|
||||
}
|
||||
else
|
||||
{
|
||||
if (state->m_blank)
|
||||
(*state->vector_add_point_function)(machine, state->m_x_int, state->m_y_int, state->m_beam_color, 2 * state->m_analog[A_Z]);
|
||||
}
|
||||
|
||||
state->m_vector_start_time = machine.time();
|
||||
|
||||
if (ptr)
|
||||
* (UINT8 *) ptr = param;
|
||||
}
|
||||
|
||||
|
||||
/*********************************************************************
|
||||
|
||||
Startup
|
||||
|
||||
*********************************************************************/
|
||||
|
||||
VIDEO_START(vectrex)
|
||||
{
|
||||
vectrex_state *state = machine.driver_data<vectrex_state>();
|
||||
screen_device *screen = machine.first_screen();
|
||||
const rectangle &visarea = screen->visible_area();
|
||||
|
||||
state->m_x_center=((visarea.max_x - visarea.min_x) / 2) << 16;
|
||||
state->m_y_center=((visarea.max_y - visarea.min_y) / 2) << 16;
|
||||
state->m_x_max = visarea.max_x << 16;
|
||||
state->m_y_max = visarea.max_y << 16;
|
||||
|
||||
state->m_imager_freq = 1;
|
||||
|
||||
state->vector_add_point_function = vectrex_add_point;
|
||||
state->m_imager_timer = machine.scheduler().timer_alloc(FUNC(vectrex_imager_eye));
|
||||
state->m_imager_timer->adjust(
|
||||
attotime::from_hz(state->m_imager_freq),
|
||||
2,
|
||||
attotime::from_hz(state->m_imager_freq));
|
||||
|
||||
state->m_lp_t = machine.scheduler().timer_alloc(FUNC(lightpen_trigger));
|
||||
|
||||
state->m_refresh = machine.scheduler().timer_alloc(FUNC(vectrex_refresh));
|
||||
|
||||
VIDEO_START_CALL(vector);
|
||||
}
|
||||
|
||||
|
||||
/*********************************************************************
|
||||
|
||||
VIA interface functions
|
||||
|
||||
*********************************************************************/
|
||||
|
||||
static void vectrex_multiplexer(running_machine &machine, int mux)
|
||||
{
|
||||
vectrex_state *state = machine.driver_data<vectrex_state>();
|
||||
device_t *dac_device = machine.device("dac");
|
||||
|
||||
machine.scheduler().timer_set(attotime::from_nsec(ANALOG_DELAY), FUNC(update_signal), state->m_via_out[PORTA], &state->m_analog[mux]);
|
||||
|
||||
if (mux == A_AUDIO)
|
||||
dac_data_w(dac_device, state->m_via_out[PORTA]);
|
||||
}
|
||||
|
||||
|
||||
static WRITE8_DEVICE_HANDLER(v_via_pb_w)
|
||||
{
|
||||
vectrex_state *state = device->machine().driver_data<vectrex_state>();
|
||||
if (!(data & 0x80))
|
||||
{
|
||||
/* RAMP is active */
|
||||
if ((state->m_ramp & 0x80))
|
||||
{
|
||||
/* RAMP was inactive before */
|
||||
|
||||
if (state->m_lightpen_down)
|
||||
{
|
||||
/* Simple lin. algebra to check if pen is near
|
||||
* the line defined by (A_X,A_Y).
|
||||
* If that is the case, set a timer which goes
|
||||
* off when the beam reaches the pen. Exact
|
||||
* timing is important here.
|
||||
*
|
||||
* lightpen
|
||||
* ^
|
||||
* _ /|
|
||||
* b / |
|
||||
* / |
|
||||
* / |d
|
||||
* / |
|
||||
* / |
|
||||
* ------+---------> beam path
|
||||
* l | _
|
||||
* a
|
||||
*/
|
||||
double a2, b2, ab, d2;
|
||||
ab = (state->m_pen_x - state->m_x_int) * state->m_analog[A_X]
|
||||
+(state->m_pen_y - state->m_y_int) * state->m_analog[A_Y];
|
||||
if (ab > 0)
|
||||
{
|
||||
a2 = (double)(state->m_analog[A_X] * state->m_analog[A_X]
|
||||
+(double)state->m_analog[A_Y] * state->m_analog[A_Y]);
|
||||
b2 = (double)(state->m_pen_x - state->m_x_int) * (state->m_pen_x - state->m_x_int)
|
||||
+(double)(state->m_pen_y - state->m_y_int) * (state->m_pen_y - state->m_y_int);
|
||||
d2 = b2 - ab * ab / a2;
|
||||
if (d2 < 2e10 && state->m_analog[A_Z] * state->m_blank > 0)
|
||||
state->m_lp_t->adjust(attotime::from_double(ab / a2 / (device->machine().device("maincpu")->unscaled_clock() * INT_PER_CLOCK)));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (!(data & 0x1) && (state->m_via_out[PORTB] & 0x1))
|
||||
{
|
||||
/* MUX has been enabled */
|
||||
device->machine().scheduler().timer_set(attotime::from_nsec(ANALOG_DELAY), FUNC(update_signal));
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
/* RAMP is inactive */
|
||||
if (!(state->m_ramp & 0x80))
|
||||
{
|
||||
/* Cancel running timer, line already finished */
|
||||
if (state->m_lightpen_down)
|
||||
state->m_lp_t->adjust(attotime::never);
|
||||
}
|
||||
}
|
||||
|
||||
/* Sound */
|
||||
if (data & 0x10)
|
||||
{
|
||||
device_t *ay8912 = device->machine().device("ay8912");
|
||||
|
||||
if (data & 0x08) /* BC1 (do we select a reg or write it ?) */
|
||||
ay8910_address_w(ay8912, 0, state->m_via_out[PORTA]);
|
||||
else
|
||||
ay8910_data_w(ay8912, 0, state->m_via_out[PORTA]);
|
||||
}
|
||||
|
||||
if (!(data & 0x1) && (state->m_via_out[PORTB] & 0x1))
|
||||
vectrex_multiplexer (device->machine(), (data >> 1) & 0x3);
|
||||
|
||||
state->m_via_out[PORTB] = data;
|
||||
device->machine().scheduler().timer_set(attotime::from_nsec(ANALOG_DELAY), FUNC(update_signal), data & 0x80, &state->m_ramp);
|
||||
}
|
||||
|
||||
|
||||
static WRITE8_DEVICE_HANDLER(v_via_pa_w)
|
||||
{
|
||||
vectrex_state *state = device->machine().driver_data<vectrex_state>();
|
||||
/* DAC output always goes to Y integrator */
|
||||
state->m_via_out[PORTA] = data;
|
||||
device->machine().scheduler().timer_set(attotime::from_nsec(ANALOG_DELAY), FUNC(update_signal), data, &state->m_analog[A_Y]);
|
||||
|
||||
if (!(state->m_via_out[PORTB] & 0x1))
|
||||
vectrex_multiplexer (device->machine(), (state->m_via_out[PORTB] >> 1) & 0x3);
|
||||
}
|
||||
|
||||
|
||||
static WRITE8_DEVICE_HANDLER(v_via_ca2_w)
|
||||
{
|
||||
if (data == 0)
|
||||
device->machine().scheduler().timer_set(attotime::from_nsec(ANALOG_DELAY), FUNC(vectrex_zero_integrators));
|
||||
}
|
||||
|
||||
|
||||
static WRITE8_DEVICE_HANDLER(v_via_cb2_w)
|
||||
{
|
||||
vectrex_state *state = device->machine().driver_data<vectrex_state>();
|
||||
int dx, dy;
|
||||
|
||||
if (state->m_cb2 != data)
|
||||
{
|
||||
|
||||
/* Check lightpen */
|
||||
if (state->m_lightpen_port != 0)
|
||||
{
|
||||
state->m_lightpen_down = input_port_read(device->machine(), "LPENCONF") & 0x10;
|
||||
|
||||
if (state->m_lightpen_down)
|
||||
{
|
||||
state->m_pen_x = input_port_read(device->machine(), "LPENX") * (state->m_x_max / 0xff);
|
||||
state->m_pen_y = input_port_read(device->machine(), "LPENY") * (state->m_y_max / 0xff);
|
||||
|
||||
dx = abs(state->m_pen_x - state->m_x_int);
|
||||
dy = abs(state->m_pen_y - state->m_y_int);
|
||||
if (dx < 500000 && dy < 500000 && data > 0)
|
||||
device->machine().scheduler().timer_set(attotime::zero, FUNC(lightpen_trigger));
|
||||
}
|
||||
}
|
||||
|
||||
device->machine().scheduler().timer_set(attotime::zero, FUNC(update_signal), data, &state->m_blank);
|
||||
state->m_cb2 = data;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/*****************************************************************
|
||||
|
||||
RA+A Spectrum I+
|
||||
|
||||
*****************************************************************/
|
||||
|
||||
const via6522_interface spectrum1_via6522_interface =
|
||||
{
|
||||
/*inputs : A/B,CA/B1,CA/B2 */ DEVCB_HANDLER(vectrex_via_pa_r), DEVCB_HANDLER(vectrex_s1_via_pb_r), DEVCB_NULL, DEVCB_NULL, DEVCB_NULL, DEVCB_NULL,
|
||||
/*outputs: A/B,CA/B1,CA/B2 */ DEVCB_HANDLER(v_via_pa_w), DEVCB_HANDLER(v_via_pb_w), DEVCB_NULL, DEVCB_NULL, DEVCB_HANDLER(v_via_ca2_w), DEVCB_HANDLER(v_via_cb2_w),
|
||||
/*irq */ DEVCB_LINE(vectrex_via_irq),
|
||||
};
|
||||
|
||||
|
||||
WRITE8_HANDLER(raaspec_led_w)
|
||||
{
|
||||
logerror("Spectrum I+ LED: %i%i%i%i%i%i%i%i\n",
|
||||
(data>>7)&0x1, (data>>6)&0x1, (data>>5)&0x1, (data>>4)&0x1,
|
||||
(data>>3)&0x1, (data>>2)&0x1, (data>>1)&0x1, data&0x1);
|
||||
}
|
||||
|
||||
|
||||
VIDEO_START(raaspec)
|
||||
{
|
||||
vectrex_state *state = machine.driver_data<vectrex_state>();
|
||||
screen_device *screen = machine.first_screen();
|
||||
const rectangle &visarea = screen->visible_area();
|
||||
|
||||
state->m_x_center=((visarea.max_x - visarea.min_x) / 2) << 16;
|
||||
state->m_y_center=((visarea.max_y - visarea.min_y) / 2) << 16;
|
||||
state->m_x_max = visarea.max_x << 16;
|
||||
state->m_y_max = visarea.max_y << 16;
|
||||
|
||||
state->vector_add_point_function = vectrex_add_point;
|
||||
state->m_refresh = machine.scheduler().timer_alloc(FUNC(vectrex_refresh));
|
||||
|
||||
VIDEO_START_CALL(vector);
|
||||
}
|
Loading…
Reference in New Issue
Block a user