Merge branch 'master' of https://github.com/86Box/86Box into qt

This commit is contained in:
ts-korhonen
2022-01-20 20:20:12 +02:00
4 changed files with 290 additions and 38 deletions

View File

@@ -9,9 +9,11 @@
#include <86box/dma.h>
#include <86box/pic.h>
#include <86box/device.h>
#include <86box/gameport.h>
#include <86box/nvr.h>
#include <86box/sound.h>
#include <86box/filters.h>
#include <86box/midi.h>
#include <86box/snd_opl.h>
#include <86box/snd_ym7128.h>
@@ -38,6 +40,10 @@ typedef struct adgold_t
int adgold_mma_intpos[2];
pc_timer_t adgold_mma_timer_count;
uint8_t adgold_midi_ctrl, midi_queue[16];
int midi_r, midi_w;
int uart_in, uart_out, sysex;
struct
{
@@ -61,7 +67,9 @@ typedef struct adgold_t
int16_t mma_buffer[2][SOUNDBUFLEN];
int pos;
int gameport_enabled;
int surround_enabled;
} adgold_t;
@@ -134,12 +142,15 @@ void adgold_update_irq_status(adgold_t *adgold)
uint8_t temp = 0xf;
if (!(adgold->adgold_mma_regs[0][8] & 0x10) && (adgold->adgold_mma_status & 0x10)) /*Timer 0*/
temp &= ~2;
temp &= ~2;
if (!(adgold->adgold_mma_regs[0][8] & 0x20) && (adgold->adgold_mma_status & 0x20)) /*Timer 1*/
temp &= ~2;
temp &= ~2;
if (!(adgold->adgold_mma_regs[0][8] & 0x40) && (adgold->adgold_mma_status & 0x40)) /*Timer 2*/
temp &= ~2;
temp &= ~2;
if (!(adgold->adgold_mma_regs[0][0xd] & 0x01) && (adgold->adgold_mma_status & 0x04))
temp &= ~2;
if (!(adgold->adgold_mma_regs[0][0xd] & 0x04) && (adgold->adgold_mma_status & 0x08))
temp &= ~2;
if ((adgold->adgold_mma_status & 0x01) && !(adgold->adgold_mma_regs[0][0xc] & 2))
temp &= ~2;
if ((adgold->adgold_mma_status & 0x02) && !(adgold->adgold_mma_regs[1][0xc] & 2))
@@ -253,7 +264,7 @@ void adgold_write(uint16_t addr, uint8_t val, void *p)
case 0x18: /*Surround*/
adgold->adgold_38x_regs[0x18] = val;
ym7128_write(&adgold->ym7128, val);
break;
break;
default:
adgold->adgold_38x_regs[adgold->adgold_38x_addr] = val;
@@ -380,6 +391,26 @@ void adgold_write(uint16_t addr, uint8_t val, void *p)
case 0xc:
adgold->adgold_mma_intpos[0] = (7 - ((val >> 2) & 7)) * 8;
break;
case 0xd:
adgold->adgold_midi_ctrl = val & 0x3f;
if ((val & 0x0f) == 0x0f) {
adgold->uart_in = 0;
adgold->midi_w = 0;
adgold->midi_r = 0;
adgold->adgold_mma_status &= ~0x0c;
} else if (adgold->adgold_midi_ctrl & 0x05) {
adgold->uart_in = 1;
} else
adgold->uart_in = 0;
adgold_update_irq_status(adgold);
break;
case 0xe:
midi_raw_out_byte(val);
break;
}
adgold->adgold_mma_regs[0][adgold->adgold_mma_addr] = val;
break;
@@ -482,7 +513,7 @@ uint8_t adgold_read(uint16_t addr, void *p)
case 4: case 6:
temp = adgold->adgold_mma_status;
adgold->adgold_mma_status = 0; /*JUKEGOLD expects timer status flags to auto-clear*/
adgold->adgold_mma_status &= ~0xf3; /*JUKEGOLD expects timer status flags to auto-clear*/
adgold_update_irq_status(adgold);
break;
case 5:
@@ -491,12 +522,26 @@ uint8_t adgold_read(uint16_t addr, void *p)
{
case 6: /*Timer 2 low*/
adgold->adgold_mma.timer2_read = adgold->adgold_mma.timer2_count;
adgold->adgold_mma_status |= 0x40;
temp = adgold->adgold_mma.timer2_read & 0xff;
break;
case 7: /*Timer 2 high*/
temp = adgold->adgold_mma.timer2_read >> 8;
break;
case 0xe:
temp = 0;
if (adgold->uart_in) {
temp = adgold->midi_queue[adgold->midi_r];
if (adgold->midi_r != adgold->midi_w) {
adgold->midi_r++;
adgold->midi_r &= 0x0f;
}
adgold->adgold_mma_status &= ~0x04;
adgold_update_irq_status(adgold);
}
break;
default:
temp = adgold->adgold_mma_regs[0][adgold->adgold_mma_addr];
break;
@@ -579,6 +624,19 @@ void adgold_timer_poll(void *p)
adgold_t *adgold = (adgold_t *)p;
timer_advance_u64(&adgold->adgold_mma_timer_count, (uint64_t)((double)TIMER_USEC * 1.88964));
if (adgold->adgold_midi_ctrl & 0x0f) {
if ((adgold->adgold_midi_ctrl & 0x0f) == 0x05) {
adgold->adgold_mma_status |= 0x08;
} else {
if ((adgold->adgold_midi_ctrl & 0x0f) == 0x02)
adgold->adgold_mma_status &= ~0x04;
else if ((adgold->adgold_midi_ctrl & 0x0f) == 0x08)
adgold->adgold_mma_status &= ~0x08;
}
adgold_update_irq_status(adgold);
}
if (adgold->adgold_mma_regs[0][8] & 0x01) /*Timer 0*/
{
adgold->adgold_mma.timer0_count--;
@@ -753,6 +811,47 @@ static void adgold_get_buffer(int32_t *buffer, int len, void *p)
}
static void adgold_input_msg(void *p, uint8_t *msg, uint32_t len)
{
adgold_t *adgold = (adgold_t *)p;
uint8_t i;
if (adgold->sysex)
return;
if (adgold->uart_in) {
adgold->adgold_mma_status |= 0x04;
for (i=0; i < len; i++) {
adgold->midi_queue[adgold->midi_w++] = msg[i];
adgold->midi_w &= 0x0f;
}
adgold_update_irq_status(adgold);
}
}
static int adgold_input_sysex(void *p, uint8_t *buffer, uint32_t len, int abort)
{
adgold_t *adgold = (adgold_t *)p;
uint32_t i;
if (abort) {
adgold->sysex = 0;
return 0;
}
adgold->sysex = 1;
for (i=0;i<len;i++) {
if (adgold->midi_r == adgold->midi_w)
return (len-i);
adgold->midi_queue[adgold->midi_w++] = buffer[i];
adgold->midi_w &= 0x0f;
}
adgold->sysex = 0;
return 0;
}
void *adgold_init(const device_t *info)
{
FILE *f;
@@ -762,6 +861,8 @@ void *adgold_init(const device_t *info)
memset(adgold, 0, sizeof(adgold_t));
adgold->surround_enabled = device_get_config_int("surround");
adgold->gameport_enabled = device_get_config_int("gameport");
opl3_init(&adgold->opl);
if (adgold->surround_enabled)
@@ -805,10 +906,16 @@ void *adgold_init(const device_t *info)
/*388/389 are handled by adlib_init*/
io_sethandler(0x0388, 0x0008, adgold_read, NULL, NULL, adgold_write, NULL, NULL, adgold);
if (adgold->gameport_enabled)
gameport_remap(gameport_add(&gameport_201_device), 0x201);
timer_add(&adgold->adgold_mma_timer_count, adgold_timer_poll, adgold, 1);
sound_add_handler(adgold_get_buffer, adgold);
if (device_get_config_int("receive_input"))
midi_in_handler(1, adgold_input_msg, adgold_input_sysex, adgold);
return adgold;
}
@@ -829,9 +936,15 @@ void adgold_close(void *p)
static const device_config_t adgold_config[] =
{
{
"gameport", "Enable Game port", CONFIG_BINARY, "", 1
},
{
"surround", "Surround module", CONFIG_BINARY, "", 1
},
{
"receive_input", "Receive input (MIDI)", CONFIG_BINARY, "", 1
},
{
"", "", -1
}

View File

@@ -70,6 +70,10 @@ typedef struct {
uint8_t uart_ctrl, uart_status,
uart_res;
uint32_t uart_fifo;
uint8_t midi_queue[64], midi_data;
int midi_r, midi_w;
int uart_in, sysex, valid;
ac97_codec_t * codec;
uint32_t codec_ctrl;
@@ -174,7 +178,6 @@ typedef struct {
static void es1371_fetch(es1371_t *dev, int dac_nr);
static void update_legacy(es1371_t *dev, uint32_t old_legacy_ctrl);
#ifdef ENABLE_AUDIOPCI_LOG
int audiopci_do_log = ENABLE_AUDIOPCI_LOG;
@@ -201,14 +204,19 @@ es1371_update_irqs(es1371_t *dev)
int irq = 0;
if ((dev->int_status & INT_STATUS_DAC1) && (dev->si_cr & SI_P1_INTR_EN))
irq = 1;
irq = 1;
if ((dev->int_status & INT_STATUS_DAC2) && (dev->si_cr & SI_P2_INTR_EN))
irq = 1;
irq = 1;
/* MIDI input is unsupported for now */
if ((dev->int_status & INT_STATUS_UART) && (dev->uart_status & UART_STATUS_TXINT) &&
((dev->uart_ctrl & UART_CTRL_TXINTEN) != 0x20))
irq = 1;
if (dev->int_status & INT_STATUS_UART) {
if (((dev->uart_ctrl & UART_CTRL_TXINTEN) != 0x20) && (dev->uart_status & UART_STATUS_TXINT) && !dev->uart_in) {
audiopci_log("TXINT\n");
irq = 1;
} else if ((dev->uart_ctrl & UART_CTRL_RXINTEN) && (dev->uart_status & UART_STATUS_RXINT) && (dev->uart_in)) {
audiopci_log("RXINT\n");
irq = 1;
}
}
if (irq)
dev->int_status |= INT_STATUS_INTR;
@@ -230,6 +238,11 @@ es1371_reset(void *p)
{
es1371_t *dev = (es1371_t *) p;
dev->uart_in = 0;
dev->midi_r = 0;
dev->midi_w = 0;
dev->valid = 0;
nmi = 0;
/* Interrupt/Chip Select Control Register, Address 00H
@@ -344,7 +357,10 @@ es1371_read_frame_reg(es1371_t *dev, int frame, int page)
/* UART FIFO Register, Address 30H, 34H, 38H, 3CH, Memory Page 1110b, 1111b
Addressable as longword only */
case 0xe: case 0xf:
ret = dev->uart_fifo;
ret = dev->midi_data;
if (dev->valid) {
ret |= 0x100;
}
break;
}
break;
@@ -363,7 +379,10 @@ es1371_read_frame_reg(es1371_t *dev, int frame, int page)
/* UART FIFO Register, Address 30H, 34H, 38H, 3CH, Memory Page 1110b, 1111b
Addressable as longword only */
case 0xe: case 0xf:
ret = dev->uart_fifo;
ret = dev->midi_data;
if (dev->valid) {
ret |= 0x100;
}
break;
}
break;
@@ -377,7 +396,10 @@ es1371_read_frame_reg(es1371_t *dev, int frame, int page)
/* UART FIFO Register, Address 30H, 34H, 38H, 3CH, Memory Page 1110b, 1111b
Addressable as longword only */
case 0xe: case 0xf:
ret = dev->uart_fifo;
ret = dev->midi_data;
if (dev->valid) {
ret |= 0x100;
}
break;
}
break;
@@ -391,12 +413,19 @@ es1371_read_frame_reg(es1371_t *dev, int frame, int page)
/* UART FIFO Register, Address 30H, 34H, 38H, 3CH, Memory Page 1110b, 1111b
Addressable as longword only */
case 0xe: case 0xf:
ret = dev->uart_fifo;
ret = dev->midi_data;
if (dev->valid) {
ret |= 0x100;
}
break;
}
break;
}
if (page == 0x0e || page == 0x0f) {
audiopci_log("Read frame = %02x, page = %02x, uart fifo valid = %02x, temp = %03x\n", frame, page, dev->valid, ret);
}
return ret;
}
@@ -419,7 +448,8 @@ es1371_write_frame_reg(es1371_t *dev, int frame, int page, uint32_t val)
break;
/* UART FIFO Register, Address 30H, 34H, 38H, 3CH, Memory Page 1110b, 1111b
Addressable as longword only */
case 0xe: case 0xf:
case 0xe:
case 0xf:
dev->uart_fifo = (dev->uart_fifo & 0xfffffe00) | (val & 0x000001ff);
break;
}
@@ -440,7 +470,8 @@ es1371_write_frame_reg(es1371_t *dev, int frame, int page, uint32_t val)
break;
/* UART FIFO Register, Address 30H, 34H, 38H, 3CH, Memory Page 1110b, 1111b
Addressable as longword only */
case 0xe: case 0xf:
case 0xe:
case 0xf:
dev->uart_fifo = (dev->uart_fifo & 0xfffffe00) | (val & 0x000001ff);
break;
}
@@ -454,7 +485,8 @@ es1371_write_frame_reg(es1371_t *dev, int frame, int page, uint32_t val)
break;
/* UART FIFO Register, Address 30H, 34H, 38H, 3CH, Memory Page 1110b, 1111b
Addressable as longword only */
case 0xe: case 0xf:
case 0xe:
case 0xf:
dev->uart_fifo = (dev->uart_fifo & 0xfffffe00) | (val & 0x000001ff);
break;
}
@@ -469,12 +501,18 @@ es1371_write_frame_reg(es1371_t *dev, int frame, int page, uint32_t val)
break;
/* UART FIFO Register, Address 30H, 34H, 38H, 3CH, Memory Page 1110b, 1111b
Addressable as longword only */
case 0xe: case 0xf:
case 0xe:
case 0xf:
dev->uart_fifo = (dev->uart_fifo & 0xfffffe00) | (val & 0x000001ff);
break;
}
break;
}
if (page == 0x0e || page == 0x0f) {
audiopci_log("Write frame = %02x, page = %02x, uart fifo = %08x, val = %02x\n", frame, page, dev->uart_fifo, val);
dev->valid = 0;
}
}
@@ -520,6 +558,19 @@ es1371_inb(uint16_t port, void *p)
Addressable as byte only */
case 0x08:
ret = 0x00;
if (dev->uart_in) {
ret = dev->midi_queue[dev->midi_r];
if (dev->midi_r != dev->midi_w) {
dev->midi_r++;
dev->midi_r &= 0x3f;
}
dev->midi_data = ret;
audiopci_log("MIDI input ret = %02x, pos = %i, valid = %i\n", ret, dev->midi_r, dev->valid);
if (!dev->valid)
dev->int_status &= ~INT_STATUS_UART;
dev->uart_status &= ~(UART_STATUS_RXINT | UART_STATUS_RXRDY);
es1371_update_irqs(dev);
}
break;
/* UART Status Register, Address 09H
@@ -661,6 +712,8 @@ es1371_inw(uint16_t port, void *p)
break;
}
audiopci_log("es1371_inw: port=%04x ret=%04x\n", port, ret);
return ret;
}
@@ -783,6 +836,7 @@ es1371_outb(uint16_t port, uint8_t val, void *p)
/* UART Data Register, Address 08H
Addressable as byte only */
case 0x08:
audiopci_log("MIDI data = %02x\n", dev->midi_data);
midi_raw_out_byte(val);
break;
@@ -790,10 +844,22 @@ es1371_outb(uint16_t port, uint8_t val, void *p)
Addressable as byte only */
case 0x09:
dev->uart_ctrl = val & 0xe3;
if ((dev->uart_ctrl & UART_CTRL_TXINTEN) != 0x20)
if ((val & 0x03) == 0x03) { /*Software reset*/
dev->uart_in = 0;
dev->uart_status = 0x00;
dev->midi_r = 0;
dev->midi_w = 0;
dev->valid = 0;
} else if (dev->uart_ctrl & UART_CTRL_RXINTEN) {
dev->uart_in = 1;
audiopci_log("ES1371 UART RX Cntrl = %02x\n", dev->uart_ctrl);
} else if ((dev->uart_ctrl & UART_CTRL_TXINTEN) != 0x20) {
dev->int_status &= ~INT_STATUS_UART;
dev->uart_in = 0;
}
es1371_update_irqs(dev);
audiopci_log("ES1371 UART Cntrl = %02x\n", dev->uart_ctrl);
break;
/* UART Reserved Register, Address 0AH
@@ -1708,19 +1774,32 @@ es1371_poll(void *p)
if (dev->int_ctrl & INT_UART_EN) {
//audiopci_log("UART INT Enabled\n");
if (dev->uart_ctrl & UART_CTRL_RXINTEN) {
/* We currently don't implement MIDI Input.
But if anything sets MIDI Input and Output together we'd have to take account
of the MIDI Output case, and disable IRQ's and RX bits when MIDI Input is
enabled as well but not in the MIDI Output portion */
dev->int_status &= ~INT_STATUS_UART;
dev->uart_status |= (UART_STATUS_TXINT | UART_STATUS_TXRDY);
} else if (!(dev->uart_ctrl & UART_CTRL_RXINTEN) && ((dev->uart_ctrl & UART_CTRL_TXINTEN))) {
/* Or enable the UART IRQ and the respective TX bits only when the MIDI Output is
enabled */
if (((dev->uart_ctrl & (UART_CTRL_RXINTEN | UART_CTRL_TXINTEN)) == UART_CTRL_RXINTEN) && dev->uart_in) {
audiopci_log("RX irq\n");
dev->int_status |= INT_STATUS_UART;
} else if (((dev->uart_ctrl & (UART_CTRL_RXINTEN | UART_CTRL_TXINTEN)) == UART_CTRL_TXINTEN) && !dev->uart_in) {
audiopci_log("TX irq\n");
dev->int_status |= INT_STATUS_UART;
} else if ((dev->uart_ctrl & (UART_CTRL_RXINTEN | UART_CTRL_TXINTEN)) == (UART_CTRL_RXINTEN | UART_CTRL_TXINTEN)) {
dev->int_status &= ~INT_STATUS_UART;
if (dev->uart_in) {
audiopci_log("No Status UART RX\n");
dev->uart_status |= (UART_STATUS_RXINT | UART_STATUS_RXRDY);
dev->uart_status &= ~(UART_STATUS_TXINT | UART_STATUS_TXRDY);
} else {
audiopci_log("No Status UART TX\n");
dev->uart_status &= ~(UART_STATUS_RXINT | UART_STATUS_RXRDY);
dev->uart_status |= (UART_STATUS_TXINT | UART_STATUS_TXRDY);
}
} else {
dev->uart_status |= (UART_STATUS_TXINT | UART_STATUS_TXRDY);
audiopci_log("STAT UART IN = %i\n", dev->uart_in);
if (dev->uart_in) {
dev->uart_status |= (UART_STATUS_RXINT | UART_STATUS_RXRDY);
dev->uart_status &= ~(UART_STATUS_TXINT | UART_STATUS_TXRDY);
} else {
dev->uart_status &= ~(UART_STATUS_RXINT | UART_STATUS_RXRDY);
dev->uart_status |= (UART_STATUS_TXINT | UART_STATUS_TXRDY);
}
}
//audiopci_log("UART control = %02x\n", dev->uart_ctrl & (UART_CTRL_RXINTEN | UART_CTRL_TXINTEN));
@@ -1846,12 +1925,63 @@ generate_es1371_filter(void)
}
static void
es1371_input_msg(void *p, uint8_t *msg, uint32_t len)
{
es1371_t *dev = (es1371_t *)p;
uint8_t i;
audiopci_log("SYSEX on MSG = %i, len = %i, midiw = %i\n", dev->sysex, len, dev->midi_w);
if (dev->sysex)
return;
if (dev->uart_in) {
audiopci_log("RX midi data\n");
dev->uart_status |= (UART_STATUS_RXINT | UART_STATUS_RXRDY);
dev->valid = 1;
for (i=0; i < len; i++) {
dev->midi_queue[dev->midi_w++] = msg[i];
dev->midi_w &= 0x3f;
}
es1371_update_irqs(dev);
}
}
static int
es1371_input_sysex(void *p, uint8_t *buffer, uint32_t len, int abort)
{
es1371_t *dev = (es1371_t *)p;
uint32_t i;
audiopci_log("SYSEX = %i, Abort = %i\n", dev->sysex, abort);
if (abort) {
dev->sysex = 0;
return 0;
}
dev->sysex = 1;
for (i=0;i<len;i++) {
if (dev->midi_r == dev->midi_w)
return (len-i);
dev->midi_queue[dev->midi_w++] = buffer[i];
dev->midi_w &= 0x3f;
}
dev->sysex = 0;
return 0;
}
static void *
es1371_init(const device_t *info)
{
es1371_t *dev = malloc(sizeof(es1371_t));
memset(dev, 0x00, sizeof(es1371_t));
if (device_get_config_int("receive_input"))
midi_in_handler(1, es1371_input_msg, es1371_input_sysex, dev);
sound_add_handler(es1371_get_buffer, dev);
sound_set_cd_audio_filter(es1371_filter_cd_audio, dev);
@@ -1920,7 +2050,11 @@ static const device_config_t es1371_config[] =
}
},
.default_int = AC97_CODEC_CS4297A
}, {
},
{
"receive_input", "Receive input (MIDI)", CONFIG_BINARY, "", 1
},
{
"", "", -1
}
};

View File

@@ -872,6 +872,8 @@ static void opengl_main(void* param)
static void opengl_blit(int x, int y, int w, int h)
{
int row;
if ((x < 0) || (y < 0) || (w <= 0) || (h <= 0) || (w > 2048) || (h > 2048) || (buffer32 == NULL) || (thread == NULL) ||
atomic_flag_test_and_set(&blit_info[write_pos].in_use))
{
@@ -879,7 +881,8 @@ static void opengl_blit(int x, int y, int w, int h)
return;
}
video_copy(blit_info[write_pos].buffer, &(buffer32->line[y][x]), h * ROW_LENGTH * sizeof(uint32_t));
for (row = 0; row < h; ++row)
video_copy(&(((uint8_t *) blit_info[write_pos].buffer)[row * ROW_LENGTH * sizeof(uint32_t)]), &(buffer32->line[y + row][x]), w * sizeof(uint32_t));
if (screenshots)
video_screenshot(blit_info[write_pos].buffer, 0, 0, ROW_LENGTH);

View File

@@ -274,6 +274,7 @@ sdl_blit_ex(int x, int y, int w, int h)
SDL_Rect r_src;
void *pixeldata;
int pitch, ret;
int row;
if (!sdl_enabled || (x < 0) || (y < 0) || (w <= 0) || (h <= 0) || (w > 2048) || (h > 2048) || (buffer32 == NULL) || (sdl_render == NULL) || (sdl_tex == NULL)) {
video_blit_complete();
@@ -284,7 +285,8 @@ sdl_blit_ex(int x, int y, int w, int h)
SDL_LockTexture(sdl_tex, 0, &pixeldata, &pitch);
video_copy(pixeldata, &(buffer32->line[y][x]), h * 2048 * sizeof(uint32_t));
for (row = 0; row < h; ++row)
video_copy(&(((uint8_t *) pixeldata)[row * 2048 * sizeof(uint32_t)]), &(buffer32->line[y + row][x]), w * sizeof(uint32_t));
if (screenshots)
video_screenshot((uint32_t *) pixeldata, 0, 0, 2048);