Small fixes and changes, nothing major.

This commit is contained in:
waltje
2018-11-22 16:39:08 -05:00
parent 72bc6f8e9e
commit bccc0d4900
22 changed files with 801 additions and 361 deletions

View File

@@ -12,7 +12,7 @@
* it on Windows XP, and possibly also Vista. Use the
* -DANSI_CFG for use on these systems.
*
* Version: @(#)config.c 1.0.39 2018/11/06
* Version: @(#)config.c 1.0.40 2018/11/20
*
* Authors: Fred N. van Kempen, <decwiz@yahoo.com>
* Miran Grca, <mgrca8@gmail.com>
@@ -305,7 +305,7 @@ save_general(const char *cat)
if (vid_resize == 0)
config_delete_var(cat, "vid_resize");
str = vidapi_internal_name(vid_api);
str = vidapi_get_internal_name(vid_api);
if (! strcmp(str, "default")) {
config_delete_var(cat, "vid_renderer");
} else {

View File

@@ -176,7 +176,6 @@ extern void (*codegen_timing_opcode)(uint8_t opcode, uint32_t fetchdat, int op_3
extern void (*codegen_timing_block_start)(void);
extern void (*codegen_timing_block_end)(void);
extern x86seg *op_ea_seg;
extern int op_ssegs;
extern uint32_t op_old_pc;

View File

@@ -14,7 +14,7 @@
* Devices currently implemented are hard disk, CD-ROM and
* ZIP IDE/ATAPI devices.
*
* Version: @(#)hdc_ide_ata.c 1.0.28 2018/11/11
* Version: @(#)hdc_ide_ata.c 1.0.29 2018/11/13
*
* Authors: Miran Grca, <mgrca8@gmail.com>
* Sarah Walker, <tommowalker@tommowalker.co.uk>
@@ -2229,6 +2229,8 @@ ide_set_handlers(uint8_t board)
static void
ide_remove_handlers(uint8_t board)
{
if (ide_boards[board] == NULL) return;
if (ide_boards[board]->bit32) {
io_removehandler(ide_base_main[board], 1,
ide_readb, ide_readw, ide_readl,

View File

@@ -10,7 +10,7 @@
*
* TODO: Add the Genius bus- and serial mouse.
*
* Version: @(#)mouse.c 1.0.15 2018/11/10
* Version: @(#)mouse.c 1.0.16 2018/11/20
*
* Authors: Fred N. van Kempen, <decwiz@yahoo.com>
* Miran Grca, <mgrca8@gmail.com>
@@ -90,6 +90,7 @@ static const struct {
const device_t *device;
} mouse_devices[] = {
{ "none", &mouse_none_device },
{ "internal", &mouse_internal_device },
{ "logibus", &mouse_logibus_device },
{ "msbus", &mouse_msinport_device },
@@ -101,6 +102,7 @@ static const struct {
{ "ltserial", &mouse_ltserial_device },
{ "mswhserial", &mouse_mswhserial_device },
{ "ps2", &mouse_ps2_device },
{ NULL, NULL }
};

View File

@@ -53,7 +53,7 @@
* Microsoft Windows NT 3.1
* Microsoft Windows 98 SE
*
* Version: @(#)mouse_bus.c 1.1.2 2018/10/21
* Version: @(#)mouse_bus.c 1.1.3 2018/11/20
*
* Authors: Fred N. van Kempen, <decwiz@yahoo.com>
* Miran Grca, <mgrca8@gmail.com>
@@ -390,6 +390,7 @@ ms_read(uint16_t port, void *priv)
}
DBGLOG(2, "MOUSE: read(%04x) = %02x\n", port, ret);
pclog(0,"MOUSE: read(%04x) = %02x\n", port, ret);
return(ret);
}
@@ -402,6 +403,7 @@ ms_write(uint16_t port, uint8_t val, void *priv)
mouse_t *dev = (mouse_t *)priv;
DBGLOG(2, "MOUSE: write(%04x, %02x)\n", port, val);
pclog(0,"MOUSE: write(%04x, %02x)\n", port, val);
switch (port & 0x0003) {
case INP_PORT_CONTROL:
@@ -724,7 +726,7 @@ bm_init(const device_t *info)
timer_add(bm_timer, &dev->timer, &dev->timer_enabled, dev);
INFO("MOUSE: %s (I/O=%04x, IRQ=%d, buttons=%d\n",
INFO("MOUSE: %s (I/O=%04x, IRQ=%i, buttons=%i\n",
dev->name, dev->base, dev->irq, dev->bn);
return(dev);
@@ -878,16 +880,17 @@ const device_t mouse_logibus_device = {
const device_t mouse_logibus_internal_device = {
"Logitech Bus Mouse (Internal)",
0,
2,
1,
bm_init, bm_close, NULL,
bm_poll, NULL, NULL, NULL,
bm_poll,
NULL, NULL, NULL,
NULL
};
const device_t mouse_msinport_device = {
"Microsoft Bus Mouse (InPort)",
DEVICE_ISA,
1,
10,
bm_init, bm_close, NULL,
bm_poll,
NULL, NULL, NULL,

View File

@@ -10,7 +10,7 @@
*
* TODO: Add the Genius Serial Mouse.
*
* Version: @(#)mouse_serial.c 1.0.11 2018/11/11
* Version: @(#)mouse_serial.c 1.0.12 2018/11/13
*
* Authors: Fred N. van Kempen, <decwiz@yahoo.com>
* Miran Grca, <mgrca8@gmail.com>
@@ -93,7 +93,7 @@ typedef struct {
int64_t period,
delay;
SERIAL *serial;
void *serial;
uint8_t id[255],
data[5];
@@ -106,22 +106,6 @@ typedef struct {
#define FLAG_ENABLED 0x01 /* dev is enabled for use */
/* Callback from serial driver: RTS was toggled. */
static void
ser_callback(struct SERIAL *serial, void *priv)
{
mouse_t *dev = (mouse_t *)priv;
dev->serial->clear_fifo(serial);
dev->pos = 0;
dev->phase = PHASE_ID;
/* Start a timer to wake us up in a little while. */
dev->delay = dev->period;
}
static uint8_t
data_msystems(mouse_t *dev, int x, int y, int b)
{
@@ -261,7 +245,7 @@ ser_report(mouse_t *dev, int x, int y, int z, int b)
{
int len = 0;
memset(dev->data, 0x00, 5);
memset(dev->data, 0x00, sizeof(dev->data));
switch(dev->type) {
case MOUSE_MSYSTEMS:
@@ -319,21 +303,22 @@ ser_report(mouse_t *dev, int x, int y, int z, int b)
if (! dev->delay)
dev->delay = dev->period;
//pclog(0,"SerMouse%d: report(%d), len=%d\n", dev->port,dev->type,dev->data_len);
}
/* Callback timer expired, now send our "mouse ID" to the serial port. */
/* Timer expired, now send data (back) to the serial port. */
static void
ser_timer(void *priv)
{
mouse_t *dev = (mouse_t *)priv;
uint8_t b;
uint8_t b = 0x00;
//pclog(0,"SerMouse%d: timer, phase=%d pos=%d\n",dev->port,dev->phase,dev->pos);
switch (dev->phase) {
case PHASE_ID:
/* Grab next ID byte. */
b = dev->id[dev->pos];
if (dev->serial != NULL)
dev->serial->write_fifo(dev->serial, &b, 1);
if (++dev->pos == dev->id_len) {
dev->delay = 0LL;
dev->pos = 0;
@@ -343,9 +328,8 @@ ser_timer(void *priv)
break;
case PHASE_DATA:
/* Grab next data byte. */
b = dev->data[dev->pos];
if (dev->serial != NULL)
dev->serial->write_fifo(dev->serial, &b, 1);
if (++dev->pos == dev->data_len) {
dev->delay = 0LL;
dev->pos = 0;
@@ -356,8 +340,6 @@ ser_timer(void *priv)
case PHASE_STATUS:
b = dev->status;
if (dev->serial != NULL)
dev->serial->write_fifo(dev->serial, &b, 1);
dev->delay = 0LL;
dev->pos = 0;
dev->phase = PHASE_IDLE;
@@ -373,8 +355,6 @@ ser_timer(void *priv)
*/
b = 0x00;
}
if (dev->serial != NULL)
dev->serial->write_fifo(dev->serial, &b, 1);
if (++dev->pos == 3) {
dev->delay = 0LL;
dev->pos = 0;
@@ -385,8 +365,6 @@ ser_timer(void *priv)
case PHASE_FMT_REV:
b = 0x10 | (dev->format << 1);
if (dev->serial != NULL)
dev->serial->write_fifo(dev->serial, &b, 1);
dev->delay = 0LL;
dev->pos = 0;
dev->phase = PHASE_IDLE;
@@ -396,8 +374,33 @@ ser_timer(void *priv)
dev->delay = 0LL;
dev->pos = 0;
dev->phase = PHASE_IDLE;
break;
return;
}
/* Send byte if we can. */
if (dev->serial != NULL) {
serial_write(dev->serial, &b, 1);
//pclog(0,"SerMouse%d: writing %02x\n",dev->port, b);
}
}
/* Callback from serial driver: RTS was toggled. */
static void
ser_callback(void *serial, void *priv)
{
mouse_t *dev = (mouse_t *)priv;
pclog(0,"Serial%d: callback @%08lx\n", dev->port, dev->serial);
if (serial == NULL) return;
serial_clear(serial);
dev->pos = 0;
dev->phase = PHASE_ID;
/* Wait a little while and then actually send the ID. */
dev->delay = dev->period;
}
@@ -407,9 +410,9 @@ ser_poll(int x, int y, int z, int b, void *priv)
mouse_t *dev = (mouse_t *)priv;
if (!x && !y && (b == dev->oldb) && dev->continuous)
return(1);
return(0);
DBGLOG(1, "MOUSE: poll(%d,%d,%d,%02x)\n", x, y, z, b);
DBGLOG(1, "MOUSE: poll(%i,%i,%i,%02x)\n", x, y, z, b);
dev->oldb = b;
@@ -444,15 +447,17 @@ ser_poll(int x, int y, int z, int b, void *priv)
if (!dev->prompt && !dev->want_data)
ser_report(dev, x, y, z, b);
return(0);
return(1);
}
static void
ltser_write(SERIAL *serial, void *priv, uint8_t data)
ltser_write(void *serial, void *priv, uint8_t data)
{
mouse_t *dev = (mouse_t *)priv;
pclog(0,"MOUSE: ltwrite(%02x) @%08lx\n", data, dev->serial);
#if 0
/* Make sure to stop any transmission when we receive a byte. */
if (dev->phase != PHASE_IDLE) {
@@ -593,6 +598,11 @@ ser_close(void *priv)
static void *
ser_init(const device_t *info)
{
static serial_ops_t ops = {
ser_callback, /* mcr */
NULL, /* read */
ltser_write, /* write */
};
mouse_t *dev;
int i;
@@ -625,7 +635,7 @@ ser_init(const device_t *info)
case 3:
dev->id_len = 2;
dev->id[1] = '3';
/*FALLTHROUGH*/
break;
case 4:
dev->type = MOUSE_MSWHEEL;
@@ -640,20 +650,15 @@ ser_init(const device_t *info)
}
/* Attach a serial port to the mouse. */
dev->serial = serial_attach(dev->port-1, ser_callback, dev);
dev->serial = serial_attach(dev->port, &ops, dev);
if (dev->serial == NULL) {
ERRLOG("MOUSE: %s (port=COM%i, butons=%i) port disabled!\n",
dev->name, dev->port+1, i);
ERRLOG("MOUSE: %s (port COM%i not available) device disabled!\n",
dev->name, dev->port+1);
free(dev);
return(NULL);
}
#if 0
/* Add our WRITE routine. */
serial_attach2(dev->port-1, ser_write, dev);
#endif
INFO("MOUSE: %s (port=COM%d, butons=%d)\n", dev->name, dev->port+1, i);
INFO("MOUSE: %s (port=COM%i, buttons=%i)\n", dev->name, dev->port+1, i);
timer_add(ser_timer, &dev->delay, &dev->delay, dev);
@@ -667,15 +672,12 @@ ser_init(const device_t *info)
static const device_config_t ser_config[] = {
{
"port", "Serial Port", CONFIG_SELECTION, "", 1, {
"port", "Serial Port", CONFIG_SELECTION, "", 0, {
{
"Disabled", 0
"COM1", 0
},
{
"COM1", 1
},
{
"COM2", 2
"COM2", 1
},
{
""

View File

@@ -6,35 +6,67 @@
*
* This file is part of the VARCem Project.
*
* Implementation of 8250-style serial port.
* Implementation of NS8250-series UART devices.
*
* Version: @(#)serial.c 1.0.11 2018/11/11
* The original IBM-PC design did not have any serial ports of
* any kind. Rather, these were offered as add-on devices, most
* likely because a) most people did not need one at the time,
* and, b) this way, IBM could make more money off them.
*
* Authors: Fred N. van Kempen, <decwiz@yahoo.com>
* Miran Grca, <mgrca8@gmail.com>
* Sarah Walker, <tommowalker@tommowalker.co.uk>
* So, for the PC, the offerings were for an IBM Asynchronous
* Communications Adapter, and, later, a model for synchronous
* communications. The "Async Adapter" was based on the NS8250
* UART chip, and is what we now call the "com" port of the PC.
*
* Of course, many system builders came up with similar boards,
* and even more boards were designed where several I/O functions
* were combined into a single "multi-I/O" board, as that saved
* space and bus slots. Early boards had discrete chips for most
* functions, but later on, many of these were integrated into a
* single "super-I/O" chip.
*
* This file implements the standard NS8250, as well as the later
* 16450 and 16550 series, which fixed bugs and added features
* like FIFO buffers, higher line speeds and DMA transfers.
*
* The lower half of the driver can interface to the host system
* serial ports, or other channels, for real-world access.
*
* Version: @(#)serial.c 1.0.12 2018/11/16
*
* Author: Fred N. van Kempen, <decwiz@yahoo.com>
*
* Copyright 2017,2018 Fred N. van Kempen.
* Copyright 2016-2018 Miran Grca.
* Copyright 2008-2018 Sarah Walker.
*
* 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.
* Redistribution and use in source and binary forms, with
* or without modification, are permitted provided that the
* following conditions are met:
*
* 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.
* 1. Redistributions of source code must retain the entire
* above notice, this list of conditions and the following
* disclaimer.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the:
* 2. Redistributions in binary form must reproduce the above
* copyright notice, this list of conditions and the
* following disclaimer in the documentation and/or other
* materials provided with the distribution.
*
* Free Software Foundation, Inc.
* 59 Temple Place - Suite 330
* Boston, MA 02111-1307
* USA.
* 3. Neither the name of the copyright holder nor the names
* of its contributors may be used to endorse or promote
* products derived from this software without specific
* prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
* PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#include <stdio.h>
#include <stdint.h>
@@ -54,12 +86,124 @@
#include "serial.h"
enum {
SERIAL_INT_LSR = 1,
SERIAL_INT_RECEIVE = 2,
SERIAL_INT_TRANSMIT = 4,
SERIAL_INT_MSR = 8
};
/* Interrupt reasons. */
#define SER_INT_LSR 0x01
#define SER_INT_RX 0x02
#define SER_INT_TX 0x04
#define SER_INT_MSR 0x08
/* IER register bits. */
#define IER_RDAIE 0x01
#define IER_THREIE 0x02
#define IER_RXLSIE 0x04
#define IER_MSIE 0x08
#define IER_SLEEP 0x10 /* NS16750 */
#define IER_LOWPOWER 0x20 /* NS16750 */
#define IER_MASK 0x0f /* not including SLEEP|LOWP */
/* IIR register bits. */
#define IIR_IP 0x01
#define IIR_IID 0x0e
# define IID_IDMDM 0x00
# define IID_IDTX 0x02
# define IID_IDRX 0x04
# define IID_IDERR 0x06
# define IID_IDTMO 0x0c /* 16550+ */
#define IIR_IIRFE 0xc0 /* 16550+ */
# define IIR_FIFO64 0x20
# define IIR_FIFOBAD 0x80
# define IIR_FIFOENB 0xc0
/* FCR register bits. */
#define FCR_FCRFE 0x01
#define FCR_RFR 0x02
#define FCR_TFR 0x04
#define FCR_SELDMA1 0x08
#define FCR_FENB64 0x20 /* 16750 */
#define FCR_RTLS 0xc0
# define FCR_RTLS1 0x00
# define FCR_RTLS4 0x40
# define FCR_RTLS8 0x80
# define FCR_RTLS14 0xc0
/* LCR register bits. */
#define LCR_WLS 0x03
# define WLS_BITS5 0x00
# define WLS_BITS6 0x01
# define WLS_BITS7 0x02
# define WLS_BITS8 0x03
#define LCR_SBS 0x04
#define LCR_PE 0x08
#define LCR_EP 0x10
#define LCR_PS 0x20
# define PAR_NONE 0x00
# define PAR_EVEN (LCR_PE | LCR_EP)
# define PAR_ODD LCR_PE
# define PAR_MARK (LCR_PE | LCR_PS)
# define PAR_SPACE (LCR_PE | LCR_PS | LCR_EP)
#define LCR_BC 0x40
#define LCR_DLAB 0x80
/* MCR register bits. */
#define MCR_DTR 0x01
#define MCR_RTS 0x02
#define MCR_OUT1 0x04 /* 8250 */
#define MCR_OUT2 0x08 /* 8250, INTEN on IBM-PC */
#define MCR_LMS 0x10
#define MCR_AUTOFLOW 0x20 /* 16750 */
/* LSR register bits. */
#define LSR_DR 0x01
#define LSR_OE 0x02
#define LSR_PE 0x04
#define LSR_FE 0x08
#define LSR_BI 0x10
#define LSR_THRE 0x20
#define LSR_TEMT 0x40
#define LSR_RXFE 0x80
#define LSR_MASK (LSR_BI|LSR_FE|LSR_PE|LSR_OE)
/* MSR register bits. */
#define MSR_DCTS 0x01
#define MSR_DDSR 0x02
#define MSR_TERI 0x04
#define MSR_DDCD 0x08
#define MSR_CTS 0x10
#define MSR_DSR 0x20
#define MSR_RI 0x40
#define MSR_DCD 0x80
#define MSR_MASK (MSR_DDCD|MSR_TERI|MSR_DDSR|MSR_DCTS)
typedef struct serial {
int8_t port; /* port number (0,1,..) */
int8_t irq; /* IRQ channel used */
uint16_t base; /* I/O address used */
int8_t is_pcjr; /* PCjr UART (fixed OUT2) */
int8_t type; /* UART type */
uint8_t int_status;
uint8_t lsr, thr, mcr, rcr, /* UART registers */
iir, ier, lcr, msr;
uint8_t dlab1, dlab2;
uint8_t dat,
hold;
uint8_t scratch;
uint8_t fcr;
/* Callback data. */
serial_ops_t *ops;
void *ops_arg;
int64_t delay;
void *bh; /* BottomHalf handler */
int fifo_read,
fifo_write;
uint8_t fifo[64];
} serial_t;
#ifdef ENABLE_SERIAL_LOG
@@ -67,19 +211,11 @@ int serial_do_log = ENABLE_SERIAL_LOG;
#endif
static const struct {
uint16_t addr;
int8_t irq;
int8_t pad;
} addr_list[] = { /* valid port addresses */
{ SERIAL1_ADDR, 4 },
{ SERIAL2_ADDR, 3 }
};
static SERIAL ports[SERIAL_MAX]; /* the ports */
static serial_t ports[SERIAL_MAX]; /* the ports */
#ifdef _LOGGING
void
static void
serial_log(int level, const char *fmt, ...)
{
# ifdef ENABLE_SERIAL_LOG
@@ -96,70 +232,107 @@ serial_log(int level, const char *fmt, ...)
static void
update_ints(SERIAL *dev)
update_ints(serial_t *dev)
{
int stat = 0;
dev->iir = 1;
/* None yet. */
dev->iir = IIR_IP;
if ((dev->ier & 4) && (dev->int_status & SERIAL_INT_LSR)) {
/*Line status interrupt*/
if ((dev->ier & IER_RXLSIE) && (dev->int_status & SER_INT_LSR)) {
/* Line Status interrupt. */
stat = 1;
dev->iir = 6;
} else if ((dev->ier & 1) && (dev->int_status & SERIAL_INT_RECEIVE)) {
/*Received data available*/
dev->iir = IID_IDERR;
} else if ((dev->ier & IER_RDAIE) && (dev->int_status & SER_INT_RX)) {
/* Received Data available. */
stat = 1;
dev->iir = 4;
} else if ((dev->ier & 2) && (dev->int_status & SERIAL_INT_TRANSMIT)) {
/*Transmit data empty*/
dev->iir = IID_IDRX;
} else if ((dev->ier & IER_THREIE) && (dev->int_status & SER_INT_TX)) {
/* Transmit Data empty. */
stat = 1;
dev->iir = 2;
} else if ((dev->ier & 8) && (dev->int_status & SERIAL_INT_MSR)) {
/*Modem status interrupt*/
dev->iir = IID_IDTX;
} else if ((dev->ier & IER_MSIE) && (dev->int_status & SER_INT_MSR)) {
/* Modem Status interrupt. */
stat = 1;
dev->iir = 0;
dev->iir = IID_IDMDM;
}
if (stat && ((dev->mcr & 8) || dev->is_pcjr))
DEBUG("Serial%d: intr, IIR=%02X, type=%d, mcr=%02X\n",
dev->port, dev->iir, dev->type, dev->mcr);
if (stat && ((dev->mcr & MCR_OUT2) || dev->is_pcjr)) {
/* Raise an interrupt. */
if (dev->type < UART_TYPE_16450) {
/* Edge-triggered. */
picint(1 << dev->irq);
} else {
/* Level-triggered. */
picintlevel(1 << dev->irq);
else
}
} else {
/* Clear an interrupt. */
picintc(1 << dev->irq);
}
}
static void
clear_fifo(SERIAL *dev)
clear_fifo(serial_t *dev)
{
memset(dev->fifo, 0x00, 256);
memset(dev->fifo, 0x00, sizeof(dev->fifo));
dev->fifo_read = dev->fifo_write = 0;
}
static void
write_fifo(SERIAL *dev, uint8_t *ptr, uint8_t len)
write_fifo(serial_t *dev, uint8_t *ptr, uint8_t len)
{
while (len-- > 0) {
dev->fifo[dev->fifo_write] = *ptr++;
dev->fifo_write = (dev->fifo_write + 1) & 0xff;
dev->fifo[dev->fifo_write++] = *ptr++;
if (dev->fifo_write == sizeof(dev->fifo))
dev->fifo_write = 0;
/*OVERFLOW NOT DETECTED*/
}
if (! (dev->lsr & 1)) {
dev->lsr |= 1;
dev->int_status |= SERIAL_INT_RECEIVE;
if (! (dev->lsr & LSR_DR)) {
dev->lsr |= LSR_DR;
dev->int_status |= SER_INT_RX;
update_ints(dev);
}
}
static uint8_t
read_fifo(SERIAL *dev)
read_fifo(serial_t *dev)
{
if (dev->fifo_read != dev->fifo_write) {
dev->dat = dev->fifo[dev->fifo_read];
dev->fifo_read = (dev->fifo_read + 1) & 0xff;
dev->dat = dev->fifo[dev->fifo_read++];
if (dev->fifo_read == sizeof(dev->fifo))
dev->fifo_read = 0;
}
#if 0
/* If we have more, generate (new) int. */
if (sp->fifo_read != sp->fifo_write) {
#if 1
sp->delay = 1000*TIMER_USEC;
#else
if (sp->bh != NULL) {
sp->int_status |= SERINT_RECEIVE;
sp->lsr |= LSR_DR;
/* Update interrupt state. */
update_ints(sp);
} else {
sp->delay = 1000*TIMER_USEC;
}
#endif
}
}
#endif
return(dev->dat);
}
@@ -167,20 +340,21 @@ read_fifo(SERIAL *dev)
static void
receive_callback(void *priv)
{
SERIAL *dev = (SERIAL *)priv;
serial_t *dev = (serial_t *)priv;
dev->delay = 0;
if (dev->fifo_read != dev->fifo_write) {
dev->lsr |= 1;
dev->int_status |= SERIAL_INT_RECEIVE;
dev->lsr |= LSR_DR;
dev->int_status |= SER_INT_RX;
update_ints(dev);
}
}
static void
reset_port(SERIAL *dev)
reset_port(serial_t *dev)
{
dev->iir = dev->ier = dev->lcr = 0;
dev->fifo_read = dev->fifo_write = 0;
@@ -189,160 +363,321 @@ reset_port(SERIAL *dev)
}
/* Fake interrupt generator, needed for Serial Mouse. */
static void
serial_write(uint16_t addr, uint8_t val, void *priv)
read_timer(void *priv)
{
SERIAL *dev = (SERIAL *)priv;
serial_t *dev = (serial_t *)priv;
switch (addr & 7) {
case 0:
if (dev->lcr & 0x80) {
dev->delay = 0;
if (dev->fifo_read != dev->fifo_write) {
dev->lsr |= LSR_DR;
dev->int_status |= SER_INT_RX;
update_ints(dev);
}
}
#ifdef USE_HOST_SERIAL
/* BHTTY READ COMPLETE handler. */
static void
read_done(void *arg, int num)
{
serial_t *dev = (serial_t *)arg;
/* We can do at least 'num' bytes.. */
while (num-- > 0) {
/* Get a byte from them. */
if (bhtty_read(dev->bh, &dev->hold, 1) < 0) break;
/* Stuff it into the FIFO and set intr. */
write_fifo(dev, &dev->hold, 1);
}
/* We have data waiting for us.. delay a little, and then read it. */
timer_add(ser_timer, &dev->delay, &dev->delay, dev);
}
#endif
static void
ser_write(uint16_t addr, uint8_t val, void *priv)
{
serial_t *dev = (serial_t *)priv;
uint8_t wl, sb, pa, msr;
uint32_t baud, speed;
DEBUG("Serial%i: write(%i, %02x)\n", dev->port, (addr & 0x0007), val);
switch (addr & 0x0007) {
case 0: /* DLAB, DATA */
if (dev->lcr & LCR_DLAB) {
/* DLAB set, set DLAB low byte. */
dev->dlab1 = val;
return;
}
/* DLAB clear, regular data write. */
dev->thr = val;
dev->lsr |= 0x20;
dev->int_status |= SERIAL_INT_TRANSMIT;
#ifdef USE_HOST_SERIAL
if (dev->bh != NULL) {
/* We are linked, so send to BH layer. */
bhtty_write((BHTTY *)dev->bh, dev->thr);
}
#endif
if (dev->ops && dev->ops->write)
dev->ops->write(dev, dev->ops_arg, val);
/* WRITE completed, we are ready for more. */
dev->lsr |= LSR_THRE;
dev->int_status |= SER_INT_TX;
update_ints(dev);
if (dev->mcr & 0x10)
/* Loopback echo data to RX needed? */
if (dev->mcr & MCR_LMS) {
write_fifo(dev, &val, 1);
dev->int_status |= SER_INT_TX;
update_ints(dev);
}
break;
case 1:
if (dev->lcr & 0x80) {
case 1: /* DLAB, IER */
if (dev->lcr & LCR_DLAB) {
/* DLAB set, set DLAB high byte. */
dev->dlab2 = val;
return;
}
dev->ier = val & 0xf;
/* DLAB clear, set IER register bits. */
dev->ier = (val & IER_MASK);
update_ints(dev);
break;
case 2:
case 2: /* FCR */
#if 0
if (dev->type >= UART_TYPE_16550) {
DEBUG("Serial%i: tried to enable FIFO (%02x), type %d!\n", dev->port, val, dev->type);
dev->fcr = val;
}
#else
dev->fcr = val;
#endif
break;
case 3:
case 3: /* LCR */
if ((dev->lcr & LCR_DLAB) && !(val & LCR_DLAB)) {
/* We dropped DLAB, so handle baudrate. */
baud = ((dev->dlab2 << 8) | dev->dlab1);
if (baud > 0) {
speed = 115200UL / baud;
DEBUG("Serial%i: divisor %u, baudrate %i\n",
dev->port, baud, speed);
#ifdef USE_HOST_SERIAL
if (dev->bh != NULL)
bhtty_speed((BHTTY *)dev->bh, speed);
#endif
} else {
DEBUG("Serial%i: divisor %u invalid!\n",
dev->port, baud);
}
}
wl = (val & LCR_WLS) + 5; /* databits */
sb = (val & LCR_SBS) ? 2 : 1; /* stopbits */
pa = (val & (LCR_PE|LCR_EP|LCR_PS)) >> 3;
DEBUG("Serial%i: WL=%i SB=%i PA=%i\n", dev->port, wl, sb, pa);
#ifdef USE_HOST_SERIAL
if (dev->bh != NULL)
bhtty_params((BHTTY *)dev->bh, wl, pa, sb);
#endif
dev->lcr = val;
break;
case 4:
if ((val & 2) && !(dev->mcr & 2)) {
if (dev->rts_callback)
dev->rts_callback(dev, dev->rts_callback_p);
case 4: /*MCR*/
#ifdef USE_HOST_SERIAL
if (dev->bh == NULL) {
/* Not linked, force LOOPBACK mode. */
val |= MCR_LMS;
}
#endif
if ((val & MCR_RTS) && !(dev->mcr & MCR_RTS)) {
/*
* This is old code for use by the Serial Mouse
* driver. If the user toggles RTS, serial mice
* are expected to send an ID, to inform any
* enumerator there 'is' something.
*/
if (dev->ops && dev->ops->mcr) {
dev->ops->mcr(dev, dev->ops_arg);
DEBUG("Serial%i: RTS raised\n", dev->port);
}
}
if ((val & MCR_OUT2) && !(dev->mcr & MCR_OUT2)) {
#ifdef USE_HOST_SERIAL
if (dev->bh != NULL) {
/* Linked, start host port. */
(void)bhtty_active(dev->bh, 1);
} else {
#endif
/* Not linked, start RX timer. */
timer_add(read_timer,
&dev->delay, &dev->delay, dev);
/* Fake CTS, DSR and DCD (for now.) */
dev->msr = (MSR_CTS | MSR_DCTS |
MSR_DSR | MSR_DDSR |
MSR_DCD | MSR_DDCD);
dev->int_status |= SER_INT_MSR;
update_ints(dev);
#ifdef USE_HOST_SERIAL
}
#endif
}
dev->mcr = val;
if (val & 0x10) {
uint8_t new_msr;
new_msr = (val & 0x0c) << 4;
new_msr |= (val & 0x02) ? 0x10: 0;
new_msr |= (val & 0x01) ? 0x20: 0;
if (val & MCR_LMS) { /* loopback mode */
msr = (val & 0x0c) << 4;
msr |= (val & MCR_RTS) ? MCR_LMS : 0;
msr |= (val & MCR_DTR) ? MCR_AUTOFLOW : 0;
if ((dev->msr ^ new_msr) & 0x10)
new_msr |= 0x01;
if ((dev->msr ^ new_msr) & 0x20)
new_msr |= 0x02;
if ((dev->msr ^ new_msr) & 0x80)
new_msr |= 0x08;
if ((dev->msr & 0x40) && !(new_msr & 0x40))
new_msr |= 0x04;
if ((dev->msr ^ msr) & MSR_CTS)
msr |= MSR_DCTS;
if ((dev->msr ^ msr) & MSR_DSR)
msr |= MSR_DDSR;
if ((dev->msr ^ msr) & MSR_DCD)
msr |= MSR_DDCD;
if ((dev->msr & MSR_TERI) && !(msr & MSR_RI))
msr |= MSR_TERI;
dev->msr = new_msr;
dev->msr = msr;
}
break;
case 5:
case 5: /*LSR*/
if (val & LSR_MASK)
dev->int_status |= SER_INT_LSR;
if (val & LSR_DR)
dev->int_status |= SER_INT_RX;
if (val & LSR_THRE)
dev->int_status |= SER_INT_TX;
dev->lsr = val;
if (dev->lsr & 0x01)
dev->int_status |= SERIAL_INT_RECEIVE;
if (dev->lsr & 0x1e)
dev->int_status |= SERIAL_INT_LSR;
if (dev->lsr & 0x20)
dev->int_status |= SERIAL_INT_TRANSMIT;
update_ints(dev);
break;
case 6:
case 6: /*MSR*/
dev->msr = val;
if (dev->msr & 0x0f)
dev->int_status |= SERIAL_INT_MSR;
if (dev->msr & MSR_MASK)
dev->int_status |= SER_INT_MSR;
update_ints(dev);
break;
case 7:
case 7: /*SCRATCH*/
if (dev->type > UART_TYPE_8250) {
dev->scratch = val;
}
break;
}
}
static uint8_t
serial_read(uint16_t addr, void *priv)
ser_read(uint16_t addr, void *priv)
{
SERIAL *dev = (SERIAL *)priv;
serial_t *dev = (serial_t *)priv;
uint8_t ret = 0x00;
switch (addr & 7) {
case 0:
if (dev->lcr & 0x80) {
switch (addr & 0x0007) {
case 0: /* DATA / DLAB1 */
if (dev->lcr & LCR_DLAB) {
/* DLAB set, read DLAB low byte. */
ret = dev->dlab1;
break;
}
dev->lsr &= ~1;
dev->int_status &= ~SERIAL_INT_RECEIVE;
/*
* DLAB clear, regular data read.
* First, clear the RXDATA interrupt.
*/
dev->lsr &= ~LSR_DR;
dev->int_status &= ~SER_INT_RX;
update_ints(dev);
/* If there is data in the RX FIFO, grab it. */
ret = read_fifo(dev);
if (dev->fifo_read != dev->fifo_write) {
dev->delay = 1000LL * TIMER_USEC;
}
break;
case 1:
if (dev->lcr & 0x80)
case 1: /* LCR / DLAB2 */
if (dev->lcr & LCR_DLAB) {
/* DLAB set, read DLAB high byte. */
ret = dev->dlab2;
else
} else {
/* DLAB clear, read IER register bits. */
ret = dev->ier;
}
break;
case 2:
case 2: /* IIR */
ret = dev->iir;
if ((ret & 0xe) == 2) {
dev->int_status &= ~SERIAL_INT_TRANSMIT;
if ((ret & IIR_IID) == IID_IDTX) {
/* Transmit is done. */
dev->int_status &= ~SER_INT_TX;
update_ints(dev);
}
if (dev->fcr & 1)
ret |= 0xc0;
if (dev->type >= UART_TYPE_16550) {
/* If FIFO enabled.. */
if (dev->fcr & FCR_FCRFE)
/* Report FIFO active. */
ret |= FCR_RTLS14;
}
break;
case 3:
case 3: /* LCR */
ret = dev->lcr;
break;
case 4:
case 4: /* MCR */
ret = dev->mcr;
break;
case 5:
if (dev->lsr & 0x20)
dev->lsr |= 0x40;
dev->lsr |= 0x20;
case 5: /* LSR */
if (dev->lsr & LSR_THRE)
dev->lsr |= LSR_TEMT;
dev->lsr |= LSR_THRE;
ret = dev->lsr;
if (dev->lsr & 0x1f)
dev->lsr &= ~0x1e;
dev->int_status &= ~SERIAL_INT_LSR;
dev->int_status &= ~SER_INT_LSR;
update_ints(dev);
break;
case 6:
case 6: /* MSR */
/* Grab current modem status and reset delta bits. */
ret = dev->msr;
dev->msr &= ~0x0f;
dev->int_status &= ~SERIAL_INT_MSR;
/* Clear MSR interrupt status. */
dev->int_status &= ~SER_INT_MSR;
update_ints(dev);
break;
case 7:
case 7: /* SCRATCH */
if (dev->type > UART_TYPE_8250) {
ret = dev->scratch;
}
break;
}
@@ -351,27 +686,22 @@ serial_read(uint16_t addr, void *priv)
static void *
serial_init(const device_t *info)
ser_init(const device_t *info)
{
SERIAL *dev;
serial_t *dev;
/* Get the correct device. */
dev = &ports[info->local - 1];
dev = &ports[(info->local & 127) - 1];
/* Set up local/weird stuff. */
if (info->local & 128)
dev->is_pcjr = 1;
/* Set up callback functions. */
dev->clear_fifo = clear_fifo;
dev->write_fifo = write_fifo;
/* Clear port. */
reset_port(dev);
/* Enable the I/O handler for this port. */
io_sethandler(dev->base, 8,
serial_read,NULL,NULL, serial_write,NULL,NULL, dev);
io_sethandler(dev->base, 8, ser_read,NULL,NULL, ser_write,NULL,NULL, dev);
timer_add(receive_callback, &dev->delay, &dev->delay, dev);
@@ -383,13 +713,19 @@ serial_init(const device_t *info)
static void
serial_close(void *priv)
ser_close(void *priv)
{
SERIAL *dev = (SERIAL *)priv;
serial_t *dev = (serial_t *)priv;
#ifdef USE_HOST_SERIAL
/* Close the host device. */
if (dev->bh != NULL)
(void)serial_link(dev->port, NULL);
#endif
/* Remove the I/O handler. */
io_removehandler(dev->base, 8,
serial_read,NULL,NULL, serial_write,NULL,NULL, dev);
ser_read,NULL,NULL, ser_write,NULL,NULL, dev);
/* Clear port. */
reset_port(dev);
@@ -400,7 +736,7 @@ const device_t serial_1_device = {
"COM1:",
0,
1,
serial_init, serial_close, NULL,
ser_init, ser_close, NULL,
NULL, NULL, NULL, NULL,
NULL
};
@@ -409,7 +745,7 @@ const device_t serial_2_device = {
"COM2:",
0,
2,
serial_init, serial_close, NULL,
ser_init, ser_close, NULL,
NULL, NULL, NULL, NULL,
NULL,
};
@@ -418,29 +754,54 @@ const device_t serial_1_pcjr_device = {
"COM1:",
0,
1+128,
serial_init, serial_close, NULL,
ser_init, ser_close, NULL,
NULL, NULL, NULL, NULL,
NULL
};
/* (Re-)initialize all serial ports. */
/* API: (re-)initialize all serial ports. */
void
serial_reset(void)
{
SERIAL *dev;
serial_t *dev;
int i;
DEBUG("SERIAL: reset ([%i] [%i])\n",
serial_enabled[0], serial_enabled[1]);
for (i = 0; i < SERIAL_MAX; i++) {
/* Get the correct device and clear it. */
dev = &ports[i];
memset(dev, 0x00, sizeof(serial_t));
dev->port = i;
dev->type = UART_TYPE_8250;
memset(dev, 0x00, sizeof(SERIAL));
/* Set up default port and IRQ for the device. */
switch(i) {
case 0: /* standard first port, "COM1" */
dev->base = SERIAL1_ADDR;
dev->irq = 4;
break;
dev->base = addr_list[i].addr;
dev->irq = addr_list[i].irq;
case 1: /* standard second port, "COM2" */
dev->base = SERIAL2_ADDR;
dev->irq = 3;
break;
case 2: /* "COM3" */
dev->base = 0x03e8;
dev->irq = 4;
break;
case 3: /* "COM4" */
dev->base = 0x02e8;
dev->irq = 3;
break;
default:
break;
}
/* Clear port. */
reset_port(dev);
@@ -448,11 +809,11 @@ serial_reset(void)
}
/* Set up (the address/IRQ of) one of the serial ports. */
/* API: set up (the address/IRQ of) one of the serial ports. */
void
serial_setup(int id, uint16_t port, int8_t irq)
{
SERIAL *dev = &ports[id];
serial_t *dev = &ports[id];
INFO("SERIAL: setting up COM%i as %04X [enabled=%i]\n",
id+1, port, serial_enabled[id]);
@@ -464,11 +825,11 @@ serial_setup(int id, uint16_t port, int8_t irq)
}
/* Attach another device (MOUSE) to a serial port. */
SERIAL *
serial_attach(int port, void *func, void *arg)
/* API: attach another device to a serial port. */
void *
serial_attach(int port, serial_ops_t *ops, void *arg)
{
SERIAL *dev;
serial_t *dev;
/* No can do if port not enabled. */
if (! serial_enabled[port]) return(NULL);
@@ -477,8 +838,28 @@ serial_attach(int port, void *func, void *arg)
dev = &ports[port];
/* Set up callback info. */
dev->rts_callback = (void (*)(struct SERIAL *, void *))func;
dev->rts_callback_p = arg;
dev->ops = ops;
dev->ops_arg = arg;
return(dev);
}
/* API: clear the FIFO buffers of a serial port. */
void
serial_clear(void *arg)
{
serial_t *dev = (serial_t *)arg;
clear_fifo(dev);
}
/* API: write data to a serial port. */
void
serial_write(void *arg, uint8_t *ptr, uint8_t len)
{
serial_t *dev = (serial_t *)arg;
write_fifo(dev, ptr, len);
}

View File

@@ -8,7 +8,7 @@
*
* Definitions for the SERIAL card.
*
* Version: @(#)serial.h 1.0.6 2018/11/11
* Version: @(#)serial.h 1.0.8 2018/11/15
*
* Author: Fred N. van Kempen, <decwiz@yahoo.com>
*
@@ -49,6 +49,7 @@
#define SERIAL_MAX 2 /* two ports supported */
#define SERIAL_FIFO_MAX 64 /* maximum FIFO size */
/* Default settings for the standard ports. */
#define SERIAL1_ADDR 0x03f8
@@ -61,64 +62,35 @@
#define UART_TYPE_8250A 1 /* updated NS8250(A) */
#define UART_TYPE_16450 2 /* 16450 */
#define UART_TYPE_16550 3 /* 16550 (broken fifo) */
#define UART_TYPE_16550A 4 /* 16550a (working fifo) */
#define UART_TYPE_16550A 4 /* 16550A (working fifo) */
#define UART_TYPE_16670 5 /* 16670 (64b fifo) */
typedef struct SERIAL {
int8_t port; /* port number (1,2,..) */
int8_t irq; /* IRQ channel used */
uint16_t base; /* I/O address used */
int8_t is_pcjr; /* PCjr UART (fixed OUT2) */
int8_t type; /* UART type */
uint8_t int_status;
uint8_t lsr, thr, mcr, rcr, /* UART registers */
iir, ier, lcr, msr;
uint8_t dlab1, dlab2;
uint8_t dat,
hold;
uint8_t scratch;
uint8_t fcr;
/* Access to internal functions. */
void (*clear_fifo)(struct SERIAL *);
void (*write_fifo)(struct SERIAL *, uint8_t *, uint8_t);
/* Data for the RTS-toggle callback. */
void (*rts_callback)(struct SERIAL *, void *);
void *rts_callback_p;
int64_t delay;
#ifdef WALTJE_SERIAL
void *bh; /* BottomHalf handler */
#endif
int fifo_read,
fifo_write;
uint8_t fifo[256];
} SERIAL;
typedef struct {
void (*mcr)(void *dev, void *arg);
uint8_t (*read)(void *dev, void *arg);
void (*write)(void *dev, void *arg, uint8_t val);
} serial_ops_t;
/* Global variables. */
#ifdef EMU_DEVICE_H
extern const device_t serial_1_device;
extern const device_t serial_1_pcjr_device;
extern const device_t serial_2_device;
extern const device_t serial_1_pcjr_device;
#endif
/* Functions. */
extern void serial_log(int level, const char *fmt, ...);
extern void serial_reset(void);
extern void serial_setup(int port, uint16_t addr, int8_t irq);
extern SERIAL *serial_attach(int port, void *func, void *priv);
#ifdef WALTJE_SERIAL
extern int serial_link(int port, char *name);
#endif
extern void serial_setup(int port, uint16_t addr, int8_t irq);
extern void *serial_attach(int port, serial_ops_t *ops, void *priv);
extern int serial_link(int port, const char *name);
extern void serial_clear(void *arg);
extern void serial_write(void *arg, uint8_t *ptr, uint8_t len);
#endif /*EMU_SERIAL_H*/

View File

@@ -6,9 +6,9 @@
*
* This file is part of the VARCem Project.
*
* Trident TVGA (8900D) emulation.
* Trident TVGA (8900C/8900D) emulation.
*
* Version: @(#)vid_tvga.c 1.0.9 2018/10/08
* Version: @(#)vid_tvga.c 1.0.10 2018/11/20
*
* Authors: Fred N. van Kempen, <decwiz@yahoo.com>
* Miran Grca, <mgrca8@gmail.com>
@@ -52,7 +52,8 @@
#include "vid_tkd8001_ramdac.h"
#define ROM_TVGA_BIOS L"video/trident/tvga/trident.bin"
#define ROM_T8900CX_BIOS L"video/trident/8916cx2/bios.bin"
#define ROM_T8900D_BIOS L"video/trident/tvga/trident.bin"
typedef struct {
@@ -342,17 +343,29 @@ tvga_init(const device_t *info)
{
tvga_t *tvga = (tvga_t *)mem_alloc(sizeof(tvga_t));
memset(tvga, 0x00, sizeof(tvga_t));
const wchar_t *fn = NULL;
tvga->vram_size = device_get_config_int("memory") << 10;
tvga->vram_mask = tvga->vram_size - 1;
rom_init(&tvga->bios_rom, ROM_TVGA_BIOS,
0xc0000, 0x8000, 0x7fff, 0, MEM_MAPPING_EXTERNAL);
svga_init(&tvga->svga, tvga, tvga->vram_size,
tvga_recalctimings, tvga_in, tvga_out, NULL, NULL);
switch(info->local) {
case 0: /* TVGA 8900CX LC2 */
fn = ROM_T8900CX_BIOS;
tvga->svga.ramdac = device_add(&tkd8001_ramdac_device);
break;
case 1: /* TVGA 8900D */
fn = ROM_T8900D_BIOS;
tvga->svga.ramdac = device_add(&tkd8001_ramdac_device);
break;
}
if (fn != NULL)
rom_init(&tvga->bios_rom, fn,
0xc0000, 0x8000, 0x7fff, 0, MEM_MAPPING_EXTERNAL);
io_sethandler(0x03c0, 32,
tvga_in,NULL,NULL, tvga_out,NULL,NULL, tvga);
@@ -393,10 +406,17 @@ tvga_force_redraw(void *p)
}
static int
tvga8900c_available(void)
{
return rom_present(ROM_T8900CX_BIOS);
}
static int
tvga8900d_available(void)
{
return rom_present(ROM_TVGA_BIOS);
return rom_present(ROM_T8900D_BIOS);
}
@@ -425,17 +445,29 @@ static const device_config_t tvga_config[] =
}
};
static const video_timings_t tvga8900d_timing = {VID_ISA,3,3,6,8,8,12};
static const video_timings_t tvga8900_timing = {VID_ISA,3,3,6,8,8,12};
const device_t tvga8900cx_device = {
"Trident TVGA 8900CX 2/4/8 LC2 Rev.A",
DEVICE_ISA,
0,
tvga_init, tvga_close, NULL,
tvga8900c_available,
tvga_speed_changed,
tvga_force_redraw,
&tvga8900_timing,
tvga_config
};
const device_t tvga8900d_device = {
"Trident TVGA 8900D",
DEVICE_ISA,
0,
1,
tvga_init, tvga_close, NULL,
tvga8900d_available,
tvga_speed_changed,
tvga_force_redraw,
&tvga8900d_timing,
&tvga8900_timing,
tvga_config
};

View File

@@ -8,7 +8,7 @@
*
* Definitions for the video controller module.
*
* Version: @(#)video.h 1.0.22 2018/10/28
* Version: @(#)video.h 1.0.23 2018/11/20
*
* Authors: Fred N. van Kempen, <decwiz@yahoo.com>
* Miran Grca, <mgrca8@gmail.com>
@@ -276,6 +276,7 @@ extern const device_t s3_virge_375_4_pci_device;
extern const device_t sigma_device;
/* Trident 8900 series cards. */
extern const device_t tvga8900cx_device;
extern const device_t tvga8900d_device;
/* Trident 9400 series cards. */

View File

@@ -12,7 +12,7 @@
* "extern" reference to its device into the video.h file,
* and add an entry for it into the table here.
*
* Version: @(#)video_dev.c 1.0.27 2018/10/24
* Version: @(#)video_dev.c 1.0.28 2018/11/20
*
* Authors: Fred N. van Kempen, <decwiz@yahoo.com>
* Miran Grca, <mgrca8@gmail.com>
@@ -108,6 +108,7 @@ static const struct {
#if defined(DEV_BRANCH) && defined(USE_TI)
{ "ti_cf62011", &ti_cf62011_device },
#endif
{ "tvga8900cx", &tvga8900cx_device },
{ "tvga8900d", &tvga8900d_device },
{ "et4000ax", &et4000_isa_device },
{ "tgkorvga", &et4000k_isa_device },

View File

@@ -8,7 +8,7 @@
*
* Define the various platform support functions.
*
* Version: @(#)plat.h 1.0.20 2018/10/24
* Version: @(#)plat.h 1.0.21 2018/11/20
*
* Author: Fred N. van Kempen, <decwiz@yahoo.com>
*
@@ -115,8 +115,11 @@ extern "C" {
/* Define a "vidapi", or, rather, a Renderer API. */
typedef struct {
const char *internal_name;
const char *name;
int local;
int (*init)(int fs);
void (*close)(void);
void (*reset)(int fs);

View File

@@ -8,7 +8,7 @@
*
* Define the various UI functions.
*
* Version: @(#)ui.h 1.0.15 2018/09/29
* Version: @(#)ui.h 1.0.16 2018/11/20
*
* Author: Fred N. van Kempen, <decwiz@yahoo.com>
*
@@ -195,7 +195,8 @@ extern int dlg_file(const wchar_t *filt, const wchar_t *ifn,
extern int vidapi_count(void);
extern int vidapi_available(int api);
extern int vidapi_from_internal_name(const char *name);
extern const char *vidapi_internal_name(int api);
extern const char *vidapi_get_internal_name(int api);
extern const char *vidapi_getname(int api);
extern int vidapi_set(int api);
extern void vidapi_resize(int x, int y);
extern int vidapi_pause(void);

View File

@@ -11,7 +11,7 @@
* This code is called by the UI frontend modules, and, also,
* depends on those same modules for lower-level functions.
*
* Version: @(#)ui_main.c 1.0.20 2018/10/26
* Version: @(#)ui_main.c 1.0.21 2018/11/20
*
* Author: Fred N. van Kempen, <decwiz@yahoo.com>
*
@@ -295,14 +295,16 @@ main_reset_all(void)
menu_set_item(IDM_REMEMBER, window_remember);
/* Add all renderers to the Renderer menu. */
for (i = 0; i < vidapi_count(); i++) {
if (vidapi_available(i)) {
for (i = 0; vidapi_getname(i) != NULL; i++) {
/* Get name of the renderer and add a menu item. */
mbstowcs(temp, vidapi_internal_name(i), sizeof_w(temp));
mbstowcs(temp, vidapi_getname(i), sizeof_w(temp));
menu_add_item(IDM_RENDER, ITEM_RADIO, IDM_RENDER_1 + i, temp);
/* Disable entries that are not available. */
if (! vidapi_available(i))
menu_enable_item(IDM_RENDER_1 + i, 0);
}
}
menu_set_radio_item(IDM_RENDER_1, vidapi_count(), vid_api);
menu_set_radio_item(IDM_RENDER_1, i, vid_api);
menu_set_radio_item(IDM_SCALE_1, 4, scale);

View File

@@ -8,7 +8,7 @@
*
* Handle the various video renderer modules.
*
* Version: @(#)ui_vidapi.c 1.0.3 2018/09/26
* Version: @(#)ui_vidapi.c 1.0.4 2018/11/20
*
* Author: Fred N. van Kempen, <decwiz@yahoo.com>
*
@@ -74,16 +74,13 @@ vidapi_available(int api)
int
vidapi_from_internal_name(const char *name)
{
int i = 0;
int i;
if (!strcasecmp(name, "default") ||
!strcasecmp(name, "system")) return(0);
while(plat_vidapis[i] != NULL) {
if (! strcasecmp(plat_vidapis[i]->name, name)) return(i);
i++;
}
for (i = 0; plat_vidapis[i] != NULL; i++)
if (! strcasecmp(plat_vidapis[i]->internal_name, name)) return(i);
/* Default value. */
return(0);
@@ -92,10 +89,23 @@ vidapi_from_internal_name(const char *name)
/* Return the VIDAPI name for the given number. */
const char *
vidapi_internal_name(int api)
vidapi_get_internal_name(int api)
{
const char *name = "default";
if (plat_vidapis[api] != NULL)
return(plat_vidapis[api]->internal_name);
return(name);
}
/* Return the VIDAPI dpslay name for the given number. */
const char *
vidapi_getname(int api)
{
const char *name = NULL;
if (plat_vidapis[api] != NULL)
return(plat_vidapis[api]->name);

View File

@@ -10,7 +10,7 @@
*
* TODO: Implement screenshots, and Audio Redirection.
*
* Version: @(#)vnc.c 1.0.7 2018/10/05
* Version: @(#)vnc.c 1.0.8 2018/11/20
*
* Author: Fred N. van Kempen, <decwiz@yahoo.com>
* Based on raw code by RichardG, <richardg867@gmail.com>
@@ -427,13 +427,17 @@ vnc_available(void)
void *handle;
handle = dynld_module(PATH_VNC_DLL, NULL);
if (handle != NULL) return(1);
if (handle != NULL) {
dynld_close(handle);
return(1);
}
return(0);
}
const vidapi_t vnc_vidapi = {
"vnc",
"VNC",
0,
vnc_init,

View File

@@ -8,7 +8,7 @@
*
* Platform main support module for Windows.
*
* Version: @(#)win.c 1.0.24 2018/10/24
* Version: @(#)win.c 1.0.25 2018/11/20
*
* Authors: Fred N. van Kempen, <decwiz@yahoo.com>
* Miran Grca, <mgrca8@gmail.com>
@@ -100,9 +100,11 @@ const vidapi_t *plat_vidapis[] = {
#ifdef USE_SDL
&sdl_vidapi,
#endif
#ifdef USE_VNC
&vnc_vidapi,
#endif
#ifdef USE_RDP
&rdp_vidapi,
#endif

View File

@@ -8,7 +8,7 @@
*
* Rendering module for Microsoft Direct2D.
*
* Version: @(#)win_d2d.cpp 1.0.2 2018/10/05
* Version: @(#)win_d2d.cpp 1.0.3 2018/11/20
*
* Authors: Fred N. van Kempen, <decwiz@yahoo.com>
* David Hrdlicka, <hrdlickadavid@outlook.com>
@@ -57,18 +57,15 @@
#include "win_d2d.h"
#ifdef USE_D2D
# if USE_D2D == 2
#if USE_D2D == 2
# define PATH_D2D_DLL "d2d1.dll"
# define DLLFUNC(x) D2D1_ ## x
/* Pointers to the real functions. */
static bool (*D2D1_CreateFactory)(
D2D1_FACTORY_TYPE factoryType,
static bool (*D2D1_CreateFactory)(D2D1_FACTORY_TYPE facType,
REFIID riid,
CONST D2D1_FACTORY_OPTIONS *pFactoryOptions,
CONST D2D1_FACTORY_OPTIONS *pFacOptions,
void **ppIFactory);
static const dllimp_t d2d_imports[] = {
@@ -77,9 +74,8 @@ static const dllimp_t d2d_imports[] = {
};
static void *d2d_handle = NULL;
# else
#else
# define DLLFUNC(x) D2D1 ## x
# endif
#endif
@@ -209,18 +205,15 @@ d2d_blit(int x, int y, int y1, int y2, int w, int h)
hr = d2d_hwndRT->CreateCompatibleRenderTarget(
D2D1::SizeF((float)w, (float)h),
&d2d_btmpRT);
if (SUCCEEDED(hr)) {
d2d_width = w;
d2d_height = h;
}
} else {
hr = d2d_hwndRT->Resize(D2D1::SizeU(w, h));
}
if (SUCCEEDED(hr)) {
d2d_width = w;
d2d_height = h;
}
}
}
if ((y1 == y2) || (buffer32 == NULL)) {
video_blit_complete();
@@ -231,31 +224,33 @@ d2d_blit(int x, int y, int y1, int y2, int w, int h)
srcdata = mem_alloc(h * w * 4);
for (yy = y1; yy < y2; yy++) {
if ((y + yy) >= 0 && (y + yy) < buffer32->h) {
#if 0
if (vid_grayscale || invert_display)
video_transform_copy(
(uint32_t *) &(((uint8_t *)srcdata)[yy * w * 4]),
(uint32_t *)&(((uint8_t *)srcdata)[yy * w * 4]),
&(((uint32_t *)buffer32->line[y + yy])[x]),
w);
else
#endif
memcpy(
(uint32_t *) &(((uint8_t *)srcdata)[yy * w * 4]),
(uint32_t *)&(((uint8_t *)srcdata)[yy * w * 4]),
&(((uint32_t *)buffer32->line[y + yy])[x]),
w * 4);
}
}
video_blit_complete();
rectU = D2D1::RectU(0, 0, w, h);
hr = d2d_bitmap->CopyFromMemory(&rectU, srcdata, w * 4);
// In fullscreen mode we first draw offscreen to an intermediate
// BitmapRenderTarget, which then gets rendered to the actual
// HwndRenderTarget in order to implement different scaling modes
// In windowed mode we draw directly to the HwndRenderTarget
/*
* In fullscreen mode we first draw offscreen to an intermediate
* BitmapRenderTarget, which then gets rendered to the actual
* HwndRenderTarget in order to implement different scaling modes.
*
* In windowed mode we draw directly to the HwndRenderTarget.
*/
if (SUCCEEDED(hr)) {
RT = d2d_fs ? (ID2D1RenderTarget *) d2d_btmpRT : (ID2D1RenderTarget *) d2d_hwndRT;
RT = d2d_fs ? (ID2D1RenderTarget *)d2d_btmpRT
: (ID2D1RenderTarget *)d2d_hwndRT;
RT->BeginDraw();
RT->DrawBitmap(d2d_bitmap,
D2D1::RectF(0, (float)y1, (float)w, (float)y2),
@@ -268,15 +263,20 @@ d2d_blit(int x, int y, int y1, int y2, int w, int h)
if (d2d_fs) {
if (SUCCEEDED(hr))
hr = d2d_btmpRT->GetBitmap(&fs_bitmap);
if (SUCCEEDED(hr)) {
d2d_stretch(&fs_w, &fs_h, &fs_x, &fs_y);
d2d_hwndRT->BeginDraw();
d2d_hwndRT->Clear(D2D1::ColorF(D2D1::ColorF::Black));
d2d_hwndRT->DrawBitmap(fs_bitmap,
D2D1::RectF(fs_x, fs_y, fs_x + fs_w, fs_y + fs_h),
1.0f,
D2D1_BITMAP_INTERPOLATION_MODE_LINEAR,
D2D1::RectF(0, 0, (float)w, (float)h));
hr = d2d_hwndRT->EndDraw();
}
}
@@ -309,10 +309,12 @@ d2d_close(void)
d2d_hwndRT->Release();
d2d_hwndRT = NULL;
}
if (d2d_factory) {
d2d_factory->Release();
d2d_factory = NULL;
}
if (d2d_hwnd) {
hwndMain = old_hwndMain;
plat_set_input(hwndMain);
@@ -321,7 +323,7 @@ d2d_close(void)
old_hwndMain = NULL;
}
#if defined(USE_D2D) && USE_D2D == 2
#if USE_D2D == 2
/* Quit and unload the DLL if possible. */
if (d2d_handle != NULL) {
dynld_close(d2d_handle);
@@ -342,7 +344,7 @@ d2d_init(int fs)
cgapal_rebuild();
#if defined(USE_D2D) && USE_D2D == 2
#if USE_D2D == 2
/* Try loading the DLL. */
d2d_handle = dynld_module(PATH_D2D_DLL, d2d_imports);
if (d2d_handle == NULL) {
@@ -436,8 +438,25 @@ d2d_screenshot(const wchar_t *fn)
}
/* See if this module is available or not. */
static int
d2d_available(void)
{
void *handle;
handle = dynld_module(PATH_D2D_DLL, NULL);
if (handle != NULL) {
dynld_close(handle);
return(1);
}
return(0);
}
const vidapi_t d2d_vidapi = {
"D2D",
"d2d",
"Direct 2D",
1,
d2d_init,
d2d_close,
@@ -445,5 +464,5 @@ const vidapi_t d2d_vidapi = {
NULL,
NULL,
d2d_screenshot,
NULL
d2d_available
};

View File

@@ -8,7 +8,7 @@
*
* Rendering module for Microsoft Direct3D 9.
*
* Version: @(#)win_d3d.cpp 1.0.12 2018/10/05
* Version: @(#)win_d3d.cpp 1.0.13 2018/11/20
*
* Authors: Fred N. van Kempen, <decwiz@yahoo.com>
* Miran Grca, <mgrca8@gmail.com>
@@ -623,7 +623,8 @@ d3d_screenshot(const wchar_t *fn)
const vidapi_t d3d_vidapi = {
"D3D",
"d3d",
"DirectDraw 3D",
1,
d3d_init,
d3d_close,

View File

@@ -760,7 +760,8 @@ ddraw_screenshot(const wchar_t *fn)
const vidapi_t ddraw_vidapi = {
"DDraw",
"ddraw",
"DirectDraw 9+",
1,
ddraw_init,
ddraw_close,

View File

@@ -12,7 +12,7 @@
* we will not use that, but, instead, use a new window which
* coverrs the entire desktop.
*
* Version: @(#)win_sdl.c 1.0.6 2018/10/21
* Version: @(#)win_sdl.c 1.0.7 2018/11/20
*
* Authors: Fred N. van Kempen, <decwiz@yahoo.com>
* Michael Dr<44>ing, <michael@drueing.de>
@@ -512,7 +512,8 @@ sdl_available(void)
const vidapi_t sdl_vidapi = {
"SDL",
"sdl",
"SDL2",
1,
sdl_init,
sdl_close,

View File

@@ -8,7 +8,7 @@
*
* Implement the user Interface module.
*
* Version: @(#)win_ui.c 1.0.32 2018/10/25
* Version: @(#)win_ui.c 1.0.33 2018/11/20
*
* Authors: Fred N. van Kempen, <decwiz@yahoo.com>
* Miran Grca, <mgrca8@gmail.com>
@@ -816,7 +816,8 @@ again:
* to the system default one instead.
*/
swprintf(title, sizeof_w(title),
get_string(IDS_ERR_NORENDR), vidapi_internal_name(vid_api));
get_string(IDS_ERR_NORENDR),
vidapi_get_internal_name(vid_api));
if (ui_msgbox(MBX_CONFIG, title) != 0) {
/* Nope, they don't, so just exit. */
return(5);