mirror of
https://github.com/86Box/86Box.git
synced 2026-02-23 18:08:20 -07:00
Merge branch '86Box:master' into master
This commit is contained in:
@@ -25,6 +25,7 @@
|
||||
#include <86box/io.h>
|
||||
#include <86box/isapnp.h>
|
||||
#include <86box/plat_unused.h>
|
||||
#include "cpu.h"
|
||||
|
||||
#define CHECK_CURRENT_LD() \
|
||||
if (!ld) { \
|
||||
@@ -42,6 +43,11 @@ const uint8_t isapnp_init_key[32] = { 0x6A, 0xB5, 0xDA, 0xED, 0xF6, 0xFB
|
||||
0xDF, 0x6F, 0x37, 0x1B, 0x0D, 0x86, 0xC3, 0x61,
|
||||
0xB0, 0x58, 0x2C, 0x16, 0x8B, 0x45, 0xA2, 0xD1,
|
||||
0xE8, 0x74, 0x3A, 0x9D, 0xCE, 0xE7, 0x73, 0x39 };
|
||||
/* Required for the RTL8019AS. */
|
||||
const uint8_t isapnp_init_key2[32] = { 0xDA, 0x6D, 0x36, 0x1B, 0x8D, 0x46, 0x23, 0x91,
|
||||
0x48, 0xA4, 0xD2, 0x69, 0x34, 0x9A, 0x4D, 0x26,
|
||||
0x13, 0x89, 0x44, 0xA2, 0x51, 0x28, 0x94, 0xCA,
|
||||
0x65, 0x32, 0x19, 0x0C, 0x86, 0x43, 0xA1, 0x50 };
|
||||
static const device_t isapnp_device;
|
||||
|
||||
#ifdef ENABLE_ISAPNP_LOG
|
||||
@@ -71,6 +77,7 @@ enum {
|
||||
|
||||
typedef struct _isapnp_device_ {
|
||||
uint8_t number;
|
||||
uint8_t defs[256];
|
||||
uint8_t regs[256];
|
||||
uint8_t mem_upperlimit;
|
||||
uint8_t irq_types;
|
||||
@@ -85,11 +92,15 @@ typedef struct _isapnp_card_ {
|
||||
uint8_t enable;
|
||||
uint8_t state;
|
||||
uint8_t csn;
|
||||
uint8_t csnsav;
|
||||
uint8_t ld;
|
||||
uint8_t id_checksum;
|
||||
uint8_t serial_read;
|
||||
uint8_t serial_read_pair;
|
||||
uint8_t serial_read_pos;
|
||||
uint8_t is_rt;
|
||||
uint8_t normal;
|
||||
uint8_t multiple_lds;
|
||||
uint8_t *rom;
|
||||
uint16_t rom_pos;
|
||||
uint16_t rom_size;
|
||||
@@ -109,6 +120,7 @@ typedef struct _isapnp_card_ {
|
||||
|
||||
typedef struct {
|
||||
uint8_t in_isolation;
|
||||
uint8_t using_key2;
|
||||
uint8_t reg;
|
||||
uint8_t key_pos : 5;
|
||||
uint16_t read_data_addr;
|
||||
@@ -166,7 +178,7 @@ isapnp_device_config_changed(isapnp_card_t *card, isapnp_device_t *ld)
|
||||
}
|
||||
for (uint8_t i = 0; i < 8; i++) {
|
||||
reg_base = 0x60 + (2 * i);
|
||||
if (ld->regs[0x31] & 0x02)
|
||||
if (!(ld->regs[0x30] & 0x01) && (ld->regs[0x31] & 0x02))
|
||||
card->config.io[i].base = 0; /* let us handle I/O range check reads */
|
||||
else
|
||||
card->config.io[i].base = (ld->regs[reg_base] << 8) | ld->regs[reg_base + 1];
|
||||
@@ -174,7 +186,7 @@ isapnp_device_config_changed(isapnp_card_t *card, isapnp_device_t *ld)
|
||||
for (uint8_t i = 0; i < 2; i++) {
|
||||
reg_base = 0x70 + (2 * i);
|
||||
card->config.irq[i].irq = ld->regs[reg_base];
|
||||
card->config.irq[i].level = ld->regs[reg_base + 1] & 0x02;
|
||||
card->config.irq[i].level = !!(ld->regs[reg_base + 1] & 0x02);
|
||||
card->config.irq[i].type = ld->regs[reg_base + 1] & 0x01;
|
||||
}
|
||||
for (uint8_t i = 0; i < 2; i++) {
|
||||
@@ -256,17 +268,29 @@ isapnp_reset_ld_regs(isapnp_device_t *ld)
|
||||
/* Set the default IRQ type bits. */
|
||||
for (uint8_t i = 0; i < 2; i++) {
|
||||
if (ld->irq_types & (0x1 << (4 * i)))
|
||||
ld->regs[0x70 + (2 * i)] = 0x02;
|
||||
ld->regs[0x71 + (2 * i)] = 0x02;
|
||||
else if (ld->irq_types & (0x2 << (4 * i)))
|
||||
ld->regs[0x70 + (2 * i)] = 0x00;
|
||||
ld->regs[0x71 + (2 * i)] = 0x00;
|
||||
else if (ld->irq_types & (0x4 << (4 * i)))
|
||||
ld->regs[0x70 + (2 * i)] = 0x03;
|
||||
ld->regs[0x71 + (2 * i)] = 0x03;
|
||||
else if (ld->irq_types & (0x8 << (4 * i)))
|
||||
ld->regs[0x70 + (2 * i)] = 0x01;
|
||||
ld->regs[0x71 + (2 * i)] = 0x01;
|
||||
}
|
||||
|
||||
/* Reset configuration registers to match the default configuration. */
|
||||
isapnp_reset_ld_config(ld);
|
||||
|
||||
if (ld->defs[0x30] != 0x00)
|
||||
ld->regs[0x30] = ld->defs[0x30];
|
||||
|
||||
if (ld->defs[0x60] != 0x00)
|
||||
ld->regs[0x60] = ld->defs[0x60];
|
||||
|
||||
if (ld->defs[0x61] != 0x00)
|
||||
ld->regs[0x61] = ld->defs[0x61];
|
||||
|
||||
if (ld->defs[0x70] != 0x00)
|
||||
ld->regs[0x70] = ld->defs[0x70];
|
||||
}
|
||||
|
||||
static uint8_t
|
||||
@@ -288,7 +312,7 @@ isapnp_read_common(isapnp_t *dev, isapnp_card_t *card, isapnp_device_t *ld, uint
|
||||
case 0x01: /* Serial Isolation */
|
||||
card = dev->first_card;
|
||||
while (card) {
|
||||
if (card->enable && card->rom && (card->state == PNP_STATE_ISOLATION))
|
||||
if (card->enable && (card->rom != NULL) && (card->state == PNP_STATE_ISOLATION))
|
||||
break;
|
||||
card = card->next;
|
||||
}
|
||||
@@ -374,6 +398,7 @@ vendor_defined:
|
||||
|
||||
default:
|
||||
if (reg >= 0x30) {
|
||||
CHECK_CURRENT_CARD();
|
||||
CHECK_CURRENT_LD();
|
||||
isapnp_log("ISAPnP: Read register %02X from CSN %02X device %02X\n", reg, card->csn, ld->number);
|
||||
ret = ld->regs[reg];
|
||||
@@ -397,7 +422,8 @@ isapnp_read_data(UNUSED(uint16_t addr), void *priv)
|
||||
card = card->next;
|
||||
}
|
||||
|
||||
isapnp_log("ISAPnP: read_data() => ");
|
||||
// isapnp_log("ISAPnP: read_data() => ");
|
||||
isapnp_log("[%04X:%08X] ISAPnP: read_data() => ", CS, cpu_state.pc);
|
||||
return isapnp_read_common(dev, card, dev->current_ld, dev->reg);
|
||||
}
|
||||
|
||||
@@ -432,26 +458,60 @@ isapnp_write_addr(UNUSED(uint16_t addr), uint8_t val, void *priv)
|
||||
|
||||
if (card->state == PNP_STATE_WAIT_FOR_KEY) { /* checking only the first card should be fine */
|
||||
/* Check written value against LFSR key. */
|
||||
if (val == isapnp_init_key[dev->key_pos]) {
|
||||
if ((val == isapnp_init_key[dev->key_pos]) || (val == isapnp_init_key2[dev->key_pos])) {
|
||||
dev->using_key2 = (val == isapnp_init_key2[dev->key_pos]);
|
||||
dev->key_pos++;
|
||||
if (!dev->key_pos) {
|
||||
isapnp_log("ISAPnP: Key unlocked, putting cards to SLEEP\n");
|
||||
while (card) {
|
||||
if (card->enable && (card->enable != ISAPNP_CARD_NO_KEY) && (card->state == PNP_STATE_WAIT_FOR_KEY))
|
||||
int match_rt = (dev->using_key2 && card->is_rt);
|
||||
int match_normal = (!dev->using_key2 && card->normal);
|
||||
if (card->enable && (match_rt || match_normal) &&
|
||||
(card->enable != ISAPNP_CARD_NO_KEY) && (card->state == PNP_STATE_WAIT_FOR_KEY))
|
||||
card->state = PNP_STATE_SLEEP;
|
||||
card = card->next;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
} else
|
||||
dev->key_pos = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
isapnp_ld_io_remove(isapnp_device_t *ld)
|
||||
{
|
||||
uint16_t io_addr;
|
||||
|
||||
for (uint8_t i = 0; i < 8; i++) {
|
||||
if (!ld->io_len[i])
|
||||
continue;
|
||||
|
||||
io_addr = (ld->regs[0x60 + (2 * i)] << 8) | ld->regs[0x61 + (2 * i)];
|
||||
|
||||
io_removehandler(io_addr, ld->io_len[i], isapnp_read_rangecheck, NULL, NULL, NULL, NULL, NULL, ld);
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
isapnp_ld_io_set(isapnp_device_t *ld)
|
||||
{
|
||||
uint16_t io_addr;
|
||||
|
||||
for (uint8_t i = 0; i < 8; i++) {
|
||||
if (!ld->io_len[i])
|
||||
continue;
|
||||
|
||||
io_addr = (ld->regs[0x60 + (2 * i)] << 8) | ld->regs[0x61 + (2 * i)];
|
||||
int ior = !(ld->regs[0x30] & 0x01) && (ld->regs[0x31] & 0x02);
|
||||
|
||||
if (ior)
|
||||
io_sethandler(io_addr, ld->io_len[i], isapnp_read_rangecheck, NULL, NULL, NULL, NULL, NULL, ld);
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
isapnp_write_common(isapnp_t *dev, isapnp_card_t *card, isapnp_device_t *ld, uint8_t reg, uint8_t val)
|
||||
{
|
||||
uint16_t io_addr;
|
||||
uint16_t reset_cards = 0;
|
||||
|
||||
isapnp_log("ISAPnP: write_common(%02X, %02X)\n", reg, val);
|
||||
@@ -493,6 +553,7 @@ isapnp_write_common(isapnp_t *dev, isapnp_card_t *card, isapnp_device_t *ld, uin
|
||||
card->state = PNP_STATE_WAIT_FOR_KEY;
|
||||
card = card->next;
|
||||
}
|
||||
dev->key_pos = 0;
|
||||
}
|
||||
if (val & 0x04) {
|
||||
isapnp_log("ISAPnP: Reset CSN\n");
|
||||
@@ -513,8 +574,22 @@ isapnp_write_common(isapnp_t *dev, isapnp_card_t *card, isapnp_device_t *ld, uin
|
||||
if (card->csn == val) {
|
||||
card->rom_pos = 0;
|
||||
card->id_checksum = isapnp_init_key[0];
|
||||
if (card->state == PNP_STATE_SLEEP)
|
||||
if (card->state == PNP_STATE_SLEEP) {
|
||||
card->state = (val == 0) ? PNP_STATE_ISOLATION : PNP_STATE_CONFIG;
|
||||
|
||||
if (!card->multiple_lds) {
|
||||
ld = card->first_ld;
|
||||
while (ld) {
|
||||
if (ld->number == 0x00) {
|
||||
isapnp_log("ISAPnP: Select CSN %02X device 00\n", card->csn);
|
||||
dev->current_ld_card = card;
|
||||
dev->current_ld = ld;
|
||||
break;
|
||||
}
|
||||
ld = ld->next;
|
||||
}
|
||||
}
|
||||
}
|
||||
} else
|
||||
card->state = PNP_STATE_SLEEP;
|
||||
|
||||
@@ -535,56 +610,47 @@ isapnp_write_common(isapnp_t *dev, isapnp_card_t *card, isapnp_device_t *ld, uin
|
||||
break;
|
||||
|
||||
case 0x07: /* Logical Device Number */
|
||||
CHECK_CURRENT_CARD();
|
||||
if (card->multiple_lds) {
|
||||
CHECK_CURRENT_CARD();
|
||||
|
||||
card->ld = val;
|
||||
ld = card->first_ld;
|
||||
while (ld) {
|
||||
if (ld->number == val) {
|
||||
isapnp_log("ISAPnP: Select CSN %02X device %02X\n", card->csn, val);
|
||||
dev->current_ld_card = card;
|
||||
dev->current_ld = ld;
|
||||
break;
|
||||
card->ld = val;
|
||||
ld = card->first_ld;
|
||||
while (ld) {
|
||||
if (ld->number == val) {
|
||||
isapnp_log("ISAPnP: Select CSN %02X device %02X\n", card->csn, val);
|
||||
dev->current_ld_card = card;
|
||||
dev->current_ld = ld;
|
||||
break;
|
||||
}
|
||||
ld = ld->next;
|
||||
}
|
||||
ld = ld->next;
|
||||
}
|
||||
|
||||
if (!ld) {
|
||||
isapnp_log("ISAPnP: CSN %02X has no device %02X, creating one\n", card->csn, val);
|
||||
dev->current_ld_card = card;
|
||||
dev->current_ld = isapnp_create_ld(card);
|
||||
dev->current_ld->number = val;
|
||||
if (!ld) {
|
||||
isapnp_log("ISAPnP: CSN %02X has no device %02X, creating one\n", card->csn, val);
|
||||
dev->current_ld_card = card;
|
||||
dev->current_ld = isapnp_create_ld(card);
|
||||
dev->current_ld->number = val;
|
||||
}
|
||||
}
|
||||
|
||||
break;
|
||||
|
||||
case 0x30: /* Activate */
|
||||
CHECK_CURRENT_LD();
|
||||
|
||||
isapnp_log("ISAPnP: %sctivate CSN %02X device %02X\n", (val & 0x01) ? "A" : "Dea", card->csn, ld->number);
|
||||
|
||||
ld->regs[reg] = val & 0x01;
|
||||
isapnp_device_config_changed(card, ld);
|
||||
|
||||
break;
|
||||
|
||||
case 0x31: /* I/O Range Check */
|
||||
CHECK_CURRENT_LD();
|
||||
|
||||
for (uint8_t i = 0; i < 8; i++) {
|
||||
if (!ld->io_len[i])
|
||||
continue;
|
||||
isapnp_log("ISAPnP: %sctivate CSN %02X device %02X\n", (ld->regs[0x30] & 0x01) ? "A" : "Dea",
|
||||
card->csn, ld->number);
|
||||
|
||||
io_addr = (ld->regs[0x60 + (2 * i)] << 8) | ld->regs[0x61 + (2 * i)];
|
||||
if (ld->regs[reg] & 0x02)
|
||||
io_removehandler(io_addr, ld->io_len[i], isapnp_read_rangecheck, NULL, NULL, NULL, NULL, NULL, ld);
|
||||
if (val & 0x02)
|
||||
io_sethandler(io_addr, ld->io_len[i], isapnp_read_rangecheck, NULL, NULL, NULL, NULL, NULL, ld);
|
||||
}
|
||||
isapnp_ld_io_remove(ld);
|
||||
|
||||
if (reg == 0x30)
|
||||
ld->regs[reg] = val & 0x01;
|
||||
else
|
||||
ld->regs[reg] = val & 0x03;
|
||||
|
||||
isapnp_ld_io_set(ld);
|
||||
|
||||
ld->regs[reg] = val & 0x03;
|
||||
isapnp_device_config_changed(card, ld);
|
||||
|
||||
break;
|
||||
|
||||
case 0x20 ... 0x2f:
|
||||
@@ -601,6 +667,7 @@ vendor_defined:
|
||||
|
||||
default:
|
||||
if (reg >= 0x40) {
|
||||
CHECK_CURRENT_CARD();
|
||||
CHECK_CURRENT_LD();
|
||||
isapnp_log("ISAPnP: Write %02X to register %02X on CSN %02X device %02X\n", val, reg, card->csn, ld->number);
|
||||
|
||||
@@ -649,7 +716,9 @@ vendor_defined:
|
||||
break;
|
||||
}
|
||||
|
||||
isapnp_ld_io_remove(ld);
|
||||
ld->regs[reg] = val;
|
||||
isapnp_ld_io_set(ld);
|
||||
isapnp_device_config_changed(card, ld);
|
||||
}
|
||||
break;
|
||||
@@ -670,7 +739,8 @@ isapnp_write_data(UNUSED(uint16_t addr), uint8_t val, void *priv)
|
||||
}
|
||||
}
|
||||
|
||||
isapnp_log("ISAPnP: write_data(%02X) => ", val);
|
||||
// isapnp_log("ISAPnP: write_data(%02X) => ", val);
|
||||
isapnp_log("[%04X:%08X] ISAPnP: write_data(%02X) => ", CS, cpu_state.pc, val);
|
||||
isapnp_write_common(dev, card, dev->current_ld, dev->reg, val);
|
||||
}
|
||||
|
||||
@@ -729,11 +799,13 @@ isapnp_add_card(uint8_t *rom, uint16_t rom_size,
|
||||
isapnp_card_t *card = (isapnp_card_t *) calloc(1, sizeof(isapnp_card_t));
|
||||
|
||||
card->enable = 1;
|
||||
card->normal = 1;
|
||||
card->priv = priv;
|
||||
card->config_changed = config_changed;
|
||||
card->csn_changed = csn_changed;
|
||||
card->read_vendor_reg = read_vendor_reg;
|
||||
card->write_vendor_reg = write_vendor_reg;
|
||||
card->multiple_lds = 1;
|
||||
|
||||
if (!dev->first_card) {
|
||||
dev->first_card = card;
|
||||
@@ -1163,6 +1235,63 @@ isapnp_read_reg(void *priv, uint8_t ldn, uint8_t reg)
|
||||
return isapnp_read_common(device_get_priv(&isapnp_device), card, ld, reg);
|
||||
}
|
||||
|
||||
void
|
||||
isapnp_set_rt(void *priv, uint8_t is_rt)
|
||||
{
|
||||
isapnp_card_t *card = (isapnp_card_t *) priv;
|
||||
|
||||
card->is_rt = is_rt;
|
||||
}
|
||||
|
||||
void
|
||||
isapnp_set_normal(void *priv, uint8_t normal)
|
||||
{
|
||||
isapnp_card_t *card = (isapnp_card_t *) priv;
|
||||
|
||||
card->normal = normal;
|
||||
}
|
||||
|
||||
void
|
||||
isapnp_activate(void *priv, uint16_t base, uint8_t irq, int active)
|
||||
{
|
||||
isapnp_card_t *card = (isapnp_card_t *) priv;
|
||||
isapnp_device_t *ld = card->first_ld;
|
||||
|
||||
while (ld) {
|
||||
if (ld->number == 0x00)
|
||||
break;
|
||||
ld = ld->next;
|
||||
}
|
||||
|
||||
if (ld != NULL) {
|
||||
ld->defs[0x30] = active;
|
||||
ld->defs[0x60] = base >> 8;
|
||||
if (!(ld->io_16bit & (1 << ((0x60 >> 1) & 0x07))))
|
||||
ld->defs[0x60] &= 0x03;
|
||||
ld->defs[0x61] = base & 0xff;
|
||||
ld->defs[0x70] = irq;
|
||||
|
||||
isapnp_reset_ld_regs(ld);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
isapnp_set_single_ld(void *priv)
|
||||
{
|
||||
isapnp_card_t *card = (isapnp_card_t *) priv;
|
||||
|
||||
card->multiple_lds = 0;
|
||||
card->ld = 0x00;
|
||||
}
|
||||
|
||||
uint8_t *
|
||||
isapnp_get_csnsav(void *priv)
|
||||
{
|
||||
isapnp_card_t *card = (isapnp_card_t *) priv;
|
||||
|
||||
return &card->csnsav;
|
||||
}
|
||||
|
||||
void
|
||||
isapnp_write_reg(void *priv, uint8_t ldn, uint8_t reg, uint8_t val)
|
||||
{
|
||||
|
||||
@@ -75,7 +75,7 @@ adgold_lowpass_iir(int c, int i, float NewSample)
|
||||
|
||||
/* fc=56Hz */
|
||||
static inline float
|
||||
adgold_pseudo_stereo_iir(float NewSample)
|
||||
adgold_pseudo_stereo_iir(int i, float NewSample)
|
||||
{
|
||||
float ACoef[NCoef + 1] = {
|
||||
0.00001409030866231767,
|
||||
@@ -89,23 +89,23 @@ adgold_pseudo_stereo_iir(float NewSample)
|
||||
0.98738361004063568000
|
||||
};
|
||||
|
||||
static float y[NCoef + 1]; /* output samples */
|
||||
static float x[NCoef + 1]; /* input samples */
|
||||
static float y[2][NCoef + 1]; /* output samples */
|
||||
static float x[2][NCoef + 1]; /* input samples */
|
||||
int n;
|
||||
|
||||
/* shift the old samples */
|
||||
for (n = NCoef; n > 0; n--) {
|
||||
x[n] = x[n - 1];
|
||||
y[n] = y[n - 1];
|
||||
x[i][n] = x[i][n - 1];
|
||||
y[i][n] = y[i][n - 1];
|
||||
}
|
||||
|
||||
/* Calculate the new output */
|
||||
x[0] = NewSample;
|
||||
y[0] = ACoef[0] * x[0];
|
||||
x[i][0] = NewSample;
|
||||
y[i][0] = ACoef[0] * x[i][0];
|
||||
for (n = 1; n <= NCoef; n++)
|
||||
y[0] += ACoef[n] * x[n] - BCoef[n] * y[n];
|
||||
y[i][0] += ACoef[n] * x[i][n] - BCoef[n] * y[i][n];
|
||||
|
||||
return y[0];
|
||||
return y[i][0];
|
||||
}
|
||||
|
||||
/* fc=3.2kHz - probably incorrect */
|
||||
|
||||
@@ -57,19 +57,24 @@ typedef struct isapnp_device_config_t {
|
||||
|
||||
extern const uint8_t isapnp_init_key[32];
|
||||
|
||||
void *isapnp_add_card(uint8_t *rom, uint16_t rom_size,
|
||||
void (*config_changed)(uint8_t ld, isapnp_device_config_t *config, void *priv),
|
||||
void (*csn_changed)(uint8_t csn, void *priv),
|
||||
uint8_t (*read_vendor_reg)(uint8_t ld, uint8_t reg, void *priv),
|
||||
void (*write_vendor_reg)(uint8_t ld, uint8_t reg, uint8_t val, void *priv),
|
||||
void *priv);
|
||||
void isapnp_update_card_rom(void *priv, uint8_t *rom, uint16_t rom_size);
|
||||
void isapnp_enable_card(void *priv, uint8_t enable);
|
||||
void isapnp_set_csn(void *priv, uint8_t csn);
|
||||
uint8_t isapnp_read_reg(void *priv, uint8_t ldn, uint8_t reg);
|
||||
void isapnp_write_reg(void *priv, uint8_t ldn, uint8_t reg, uint8_t val);
|
||||
void isapnp_set_device_defaults(void *priv, uint8_t ldn, const isapnp_device_config_t *config);
|
||||
void isapnp_reset_card(void *priv);
|
||||
void isapnp_reset_device(void *priv, uint8_t ld);
|
||||
extern void *isapnp_add_card(uint8_t *rom, uint16_t rom_size,
|
||||
void (*config_changed)(uint8_t ld, isapnp_device_config_t *config, void *priv),
|
||||
void (*csn_changed)(uint8_t csn, void *priv),
|
||||
uint8_t (*read_vendor_reg)(uint8_t ld, uint8_t reg, void *priv),
|
||||
void (*write_vendor_reg)(uint8_t ld, uint8_t reg, uint8_t val, void *priv),
|
||||
void *priv);
|
||||
extern void isapnp_update_card_rom(void *priv, uint8_t *rom, uint16_t rom_size);
|
||||
extern void isapnp_enable_card(void *priv, uint8_t enable);
|
||||
extern void isapnp_set_csn(void *priv, uint8_t csn);
|
||||
extern uint8_t isapnp_read_reg(void *priv, uint8_t ldn, uint8_t reg);
|
||||
extern void isapnp_write_reg(void *priv, uint8_t ldn, uint8_t reg, uint8_t val);
|
||||
extern void isapnp_set_device_defaults(void *priv, uint8_t ldn, const isapnp_device_config_t *config);
|
||||
extern void isapnp_reset_card(void *priv);
|
||||
extern void isapnp_reset_device(void *priv, uint8_t ld);
|
||||
extern void isapnp_set_rt(void *priv, uint8_t is_rt);
|
||||
extern void isapnp_set_normal(void *priv, uint8_t normal);
|
||||
extern void isapnp_activate(void *priv, uint16_t base, uint8_t irq, int active);
|
||||
extern void isapnp_set_single_ld(void *priv);
|
||||
extern uint8_t *isapnp_get_csnsav(void *priv);
|
||||
|
||||
#endif /*EMU_ISAPNP_H*/
|
||||
|
||||
@@ -1117,6 +1117,9 @@ extern int machine_at_p65up5_cpknd_init(const machine_t *);
|
||||
extern int machine_at_kn97_init(const machine_t *);
|
||||
|
||||
/* i440LX */
|
||||
#ifdef EMU_DEVICE_H
|
||||
extern const device_t lx6_device;
|
||||
#endif
|
||||
extern int machine_at_lx6_init(const machine_t *);
|
||||
extern int machine_at_optiplexgxa_init(const machine_t *);
|
||||
extern int machine_at_spitfire_init(const machine_t *);
|
||||
|
||||
@@ -19,18 +19,18 @@ typedef struct ym7128_t {
|
||||
int c1;
|
||||
int t[9];
|
||||
|
||||
int16_t filter_dat;
|
||||
int16_t prev_l;
|
||||
int16_t prev_r;
|
||||
int16_t filter_dat[2];
|
||||
int16_t prev_l[2];
|
||||
int16_t prev_r[2];
|
||||
|
||||
int16_t delay_buffer[2400];
|
||||
int delay_pos;
|
||||
int16_t delay_buffer[2][2400];
|
||||
int delay_pos[2];
|
||||
|
||||
int16_t last_samp;
|
||||
} ym7128_t;
|
||||
|
||||
void ym7128_init(ym7128_t *ym7128);
|
||||
void ym7128_write(ym7128_t *ym7128, uint8_t val);
|
||||
void ym7128_apply(ym7128_t *ym7128, int16_t *buffer, int len);
|
||||
void ym7128_apply(ym7128_t *ym7128, int16_t *buffer, int i, int len);
|
||||
|
||||
#endif /*SOUND_YM7128_H*/
|
||||
|
||||
@@ -151,17 +151,57 @@ machine_at_kn97_init(const machine_t *model)
|
||||
}
|
||||
|
||||
/* i440LX */
|
||||
static const device_config_t lx6_config[] = {
|
||||
// clang-format off
|
||||
{
|
||||
.name = "bios",
|
||||
.description = "BIOS Version",
|
||||
.type = CONFIG_BIOS,
|
||||
.default_string = "lx6",
|
||||
.default_int = 0,
|
||||
.file_filter = "",
|
||||
.spinner = { 0 },
|
||||
.bios = {
|
||||
{ .name = "Award Modular BIOS v4.51PG - Revision LY", .internal_name = "lx6", .bios_type = BIOS_NORMAL,
|
||||
.files_no = 1, .local = 0, .size = 131072, .files = { "roms/machines/lx6/LX6C_LY.BIN", "" } },
|
||||
{ .name = "Award Modular BIOS v4.51PG - Revision PZ Beta", .internal_name = "lx6_beta", .bios_type = BIOS_NORMAL,
|
||||
.files_no = 1, .local = 0, .size = 131072, .files = { "roms/machines/lx6/LX6C_PZ.B00", "" } },
|
||||
{ .files_no = 0 }
|
||||
},
|
||||
},
|
||||
{ .name = "", .description = "", .type = CONFIG_END }
|
||||
// clang-format on
|
||||
};
|
||||
|
||||
const device_t lx6_device = {
|
||||
.name = "ABIT AB-LX6",
|
||||
.internal_name = "lx6_device",
|
||||
.flags = 0,
|
||||
.local = 0,
|
||||
.init = NULL,
|
||||
.close = NULL,
|
||||
.reset = NULL,
|
||||
.available = NULL,
|
||||
.speed_changed = NULL,
|
||||
.force_redraw = NULL,
|
||||
.config = lx6_config
|
||||
};
|
||||
|
||||
int
|
||||
machine_at_lx6_init(const machine_t *model)
|
||||
{
|
||||
int ret;
|
||||
int ret = 0;
|
||||
const char* fn;
|
||||
|
||||
ret = bios_load_linear("roms/machines/lx6/LX6C_PZ.B00",
|
||||
0x000e0000, 131072, 0);
|
||||
|
||||
if (bios_only || !ret)
|
||||
/* No ROMs available */
|
||||
if (!device_available(model->device))
|
||||
return ret;
|
||||
|
||||
device_context(model->device);
|
||||
fn = device_get_bios_file(machine_get_device(machine), device_get_config_bios("bios"), 0);
|
||||
ret = bios_load_linear(fn, 0x000e0000, 131072, 0);
|
||||
device_context_restore();
|
||||
|
||||
machine_at_common_init_ex(model, 2);
|
||||
|
||||
pci_init(PCI_CONFIG_TYPE_1);
|
||||
|
||||
@@ -216,7 +216,7 @@ machine_at_403tg_init(const machine_t *model)
|
||||
return ret;
|
||||
|
||||
device_context(model->device);
|
||||
int nvr_hack = !strcmp(device_get_config_bios("bios"), "403tg_d");
|
||||
int nvr_hack = !strcmp(device_get_config_bios("bios"), "403tg");
|
||||
fn = device_get_bios_file(machine_get_device(machine), device_get_config_bios("bios"), 0);
|
||||
ret = bios_load_linear(fn, 0x000f0000, 65536, 0);
|
||||
|
||||
|
||||
@@ -17217,7 +17217,7 @@ const machine_t machines[] = {
|
||||
.kbc_p1 = 0x00000cf0,
|
||||
.gpio = 0xffffffff,
|
||||
.gpio_acpi = 0xffffffff,
|
||||
.device = NULL,
|
||||
.device = &lx6_device,
|
||||
.kbd_device = NULL,
|
||||
.fdc_device = NULL,
|
||||
.sio_device = NULL,
|
||||
|
||||
@@ -514,7 +514,7 @@ dp8390_page0_write(dp8390_t *dev, uint32_t off, uint32_t val, UNUSED(unsigned le
|
||||
{
|
||||
uint8_t val2;
|
||||
|
||||
dp8390_log("DP839: Page0 write to register 0x%02x, value=0x%02x\n",
|
||||
dp8390_log("DP8390: Page0 write to register 0x%02x, value=0x%02x\n",
|
||||
off, val);
|
||||
|
||||
switch (off) {
|
||||
|
||||
@@ -65,9 +65,11 @@
|
||||
#include <86box/network.h>
|
||||
#include <86box/net_dp8390.h>
|
||||
#include <86box/net_ne2000.h>
|
||||
#include <86box/nmc93cxx.h>
|
||||
#include <86box/isapnp.h>
|
||||
#include <86box/plat_fallthrough.h>
|
||||
#include <86box/plat_unused.h>
|
||||
#include "cpu.h"
|
||||
|
||||
/* ROM BIOS file paths. */
|
||||
#define ROM_PATH_NE1000 "roms/network/ne1000/ne1000.rom"
|
||||
@@ -85,30 +87,33 @@ typedef struct nic_t {
|
||||
|
||||
const char *name;
|
||||
|
||||
uint8_t pnp_csnsav;
|
||||
uint8_t pci_slot;
|
||||
uint8_t irq_state;
|
||||
uint8_t pad;
|
||||
uint8_t csnsav;
|
||||
|
||||
/* RTL8019AS/RTL8029AS registers */
|
||||
uint8_t _9346cr;
|
||||
uint8_t config0;
|
||||
uint8_t config1;
|
||||
uint8_t config2;
|
||||
uint8_t config3;
|
||||
uint8_t _9346cr;
|
||||
uint8_t res;
|
||||
|
||||
uint8_t pci_regs[PCI_REGSIZE];
|
||||
uint8_t eeprom[128]; /* for RTL8029AS */
|
||||
|
||||
uint8_t maclocal[6]; /* configured MAC (local) address */
|
||||
|
||||
/* POS registers, MCA boards only */
|
||||
uint8_t pos_regs[8];
|
||||
|
||||
uint8_t eeprom_data[128];
|
||||
|
||||
int board;
|
||||
int is_pci;
|
||||
int is_mca;
|
||||
int is_8bit;
|
||||
int base_irq;
|
||||
int irq_level;
|
||||
int has_bios;
|
||||
|
||||
uint32_t base_address;
|
||||
@@ -121,6 +126,9 @@ typedef struct nic_t {
|
||||
rom_t bios_rom;
|
||||
|
||||
void *pnp_card;
|
||||
uint8_t *pnp_csnsav;
|
||||
|
||||
nmc93cxx_eeprom_t *eeprom;
|
||||
} nic_t;
|
||||
|
||||
#ifdef ENABLE_NE2K_LOG
|
||||
@@ -144,7 +152,14 @@ nelog(int lvl, const char *fmt, ...)
|
||||
static void
|
||||
nic_interrupt(void *priv, int set)
|
||||
{
|
||||
nic_t *dev = (nic_t *) priv;
|
||||
nic_t *dev = (nic_t *) priv;
|
||||
int enabled = 1;
|
||||
|
||||
if (!dev->irq_level)
|
||||
set ^= 1;
|
||||
|
||||
if (dev->board == NE2K_RTL8019AS_PNP)
|
||||
enabled = dev->config1 & 0x80;
|
||||
|
||||
if (dev->is_pci) {
|
||||
if (set)
|
||||
@@ -152,13 +167,32 @@ nic_interrupt(void *priv, int set)
|
||||
else
|
||||
pci_clear_irq(dev->pci_slot, PCI_INTA, &dev->irq_state);
|
||||
} else {
|
||||
if (set)
|
||||
picint(1 << dev->base_irq);
|
||||
else
|
||||
if (enabled && (dev->base_irq != 0x02)) {
|
||||
if (set)
|
||||
picint(1 << dev->base_irq);
|
||||
else
|
||||
picintc(1 << dev->base_irq);
|
||||
} else if (dev->base_irq != 0x02)
|
||||
picintc(1 << dev->base_irq);
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
nic_config_reset(void *priv)
|
||||
{
|
||||
nic_t *dev = (nic_t *) priv;
|
||||
|
||||
uint8_t *data = (uint8_t *) nmc93cxx_eeprom_data(dev->eeprom);
|
||||
|
||||
dev->config1 = (data[0x00] & 0x7f) | 0x80;
|
||||
dev->config2 = (data[0x01] & 0xdf);
|
||||
dev->config3 = (data[0x02] & 0xf7);
|
||||
dev->irq_level = 0x02;
|
||||
|
||||
if (dev->pnp_card != NULL)
|
||||
isapnp_set_normal(dev->pnp_card, !!(dev->config3 & 0x80));
|
||||
}
|
||||
|
||||
/* reset - restore state to power-up, cancelling all i/o */
|
||||
static void
|
||||
nic_reset(void *priv)
|
||||
@@ -168,6 +202,11 @@ nic_reset(void *priv)
|
||||
nelog(1, "%s: reset\n", dev->name);
|
||||
|
||||
dp8390_reset(dev->dp8390);
|
||||
|
||||
if (dev->board >= NE2K_RTL8019AS_PNP)
|
||||
nic_config_reset(priv);
|
||||
else
|
||||
dev->irq_level = 0x02;
|
||||
}
|
||||
|
||||
static void
|
||||
@@ -176,6 +215,11 @@ nic_soft_reset(void *priv)
|
||||
nic_t *dev = (nic_t *) priv;
|
||||
|
||||
dp8390_soft_reset(dev->dp8390);
|
||||
|
||||
if (dev->board >= NE2K_RTL8019AS_PNP)
|
||||
nic_config_reset(priv);
|
||||
else
|
||||
dev->irq_level = 0x02;
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -236,6 +280,7 @@ asic_read(nic_t *dev, uint32_t off, unsigned int len)
|
||||
|
||||
/* If all bytes have been written, signal remote-DMA complete */
|
||||
if (dev->dp8390->remote_bytes == 0) {
|
||||
nelog(3, "%s: DMA read: done (%i)\n", dev->name, dev->dp8390->IMR.rdma_inte);
|
||||
dev->dp8390->ISR.rdma_done = 1;
|
||||
if (dev->dp8390->IMR.rdma_inte)
|
||||
nic_interrupt(dev, 1);
|
||||
@@ -262,6 +307,11 @@ asic_write(nic_t *dev, uint32_t off, uint32_t val, unsigned len)
|
||||
dev->name, (unsigned) off, (unsigned) val);
|
||||
|
||||
switch (off) {
|
||||
default: /* this is invalid, but happens under win95 device detection */
|
||||
nelog(3, "%s: ASIC write invalid address %04x, ignoring\n",
|
||||
dev->name, (unsigned) off);
|
||||
break;
|
||||
|
||||
case 0x00: /* Data register - see asic_read for a description */
|
||||
if ((len > 1) && (dev->dp8390->DCR.wdsize == 0)) {
|
||||
nelog(3, "%s: DMA write length %d on byte mode operation\n",
|
||||
@@ -299,11 +349,6 @@ asic_write(nic_t *dev, uint32_t off, uint32_t val, unsigned len)
|
||||
case 0x0f: /* Reset register */
|
||||
/* end of reset pulse */
|
||||
break;
|
||||
|
||||
default: /* this is invalid, but happens under win95 device detection */
|
||||
nelog(3, "%s: ASIC write invalid address %04x, ignoring\n",
|
||||
dev->name, (unsigned) off);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -311,59 +356,159 @@ asic_write(nic_t *dev, uint32_t off, uint32_t val, unsigned len)
|
||||
static uint32_t
|
||||
page3_read(nic_t *dev, uint32_t off, UNUSED(unsigned int len))
|
||||
{
|
||||
uint8_t ret = 0x00;
|
||||
|
||||
if (dev->board >= NE2K_RTL8019AS_PNP)
|
||||
switch (off) {
|
||||
case 0x1: /* 9346CR */
|
||||
return (dev->_9346cr);
|
||||
default:
|
||||
break;
|
||||
|
||||
case 0x3: /* CONFIG0 */
|
||||
return 0x00; /* Cable not BNC */
|
||||
case 0x1: /* 9346CR */
|
||||
ret = (dev->_9346cr & 0xfe);
|
||||
|
||||
if (((ret & 0xc0) == 0x80) && nmc93cxx_eeprom_read(dev->eeprom))
|
||||
ret |= 0x01;
|
||||
break;
|
||||
|
||||
case 0x3: /* CONFIG0 */
|
||||
if (dev->board == NE2K_RTL8019AS_PNP)
|
||||
ret = dev->config0;
|
||||
else
|
||||
ret = 0x00; /* Cable not BNC */
|
||||
break;
|
||||
|
||||
case 0x4: /* CONFIG1 */
|
||||
if (dev->board == NE2K_RTL8019AS_PNP)
|
||||
ret = dev->config1;
|
||||
break;
|
||||
|
||||
case 0x5: /* CONFIG2 */
|
||||
return (dev->config2 & 0xe0);
|
||||
if (dev->board == NE2K_RTL8019AS_PNP)
|
||||
ret = dev->config2;
|
||||
else
|
||||
ret = (dev->config2 & 0xe0);
|
||||
break;
|
||||
|
||||
case 0x6: /* CONFIG3 */
|
||||
return (dev->config3 & 0x46);
|
||||
if (dev->board == NE2K_RTL8019AS_PNP)
|
||||
ret = dev->config3;
|
||||
else
|
||||
ret = (dev->config3 & 0x46);
|
||||
break;
|
||||
|
||||
case 0x7: /* Reserved, Do not write */
|
||||
if (dev->board == NE2K_RTL8019AS_PNP)
|
||||
ret = dev->res;
|
||||
break;
|
||||
|
||||
case 0x8: /* CSNSAV */
|
||||
return ((dev->board == NE2K_RTL8019AS_PNP) ? dev->pnp_csnsav : 0x00);
|
||||
ret = ((dev->board == NE2K_RTL8019AS_PNP) ? *dev->pnp_csnsav : 0x00);
|
||||
break;
|
||||
|
||||
case 0x9: case 0xa:
|
||||
case 0xc:
|
||||
ret = 0xff;
|
||||
break;
|
||||
|
||||
case 0xb: /* INTR */
|
||||
if (dev->board == NE2K_RTL8019AS_PNP) {
|
||||
ret = (pic2.irr & 0x02) ? 0x01 : 0x00;
|
||||
ret |= (pic.irr & 0x08) ? 0x02 : 0x00;
|
||||
ret |= (pic.irr & 0x10) ? 0x04 : 0x00;
|
||||
ret |= (pic.irr & 0x20) ? 0x08 : 0x00;
|
||||
ret |= (pic2.irr & 0x04) ? 0x10 : 0x00;
|
||||
ret |= (pic2.irr & 0x08) ? 0x20 : 0x00;
|
||||
ret |= (pic2.irr & 0x10) ? 0x40 : 0x00;
|
||||
ret |= (pic2.irr & 0x80) ? 0x80 : 0x00;
|
||||
}
|
||||
break;
|
||||
|
||||
case 0xd: /* CONFIG4 */
|
||||
if (dev->board == NE2K_RTL8019AS_PNP) {
|
||||
uint8_t *data = (uint8_t *) nmc93cxx_eeprom_data(dev->eeprom);
|
||||
ret = data[0x03];
|
||||
}
|
||||
break;
|
||||
|
||||
case 0xe: /* 8029ASID0 */
|
||||
if (dev->board == NE2K_RTL8029AS)
|
||||
return 0x29;
|
||||
ret = 0x29;
|
||||
else
|
||||
ret = 0xff;
|
||||
break;
|
||||
|
||||
case 0xf: /* 8029ASID1 */
|
||||
if (dev->board == NE2K_RTL8029AS)
|
||||
return 0x80;
|
||||
break;
|
||||
|
||||
default:
|
||||
ret = 0x80;
|
||||
else
|
||||
ret = 0xff;
|
||||
break;
|
||||
}
|
||||
|
||||
nelog(3, "%s: Page3 read register 0x%02x attempted\n", dev->name, off);
|
||||
return 0x00;
|
||||
nelog(3, "%s: Page3 read register 0x%02x, value=0x%04x\n", dev->name, off, ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
static void
|
||||
page3_write(nic_t *dev, uint32_t off, uint32_t val, UNUSED(unsigned len))
|
||||
{
|
||||
int cfg_write_enable = ((dev->_9346cr & 0xc0) == 0xc0);
|
||||
|
||||
if (dev->board >= NE2K_RTL8019AS_PNP) {
|
||||
nelog(3, "%s: Page2 write to register 0x%02x, len=%u, value=0x%04x\n",
|
||||
nelog(3, "%s: Page3 write to register 0x%02x, len=%u, value=0x%04x\n",
|
||||
dev->name, off, len, val);
|
||||
|
||||
switch (off) {
|
||||
case 0x01: /* 9346CR */
|
||||
dev->_9346cr = (val & 0xfe);
|
||||
if ((val & 0xc0) == 0x80)
|
||||
nmc93cxx_eeprom_write(dev->eeprom, !!(val & 0x08), !!(val & 0x04), !!(val & 0x02));
|
||||
else if ((val & 0xc0) == 0x40) {
|
||||
uint8_t *data = (uint8_t *) nmc93cxx_eeprom_data(dev->eeprom);
|
||||
|
||||
dev->config1 = (data[0x00] & 0x7f) | 0x80;
|
||||
dev->config2 = (data[0x01] & 0xdf);
|
||||
dev->config3 = (data[0x02] & 0xf7);
|
||||
dev->_9346cr = 0x21;
|
||||
|
||||
isapnp_set_normal(dev->pnp_card, !!(dev->config3 & 0x80));
|
||||
}
|
||||
break;
|
||||
|
||||
case 0x03: /* CONFIG0 */
|
||||
if (cfg_write_enable && (dev->board == NE2K_RTL8019AS_PNP))
|
||||
dev->config0 = (dev->config0 & 0x3f) | (val & 0xc0);
|
||||
break;
|
||||
|
||||
case 0x04: /* CONFIG1 */
|
||||
if (cfg_write_enable && (dev->board == NE2K_RTL8019AS_PNP)) {
|
||||
dev->config1 = (dev->config1 & 0x7f) | (val & 0x80);
|
||||
if (val & 0x80)
|
||||
nic_interrupt(dev, 1);
|
||||
}
|
||||
break;
|
||||
|
||||
case 0x05: /* CONFIG2 */
|
||||
dev->config2 = (val & 0xe0);
|
||||
if (cfg_write_enable) {
|
||||
if (dev->board == NE2K_RTL8019AS_PNP)
|
||||
dev->config2 = (dev->config2 & 0x1f) | (val & 0xe0);
|
||||
else
|
||||
dev->config2 = (val & 0xe0);
|
||||
}
|
||||
break;
|
||||
|
||||
case 0x06: /* CONFIG3 */
|
||||
dev->config3 = (val & 0x46);
|
||||
if (cfg_write_enable) {
|
||||
if (dev->board == NE2K_RTL8019AS_PNP)
|
||||
dev->config3 = (dev->config3 & 0xf9) | (val & 0x06);
|
||||
else
|
||||
dev->config3 = (val & 0x46);
|
||||
}
|
||||
break;
|
||||
|
||||
case 0x7: /* Reserved, Do not write */
|
||||
if (dev->board == NE2K_RTL8019AS_PNP)
|
||||
dev->res = val;
|
||||
break;
|
||||
|
||||
case 0x09: /* HLTCLK */
|
||||
@@ -491,6 +636,10 @@ static void nic_ioremove(nic_t *dev, uint16_t addr);
|
||||
static void
|
||||
nic_pnp_config_changed(uint8_t ld, isapnp_device_config_t *config, void *priv)
|
||||
{
|
||||
uint8_t irq_map[16] = { 0x00, 0x00, 0x00, 0x10, 0x20, 0x30, 0x00, 0x00,
|
||||
0x00, 0x00, 0x40, 0x50, 0x60, 0x00, 0x00, 0x70 };
|
||||
uint8_t ios = 0x00;
|
||||
|
||||
if (ld)
|
||||
return;
|
||||
|
||||
@@ -502,10 +651,22 @@ nic_pnp_config_changed(uint8_t ld, isapnp_device_config_t *config, void *priv)
|
||||
}
|
||||
|
||||
dev->base_address = config->io[0].base;
|
||||
dev->base_irq = config->irq[0].irq;
|
||||
|
||||
if (config->activate && (dev->base_address != ISAPNP_IO_DISABLED))
|
||||
dev->base_irq = config->irq[0].irq;
|
||||
dev->irq_level = config->irq[0].level;
|
||||
if ((dev->base_irq >= 0x00) && (dev->base_irq <= 0x0f))
|
||||
dev->config1 = (dev->config1 & 0x8f) | irq_map[dev->base_irq];
|
||||
else
|
||||
dev->config1 = (dev->config1 & 0x8f);
|
||||
|
||||
if (config->activate && (dev->base_address != ISAPNP_IO_DISABLED)) {
|
||||
nic_ioset(dev, dev->base_address);
|
||||
ios |= (dev->base_address & 0x0100) ? 0x00 : 0x04;
|
||||
ios |= (dev->base_address & 0x0080) ? 0x08 : 0x00;
|
||||
ios |= (dev->base_address & 0x0040) ? 0x02 : 0x00;
|
||||
ios |= (dev->base_address & 0x0020) ? 0x01 : 0x00;
|
||||
dev->config1 = (dev->config1 & 0xf0) | ios;
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
@@ -513,35 +674,44 @@ nic_pnp_csn_changed(uint8_t csn, void *priv)
|
||||
{
|
||||
nic_t *dev = (nic_t *) priv;
|
||||
|
||||
dev->pnp_csnsav = csn;
|
||||
*dev->pnp_csnsav = csn;
|
||||
}
|
||||
|
||||
static uint8_t
|
||||
nic_pnp_read_vendor_reg(uint8_t ld, uint8_t reg, void *priv)
|
||||
{
|
||||
if (ld != 0)
|
||||
return 0x00;
|
||||
uint8_t ret = 0x00;
|
||||
|
||||
const nic_t *dev = (nic_t *) priv;
|
||||
|
||||
switch (reg) {
|
||||
case 0xF0:
|
||||
return dev->config0;
|
||||
|
||||
case 0xF2:
|
||||
return dev->config2;
|
||||
|
||||
case 0xF3:
|
||||
return dev->config3;
|
||||
|
||||
case 0xF5:
|
||||
return dev->pnp_csnsav;
|
||||
|
||||
if (ld == 0) switch (reg) {
|
||||
default:
|
||||
break;
|
||||
|
||||
case 0xf0: /* CONFIG0 */
|
||||
ret = dev->config0;
|
||||
break;
|
||||
|
||||
case 0xf1: /* CONFIG1 */
|
||||
ret = dev->config1;
|
||||
break;
|
||||
|
||||
case 0xf2: /* CONFIG2 */
|
||||
ret = dev->config2;
|
||||
break;
|
||||
|
||||
case 0xf3: /* CONFIG3 */
|
||||
ret = dev->config3;
|
||||
break;
|
||||
|
||||
case 0xf5:
|
||||
ret = *dev->pnp_csnsav;
|
||||
break;
|
||||
}
|
||||
|
||||
return 0x00;
|
||||
nelog(3, "[R] Vendor register: %02X (LD = %02X) = %02X\n", reg, ld, ret);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static void
|
||||
@@ -549,10 +719,12 @@ nic_pnp_write_vendor_reg(uint8_t ld, uint8_t reg, uint8_t val, void *priv)
|
||||
{
|
||||
nic_t *dev = (nic_t *) priv;
|
||||
|
||||
nelog(3, "[W] Vendor register: %02X (LD = %02X) = %02X\n", reg, ld, val);
|
||||
|
||||
if ((ld == 0) && (reg == 0xf6) && (val & 0x04)) {
|
||||
uint8_t csn = dev->pnp_csnsav;
|
||||
uint8_t csn = *dev->pnp_csnsav;
|
||||
isapnp_set_csn(dev->pnp_card, 0);
|
||||
dev->pnp_csnsav = csn;
|
||||
*dev->pnp_csnsav = csn;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -913,6 +1085,7 @@ nic_init(const device_t *info)
|
||||
char *rom = NULL;
|
||||
nic_t *dev;
|
||||
int set_oui = 0;
|
||||
int use_nvr = 0;
|
||||
|
||||
dev = calloc(1, sizeof(nic_t));
|
||||
dev->name = info->name;
|
||||
@@ -1144,26 +1317,33 @@ nic_init(const device_t *info)
|
||||
}
|
||||
|
||||
/* Initialize the RTL80x9 EEPROM. */
|
||||
memset(dev->eeprom, 0x00, sizeof(dev->eeprom));
|
||||
memset(dev->eeprom_data, 0x00, sizeof(dev->eeprom_data));
|
||||
|
||||
if (dev->board == NE2K_RTL8029AS) {
|
||||
memcpy(&dev->eeprom[0x02], dev->maclocal, 6);
|
||||
dev->eeprom_data[0x00] = 0x00;
|
||||
dev->eeprom_data[0x01] = 0x00;
|
||||
|
||||
dev->eeprom[0x76] = dev->eeprom[0x7A] = dev->eeprom[0x7E] = (PCI_DEVID & 0xff);
|
||||
dev->eeprom[0x77] = dev->eeprom[0x7B] = dev->eeprom[0x7F] = (PCI_DEVID >> 8);
|
||||
dev->eeprom[0x78] = dev->eeprom[0x7C] = (PCI_VENDID & 0xff);
|
||||
dev->eeprom[0x79] = dev->eeprom[0x7D] = (PCI_VENDID >> 8);
|
||||
memcpy(&dev->eeprom_data[0x02], dev->maclocal, 6);
|
||||
|
||||
dev->eeprom_data[0x76] = dev->eeprom_data[0x7a] = dev->eeprom_data[0x7e] = (PCI_DEVID & 0xff);
|
||||
dev->eeprom_data[0x77] = dev->eeprom_data[0x7b] = dev->eeprom_data[0x7f] = (PCI_DEVID >> 8);
|
||||
dev->eeprom_data[0x78] = dev->eeprom_data[0x7c] = (PCI_VENDID & 0xff);
|
||||
dev->eeprom_data[0x79] = dev->eeprom_data[0x7d] = (PCI_VENDID >> 8);
|
||||
|
||||
use_nvr = 1;
|
||||
} else {
|
||||
const char *pnp_rom_file = NULL;
|
||||
int pnp_rom_len = 0x4a;
|
||||
switch (dev->board) {
|
||||
case NE2K_RTL8019AS_PNP:
|
||||
pnp_rom_file = "roms/network/rtl8019as/RTL8019A.BIN";
|
||||
use_nvr = 1;
|
||||
break;
|
||||
|
||||
case NE2K_DE220P:
|
||||
pnp_rom_file = "roms/network/de220p/dlk2201a.bin";
|
||||
pnp_rom_len = 0x43;
|
||||
pnp_rom_len = 0x43;
|
||||
use_nvr = 1;
|
||||
break;
|
||||
|
||||
default:
|
||||
@@ -1174,8 +1354,8 @@ nic_init(const device_t *info)
|
||||
if (pnp_rom_file) {
|
||||
FILE *fp = rom_fopen(pnp_rom_file, "rb");
|
||||
if (fp) {
|
||||
if (fread(&dev->eeprom[0x12], 1, pnp_rom_len, fp) == pnp_rom_len)
|
||||
pnp_rom = &dev->eeprom[0x12];
|
||||
if (fread(&dev->eeprom_data[0x12], 1, pnp_rom_len, fp) == pnp_rom_len)
|
||||
pnp_rom = &dev->eeprom_data[0x12];
|
||||
fclose(fp);
|
||||
}
|
||||
}
|
||||
@@ -1183,10 +1363,22 @@ nic_init(const device_t *info)
|
||||
switch (info->local) {
|
||||
case NE2K_RTL8019AS_PNP:
|
||||
case NE2K_DE220P:
|
||||
dev->pnp_card = isapnp_add_card(pnp_rom, pnp_rom_len,
|
||||
nic_pnp_config_changed, nic_pnp_csn_changed,
|
||||
nic_pnp_read_vendor_reg, nic_pnp_write_vendor_reg,
|
||||
dev);
|
||||
dev->pnp_card = isapnp_add_card(pnp_rom, pnp_rom_len,
|
||||
nic_pnp_config_changed, nic_pnp_csn_changed,
|
||||
nic_pnp_read_vendor_reg, nic_pnp_write_vendor_reg,
|
||||
dev);
|
||||
dev->pnp_csnsav = isapnp_get_csnsav(dev->pnp_card);
|
||||
dev->config0 = 0x10 /* Cable not BNC */;
|
||||
dev->config1 = 0x80;
|
||||
dev->config2 = 0x00;
|
||||
dev->config3 = 0x80;
|
||||
isapnp_set_rt(dev->pnp_card, 1);
|
||||
|
||||
dev->eeprom_data[0x00] = 0x80;
|
||||
dev->eeprom_data[0x01] = 0x00;
|
||||
dev->eeprom_data[0x02] = 0x81;
|
||||
dev->eeprom_data[0x03] = 0x01;
|
||||
memcpy(&dev->eeprom_data[0x04], dev->maclocal, 6);
|
||||
break;
|
||||
|
||||
default:
|
||||
@@ -1195,6 +1387,50 @@ nic_init(const device_t *info)
|
||||
}
|
||||
}
|
||||
|
||||
if (use_nvr) {
|
||||
nmc93cxx_eeprom_params_t params;
|
||||
char filename[1024] = { 0 };
|
||||
|
||||
params.nwords = 64;
|
||||
params.default_content = (uint16_t *) dev->eeprom_data;
|
||||
params.filename = filename;
|
||||
int inst = device_get_instance();
|
||||
snprintf(filename, sizeof(filename), "nmc93cxx_eeprom_%s_%d.nvr", info->internal_name, inst);
|
||||
dev->eeprom = device_add_inst_params(&nmc93cxx_device, inst, ¶ms);
|
||||
if (dev->eeprom == NULL) {
|
||||
free(dev);
|
||||
return NULL;
|
||||
}
|
||||
if (info->local == NE2K_RTL8019AS_PNP) {
|
||||
uint8_t *data = (uint8_t *) nmc93cxx_eeprom_data(dev->eeprom);
|
||||
|
||||
dev->config1 = (data[0x00] & 0x7f) | 0x80;
|
||||
dev->config2 = (data[0x01] & 0xdf);
|
||||
dev->config3 = (data[0x02] & 0xf7);
|
||||
|
||||
isapnp_set_normal(dev->pnp_card, !!(dev->config3 & 0x80));
|
||||
isapnp_set_single_ld(dev->pnp_card);
|
||||
|
||||
uint8_t irq_map[8] = { 9, 3, 4, 5, 10, 11, 12, 15 };
|
||||
|
||||
dev->base_address = 0x0200;
|
||||
dev->base_address |= (dev->config1 & 0x01) ? 0x0020 : 0x0000;
|
||||
dev->base_address |= (dev->config1 & 0x02) ? 0x0040 : 0x0000;
|
||||
dev->base_address |= (dev->config1 & 0x04) ? 0x0000 : 0x0100;
|
||||
dev->base_address |= (dev->config1 & 0x08) ? 0x0080 : 0x0000;
|
||||
|
||||
dev->base_irq = irq_map[(dev->config1 >> 4) & 0x07];
|
||||
|
||||
if (!(dev->config3 & 0x01))
|
||||
nic_ioset(dev, dev->base_address);
|
||||
|
||||
isapnp_activate(dev->pnp_card, dev->base_address, dev->base_irq, !(dev->config3 & 0x01));
|
||||
}
|
||||
}
|
||||
|
||||
if (dev->pnp_csnsav == NULL)
|
||||
dev->pnp_csnsav = &dev->csnsav;
|
||||
|
||||
if (dev->board != NE2K_ETHERNEXT_MC)
|
||||
/* Reset the board. */
|
||||
nic_reset(dev);
|
||||
@@ -1773,7 +2009,7 @@ const device_t rtl8019as_pnp_device = {
|
||||
.local = NE2K_RTL8019AS_PNP,
|
||||
.init = nic_init,
|
||||
.close = nic_close,
|
||||
.reset = NULL,
|
||||
.reset = nic_config_reset,
|
||||
.available = rtl8019as_available,
|
||||
.speed_changed = NULL,
|
||||
.force_redraw = NULL,
|
||||
@@ -1787,7 +2023,7 @@ const device_t de220p_device = {
|
||||
.local = NE2K_DE220P,
|
||||
.init = nic_init,
|
||||
.close = nic_close,
|
||||
.reset = NULL,
|
||||
.reset = nic_config_reset,
|
||||
.available = de220p_available,
|
||||
.speed_changed = NULL,
|
||||
.force_redraw = NULL,
|
||||
@@ -1801,7 +2037,7 @@ const device_t rtl8029as_device = {
|
||||
.local = NE2K_RTL8029AS,
|
||||
.init = nic_init,
|
||||
.close = nic_close,
|
||||
.reset = NULL,
|
||||
.reset = nic_config_reset,
|
||||
.available = NULL,
|
||||
.speed_changed = NULL,
|
||||
.force_redraw = NULL,
|
||||
|
||||
@@ -542,6 +542,17 @@ main(int argc, char *argv[])
|
||||
#endif
|
||||
QApplication::setAttribute(Qt::AA_UseDesktopOpenGL);
|
||||
|
||||
QSurfaceFormat fmt = QSurfaceFormat::defaultFormat();
|
||||
fmt.setSwapInterval(0);
|
||||
fmt.setProfile(QSurfaceFormat::OpenGLContextProfile::CoreProfile);
|
||||
fmt.setRenderableType(QSurfaceFormat::OpenGL);
|
||||
#ifdef Q_OS_MACOS
|
||||
fmt.setVersion(4, 1);
|
||||
#else
|
||||
fmt.setVersion(3, 2);
|
||||
#endif
|
||||
QSurfaceFormat::setDefaultFormat(fmt);
|
||||
|
||||
QApplication app(argc, argv);
|
||||
QLocale::setDefault(QLocale::C);
|
||||
setlocale(LC_NUMERIC, "C");
|
||||
@@ -573,9 +584,6 @@ main(int argc, char *argv[])
|
||||
|
||||
Q_INIT_RESOURCE(qt_resources);
|
||||
Q_INIT_RESOURCE(qt_translations);
|
||||
QSurfaceFormat fmt = QSurfaceFormat::defaultFormat();
|
||||
fmt.setSwapInterval(0);
|
||||
QSurfaceFormat::setDefaultFormat(fmt);
|
||||
|
||||
#ifdef __APPLE__
|
||||
CocoaEventFilter cocoafilter;
|
||||
|
||||
@@ -75,7 +75,11 @@ extern int video_focus_dim;
|
||||
extern int video_refresh_rate;
|
||||
|
||||
const char* vertex_shader_default_tex_src =
|
||||
#ifdef __APPLE__
|
||||
"#version 150\n"
|
||||
#else
|
||||
"#version 130\n"
|
||||
#endif
|
||||
"\n"
|
||||
"in vec4 VertexCoord;\n"
|
||||
"in vec2 TexCoord;\n"
|
||||
@@ -89,7 +93,11 @@ const char* vertex_shader_default_tex_src =
|
||||
"}\n";
|
||||
|
||||
const char* fragment_shader_default_tex_src =
|
||||
#ifdef __APPLE__
|
||||
"#version 150\n"
|
||||
#else
|
||||
"#version 130\n"
|
||||
#endif
|
||||
"\n"
|
||||
"in vec2 texCoord;\n"
|
||||
"uniform sampler2D Texture;\n"
|
||||
@@ -103,7 +111,11 @@ const char* fragment_shader_default_tex_src =
|
||||
"}\n";
|
||||
|
||||
const char* vertex_shader_default_color_src =
|
||||
#ifdef __APPLE__
|
||||
"#version 150\n"
|
||||
#else
|
||||
"#version 130\n"
|
||||
#endif
|
||||
"\n"
|
||||
"in vec4 VertexCoord;\n"
|
||||
"in vec4 Color;\n"
|
||||
@@ -117,7 +129,11 @@ const char* vertex_shader_default_color_src =
|
||||
"}\n";
|
||||
|
||||
const char* fragment_shader_default_color_src =
|
||||
#ifdef __APPLE__
|
||||
"#version 150\n"
|
||||
#else
|
||||
"#version 130\n"
|
||||
#endif
|
||||
"\n"
|
||||
"in vec4 color;\n"
|
||||
"\n"
|
||||
@@ -814,11 +830,9 @@ OpenGLRenderer::OpenGLRenderer(QWidget *parent)
|
||||
format.setVersion(3, 2);
|
||||
#endif
|
||||
format.setProfile(QSurfaceFormat::OpenGLContextProfile::CoreProfile);
|
||||
|
||||
if (QOpenGLContext::openGLModuleType() == QOpenGLContext::LibGLES)
|
||||
format.setRenderableType(QSurfaceFormat::OpenGLES);
|
||||
|
||||
format.setRenderableType(QSurfaceFormat::OpenGL);
|
||||
format.setSwapInterval(video_vsync ? 1 : 0);
|
||||
format.setAlphaBufferSize(0);
|
||||
|
||||
setFormat(format);
|
||||
|
||||
|
||||
@@ -441,6 +441,7 @@ RendererStack::createRenderer(Renderer renderer)
|
||||
current->setFocusProxy(this);
|
||||
current->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding);
|
||||
current->setStyleSheet("background-color: black");
|
||||
current->setAttribute(Qt::WA_AlwaysStackOnTop);
|
||||
addWidget(current.get());
|
||||
|
||||
this->setStyleSheet("background-color: black");
|
||||
|
||||
@@ -654,6 +654,9 @@ VMManagerSystem::setupVars() {
|
||||
voodoo_name = tr("3Dfx Voodoo 2");
|
||||
break;
|
||||
}
|
||||
|
||||
if (voodoo_config["sli"].toInt() == 1)
|
||||
voodoo_name.append(" (SLI)");
|
||||
}
|
||||
display_table[VMManager::Display::Name::Voodoo] = voodoo_name;
|
||||
|
||||
|
||||
@@ -82,7 +82,8 @@ typedef struct adgold_t {
|
||||
int treble;
|
||||
int bass;
|
||||
|
||||
int16_t opl_buffer[SOUNDBUFLEN * 2];
|
||||
int16_t samp_buffer[SOUNDBUFLEN * 2];
|
||||
int16_t opl_buffer[MUSICBUFLEN * 2];
|
||||
int16_t mma_buffer[2][SOUNDBUFLEN];
|
||||
|
||||
int pos;
|
||||
@@ -90,6 +91,8 @@ typedef struct adgold_t {
|
||||
int gameport_enabled;
|
||||
|
||||
int surround_enabled;
|
||||
|
||||
int finish_dma;
|
||||
} adgold_t;
|
||||
|
||||
static int attenuation[0x40];
|
||||
@@ -173,33 +176,41 @@ adgold_update_irq_status(adgold_t *adgold)
|
||||
temp &= ~2;
|
||||
if ((adgold->adgold_mma_status & 0x02) && !(adgold->adgold_mma_regs[1][0xc] & 2))
|
||||
temp &= ~2;
|
||||
|
||||
adgold->adgold_status = temp;
|
||||
|
||||
if ((adgold->adgold_status ^ 0xf) && !adgold->adgold_irq_status) {
|
||||
if ((adgold->adgold_status ^ 0xf) && !adgold->adgold_irq_status)
|
||||
picint(1 << adgold->irq);
|
||||
}
|
||||
else if (!(adgold->adgold_status ^ 0xf) && adgold->adgold_irq_status)
|
||||
picintc(1 << adgold->irq);
|
||||
|
||||
adgold->adgold_irq_status = adgold->adgold_status ^ 0xf;
|
||||
}
|
||||
|
||||
int
|
||||
void
|
||||
adgold_getsamp_dma(adgold_t *adgold, int channel)
|
||||
{
|
||||
int temp;
|
||||
dma_set_drq(adgold->dma, 1);
|
||||
int dma_dat;
|
||||
|
||||
if ((adgold->adgold_mma_regs[channel][0xc] & 0x60) && (((adgold->adgold_mma_fifo_end[channel] - adgold->adgold_mma_fifo_start[channel]) & 255) >= 127))
|
||||
return 2;
|
||||
adgold->finish_dma = 0;
|
||||
|
||||
temp = dma_channel_read(adgold->dma);
|
||||
if (temp == DMA_NODATA) {
|
||||
return 1;
|
||||
if ((adgold->adgold_mma_regs[channel][0xc] & 0x60) && (((adgold->adgold_mma_fifo_end[channel] - adgold->adgold_mma_fifo_start[channel]) & 255) >= 127)) {
|
||||
adgold->finish_dma = 1;
|
||||
return;
|
||||
}
|
||||
adgold->adgold_mma_fifo[channel][adgold->adgold_mma_fifo_end[channel]] = temp;
|
||||
adgold->adgold_mma_fifo_end[channel] = (adgold->adgold_mma_fifo_end[channel] + 1) & 255;
|
||||
|
||||
dma_set_drq(adgold->dma, 1);
|
||||
dma_dat = dma_channel_read(adgold->dma);
|
||||
if (dma_dat == DMA_NODATA)
|
||||
return;
|
||||
|
||||
adgold->adgold_mma_fifo[channel][adgold->adgold_mma_fifo_end[channel]] = dma_dat;
|
||||
adgold->adgold_mma_fifo_end[channel] = (adgold->adgold_mma_fifo_end[channel] + 1) & 255;
|
||||
if (adgold->adgold_mma_regs[channel][0xc] & 0x60) {
|
||||
temp = dma_channel_read(adgold->dma);
|
||||
adgold->adgold_mma_fifo[channel][adgold->adgold_mma_fifo_end[channel]] = temp;
|
||||
dma_dat = dma_channel_read(adgold->dma);
|
||||
if (dma_dat == DMA_NODATA)
|
||||
return;
|
||||
adgold->adgold_mma_fifo[channel][adgold->adgold_mma_fifo_end[channel]] = dma_dat;
|
||||
adgold->adgold_mma_fifo_end[channel] = (adgold->adgold_mma_fifo_end[channel] + 1) & 255;
|
||||
}
|
||||
if (((adgold->adgold_mma_fifo_end[channel] - adgold->adgold_mma_fifo_start[channel]) & 255) >= adgold->adgold_mma_intpos[channel]) {
|
||||
@@ -207,8 +218,6 @@ adgold_getsamp_dma(adgold_t *adgold, int channel)
|
||||
adgold_update_irq_status(adgold);
|
||||
dma_set_drq(adgold->dma, 0);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
void
|
||||
@@ -291,7 +300,8 @@ adgold_write(uint16_t addr, uint8_t val, void *priv)
|
||||
|
||||
case 0x18: /*Surround*/
|
||||
adgold->adgold_38x_regs[0x18] = val;
|
||||
ym7128_write(&adgold->ym7128, val);
|
||||
if (adgold->surround_enabled)
|
||||
ym7128_write(&adgold->ym7128, val);
|
||||
break;
|
||||
|
||||
default:
|
||||
@@ -379,16 +389,10 @@ adgold_write(uint16_t addr, uint8_t val, void *priv)
|
||||
adgold->adgold_mma.voice_count[1] = adgold->adgold_mma.voice_latch[1];
|
||||
|
||||
while (((adgold->adgold_mma_fifo_end[0] - adgold->adgold_mma_fifo_start[0]) & 255) < 128) {
|
||||
if (adgold_getsamp_dma(adgold, 0)) {
|
||||
adgold->adgold_mma_fifo_end[0] = 0;
|
||||
adgold->adgold_mma_fifo_start[0] = 0;
|
||||
adgold_getsamp_dma(adgold, 0);
|
||||
adgold_getsamp_dma(adgold, 1);
|
||||
if (adgold->finish_dma)
|
||||
break;
|
||||
}
|
||||
if (adgold_getsamp_dma(adgold, 1)) {
|
||||
adgold->adgold_mma_fifo_end[1] = 0;
|
||||
adgold->adgold_mma_fifo_start[1] = 0;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (((adgold->adgold_mma_fifo_end[0] - adgold->adgold_mma_fifo_start[0]) & 255) >= adgold->adgold_mma_intpos[0]) {
|
||||
adgold->adgold_mma_status &= ~0x01;
|
||||
@@ -402,11 +406,9 @@ adgold_write(uint16_t addr, uint8_t val, void *priv)
|
||||
}
|
||||
} else {
|
||||
while (((adgold->adgold_mma_fifo_end[0] - adgold->adgold_mma_fifo_start[0]) & 255) < 128) {
|
||||
if (adgold_getsamp_dma(adgold, 0)) {
|
||||
adgold->adgold_mma_fifo_end[0] = 0;
|
||||
adgold->adgold_mma_fifo_start[0] = 0;
|
||||
adgold_getsamp_dma(adgold, 0);
|
||||
if (adgold->finish_dma)
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (((adgold->adgold_mma_fifo_end[0] - adgold->adgold_mma_fifo_start[0]) & 255) >= adgold->adgold_mma_intpos[0]) {
|
||||
adgold->adgold_mma_status &= ~0x01;
|
||||
@@ -516,11 +518,9 @@ adgold_write(uint16_t addr, uint8_t val, void *priv)
|
||||
|
||||
if (adgold->adgold_mma_regs[1][0xc] & 1) {
|
||||
while (((adgold->adgold_mma_fifo_end[1] - adgold->adgold_mma_fifo_start[1]) & 255) < 128) {
|
||||
if (adgold_getsamp_dma(adgold, 1)) {
|
||||
adgold->adgold_mma_fifo_end[1] = 0;
|
||||
adgold->adgold_mma_fifo_start[1] = 0;
|
||||
adgold_getsamp_dma(adgold, 1);
|
||||
if (adgold->finish_dma)
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -598,7 +598,6 @@ adgold_read(uint16_t addr, void *priv)
|
||||
temp = adgold->adgold_mma_status;
|
||||
adgold->adgold_mma_status &= ~0xf3; /*JUKEGOLD expects timer status flags to auto-clear*/
|
||||
adgold_update_irq_status(adgold);
|
||||
picintc(1 << adgold->irq);
|
||||
break;
|
||||
case 5:
|
||||
if (adgold->adgold_mma_addr >= 0xf)
|
||||
@@ -693,11 +692,9 @@ adgold_mma_poll(adgold_t *adgold, int channel)
|
||||
}
|
||||
|
||||
if (adgold->adgold_mma_regs[channel][0xc] & 1) {
|
||||
if (adgold_getsamp_dma(adgold, channel)) {
|
||||
adgold->adgold_mma_fifo_end[channel] = 0;
|
||||
adgold->adgold_mma_fifo_start[channel] = 0;
|
||||
adgold_getsamp_dma(adgold, channel);
|
||||
if (adgold->finish_dma)
|
||||
return;
|
||||
}
|
||||
}
|
||||
if (((adgold->adgold_mma_fifo_end[channel] - adgold->adgold_mma_fifo_start[channel]) & 255) < adgold->adgold_mma_intpos[channel] && !(adgold->adgold_mma_status & 0x01)) {
|
||||
adgold->adgold_mma_status |= (1 << channel);
|
||||
@@ -782,34 +779,30 @@ static void
|
||||
adgold_get_buffer(int32_t *buffer, int len, void *priv)
|
||||
{
|
||||
adgold_t *adgold = (adgold_t *) priv;
|
||||
int16_t *adgold_buffer = malloc(sizeof(int16_t) * len * 2);
|
||||
if (adgold_buffer == NULL)
|
||||
fatal("adgold_buffer = NULL");
|
||||
|
||||
int c;
|
||||
|
||||
adgold_update(adgold);
|
||||
|
||||
for (c = 0; c < len * 2; c += 2) {
|
||||
adgold_buffer[c] = ((adgold->mma_buffer[0][c >> 1] * adgold->samp_vol_l) >> 7) / 4;
|
||||
adgold_buffer[c + 1] = ((adgold->mma_buffer[1][c >> 1] * adgold->samp_vol_r) >> 7) / 4;
|
||||
adgold->samp_buffer[c] = ((adgold->mma_buffer[0][c >> 1] * adgold->samp_vol_l) >> 7) / 4;
|
||||
adgold->samp_buffer[c + 1] = ((adgold->mma_buffer[1][c >> 1] * adgold->samp_vol_r) >> 7) / 4;
|
||||
}
|
||||
|
||||
if (adgold->surround_enabled)
|
||||
ym7128_apply(&adgold->ym7128, adgold_buffer, len);
|
||||
ym7128_apply(&adgold->ym7128, adgold->samp_buffer, 0, len);
|
||||
|
||||
switch (adgold->adgold_38x_regs[0x8] & 6) {
|
||||
case 0:
|
||||
for (c = 0; c < len * 2; c++)
|
||||
adgold_buffer[c] = 0;
|
||||
adgold->samp_buffer[c] = 0;
|
||||
break;
|
||||
case 2: /*Left channel only*/
|
||||
for (c = 0; c < len * 2; c += 2)
|
||||
adgold_buffer[c + 1] = adgold_buffer[c];
|
||||
adgold->samp_buffer[c + 1] = adgold->samp_buffer[c];
|
||||
break;
|
||||
case 4: /*Right channel only*/
|
||||
for (c = 0; c < len * 2; c += 2)
|
||||
adgold_buffer[c] = adgold_buffer[c + 1];
|
||||
adgold->samp_buffer[c] = adgold->samp_buffer[c + 1];
|
||||
break;
|
||||
case 6: /*Left and right channels*/
|
||||
break;
|
||||
@@ -821,7 +814,7 @@ adgold_get_buffer(int32_t *buffer, int len, void *priv)
|
||||
switch (adgold->adgold_38x_regs[0x8] & 0x18) {
|
||||
case 0x00: /*Forced mono*/
|
||||
for (c = 0; c < len * 2; c += 2)
|
||||
adgold_buffer[c] = adgold_buffer[c + 1] = ((int32_t) adgold_buffer[c] + (int32_t) adgold_buffer[c + 1]) / 2;
|
||||
adgold->samp_buffer[c] = adgold->samp_buffer[c + 1] = ((int32_t) adgold->samp_buffer[c] + (int32_t) adgold->samp_buffer[c + 1]) / 2;
|
||||
break;
|
||||
case 0x08: /*Linear stereo*/
|
||||
break;
|
||||
@@ -829,17 +822,17 @@ adgold_get_buffer(int32_t *buffer, int len, void *priv)
|
||||
/*Filter left channel, leave right channel unchanged*/
|
||||
/*Filter cutoff is largely a guess*/
|
||||
for (c = 0; c < len * 2; c += 2)
|
||||
adgold_buffer[c] += adgold_pseudo_stereo_iir(adgold_buffer[c]);
|
||||
adgold->samp_buffer[c] += adgold_pseudo_stereo_iir(0, adgold->samp_buffer[c]);
|
||||
break;
|
||||
case 0x18: /*Spatial stereo*/
|
||||
/*Quite probably wrong, I only have the diagram in the TDA8425 datasheet
|
||||
and a very vague understanding of how op-amps work to go on*/
|
||||
for (c = 0; c < len * 2; c += 2) {
|
||||
int16_t l = adgold_buffer[c];
|
||||
int16_t r = adgold_buffer[c + 1];
|
||||
int16_t l = adgold->samp_buffer[c];
|
||||
int16_t r = adgold->samp_buffer[c + 1];
|
||||
|
||||
adgold_buffer[c] += (r / 3) + ((l * 2) / 3);
|
||||
adgold_buffer[c + 1] += (l / 3) + ((r * 2) / 3);
|
||||
adgold->samp_buffer[c] += (r / 3) + ((l * 2) / 3);
|
||||
adgold->samp_buffer[c + 1] += (l / 3) + ((r * 2) / 3);
|
||||
}
|
||||
break;
|
||||
|
||||
@@ -853,7 +846,7 @@ adgold_get_buffer(int32_t *buffer, int len, void *priv)
|
||||
int32_t highpass;
|
||||
|
||||
/*Output is deliberately halved to avoid clipping*/
|
||||
temp = ((int32_t) adgold_buffer[c] * adgold->vol_l) >> 17;
|
||||
temp = ((int32_t) adgold->samp_buffer[c] * adgold->vol_l) >> 17;
|
||||
lowpass = adgold_lowpass_iir(0, 0, temp);
|
||||
highpass = adgold_highpass_iir(0, 0, temp);
|
||||
if (adgold->bass > 6)
|
||||
@@ -870,7 +863,7 @@ adgold_get_buffer(int32_t *buffer, int len, void *priv)
|
||||
temp = 32767;
|
||||
buffer[c] += temp;
|
||||
|
||||
temp = ((int32_t) adgold_buffer[c + 1] * adgold->vol_r) >> 17;
|
||||
temp = ((int32_t) adgold->samp_buffer[c + 1] * adgold->vol_r) >> 17;
|
||||
lowpass = adgold_lowpass_iir(0, 1, temp);
|
||||
highpass = adgold_highpass_iir(0, 1, temp);
|
||||
if (adgold->bass > 6)
|
||||
@@ -889,42 +882,36 @@ adgold_get_buffer(int32_t *buffer, int len, void *priv)
|
||||
}
|
||||
|
||||
adgold->pos = 0;
|
||||
|
||||
free(adgold_buffer);
|
||||
}
|
||||
|
||||
static void
|
||||
adgold_get_music_buffer(int32_t *buffer, int len, void *priv)
|
||||
{
|
||||
adgold_t *adgold = (adgold_t *) priv;
|
||||
int16_t *adgold_buffer = malloc(sizeof(int16_t) * len * 2);
|
||||
if (adgold_buffer == NULL)
|
||||
fatal("adgold_buffer = NULL");
|
||||
|
||||
int c;
|
||||
|
||||
const int32_t *opl_buf = adgold->opl.update(adgold->opl.priv);
|
||||
|
||||
for (c = 0; c < len * 2; c += 2) {
|
||||
adgold_buffer[c] = ((opl_buf[c] * adgold->fm_vol_l) >> 7) / 2;
|
||||
adgold_buffer[c + 1] = ((opl_buf[c + 1] * adgold->fm_vol_r) >> 7) / 2;
|
||||
adgold->opl_buffer[c] = ((opl_buf[c] * adgold->fm_vol_l) >> 7) / 2;
|
||||
adgold->opl_buffer[c + 1] = ((opl_buf[c + 1] * adgold->fm_vol_r) >> 7) / 2;
|
||||
}
|
||||
|
||||
if (adgold->surround_enabled)
|
||||
ym7128_apply(&adgold->ym7128, adgold_buffer, len);
|
||||
ym7128_apply(&adgold->ym7128, adgold->opl_buffer, 1, len);
|
||||
|
||||
switch (adgold->adgold_38x_regs[0x8] & 6) {
|
||||
case 0:
|
||||
for (c = 0; c < len * 2; c++)
|
||||
adgold_buffer[c] = 0;
|
||||
adgold->opl_buffer[c] = 0;
|
||||
break;
|
||||
case 2: /*Left channel only*/
|
||||
for (c = 0; c < len * 2; c += 2)
|
||||
adgold_buffer[c + 1] = adgold_buffer[c];
|
||||
adgold->opl_buffer[c + 1] = adgold->opl_buffer[c];
|
||||
break;
|
||||
case 4: /*Right channel only*/
|
||||
for (c = 0; c < len * 2; c += 2)
|
||||
adgold_buffer[c] = adgold_buffer[c + 1];
|
||||
adgold->opl_buffer[c] = adgold->opl_buffer[c + 1];
|
||||
break;
|
||||
case 6: /*Left and right channels*/
|
||||
break;
|
||||
@@ -936,7 +923,7 @@ adgold_get_music_buffer(int32_t *buffer, int len, void *priv)
|
||||
switch (adgold->adgold_38x_regs[0x8] & 0x18) {
|
||||
case 0x00: /*Forced mono*/
|
||||
for (c = 0; c < len * 2; c += 2)
|
||||
adgold_buffer[c] = adgold_buffer[c + 1] = ((int32_t) adgold_buffer[c] + (int32_t) adgold_buffer[c + 1]) / 2;
|
||||
adgold->opl_buffer[c] = adgold->opl_buffer[c + 1] = ((int32_t) adgold->opl_buffer[c] + (int32_t) adgold->opl_buffer[c + 1]) / 2;
|
||||
break;
|
||||
case 0x08: /*Linear stereo*/
|
||||
break;
|
||||
@@ -944,17 +931,17 @@ adgold_get_music_buffer(int32_t *buffer, int len, void *priv)
|
||||
/*Filter left channel, leave right channel unchanged*/
|
||||
/*Filter cutoff is largely a guess*/
|
||||
for (c = 0; c < len * 2; c += 2)
|
||||
adgold_buffer[c] += adgold_pseudo_stereo_iir(adgold_buffer[c]);
|
||||
adgold->opl_buffer[c] += adgold_pseudo_stereo_iir(1, adgold->opl_buffer[c]);
|
||||
break;
|
||||
case 0x18: /*Spatial stereo*/
|
||||
/*Quite probably wrong, I only have the diagram in the TDA8425 datasheet
|
||||
and a very vague understanding of how op-amps work to go on*/
|
||||
for (c = 0; c < len * 2; c += 2) {
|
||||
int16_t l = adgold_buffer[c];
|
||||
int16_t r = adgold_buffer[c + 1];
|
||||
int16_t l = adgold->opl_buffer[c];
|
||||
int16_t r = adgold->opl_buffer[c + 1];
|
||||
|
||||
adgold_buffer[c] += (r / 3) + ((l * 2) / 3);
|
||||
adgold_buffer[c + 1] += (l / 3) + ((r * 2) / 3);
|
||||
adgold->opl_buffer[c] += (r / 3) + ((l * 2) / 3);
|
||||
adgold->opl_buffer[c + 1] += (l / 3) + ((r * 2) / 3);
|
||||
}
|
||||
break;
|
||||
|
||||
@@ -968,7 +955,7 @@ adgold_get_music_buffer(int32_t *buffer, int len, void *priv)
|
||||
int32_t highpass;
|
||||
|
||||
/*Output is deliberately halved to avoid clipping*/
|
||||
temp = ((int32_t) adgold_buffer[c] * adgold->vol_l) >> 17;
|
||||
temp = ((int32_t) adgold->opl_buffer[c] * adgold->vol_l) >> 17;
|
||||
lowpass = adgold_lowpass_iir(1, 0, temp);
|
||||
highpass = adgold_highpass_iir(1, 0, temp);
|
||||
if (adgold->bass > 6)
|
||||
@@ -985,7 +972,7 @@ adgold_get_music_buffer(int32_t *buffer, int len, void *priv)
|
||||
temp = 32767;
|
||||
buffer[c] += temp;
|
||||
|
||||
temp = ((int32_t) adgold_buffer[c + 1] * adgold->vol_r) >> 17;
|
||||
temp = ((int32_t) adgold->opl_buffer[c + 1] * adgold->vol_r) >> 17;
|
||||
lowpass = adgold_lowpass_iir(1, 1, temp);
|
||||
highpass = adgold_highpass_iir(1, 1, temp);
|
||||
if (adgold->bass > 6)
|
||||
@@ -1004,8 +991,6 @@ adgold_get_music_buffer(int32_t *buffer, int len, void *priv)
|
||||
}
|
||||
|
||||
adgold->opl.reset_buffer(adgold->opl.priv);
|
||||
|
||||
free(adgold_buffer);
|
||||
}
|
||||
|
||||
static void
|
||||
@@ -1073,7 +1058,7 @@ adgold_init(UNUSED(const device_t *info))
|
||||
adgold->surround_enabled = device_get_config_int("surround");
|
||||
adgold->gameport_enabled = device_get_config_int("gameport");
|
||||
|
||||
fm_driver_get(FM_YMF262, &adgold->opl);
|
||||
fm_driver_get(FM_YMF289B, &adgold->opl);
|
||||
if (adgold->surround_enabled)
|
||||
ym7128_init(&adgold->ym7128);
|
||||
|
||||
|
||||
@@ -111,10 +111,10 @@ ym7128_write(ym7128_t *ym7128, uint8_t val)
|
||||
ym7128->a0 = new_a0;
|
||||
}
|
||||
|
||||
#define GET_DELAY_SAMPLE(ym7128, offset) (((ym7128->delay_pos - offset) < 0) ? ym7128->delay_buffer[(ym7128->delay_pos - offset) + 2400] : ym7128->delay_buffer[ym7128->delay_pos - offset])
|
||||
#define GET_DELAY_SAMPLE(ym7128, offset) (((ym7128->delay_pos[i] - offset) < 0) ? ym7128->delay_buffer[i][(ym7128->delay_pos[i] - offset) + 2400] : ym7128->delay_buffer[i][ym7128->delay_pos[i] - offset])
|
||||
|
||||
void
|
||||
ym7128_apply(ym7128_t *ym7128, int16_t *buffer, int len)
|
||||
ym7128_apply(ym7128_t *ym7128, int16_t *buffer, int i, int len)
|
||||
{
|
||||
for (int c = 0; c < len * 2; c += 4) {
|
||||
/*YM7128 samples a mono stream at ~24 kHz, so downsample*/
|
||||
@@ -125,13 +125,13 @@ ym7128_apply(ym7128_t *ym7128, int16_t *buffer, int len)
|
||||
int32_t samp_r = 0;
|
||||
|
||||
filter_temp = GET_DELAY_SAMPLE(ym7128, ym7128->t[0]);
|
||||
filter_out = ((filter_temp * ym7128->c0) >> 11) + ((ym7128->filter_dat * ym7128->c1) >> 11);
|
||||
filter_out = ((filter_temp * ym7128->c0) >> 11) + ((ym7128->filter_dat[i] * ym7128->c1) >> 11);
|
||||
filter_out = (filter_out * ym7128->vc) >> 16;
|
||||
|
||||
samp = (samp * ym7128->vm) >> 16;
|
||||
samp += filter_out;
|
||||
|
||||
ym7128->delay_buffer[ym7128->delay_pos] = samp;
|
||||
ym7128->delay_buffer[i][ym7128->delay_pos[i]] = samp;
|
||||
|
||||
for (uint8_t d = 0; d < 8; d++) {
|
||||
samp_l += (GET_DELAY_SAMPLE(ym7128, ym7128->t[d + 1]) * ym7128->gl[d]) >> 16;
|
||||
@@ -141,17 +141,17 @@ ym7128_apply(ym7128_t *ym7128, int16_t *buffer, int len)
|
||||
samp_l = (samp_l * ym7128->vl * 2) >> 16;
|
||||
samp_r = (samp_r * ym7128->vr * 2) >> 16;
|
||||
|
||||
buffer[c] += (samp_l + (int32_t) ym7128->prev_l) / 2;
|
||||
buffer[c + 1] += (samp_r + (int32_t) ym7128->prev_r) / 2;
|
||||
buffer[c] += (samp_l + (int32_t) ym7128->prev_l[i]) / 2;
|
||||
buffer[c + 1] += (samp_r + (int32_t) ym7128->prev_r[i]) / 2;
|
||||
buffer[c + 2] += samp_l;
|
||||
buffer[c + 3] += samp_r;
|
||||
|
||||
ym7128->delay_pos++;
|
||||
if (ym7128->delay_pos >= 2400)
|
||||
ym7128->delay_pos = 0;
|
||||
ym7128->delay_pos[i]++;
|
||||
if (ym7128->delay_pos[i] >= 2400)
|
||||
ym7128->delay_pos[i] = 0;
|
||||
|
||||
ym7128->filter_dat = filter_temp;
|
||||
ym7128->prev_l = samp_l;
|
||||
ym7128->prev_r = samp_r;
|
||||
ym7128->filter_dat[i] = filter_temp;
|
||||
ym7128->prev_l[i] = samp_l;
|
||||
ym7128->prev_r[i] = samp_r;
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user