はじめにMSYS2 MinGWをインストールして、Windowsで最新版のMAMEがビルドできることを確認します。
www.msys2.org
gist.github.com
つぎにLinuxのMAMEVECTOR64をWindowsでビルドします。
trmm.net
termios.hについてはこちらをベースにしました。
github.com
エラーが出たら修正を繰り返してビルドできました。
$ git clone https://github.com/veeso/termiWin
$ cp termiWin/include/termi*.h /mingw64/include/
$ git clone https://github.com/osresearch/mame/
$ cd mame
$ export MINGW64=/mingw64
$ make NOWERROR=1 SUBTARGET=vector
$ ar rcs build/mingw-gcc/bin/x64/Release/libformats.a build/mingw-gcc/obj/x64/Release/src/lib/formats/*.o
$ make NOWERROR=1 SUBTARGET=vector
$ ar rcs build/mingw-gcc/bin/x64/Release/mame_vector/liboptional.a $(find build/mingw-gcc/obj/x64/Release/src/devices/cpu -name "*.o")
$ make NOWERROR=1 SUBTARGET=vector
$ ar rcs build/mingw-gcc/bin/x64/Release/mame_vector/libbus.a build/mingw-gcc/obj/x64/Release/src/devices/bus/generic/*.o
$ make NOWERROR=1 SUBTARGET=vector
$ ar rcs build/mingw-gcc/bin/x64/Release/mame_vector/liboptional.a $(find build/mingw-gcc/obj/x64/Release/src/devices/machine -name "*.o")
$ ar rcs build/mingw-gcc/bin/x64/Release/mame_vector/liboptional.a $(find build/mingw-gcc/obj/x64/Release/src/devices/sound -name "*.o")
$ ar rcs build/mingw-gcc/bin/x64/Release/mame_vector/libbus.a $(find build/mingw-gcc/obj/x64/Release/src/devices/bus/vectrex -name "*.o")
$ make NOWERROR=1 SUBTARGET=vector
以下のファイルを修正しました。
scripts/build/verinfo.py(抜粋)
try:
fp = open(srcfile, 'r')
except IOError:
sys.stderr.write("Unable to open source file '%s'\n" % srcfile)
sys.exit(1)
src/devices/cpu/m6502/m6502make.py(抜粋)
try:
f = open(fname, "r")
except Exception:
err = sys.exc_info()[1]
logging.error("cannot read opcodes file %s [%s]", fname, err)
sys.exit(1)
(省略)
try:
f = open(fname, "r")
except Exception:
err = sys.exc_info()[1]
logging.error("cannot read display file %s [%s]", fname, err)
sys.exit(1)
src/devices/cpu/m6809/m6809make.py(抜粋)
try:
f = open(fname, "r")
except Exception:
err = sys.exc_info()[1]
sys.stderr.write("Cannot read opcodes file %s [%s]\n" % (fname, err))
sys.exit(1)
src/emu/video/vector.cpp
#include "emu.h"
#include "emuopts.h"
#include "rendutil.h"
#include "vector.h"
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>
#include <termios.h>
#include <errno.h>
#include <inttypes.h>
#include <sys/time.h>
#define FLT_EPSILON 1E-5
#define VECTOR_WIDTH_DENOM 512
#define MAX_POINTS 10000
#define VECTOR_SERIAL_MAX 4095
#define VECTOR_TEAM \
"-* Vector Heads *-\n" \
"Brad Oliver\n" \
"Aaron Giles\n" \
"Bernd Wiebelt\n" \
"Allard van der Bas\n" \
"Al Kossow (VECSIM)\n" \
"Hedley Rainnie (VECSIM)\n" \
"Eric Smith (VECSIM)\n" \
"Neil Bradley (technical advice)\n" \
"Andrew Caldwell (anti-aliasing)\n" \
"- *** -\n"
#ifdef __cplusplus > 201711L
#define TERMIWIN_MAYBE_UNUSED [[maybe_unused]]
#else
#ifdef __GNUC__
#define TERMIWIN_MAYBE_UNUSED __attribute__((unused))
#else
#define TERMIWIN_MAYBE_UNUSED
#endif
#endif
#include <fcntl.h>
#include <stdlib.h>
typedef struct COM {
HANDLE hComm;
int fd;
char port[128];
} COM;
DCB SerialParams = { 0 };
struct COM com;
COMMTIMEOUTS timeouts = { 0 };
int getByte(tcflag_t flag, int nbyte, int nibble) {
int byte;
if (nibble == 1)
byte = (flag >> (8 * (nbyte)) & 0x0f);
else
byte = (flag >> (8 * (nbyte)) & 0xf0);
return byte;
}
enum{
i_IXOFF = 0x01,
i_IXON = 0x02,
i_IXOFF_IXON = 0x03,
i_PARMRK = 0x04,
i_PARMRK_IXOFF = 0x05,
i_PARMRK_IXON = 0x06,
i_PARMRK_IXON_IXOFF = 0x07
};
int getIXOptions(tcflag_t flag) {
int byte = getByte(flag, 1, 1);
return byte;
}
enum{
l_NOECHO = 0x00,
l_ECHO = 0x01,
l_ECHO_ECHOE = 0x03,
l_ECHO_ECHOK = 0x05,
l_ECHO_ECHONL = 0x09,
l_ECHO_ECHOE_ECHOK = 0x07,
l_ECHO_ECHOE_ECHONL = 0x0b,
l_ECHO_ECHOE_ECHOK_ECHONL = 0x0f,
l_ECHO_ECHOK_ECHONL = 0x0d,
l_ECHOE = 0x02,
l_ECHOE_ECHOK = 0x06,
l_ECHOE_ECHONL = 0x0a,
l_ECHOE_ECHOK_ECHONL = 0x0e,
l_ECHOK = 0x04,
l_ECHOK_ECHONL = 0x0c,
l_ECHONL = 0x08
};
int getEchoOptions(tcflag_t flag) {
int byte = getByte(flag, 1, 1);
return byte;
}
enum{
l_ICANON = 0x10,
l_ICANON_ISIG = 0x50,
l_ICANON_IEXTEN = 0x30,
l_ICANON_NOFLSH = 0x90,
l_ICANON_ISIG_IEXTEN = 0x70,
l_ICANON_ISIG_NOFLSH = 0xd0,
l_ICANON_IEXTEN_NOFLSH = 0xb0,
l_ICANON_ISIG_IEXTEN_NOFLSH = 0xf0,
l_ISIG = 0x40,
l_ISIG_IEXTEN = 0x60,
l_ISIG_NOFLSH = 0xc0,
l_ISIG_IEXTEN_NOFLSH = 0xe0,
l_IEXTEN = 0x20,
l_IEXTEN_NOFLSH = 0xa0,
l_NOFLSH = 0x80,
};
int getLocalOptions(tcflag_t flag) {
int byte = getByte(flag, 1, 0);
return byte;
}
enum{
l_TOSTOP = 0x01
};
int getToStop(tcflag_t flag) {
int byte = getByte(flag, 1, 1);
return byte;
}
int getCharSet(tcflag_t flag) {
int byte = getByte(flag, 1, 1);
switch (byte) {
case 0X0:
return CS5;
break;
case 0X4:
return CS6;
break;
case 0X8:
return CS7;
break;
case 0Xc:
return CS8;
break;
default:
return CS8;
break;
}
}
enum{
c_ALL_ENABLED = 0xd0,
c_PAREVEN_CSTOPB = 0x50,
c_PAREVEN_NOCSTOPB = 0x40,
c_PARODD_NOCSTOPB = 0xc0,
c_NOPARENB_CSTOPB = 0x10,
c_ALL_DISABLED = 0x00,
};
int getControlOptions(tcflag_t flag) {
int byte = getByte(flag, 1, 0);
return byte;
}
int tcgetattr(int fd, struct termios* TERMIWIN_MAYBE_UNUSED termios_p) {
if (fd != com.fd) return -1;
int TERMIWIN_MAYBE_UNUSED ret = 0;
ret = GetCommState(com.hComm, &SerialParams);
return 0;
}
int tcsetattr(int fd, int TERMIWIN_MAYBE_UNUSED optional_actions, const struct termios* termios_p) {
if (fd != com.fd) return -1;
int ret = 0;
tcflag_t iflag = termios_p->c_iflag;
tcflag_t lflag = termios_p->c_lflag;
tcflag_t cflag = termios_p->c_cflag;
tcflag_t TERMIWIN_MAYBE_UNUSED oflag = termios_p->c_oflag;
int IX = getIXOptions(iflag);
if ((IX == i_IXOFF_IXON) || (IX == i_PARMRK_IXON_IXOFF)) {
SerialParams.fOutX = TRUE;
SerialParams.fInX = TRUE;
SerialParams.fTXContinueOnXoff = TRUE;
}
int TERMIWIN_MAYBE_UNUSED EchoOpt = getEchoOptions(lflag);
int TERMIWIN_MAYBE_UNUSED l_opt = getLocalOptions(lflag);
int TERMIWIN_MAYBE_UNUSED tostop = getToStop(lflag);
int CharSet = getCharSet(cflag);
int c_opt = getControlOptions(cflag);
switch (CharSet) {
case CS5:
SerialParams.ByteSize = 5;
break;
case CS6:
SerialParams.ByteSize = 6;
break;
case CS7:
SerialParams.ByteSize = 7;
break;
case CS8:
SerialParams.ByteSize = 8;
break;
}
switch (c_opt) {
case c_ALL_ENABLED:
SerialParams.Parity = ODDPARITY;
SerialParams.StopBits = TWOSTOPBITS;
break;
case c_ALL_DISABLED:
SerialParams.Parity = NOPARITY;
SerialParams.StopBits = ONESTOPBIT;
break;
case c_PAREVEN_CSTOPB:
SerialParams.Parity = EVENPARITY;
SerialParams.StopBits = TWOSTOPBITS;
break;
case c_PAREVEN_NOCSTOPB:
SerialParams.Parity = EVENPARITY;
SerialParams.StopBits = ONESTOPBIT;
break;
case c_PARODD_NOCSTOPB:
SerialParams.Parity = ODDPARITY;
SerialParams.StopBits = ONESTOPBIT;
break;
case c_NOPARENB_CSTOPB:
SerialParams.Parity = NOPARITY;
SerialParams.StopBits = TWOSTOPBITS;
break;
}
if (termios_p->c_cc[VEOF] != 0) SerialParams.EofChar = (char)termios_p->c_cc[VEOF];
if (termios_p->c_cc[VINTR] != 0) SerialParams.EvtChar = (char)termios_p->c_cc[VINTR];
if (termios_p->c_cc[VMIN] == 1) {
timeouts.ReadIntervalTimeout = 0;
timeouts.ReadTotalTimeoutConstant = 0;
timeouts.ReadTotalTimeoutMultiplier = 0;
timeouts.WriteTotalTimeoutConstant = 0;
timeouts.WriteTotalTimeoutMultiplier = 0;
} else {
timeouts.ReadIntervalTimeout = termios_p->c_cc[VTIME] * 100;
timeouts.ReadTotalTimeoutConstant = termios_p->c_cc[VTIME] * 100;
timeouts.ReadTotalTimeoutMultiplier = termios_p->c_cc[VTIME] * 100;
timeouts.WriteTotalTimeoutConstant = termios_p->c_cc[VTIME] * 100;
timeouts.WriteTotalTimeoutMultiplier = termios_p->c_cc[VTIME] * 100;
}
SetCommTimeouts(com.hComm, &timeouts);
ret = SetCommState(com.hComm, &SerialParams);
if (ret != 0)
return 0;
else
return -1;
}
int tcsendbreak(int fd, int TERMIWIN_MAYBE_UNUSED duration) {
if (fd != com.fd) return -1;
int ret = 0;
ret = TransmitCommChar(com.hComm, '\x00');
if (ret != 0)
return 0;
else
return -1;
}
int tcdrain(int fd) {
if (fd != com.fd) return -1;
return FlushFileBuffers(com.hComm);
}
int tcflush(int fd, int queue_selector) {
if (fd != com.fd) return -1;
int rc = 0;
switch (queue_selector) {
case TCIFLUSH:
rc = PurgeComm(com.hComm, PURGE_RXCLEAR);
break;
case TCOFLUSH:
rc = PurgeComm(com.hComm, PURGE_TXCLEAR);
break;
case TCIOFLUSH:
rc = PurgeComm(com.hComm, PURGE_RXCLEAR);
rc *= PurgeComm(com.hComm, PURGE_TXCLEAR);
break;
default:
rc = 0;
break;
}
if (rc != 0)
return 0;
else
return -1;
}
int tcflow(int fd, int action) {
if (fd != com.fd) return -1;
int rc = 0;
switch (action) {
case TCOOFF:
rc = PurgeComm(com.hComm, PURGE_TXABORT);
break;
case TCOON:
rc = ClearCommBreak(com.hComm);
break;
case TCIOFF:
rc = PurgeComm(com.hComm, PURGE_RXABORT);
break;
case TCION:
rc = ClearCommBreak(com.hComm);
break;
default:
rc = 0;
break;
}
if (rc != 0)
return 0;
else
return -1;
}
void cfmakeraw(struct termios* TERMIWIN_MAYBE_UNUSED termios_p) {
SerialParams.ByteSize = 8;
SerialParams.StopBits = ONESTOPBIT;
SerialParams.Parity = NOPARITY;
}
speed_t cfgetispeed(const struct termios* TERMIWIN_MAYBE_UNUSED termios_p) {
return SerialParams.BaudRate;
}
speed_t cfgetospeed(const struct termios* TERMIWIN_MAYBE_UNUSED termios_p) {
return SerialParams.BaudRate;
}
int cfsetispeed(struct termios* TERMIWIN_MAYBE_UNUSED termios_p, speed_t speed) {
SerialParams.BaudRate = speed;
return 0;
}
int cfsetospeed(struct termios* TERMIWIN_MAYBE_UNUSED termios_p, speed_t speed) {
SerialParams.BaudRate = speed;
return 0;
}
int cfsetspeed(struct termios* TERMIWIN_MAYBE_UNUSED termios_p, speed_t speed) {
SerialParams.BaudRate = speed;
return 0;
}
ssize_t read_serial(int fd, void* buffer, size_t count) {
if (fd != com.fd) return -1;
DWORD rc = 0;
int ret;
ret = ReadFile(com.hComm, buffer, count, &rc, NULL);
if (ret == 0)
return -1;
else
return rc;
}
ssize_t write_serial(int fd, const void* buffer, size_t count) {
if (fd != com.fd) return -1;
DWORD rc = 0;
int ret;
ret = WriteFile(com.hComm, buffer, count, &rc, NULL);
if (ret == 0)
return -1;
else
return rc;
}
int open_serial(const char* portname, int opt) {
if (strlen(portname) < 4) return -1;
memset(com.port, 0x00, 128);
size_t portSize = 0;
if (strlen(portname) > 4) {
portSize = sizeof(char) * strlen("\\\\.\\COM10") + 1;
#ifdef _MSC_VER
strncat_s(com.port, portSize, "\\\\.\\", strlen("\\\\.\\"));
#else
strncat(com.port, "\\\\.\\", strlen("\\\\.\\"));
#endif
}
else {
portSize = sizeof(char) * 5;
}
#ifdef _MSC_VER
strncat_s(com.port, portSize, portname, 4);
#else
strncat(com.port, portname, 4);
#endif
com.port[portSize] = 0x00;
switch (opt) {
case O_RDWR:
com.hComm = CreateFile(com.port, GENERIC_READ | GENERIC_WRITE, 0, NULL, OPEN_EXISTING, 0, NULL);
break;
case O_RDONLY:
com.hComm = CreateFile(com.port, GENERIC_READ, 0, NULL, OPEN_EXISTING, 0, NULL);
break;
case O_WRONLY:
com.hComm = CreateFile(com.port, GENERIC_WRITE, 0, NULL, OPEN_EXISTING, 0, NULL);
break;
}
if (com.hComm == INVALID_HANDLE_VALUE) {
return -1;
}
com.fd = atoi(portname + 3);
SerialParams.DCBlength = sizeof(SerialParams);
return com.fd;
}
int close_serial(int TERMIWIN_MAYBE_UNUSED fd) {
int ret = CloseHandle(com.hComm);
if (ret != 0)
return 0;
else
return -1;
}
int select_serial(int TERMIWIN_MAYBE_UNUSED nfds, fd_set* readfds, fd_set* TERMIWIN_MAYBE_UNUSED writefds, fd_set* TERMIWIN_MAYBE_UNUSED exceptfds, struct timeval* TERMIWIN_MAYBE_UNUSED timeout) {
SetCommMask(com.hComm, EV_RXCHAR);
DWORD dwEventMask;
if (WaitCommEvent(com.hComm, &dwEventMask, NULL) == 0) {
return -1;
}
if (dwEventMask == EV_RXCHAR) {
return com.fd;
} else {
if (readfds) {
FD_CLR(com.fd, readfds);
}
}
NOTE
NOTE
return 0;
}
HANDLE getHandle() {
return com.hComm;
}
#define VCLEAN 0
#define VDIRTY 1
#define VCLIP 2
const device_type VECTOR = &device_creator<vector_device>;
vector_device::vector_device(const machine_config &mconfig, device_type type, const char *name, const char *tag, device_t *owner, UINT32 clock, const char *shortname, const char *source)
: device_t(mconfig, type, name, tag, owner, clock, shortname, source),
device_video_interface(mconfig, *this),
m_vector_list(nullptr),
m_min_intensity(255),
m_max_intensity(0)
{
}
vector_device::vector_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock)
: device_t(mconfig, VECTOR, "VECTOR", tag, owner, clock, "vector_device", __FILE__),
device_video_interface(mconfig, *this),
m_vector_list(nullptr),
m_min_intensity(255),
m_max_intensity(0)
{
}
float vector_device::m_flicker = 0.0f;
float vector_device::m_beam_width_min = 0.0f;
float vector_device::m_beam_width_max = 0.0f;
float vector_device::m_beam_intensity_weight = 0.0f;
int vector_device::m_vector_index;
struct serial_segment_t {
struct serial_segment_t * next;
int intensity;
int x0;
int y0;
int x1;
int y1;
serial_segment_t(
int x0,
int y0,
int x1,
int y1,
int intensity
) :
next(NULL),
intensity(intensity),
x0(x0),
y0(y0),
x1(x1),
y1(y1)
{
}
};
int
serial_open(
const char * const dev
)
{
const int fd = open(dev, O_RDWR, 0666);
if (fd < 0)
return -1;
struct termios attr;
tcgetattr(fd, &attr);
attr.c_cflag |= CLOCAL | CREAD;
attr.c_oflag &= ~OPOST;
tcsetattr(fd, TCSANOW, &attr);
return fd;
}
void vector_device::serial_draw_point(
unsigned x,
unsigned y,
int intensity
)
{
if (x < 0) x = 0;
if (y < 0) y = 0;
if (x > VECTOR_SERIAL_MAX) x = VECTOR_SERIAL_MAX;
if (y > VECTOR_SERIAL_MAX) y = VECTOR_SERIAL_MAX;
y = VECTOR_SERIAL_MAX - y;
unsigned bright;
if (intensity > m_serial_bright)
bright = 63;
else
if (intensity <= 0)
bright = 0;
else
bright = (intensity * 64) / 256;
if (bright > 63)
bright = 63;
if (m_serial_rotate == 1)
{
unsigned tmp = x;
x = VECTOR_SERIAL_MAX - y;
y = tmp;
} else
if (m_serial_rotate == 2)
{
x = VECTOR_SERIAL_MAX - x;
y = VECTOR_SERIAL_MAX - y;
} else
if (m_serial_rotate == 3)
{
unsigned t = x;
x = y;
y = VECTOR_SERIAL_MAX - t;
}
uint32_t cmd = 0
| (2 << 30)
| (bright & 0x3F) << 24
| (x & 0xFFF) << 12
| (y & 0xFFF) << 0
;
m_serial_buf[m_serial_offset++] = cmd >> 24;
m_serial_buf[m_serial_offset++] = cmd >> 16;
m_serial_buf[m_serial_offset++] = cmd >> 8;
m_serial_buf[m_serial_offset++] = cmd >> 0;
}
void vector_device::serial_draw_line(
float xf0,
float yf0,
float xf1,
float yf1,
int intensity
)
{
if (m_serial_fd < 0)
return;
const int x0 = (xf0 * VECTOR_SERIAL_MAX - VECTOR_SERIAL_MAX/2) * m_serial_scale_x + m_serial_offset_x;
const int y0 = (yf0 * VECTOR_SERIAL_MAX - VECTOR_SERIAL_MAX/2) * m_serial_scale_y + m_serial_offset_y;
const int x1 = (xf1 * VECTOR_SERIAL_MAX - VECTOR_SERIAL_MAX/2) * m_serial_scale_x + m_serial_offset_x;
const int y1 = (yf1 * VECTOR_SERIAL_MAX - VECTOR_SERIAL_MAX/2) * m_serial_scale_y + m_serial_offset_y;
serial_segment_t * const new_segment
= new serial_segment_t(x0, y0, x1, y1, intensity);
if (this->m_serial_segments_tail)
this->m_serial_segments_tail->next = new_segment;
else
this->m_serial_segments = new_segment;
this->m_serial_segments_tail = new_segment;
}
void vector_device::serial_reset()
{
m_serial_offset = 0;
m_serial_buf[m_serial_offset++] = 0;
m_serial_buf[m_serial_offset++] = 0;
m_serial_buf[m_serial_offset++] = 0;
m_serial_buf[m_serial_offset++] = 0;
m_serial_buf[m_serial_offset++] = 0;
m_serial_buf[m_serial_offset++] = 0;
m_serial_buf[m_serial_offset++] = 0;
m_serial_buf[m_serial_offset++] = 0;
m_vector_transit[0] = 0;
m_vector_transit[1] = 0;
m_vector_transit[2] = 0;
}
void vector_device::serial_send()
{
if (m_serial_fd < 0)
return;
int last_x = -1;
int last_y = -1;
while(this->m_serial_segments)
{
int reverse = 0;
int min = 1e6;
serial_segment_t ** min_seg
= &this->m_serial_segments;
if (m_serial_sort)
for(serial_segment_t ** s = min_seg ; *s ; s = &(*s)->next)
{
int dx0 = (*s)->x0 - last_x;
int dy0 = (*s)->y0 - last_y;
int dx1 = (*s)->x1 - last_x;
int dy1 = (*s)->y1 - last_y;
int d0 = sqrt(dx0*dx0 + dy0*dy0);
int d1 = sqrt(dx1*dx1 + dy1*dy1);
if(d0 < min)
{
min_seg = s;
min = d0;
reverse = 0;
}
if (d1 < min)
{
min_seg = s;
min = d1;
reverse = 1;
}
if (min == 0)
break;
}
serial_segment_t * const s = *min_seg;
if (!s)
break;
const int x0 = reverse ? s->x1 : s->x0;
const int y0 = reverse ? s->y1 : s->y0;
const int x1 = reverse ? s->x0 : s->x1;
const int y1 = reverse ? s->y0 : s->y1;
if (last_x != x0 || last_y != y0)
{
serial_draw_point(x0, y0, 0);
int dx = x0 - last_x;
int dy = y0 - last_y;
m_vector_transit[0] += sqrt(dx*dx + dy*dy);
}
int dx = x1 - x0;
int dy = y1 - y0;
int dist = sqrt(dx*dx + dy*dy);
serial_draw_point(x1, y1, s->intensity);
last_x = x1;
last_y = y1;
if (s->intensity > m_serial_bright)
m_vector_transit[2] += dist;
else
m_vector_transit[1] += dist;
*min_seg = s->next;
delete s;
}
if(this->m_serial_segments != NULL)
fprintf(stderr, "errr?\n");
this->m_serial_segments = NULL;
this->m_serial_segments_tail = NULL;
m_serial_buf[m_serial_offset++] = 1;
m_serial_buf[m_serial_offset++] = 1;
m_serial_buf[m_serial_offset++] = 1;
m_serial_buf[m_serial_offset++] = 1;
size_t offset = 0;
if(1)
printf("%zu vectors: off=%u on=%u bright=%u%s\n",
m_serial_offset/4,
m_vector_transit[0],
m_vector_transit[1],
m_vector_transit[2],
m_serial_drop_frame ? " !" : ""
);
static unsigned skip_frame;
unsigned eagain = 0;
if (m_serial_drop_frame || skip_frame++ % 2 != 0)
{
m_serial_drop_frame = 0;
} else
while (offset < m_serial_offset)
{
size_t wlen = m_serial_offset - offset;
if (wlen > 4096)
wlen = 4096;
ssize_t rc = write(m_serial_fd, m_serial_buf + offset, m_serial_offset - offset);
if (rc <= 0)
{
eagain++;
if (errno == EAGAIN)
continue;
perror(m_serial);
close(m_serial_fd);
m_serial_fd = -1;
break;
}
offset += rc;
}
printf("%d eagain.\n", eagain);
if (eagain > 20)
m_serial_drop_frame = 1;
serial_reset();
}
void vector_device::device_start()
{
m_beam_width_min = machine().options().beam_width_min();
m_beam_width_max = machine().options().beam_width_max();
m_beam_intensity_weight = machine().options().beam_intensity_weight();
m_flicker = machine().options().flicker();
m_vector_index = 0;
m_vector_list = make_unique_clear<point[]>(MAX_POINTS);
m_serial = machine().options().vector_serial();
const float scale = machine().options().vector_scale();
if (scale != 0.0)
{
m_serial_scale_x = m_serial_scale_y = scale;
} else {
m_serial_scale_x = machine().options().vector_scale_x();
m_serial_scale_y = machine().options().vector_scale_y();
}
m_serial_segments = m_serial_segments_tail = NULL;
m_serial_offset_x = machine().options().vector_offset_x();
m_serial_offset_y = machine().options().vector_offset_y();
m_serial_rotate = machine().options().vector_rotate();
m_serial_bright = machine().options().vector_bright();
m_serial_drop_frame = 0;
m_serial_sort = 1;
m_serial_buf = auto_alloc_array_clear(machine(), unsigned char, (MAX_POINTS+2) * 4);
if (!m_serial_buf)
{
}
serial_reset();
if (!m_serial || strcmp(m_serial,"") == 0)
{
fprintf(stderr, "no serial vector display configured\n");
m_serial_fd = -1;
} else {
m_serial_fd = serial_open(m_serial);
fprintf(stderr, "serial dev='%s' fd=%d\n", m_serial, m_serial_fd);
}
}
void vector_device::set_flicker(float newval)
{
m_flicker = newval;
}
float vector_device::get_flicker()
{
return m_flicker;
}
void vector_device::set_beam_width_min(float newval)
{
m_beam_width_min = newval;
}
float vector_device::get_beam_width_min()
{
return m_beam_width_min;
}
void vector_device::set_beam_width_max(float newval)
{
m_beam_width_max = newval;
}
float vector_device::get_beam_width_max()
{
return m_beam_width_max;
}
void vector_device::set_beam_intensity_weight(float newval)
{
m_beam_intensity_weight = newval;
}
float vector_device::get_beam_intensity_weight()
{
return m_beam_intensity_weight;
}
float vector_device::normalized_sigmoid(float n, float k)
{
return (n - n * k) / (k - fabs(n) * 2.0f * k + 1.0f);
}
void vector_device::add_point(int x, int y, rgb_t color, int intensity)
{
point *newpoint;
if (color.r() == 128
&& color.b() == 128
&& color.g() == 128
&& intensity == 255)
{
color = rgb_t(255,255,255);
intensity = 128;
}
intensity = MAX(0, MIN(255, intensity));
m_min_intensity = intensity > 0 ? MIN(m_min_intensity, intensity) : m_min_intensity;
m_max_intensity = intensity > 0 ? MAX(m_max_intensity, intensity) : m_max_intensity;
if (m_flicker && (intensity > 0))
{
float random = (float)(machine().rand() & 255) / 255.0f;
intensity -= (int)(intensity * random * m_flicker);
intensity = MAX(0, MIN(255, intensity));
}
newpoint = &m_vector_list[m_vector_index];
newpoint->x = x;
newpoint->y = y;
newpoint->col = color;
newpoint->intensity = intensity;
newpoint->status = VDIRTY;
m_vector_index++;
if (m_vector_index >= MAX_POINTS)
{
m_vector_index--;
logerror("*** Warning! Vector list overflow!\n");
}
}
void vector_device::add_clip(int x1, int yy1, int x2, int y2)
{
point *newpoint;
newpoint = &m_vector_list[m_vector_index];
newpoint->x = x1;
newpoint->y = yy1;
newpoint->arg1 = x2;
newpoint->arg2 = y2;
newpoint->status = VCLIP;
m_vector_index++;
if (m_vector_index >= MAX_POINTS)
{
m_vector_index--;
logerror("*** Warning! Vector list overflow!\n");
}
}
void vector_device::clear_list(void)
{
m_vector_index = 0;
}
UINT32 vector_device::screen_update(screen_device &screen, bitmap_rgb32 &bitmap, const rectangle &cliprect)
{
UINT32 flags = PRIMFLAG_ANTIALIAS(screen.machine().options().antialias() ? 1 : 0) | PRIMFLAG_BLENDMODE(BLENDMODE_ADD) | PRIMFLAG_VECTOR(1);
const rectangle &visarea = screen.visible_area();
float xscale = 1.0f / (65536 * visarea.width());
float yscale = 1.0f / (65536 * visarea.height());
float xoffs = (float)visarea.min_x;
float yoffs = (float)visarea.min_y;
float xratio = xscale / yscale;
float yratio = yscale / xscale;
xratio = (xratio < 1.0f) ? xratio : 1.0f;
yratio = (yratio < 1.0f) ? yratio : 1.0f;
point *curpoint;
render_bounds clip;
int lastx = 0;
int lasty = 0;
curpoint = m_vector_list.get();
screen.container().empty();
screen.container().add_rect(0.0f, 0.0f, 1.0f, 1.0f, rgb_t(0xff,0x00,0x00,0x00), PRIMFLAG_BLENDMODE(BLENDMODE_ALPHA) | PRIMFLAG_VECTORBUF(1));
clip.x0 = clip.y0 = 0.0f;
clip.x1 = clip.y1 = 1.0f;
for (int i = 0; i < m_vector_index; i++)
{
render_bounds coords;
if (curpoint->status == VCLIP)
{
coords.x0 = ((float)curpoint->x - xoffs) * xscale;
coords.y0 = ((float)curpoint->y - yoffs) * yscale;
coords.x1 = ((float)curpoint->arg1 - xoffs) * xscale;
coords.y1 = ((float)curpoint->arg2 - yoffs) * yscale;
clip.x0 = (coords.x0 > 0.0f) ? coords.x0 : 0.0f;
clip.y0 = (coords.y0 > 0.0f) ? coords.y0 : 0.0f;
clip.x1 = (coords.x1 < 1.0f) ? coords.x1 : 1.0f;
clip.y1 = (coords.y1 < 1.0f) ? coords.y1 : 1.0f;
}
else
{
float beam_intensity_width = m_beam_width_min;
float intensity = (float)curpoint->intensity / 255.0f;
if (m_min_intensity != m_max_intensity)
{
float intensity_weight = normalized_sigmoid(intensity, m_beam_intensity_weight);
beam_intensity_width = (m_beam_width_max - m_beam_width_min) * intensity_weight + m_beam_width_min;
}
float beam_width = beam_intensity_width * (1.0f / (float)VECTOR_WIDTH_DENOM);
coords.x0 = ((float)lastx - xoffs) * xscale;
coords.y0 = ((float)lasty - yoffs) * yscale;
coords.x1 = ((float)curpoint->x - xoffs) * xscale;
coords.y1 = ((float)curpoint->y - yoffs) * yscale;
if (fabs(coords.x0 - coords.x1) < FLT_EPSILON &&
fabs(coords.y0 - coords.y1) < FLT_EPSILON)
{
coords.x0 += xratio * beam_width * 0.25f;
coords.y0 += yratio * beam_width * 0.25f;
coords.x1 -= xratio * beam_width * 0.25f;
coords.y1 -= yratio * beam_width * 0.25f;
}
if (curpoint->intensity != 0 && !render_clip_line(&coords, &clip))
{
screen.container().add_line(
coords.x0, coords.y0, coords.x1, coords.y1,
beam_width,
(curpoint->intensity << 24) | (curpoint->col & 0xffffff),
flags);
serial_draw_line(
coords.x0, coords.y0,
coords.x1, coords.y1,
curpoint->intensity);
}
lastx = curpoint->x;
lasty = curpoint->y;
}
curpoint++;
}
serial_send();
return 0;
}