mirror of
https://github.com/86Box/86Box.git
synced 2026-02-22 17:45:31 -07:00
Merge master
This commit is contained in:
1
.github/pull_request_template.md
vendored
1
.github/pull_request_template.md
vendored
@@ -5,6 +5,7 @@ _Briefly describe what you are submitting._
|
||||
Checklist
|
||||
=========
|
||||
* [ ] Closes #xxx
|
||||
* [ ] I have tested my changes locally and validated that the functionality works as intended
|
||||
* [ ] I have discussed this with core contributors already
|
||||
* [ ] This pull request requires changes to the ROM set
|
||||
* [ ] I have opened a roms pull request - https://github.com/86Box/roms/pull/changeme/
|
||||
|
||||
4
.github/workflows/codeql_linux.yml
vendored
4
.github/workflows/codeql_linux.yml
vendored
@@ -121,7 +121,7 @@ jobs:
|
||||
fetch-depth: 0 # Shallow clones should be disabled for a better relevancy of analysis
|
||||
|
||||
- name: Install Build Wrapper
|
||||
uses: SonarSource/sonarqube-scan-action/install-build-wrapper@v5
|
||||
uses: SonarSource/sonarqube-scan-action/install-build-wrapper@v6
|
||||
|
||||
- name: Initialize CodeQL
|
||||
uses: github/codeql-action/init@v3
|
||||
@@ -149,7 +149,7 @@ jobs:
|
||||
- name: SonarQube Scan
|
||||
if: matrix.build.preset == 'dev_debug' && matrix.dynarec.new == 'on' && matrix.ui.qt == 'on' && env.SONAR_TOKEN != ''
|
||||
# if: 0
|
||||
uses: SonarSource/sonarqube-scan-action@v5
|
||||
uses: SonarSource/sonarqube-scan-action@v6
|
||||
env:
|
||||
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||
SONAR_TOKEN: ${{ secrets.SONAR_TOKEN }}
|
||||
|
||||
4
.github/workflows/codeql_macos.yml
vendored
4
.github/workflows/codeql_macos.yml
vendored
@@ -109,7 +109,7 @@ jobs:
|
||||
fetch-depth: 0 # Shallow clones should be disabled for a better relevancy of analysis
|
||||
|
||||
- name: Install Build Wrapper
|
||||
uses: SonarSource/sonarqube-scan-action/install-build-wrapper@v5
|
||||
uses: SonarSource/sonarqube-scan-action/install-build-wrapper@v6
|
||||
|
||||
- name: Initialize CodeQL
|
||||
uses: github/codeql-action/init@v3
|
||||
@@ -140,7 +140,7 @@ jobs:
|
||||
- name: SonarQube Scan
|
||||
# if: matrix.build.preset == 'dev_debug' && matrix.dynarec.new == 'on' && matrix.ui.qt == 'on' && env.SONAR_TOKEN != ''
|
||||
if: 0
|
||||
uses: SonarSource/sonarqube-scan-action@v5
|
||||
uses: SonarSource/sonarqube-scan-action@v6
|
||||
env:
|
||||
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||
SONAR_TOKEN: ${{ secrets.SONAR_TOKEN }}
|
||||
|
||||
2
.github/workflows/codeql_windows_msys2.yml
vendored
2
.github/workflows/codeql_windows_msys2.yml
vendored
@@ -169,7 +169,7 @@ jobs:
|
||||
- name: SonarQube Scan
|
||||
# if: matrix.build.preset == 'dev_debug' && matrix.dynarec.new == 'on' && matrix.ui.qt == 'on' && env.SONAR_TOKEN != ''
|
||||
if: 0
|
||||
uses: SonarSource/sonarqube-scan-action@v5
|
||||
uses: SonarSource/sonarqube-scan-action@v6
|
||||
env:
|
||||
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||
SONAR_TOKEN: ${{ secrets.SONAR_TOKEN }}
|
||||
|
||||
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
@@ -1,7 +0,0 @@
|
||||
Mitsumi samples have been edited from Shiru's recordings.
|
||||
|
||||
Original Mitsumi samples can be found here:
|
||||
http://shiru.untergrund.net/files/flopster.zip
|
||||
|
||||
Samples can edited and used separately from the Flopster VSTi under the
|
||||
Creative Commons Attribution (CC-BY) license terms.
|
||||
@@ -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)
|
||||
{
|
||||
|
||||
1522
src/floppy/fdc.c
1522
src/floppy/fdc.c
File diff suppressed because it is too large
Load Diff
151
src/floppy/fdd.c
151
src/floppy/fdd.c
@@ -79,11 +79,34 @@ typedef struct fdd_t {
|
||||
|
||||
fdd_t fdd[FDD_NUM];
|
||||
|
||||
enum {
|
||||
FDD_OP_NONE = 0,
|
||||
FDD_OP_READ,
|
||||
FDD_OP_WRITE,
|
||||
FDD_OP_COMPARE,
|
||||
FDD_OP_READADDR,
|
||||
FDD_OP_FORMAT
|
||||
};
|
||||
|
||||
typedef struct fdd_pending_op_t {
|
||||
int pending;
|
||||
int op;
|
||||
int sector;
|
||||
int track;
|
||||
int side;
|
||||
int density;
|
||||
int sector_size;
|
||||
uint8_t fill;
|
||||
} fdd_pending_op_t;
|
||||
|
||||
static fdd_pending_op_t fdd_pending[FDD_NUM];
|
||||
|
||||
char floppyfns[FDD_NUM][512];
|
||||
char *fdd_image_history[FDD_NUM][FLOPPY_IMAGE_HISTORY];
|
||||
|
||||
pc_timer_t fdd_poll_time[FDD_NUM];
|
||||
pc_timer_t fdd_seek_timer[FDD_NUM];
|
||||
int fdd_seek_in_progress[FDD_NUM] = { 0, 0, 0, 0 };
|
||||
|
||||
static int fdd_notfound = 0;
|
||||
static int driveloaders[FDD_NUM];
|
||||
@@ -293,10 +316,49 @@ fdd_seek_complete_callback(void *priv)
|
||||
{
|
||||
DRIVE *drive = (DRIVE *) priv;
|
||||
|
||||
fdd_seek_in_progress[drive->id] = 0;
|
||||
|
||||
fdd_log("fdd_seek_complete_callback(drive=%d) - TIMER FIRED! seek_in_progress=1\n", drive->id);
|
||||
fdd_log("Notifying FDC of seek completion\n");
|
||||
fdd_do_seek(drive->id, fdd[drive->id].track);
|
||||
fdc_seek_complete_interrupt(fdd_fdc, drive->id);
|
||||
|
||||
int had_pending = fdd_pending[drive->id].pending;
|
||||
if (had_pending) {
|
||||
fdd_pending_op_t *po = &fdd_pending[drive->id];
|
||||
fdd_log("Starting deferred op %d after seek on drive %d (trk=%d, side=%d, sec=%d)\n",
|
||||
po->op, drive->id, po->track, po->side, po->sector);
|
||||
|
||||
switch (po->op) {
|
||||
case FDD_OP_READ:
|
||||
if (drives[drive->id].readsector)
|
||||
drives[drive->id].readsector(drive->id, po->sector, po->track, po->side, po->density, po->sector_size);
|
||||
break;
|
||||
case FDD_OP_WRITE:
|
||||
if (drives[drive->id].writesector)
|
||||
drives[drive->id].writesector(drive->id, po->sector, po->track, po->side, po->density, po->sector_size);
|
||||
break;
|
||||
case FDD_OP_COMPARE:
|
||||
if (drives[drive->id].comparesector)
|
||||
drives[drive->id].comparesector(drive->id, po->sector, po->track, po->side, po->density, po->sector_size);
|
||||
break;
|
||||
case FDD_OP_READADDR:
|
||||
if (drives[drive->id].readaddress)
|
||||
drives[drive->id].readaddress(drive->id, po->side, po->density);
|
||||
break;
|
||||
case FDD_OP_FORMAT:
|
||||
if (drives[drive->id].format)
|
||||
drives[drive->id].format(drive->id, po->side, po->density, po->fill);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
po->pending = 0;
|
||||
po->op = FDD_OP_NONE;
|
||||
}
|
||||
|
||||
if (!had_pending)
|
||||
fdc_seek_complete_interrupt(fdd_fdc, drive->id);
|
||||
}
|
||||
|
||||
void
|
||||
@@ -306,6 +368,11 @@ fdd_seek(int drive, int track_diff)
|
||||
if (!track_diff)
|
||||
return;
|
||||
|
||||
if (fdd_seek_in_progress[drive]) {
|
||||
fdd_log("Seek already in progress for drive %d, ignoring new seek request\n", drive);
|
||||
return;
|
||||
}
|
||||
|
||||
int old_track = fdd[drive].track;
|
||||
|
||||
fdd[drive].track += track_diff;
|
||||
@@ -327,12 +394,14 @@ fdd_seek(int drive, int track_diff)
|
||||
/* Multi-track seek */
|
||||
fdd_audio_play_multi_track_seek(drive, old_track, fdd[drive].track);
|
||||
}
|
||||
|
||||
|
||||
if (old_track + track_diff < 0) {
|
||||
fdd_do_seek(drive, fdd[drive].track);
|
||||
return;
|
||||
}
|
||||
|
||||
fdd_seek_in_progress[drive] = 1;
|
||||
|
||||
if (!fdd_seek_timer[drive].callback) {
|
||||
timer_add(&(fdd_seek_timer[drive]), fdd_seek_complete_callback, &drives[drive], 0);
|
||||
}
|
||||
@@ -629,7 +698,7 @@ fdd_set_motor_enable(int drive, int motor_enable)
|
||||
{
|
||||
fdd_log("fdd_set_motor_enable(%d, %d)\n", drive, motor_enable);
|
||||
fdd_audio_set_motor_enable(drive, motor_enable);
|
||||
|
||||
|
||||
if (motor_enable && !motoron[drive]) {
|
||||
timer_set_delay_u64(&fdd_poll_time[drive], fdd_byteperiod(drive));
|
||||
} else if (!motor_enable && motoron[drive]) {
|
||||
@@ -700,6 +769,22 @@ void
|
||||
fdd_readsector(int drive, int sector, int track, int side, int density, int sector_size)
|
||||
{
|
||||
fdd_log("fdd_readsector(%d, %d, %d, %d, %d, %d)\n", drive, sector, track, side, density, sector_size);
|
||||
|
||||
if (fdd_seek_in_progress[drive]) {
|
||||
fdd_log("Seek in progress on drive %d, deferring READ (trk=%d->%d, side=%d, sec=%d)\n",
|
||||
drive, fdd[drive].track, track, side, sector);
|
||||
fdd_pending[drive] = (fdd_pending_op_t) {
|
||||
.pending = 1,
|
||||
.op = FDD_OP_READ,
|
||||
.sector = sector,
|
||||
.track = track,
|
||||
.side = side,
|
||||
.density = density,
|
||||
.sector_size = sector_size
|
||||
};
|
||||
return;
|
||||
}
|
||||
|
||||
if (drives[drive].readsector)
|
||||
drives[drive].readsector(drive, sector, track, side, density, sector_size);
|
||||
else
|
||||
@@ -710,6 +795,22 @@ void
|
||||
fdd_writesector(int drive, int sector, int track, int side, int density, int sector_size)
|
||||
{
|
||||
fdd_log("fdd_writesector(%d, %d, %d, %d, %d, %d)\n", drive, sector, track, side, density, sector_size);
|
||||
|
||||
if (fdd_seek_in_progress[drive]) {
|
||||
fdd_log("Seek in progress on drive %d, deferring WRITE (trk=%d->%d, side=%d, sec=%d)\n",
|
||||
drive, fdd[drive].track, track, side, sector);
|
||||
fdd_pending[drive] = (fdd_pending_op_t) {
|
||||
.pending = 1,
|
||||
.op = FDD_OP_WRITE,
|
||||
.sector = sector,
|
||||
.track = track,
|
||||
.side = side,
|
||||
.density = density,
|
||||
.sector_size = sector_size
|
||||
};
|
||||
return;
|
||||
}
|
||||
|
||||
if (drives[drive].writesector)
|
||||
drives[drive].writesector(drive, sector, track, side, density, sector_size);
|
||||
else
|
||||
@@ -719,6 +820,21 @@ fdd_writesector(int drive, int sector, int track, int side, int density, int sec
|
||||
void
|
||||
fdd_comparesector(int drive, int sector, int track, int side, int density, int sector_size)
|
||||
{
|
||||
if (fdd_seek_in_progress[drive]) {
|
||||
fdd_log("Seek in progress on drive %d, deferring COMPARE (trk=%d->%d, side=%d, sec=%d)\n",
|
||||
drive, fdd[drive].track, track, side, sector);
|
||||
fdd_pending[drive] = (fdd_pending_op_t) {
|
||||
.pending = 1,
|
||||
.op = FDD_OP_COMPARE,
|
||||
.sector = sector,
|
||||
.track = track,
|
||||
.side = side,
|
||||
.density = density,
|
||||
.sector_size = sector_size
|
||||
};
|
||||
return;
|
||||
}
|
||||
|
||||
if (drives[drive].comparesector)
|
||||
drives[drive].comparesector(drive, sector, track, side, density, sector_size);
|
||||
else
|
||||
@@ -728,6 +844,19 @@ fdd_comparesector(int drive, int sector, int track, int side, int density, int s
|
||||
void
|
||||
fdd_readaddress(int drive, int side, int density)
|
||||
{
|
||||
if (fdd_seek_in_progress[drive]) {
|
||||
fdd_log("Seek in progress on drive %d, deferring READADDRESS (trk=%d, side=%d)\n",
|
||||
drive, fdd[drive].track, side);
|
||||
fdd_pending[drive] = (fdd_pending_op_t) {
|
||||
.pending = 1,
|
||||
.op = FDD_OP_READADDR,
|
||||
.track = fdd[drive].track,
|
||||
.side = side,
|
||||
.density = density
|
||||
};
|
||||
return;
|
||||
}
|
||||
|
||||
if (drives[drive].readaddress)
|
||||
drives[drive].readaddress(drive, side, density);
|
||||
}
|
||||
@@ -735,6 +864,20 @@ fdd_readaddress(int drive, int side, int density)
|
||||
void
|
||||
fdd_format(int drive, int side, int density, uint8_t fill)
|
||||
{
|
||||
if (fdd_seek_in_progress[drive]) {
|
||||
fdd_log("Seek in progress on drive %d, deferring FORMAT (trk=%d, side=%d)\n",
|
||||
drive, fdd[drive].track, side);
|
||||
fdd_pending[drive] = (fdd_pending_op_t) {
|
||||
.pending = 1,
|
||||
.op = FDD_OP_FORMAT,
|
||||
.track = fdd[drive].track,
|
||||
.side = side,
|
||||
.density = density,
|
||||
.fill = fill
|
||||
};
|
||||
return;
|
||||
}
|
||||
|
||||
if (drives[drive].format)
|
||||
drives[drive].format(drive, side, density, fill);
|
||||
else
|
||||
@@ -777,7 +920,7 @@ fdd_init(void)
|
||||
|
||||
if (fdd_sounds_enabled) {
|
||||
fdd_audio_init();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
|
||||
@@ -879,6 +879,7 @@ e22:
|
||||
|
||||
/* Read by qwords, then by dwords, then by words, then by bytes. */
|
||||
i = 0;
|
||||
cpl_override = 1;
|
||||
if (is386) {
|
||||
for (; i < (k & ~7); i += 8) {
|
||||
*((uint64_t *) buf) = readmemql(j);
|
||||
@@ -900,6 +901,7 @@ e22:
|
||||
buf[0] = readmembl(j++);
|
||||
gdbstub_client_respond_hex(client, buf, 1);
|
||||
}
|
||||
cpl_override = 0;
|
||||
break;
|
||||
|
||||
case 'M': /* write memory */
|
||||
@@ -934,6 +936,7 @@ e22:
|
||||
/* Write by qwords, then by dwords, then by words, then by bytes. */
|
||||
p = client->packet;
|
||||
i = 0;
|
||||
cpl_override = 1;
|
||||
if (is386) {
|
||||
for (; i < (k & ~7); i += 8) {
|
||||
writememql(j, *((uint64_t *) p));
|
||||
@@ -955,6 +958,7 @@ e22:
|
||||
writemembl(j++, p[0]);
|
||||
p++;
|
||||
}
|
||||
cpl_override = 0;
|
||||
|
||||
/* Respond positively. */
|
||||
goto ok;
|
||||
|
||||
@@ -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);
|
||||
|
||||
|
||||
@@ -12388,7 +12388,7 @@ const machine_t machines[] = {
|
||||
},
|
||||
/* The BIOS sends KBC command B3 which indicates an AMI (or VIA VT82C42N) KBC. */
|
||||
{
|
||||
.name = "[i430FX] NEC PowerMate V",
|
||||
.name = "[i430FX] NEC PowerMate Vxxx",
|
||||
.internal_name = "powermatev",
|
||||
.type = MACHINE_TYPE_SOCKET5,
|
||||
.chipset = MACHINE_CHIPSET_INTEL_430FX,
|
||||
@@ -12973,7 +12973,7 @@ const machine_t machines[] = {
|
||||
/* Has a SM(S)C FDC37C932 Super I/O chip with on-chip KBC with AMI
|
||||
MegaKey (revision '5') KBC firmware. */
|
||||
{
|
||||
.name = "[i430FX] HP Vectra VL 5 Series 4",
|
||||
.name = "[i430FX] HP Vectra VL 5/xxx Series 4 (Chimay)",
|
||||
.internal_name = "vectra54",
|
||||
.type = MACHINE_TYPE_SOCKET7_3V,
|
||||
.chipset = MACHINE_CHIPSET_INTEL_430FX,
|
||||
@@ -15329,7 +15329,7 @@ const machine_t machines[] = {
|
||||
.snd_device = NULL,
|
||||
.net_device = NULL
|
||||
},
|
||||
/* This has the Phoenix MultiKey KBC firmware on the NSC Suepr I/O chip. */
|
||||
/* This has the Phoenix MultiKey KBC firmware on the NSC Super I/O chip. */
|
||||
{
|
||||
.name = "[i430TX] Packard Bell PB790",
|
||||
.internal_name = "an430tx",
|
||||
@@ -16009,7 +16009,7 @@ const machine_t machines[] = {
|
||||
},
|
||||
/* M1534c kbc */
|
||||
{
|
||||
.name = "[ALi ALADDiN V] Gateway Lucas",
|
||||
.name = "[ALi ALADDiN V] Gateway Lucas (MSI MS-5185)",
|
||||
.internal_name = "gwlucas",
|
||||
.type = MACHINE_TYPE_SOCKETS7,
|
||||
.chipset = MACHINE_CHIPSET_ALI_ALADDIN_V,
|
||||
@@ -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;
|
||||
|
||||
@@ -84,6 +84,7 @@ extern bool cpu_thread_running;
|
||||
#include <QMenuBar>
|
||||
#include <QCheckBox>
|
||||
#include <QActionGroup>
|
||||
#include <QSize>
|
||||
#include <QOpenGLContext>
|
||||
#include <QScreen>
|
||||
#include <QString>
|
||||
@@ -171,8 +172,6 @@ extern "C" void qt_blit(int x, int y, int w, int h, int monitor_index);
|
||||
|
||||
extern MainWindow *main_window;
|
||||
|
||||
bool MainWindow::s_adjustingForce43 = false;
|
||||
|
||||
MainWindow::MainWindow(QWidget *parent)
|
||||
: QMainWindow(parent)
|
||||
, ui(new Ui::MainWindow)
|
||||
@@ -933,11 +932,18 @@ MainWindow::closeEvent(QCloseEvent *event)
|
||||
}
|
||||
}
|
||||
if (window_remember) {
|
||||
window_w = ui->stackedWidget->width();
|
||||
window_h = ui->stackedWidget->height();
|
||||
// If maximized, persist the normal (restorable) geometry
|
||||
const bool wasMax = isMaximized();
|
||||
QRect normal = wasMax ? this->normalGeometry() : this->geometry();
|
||||
// Save WINDOW size (not the content widget’s 4:3 box)
|
||||
const int chromeHeight = geometry().height() - ui->stackedWidget->height();
|
||||
window_w = normal.width();
|
||||
window_h = normal.height() - chromeHeight;
|
||||
if (window_h < 0)
|
||||
window_h = 0;
|
||||
if (!QApplication::platformName().contains("wayland")) {
|
||||
window_x = this->geometry().x();
|
||||
window_y = this->geometry().y();
|
||||
window_x = normal.x();
|
||||
window_y = normal.y();
|
||||
}
|
||||
for (int i = 1; i < MONITORS_NUM; i++) {
|
||||
if (renderers[i]) {
|
||||
@@ -1021,65 +1027,56 @@ void MainWindow::updateShortcuts()
|
||||
seq = QKeySequence::fromString(acc_keys[accID].seq);
|
||||
ui->actionMute_Unmute->setShortcut(seq);
|
||||
}
|
||||
|
||||
void
|
||||
MainWindow::adjustForForce43(const QSize &newWinSize)
|
||||
|
||||
void
|
||||
MainWindow::applyContentLayoutForCurrentState()
|
||||
{
|
||||
// Only act in resizable mode with Force 4:3 enabled and not fullscreen
|
||||
if (!(vid_resize == 1 && force_43 > 0) || video_fullscreen || s_adjustingForce43)
|
||||
return;
|
||||
auto applyFill = [this](const QRect& r){
|
||||
ui->stackedWidget->setGeometry(r);
|
||||
ui->stackedWidget->onResize(r.width(), r.height());
|
||||
if (monitors[0].mon_scrnsz_x != r.width() || monitors[0].mon_scrnsz_y != r.height()) {
|
||||
monitors[0].mon_scrnsz_x = r.width();
|
||||
monitors[0].mon_scrnsz_y = r.height();
|
||||
plat_resize_request(r.width(), r.height(), 0);
|
||||
}
|
||||
};
|
||||
|
||||
s_adjustingForce43 = true;
|
||||
auto apply43 = [this](const QRect& area){
|
||||
int areaW = area.width();
|
||||
int areaH = area.height();
|
||||
if (areaW <= 0 || areaH <= 0) return;
|
||||
|
||||
// Height consumed by menu/status/toolbars
|
||||
int chromeH = menuBar()->height()
|
||||
+ (hide_status_bar ? 0 : statusBar()->height())
|
||||
+ (hide_tool_bar ? 0 : ui->toolBar->height());
|
||||
int targetW = areaW;
|
||||
int targetH = (areaW * 3) / 4;
|
||||
if (targetH > areaH) {
|
||||
targetH = areaH;
|
||||
targetW = (areaH * 4) / 3;
|
||||
}
|
||||
|
||||
// Compute client area size in device‑independent pixels
|
||||
double dpr = (!dpi_scale ? util::screenOfWidget(this)->devicePixelRatio() : 1.0);
|
||||
int winW = newWinSize.width();
|
||||
int winH = newWinSize.height();
|
||||
int clientW = static_cast<int>(winW / dpr);
|
||||
int clientH = static_cast<int>((winH - chromeH) / dpr);
|
||||
const int x = area.x() + (areaW - targetW) / 2;
|
||||
const int y = area.y() + (areaH - targetH) / 2;
|
||||
|
||||
if (clientW <= 0 || clientH <= 0) {
|
||||
s_adjustingForce43 = false;
|
||||
return;
|
||||
}
|
||||
ui->stackedWidget->setGeometry(x, y, targetW, targetH);
|
||||
ui->stackedWidget->onResize(targetW, targetH);
|
||||
|
||||
// Decide which dimension the user changed most – adjust the other
|
||||
int curW = static_cast<int>(width() / dpr);
|
||||
int curH = static_cast<int>((height() - chromeH) / dpr);
|
||||
bool widthChanged = std::abs(clientW - curW) >= std::abs(clientH - curH);
|
||||
if (monitors[0].mon_scrnsz_x != targetW || monitors[0].mon_scrnsz_y != targetH) {
|
||||
monitors[0].mon_scrnsz_x = targetW;
|
||||
monitors[0].mon_scrnsz_y = targetH;
|
||||
plat_resize_request(targetW, targetH, 0);
|
||||
}
|
||||
};
|
||||
|
||||
int targetW, targetH;
|
||||
if (widthChanged) {
|
||||
// user dragged width – compute matching height for 4:3
|
||||
targetW = clientW;
|
||||
targetH = (clientW * 3) / 4;
|
||||
} else {
|
||||
// user dragged height – compute matching width for 4:3
|
||||
targetH = clientH;
|
||||
targetW = (clientH * 4) / 3;
|
||||
}
|
||||
QWidget *cw = this->centralWidget();
|
||||
if (!cw) return;
|
||||
|
||||
// Convert back to window size including chrome and apply
|
||||
int newW = static_cast<int>(targetW * dpr);
|
||||
int newH = static_cast<int>(targetH * dpr) + chromeH;
|
||||
if (newW != winW || newH != winH)
|
||||
resize(newW, newH);
|
||||
const QRect area = cw->contentsRect();
|
||||
|
||||
// Update emulator framebuffer size and notify platform
|
||||
monitors[0].mon_scrnsz_x = targetW;
|
||||
monitors[0].mon_scrnsz_y = targetH;
|
||||
plat_resize_request(targetW, targetH, 0);
|
||||
// Fullscreen always fills (legacy behavior)
|
||||
if (video_fullscreen) { applyFill(area); return; }
|
||||
|
||||
// Allow renderer widget to grow and recompute scaling
|
||||
ui->stackedWidget->setFixedSize(QWIDGETSIZE_MAX, QWIDGETSIZE_MAX);
|
||||
ui->stackedWidget->onResize(width(), height());
|
||||
|
||||
s_adjustingForce43 = false;
|
||||
// Windowed: enforce 4:3 only when requested, otherwise fill
|
||||
if (force_43 > 0) apply43(area);
|
||||
else applyFill(area);
|
||||
}
|
||||
|
||||
void
|
||||
@@ -1088,26 +1085,10 @@ MainWindow::resizeEvent(QResizeEvent *event)
|
||||
//qDebug() << pos().x() + event->size().width();
|
||||
//qDebug() << pos().y() + event->size().height();
|
||||
|
||||
// Enforce 4:3 aspect ratio in resizable mode when the option is set
|
||||
adjustForForce43(event->size());
|
||||
|
||||
if (vid_resize == 1 || video_fullscreen)
|
||||
return;
|
||||
// Always let QMainWindow do its layout first
|
||||
QMainWindow::resizeEvent(event);
|
||||
|
||||
int newX = pos().x();
|
||||
int newY = pos().y();
|
||||
|
||||
if (((frameGeometry().x() + event->size().width() + 1) > util::screenOfWidget(this)->availableGeometry().right())) {
|
||||
//move(util::screenOfWidget(this)->availableGeometry().right() - size().width() - 1, pos().y());
|
||||
newX = util::screenOfWidget(this)->availableGeometry().right() - frameGeometry().width() - 1;
|
||||
if (newX < 1) newX = 1;
|
||||
}
|
||||
|
||||
if (((frameGeometry().y() + event->size().height() + 1) > util::screenOfWidget(this)->availableGeometry().bottom())) {
|
||||
newY = util::screenOfWidget(this)->availableGeometry().bottom() - frameGeometry().height() - 1;
|
||||
if (newY < 1) newY = 1;
|
||||
}
|
||||
move(newX, newY);
|
||||
applyContentLayoutForCurrentState();
|
||||
}
|
||||
|
||||
void
|
||||
@@ -1201,12 +1182,25 @@ MainWindow::showEvent(QShowEvent *event)
|
||||
monitors[0].mon_scrnsz_y = fixed_size_y;
|
||||
}
|
||||
if (window_remember && vid_resize == 1) {
|
||||
ui->stackedWidget->setFixedSize(window_w, window_h);
|
||||
const QSize target(window_w, window_h);
|
||||
const QSize prevMin = ui->stackedWidget->minimumSize();
|
||||
const QSize prevMax = ui->stackedWidget->maximumSize();
|
||||
|
||||
ui->stackedWidget->setMinimumSize(target);
|
||||
ui->stackedWidget->setMaximumSize(target);
|
||||
#ifndef Q_OS_MACOS
|
||||
QApplication::processEvents();
|
||||
#endif
|
||||
this->adjustSize();
|
||||
|
||||
ui->stackedWidget->setMinimumSize(prevMin);
|
||||
ui->stackedWidget->setMaximumSize(prevMax);
|
||||
ui->stackedWidget->resize(target);
|
||||
}
|
||||
|
||||
QTimer::singleShot(0, this, [this]{
|
||||
applyContentLayoutForCurrentState();
|
||||
});
|
||||
}
|
||||
|
||||
void
|
||||
@@ -1509,6 +1503,7 @@ MainWindow::on_actionFullscreen_triggered()
|
||||
{
|
||||
if (video_fullscreen > 0) {
|
||||
showNormal();
|
||||
QTimer::singleShot(0, this, [this]{ applyContentLayoutForCurrentState(); });
|
||||
ui->menubar->show();
|
||||
if (!hide_status_bar)
|
||||
ui->statusbar->show();
|
||||
@@ -2146,16 +2141,7 @@ MainWindow::on_actionForce_4_3_display_ratio_triggered()
|
||||
{
|
||||
video_toggle_option(ui->actionForce_4_3_display_ratio, &force_43);
|
||||
|
||||
// When turning on Force 4:3 in resizable mode, immediately snap to 4:3
|
||||
if (vid_resize == 1 && !video_fullscreen) {
|
||||
ui->stackedWidget->setFixedSize(QWIDGETSIZE_MAX, QWIDGETSIZE_MAX);
|
||||
if (force_43 > 0) {
|
||||
adjustForForce43(size());
|
||||
} else {
|
||||
// Turning off: refresh renderer scaling
|
||||
ui->stackedWidget->onResize(width(), height());
|
||||
}
|
||||
}
|
||||
QTimer::singleShot(0, this, [this]{ applyContentLayoutForCurrentState(); });
|
||||
}
|
||||
|
||||
void
|
||||
@@ -2524,4 +2510,3 @@ void MainWindow::on_actionCGA_composite_settings_triggered()
|
||||
isNonPause = false;
|
||||
config_save();
|
||||
}
|
||||
|
||||
|
||||
@@ -179,8 +179,8 @@ private:
|
||||
std::shared_ptr<MediaMenu> mm;
|
||||
|
||||
static bool s_adjustingForce43; // guard against recursion
|
||||
void adjustForForce43(const QSize &newWinSize);
|
||||
|
||||
void applyContentLayoutForCurrentState();
|
||||
|
||||
void updateShortcuts();
|
||||
void processKeyboardInput(bool down, uint32_t keycode);
|
||||
#ifdef Q_OS_MACOS
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -39,6 +39,7 @@
|
||||
#include <86box/vid_svga.h>
|
||||
#include <86box/vid_svga_render.h>
|
||||
#include <86box/vid_ati_eeprom.h>
|
||||
#include <86box/bswap.h>
|
||||
|
||||
#ifdef CLAMP
|
||||
# undef CLAMP
|
||||
@@ -80,6 +81,7 @@ enum {
|
||||
typedef struct mach64_t {
|
||||
mem_mapping_t linear_mapping;
|
||||
mem_mapping_t mmio_mapping;
|
||||
mem_mapping_t linear_mapping_big_endian;
|
||||
mem_mapping_t mmio_linear_mapping;
|
||||
mem_mapping_t mmio_linear_mapping_2;
|
||||
|
||||
@@ -98,6 +100,8 @@ typedef struct mach64_t {
|
||||
uint8_t pci_slot;
|
||||
uint8_t irq_state;
|
||||
|
||||
uint8_t on_board;
|
||||
|
||||
uint8_t pci_regs[256];
|
||||
uint8_t int_line;
|
||||
|
||||
@@ -272,7 +276,7 @@ typedef struct mach64_t {
|
||||
uint32_t cur_clr0;
|
||||
uint32_t cur_clr1;
|
||||
|
||||
uint32_t overlay_dat[1024];
|
||||
uint32_t overlay_dat[2048];
|
||||
uint32_t overlay_graphics_key_clr;
|
||||
uint32_t overlay_graphics_key_msk;
|
||||
uint32_t overlay_video_key_clr;
|
||||
@@ -286,12 +290,17 @@ typedef struct mach64_t {
|
||||
uint32_t scaler_height_width;
|
||||
int scaler_format;
|
||||
int scaler_update;
|
||||
int scaler_yuv_aper;
|
||||
|
||||
uint32_t buf_offset[2];
|
||||
uint32_t buf_pitch[2];
|
||||
|
||||
int overlay_v_acc;
|
||||
|
||||
uint32_t overlay_uv_addr;
|
||||
uint32_t overlay_cur_y;
|
||||
uint32_t overlay_base;
|
||||
|
||||
uint8_t thread_run;
|
||||
void *i2c;
|
||||
void *ddc;
|
||||
@@ -381,6 +390,9 @@ void mach64_ext_writeb(uint32_t addr, uint8_t val, void *priv);
|
||||
void mach64_ext_writew(uint32_t addr, uint16_t val, void *priv);
|
||||
void mach64_ext_writel(uint32_t addr, uint32_t val, void *priv);
|
||||
|
||||
uint8_t mach64_readb_be(uint32_t addr, void *priv);
|
||||
void mach64_writeb_be(uint32_t addr, uint8_t val, void *priv);
|
||||
|
||||
#ifdef ENABLE_MACH64_LOG
|
||||
int mach64_do_log = ENABLE_MACH64_LOG;
|
||||
|
||||
@@ -591,6 +603,7 @@ mach64_updatemapping(mach64_t *mach64)
|
||||
mach64_log("Update mapping - PCI disabled\n");
|
||||
mem_mapping_disable(&svga->mapping);
|
||||
mem_mapping_disable(&mach64->linear_mapping);
|
||||
mem_mapping_disable(&mach64->linear_mapping_big_endian);
|
||||
mem_mapping_disable(&mach64->mmio_mapping);
|
||||
mem_mapping_disable(&mach64->mmio_linear_mapping);
|
||||
mem_mapping_disable(&mach64->mmio_linear_mapping_2);
|
||||
@@ -645,14 +658,16 @@ mach64_updatemapping(mach64_t *mach64)
|
||||
}
|
||||
} else {
|
||||
/*2*8 MB aperture*/
|
||||
mem_mapping_set_addr(&mach64->linear_mapping, mach64->linear_base, (8 << 20) - 0x4000);
|
||||
mem_mapping_set_addr(&mach64->mmio_linear_mapping, mach64->linear_base + ((8 << 20) - 0x4000), 0x4000);
|
||||
mem_mapping_set_addr(&mach64->mmio_linear_mapping_2, mach64->linear_base + ((16 << 20) - 0x4000), 0x4000);
|
||||
mem_mapping_set_addr(&mach64->linear_mapping, mach64->linear_base, (8 << 20) - 4096);
|
||||
mem_mapping_set_addr(&mach64->mmio_linear_mapping, mach64->linear_base + ((8 << 20) - 4096), 4096);
|
||||
mem_mapping_set_addr(&mach64->linear_mapping_big_endian, mach64->linear_base + (8 << 20), (8 << 20) - 0x1000);
|
||||
mem_mapping_set_addr(&mach64->mmio_linear_mapping_2, mach64->linear_base + ((16 << 20) - 0x1000), 0x1000);
|
||||
}
|
||||
} else {
|
||||
mem_mapping_disable(&mach64->linear_mapping);
|
||||
mem_mapping_disable(&mach64->mmio_linear_mapping);
|
||||
mem_mapping_disable(&mach64->mmio_linear_mapping_2);
|
||||
mem_mapping_disable(&mach64->linear_mapping_big_endian);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2310,8 +2325,11 @@ mach64_vblank_start(svga_t *svga)
|
||||
|
||||
svga->overlay.ena = (mach64->overlay_scale_cntl & OVERLAY_EN) && (overlay_cmp_mix != 1);
|
||||
|
||||
mach64->overlay_v_acc = 0;
|
||||
mach64->scaler_update = 1;
|
||||
mach64->overlay_v_acc = 0;
|
||||
mach64->scaler_update = 1;
|
||||
mach64->overlay_uv_addr = svga->overlay.addr;
|
||||
mach64->overlay_cur_y = 0;
|
||||
mach64->overlay_base = svga->overlay.addr;
|
||||
}
|
||||
|
||||
uint8_t
|
||||
@@ -2389,6 +2407,10 @@ mach64_ext_readb(uint32_t addr, void *priv)
|
||||
case 0x4a:
|
||||
ret = mach64->scaler_format;
|
||||
break;
|
||||
|
||||
case 0x4b:
|
||||
ret = mach64->scaler_yuv_aper;
|
||||
break;
|
||||
|
||||
default:
|
||||
ret = 0xff;
|
||||
@@ -2558,7 +2580,7 @@ mach64_ext_readb(uint32_t addr, void *priv)
|
||||
|
||||
case 0xc7:
|
||||
READ8(addr, mach64->dac_cntl);
|
||||
if (mach64->type == MACH64_VT2) {
|
||||
if (mach64->type >= MACH64_VT2) {
|
||||
ret &= 0xf9;
|
||||
if (i2c_gpio_get_scl(mach64->i2c))
|
||||
ret |= 0x04;
|
||||
@@ -2957,7 +2979,8 @@ mach64_ext_readw(uint32_t addr, void *priv)
|
||||
|
||||
if (!(addr & 0x400)) {
|
||||
mach64_log("mach64_ext_readw: addr=%04x\n", addr);
|
||||
ret = 0xffff;
|
||||
ret = mach64_ext_readb(addr, priv);
|
||||
ret |= mach64_ext_readb(addr + 1, priv) << 8;
|
||||
} else
|
||||
switch (addr & 0x3ff) {
|
||||
case 0xb4:
|
||||
@@ -2986,7 +3009,8 @@ mach64_ext_readl(uint32_t addr, void *priv)
|
||||
|
||||
if (!(addr & 0x400)) {
|
||||
mach64_log("mach64_ext_readl: addr=%04x\n", addr);
|
||||
ret = 0xffffffff;
|
||||
ret = mach64_ext_readw(addr, priv);
|
||||
ret |= mach64_ext_readw(addr + 2, priv) << 16;
|
||||
} else
|
||||
switch (addr & 0x3ff) {
|
||||
case 0x18:
|
||||
@@ -3087,6 +3111,10 @@ mach64_ext_writeb(uint32_t addr, uint8_t val, void *priv)
|
||||
case 0x4a:
|
||||
mach64->scaler_format = val & 0xf;
|
||||
break;
|
||||
|
||||
case 0x4b:
|
||||
mach64->scaler_yuv_aper = val;
|
||||
break;
|
||||
|
||||
case 0x80:
|
||||
case 0x81:
|
||||
@@ -4106,76 +4134,113 @@ mach64_int_hwcursor_draw(svga_t *svga, int displine)
|
||||
} \
|
||||
} while (0)
|
||||
|
||||
#define DECODE_VYUY422() \
|
||||
do { \
|
||||
for (x = 0; x < mach64->svga.overlay_latch.cur_xsize; x += 2) { \
|
||||
uint8_t y1, y2; \
|
||||
int8_t u, v; \
|
||||
int dR, dG, dB; \
|
||||
int r, g, b; \
|
||||
\
|
||||
y1 = src[0]; \
|
||||
u = src[1] - 0x80; \
|
||||
y2 = src[2]; \
|
||||
v = src[3] - 0x80; \
|
||||
src += 4; \
|
||||
\
|
||||
dR = (359 * v) >> 8; \
|
||||
dG = (88 * u + 183 * v) >> 8; \
|
||||
dB = (453 * u) >> 8; \
|
||||
\
|
||||
r = y1 + dR; \
|
||||
CLAMP(r); \
|
||||
g = y1 - dG; \
|
||||
CLAMP(g); \
|
||||
b = y1 + dB; \
|
||||
CLAMP(b); \
|
||||
mach64->overlay_dat[x] = (r << 16) | (g << 8) | b; \
|
||||
\
|
||||
r = y2 + dR; \
|
||||
CLAMP(r); \
|
||||
g = y2 - dG; \
|
||||
CLAMP(g); \
|
||||
b = y2 + dB; \
|
||||
CLAMP(b); \
|
||||
mach64->overlay_dat[x + 1] = (r << 16) | (g << 8) | b; \
|
||||
} \
|
||||
#define DECODE_VYUY422() \
|
||||
do { \
|
||||
for (x = 0; x < src_w; x += 1) { \
|
||||
uint8_t y1, y2; \
|
||||
int8_t u, v; \
|
||||
int dR, dG, dB; \
|
||||
int r, g, b; \
|
||||
\
|
||||
y1 = src[0]; \
|
||||
u = src[1] - 0x80; \
|
||||
y2 = src[2]; \
|
||||
v = src[3] - 0x80; \
|
||||
src += 4; \
|
||||
\
|
||||
dR = (359 * v) >> 8; \
|
||||
dG = (88 * u + 183 * v) >> 8; \
|
||||
dB = (453 * u) >> 8; \
|
||||
\
|
||||
r = y1 + dR; \
|
||||
CLAMP(r); \
|
||||
g = y1 - dG; \
|
||||
CLAMP(g); \
|
||||
b = y1 + dB; \
|
||||
CLAMP(b); \
|
||||
mach64->overlay_dat[x * 2] = (r << 16) | (g << 8) | b; \
|
||||
\
|
||||
r = y2 + dR; \
|
||||
CLAMP(r); \
|
||||
g = y2 - dG; \
|
||||
CLAMP(g); \
|
||||
b = y2 + dB; \
|
||||
CLAMP(b); \
|
||||
mach64->overlay_dat[(x * 2) + 1] = (r << 16) | (g << 8) | b; \
|
||||
} \
|
||||
} while (0)
|
||||
|
||||
#define DECODE_YVYU422() \
|
||||
do { \
|
||||
for (x = 0; x < mach64->svga.overlay_latch.cur_xsize; x += 2) { \
|
||||
uint8_t y1, y2; \
|
||||
int8_t u, v; \
|
||||
int dR, dG, dB; \
|
||||
int r, g, b; \
|
||||
\
|
||||
u = src[0] - 0x80; \
|
||||
y1 = src[1]; \
|
||||
v = src[2] - 0x80; \
|
||||
y2 = src[3]; \
|
||||
src += 4; \
|
||||
\
|
||||
dR = (359 * v) >> 8; \
|
||||
dG = (88 * u + 183 * v) >> 8; \
|
||||
dB = (453 * u) >> 8; \
|
||||
\
|
||||
r = y1 + dR; \
|
||||
CLAMP(r); \
|
||||
g = y1 - dG; \
|
||||
CLAMP(g); \
|
||||
b = y1 + dB; \
|
||||
CLAMP(b); \
|
||||
mach64->overlay_dat[x] = (r << 16) | (g << 8) | b; \
|
||||
\
|
||||
r = y2 + dR; \
|
||||
CLAMP(r); \
|
||||
g = y2 - dG; \
|
||||
CLAMP(g); \
|
||||
b = y2 + dB; \
|
||||
CLAMP(b); \
|
||||
mach64->overlay_dat[x + 1] = (r << 16) | (g << 8) | b; \
|
||||
} \
|
||||
#define DECODE_YVYU422() \
|
||||
do { \
|
||||
for (x = 0; x < src_w; x += 1) { \
|
||||
uint8_t y1, y2; \
|
||||
int8_t u, v; \
|
||||
int dR, dG, dB; \
|
||||
int r, g, b; \
|
||||
\
|
||||
u = src[0] - 0x80; \
|
||||
y1 = src[1]; \
|
||||
v = src[2] - 0x80; \
|
||||
y2 = src[3]; \
|
||||
src += 4; \
|
||||
\
|
||||
dR = (359 * v) >> 8; \
|
||||
dG = (88 * u + 183 * v) >> 8; \
|
||||
dB = (453 * u) >> 8; \
|
||||
\
|
||||
r = y1 + dR; \
|
||||
CLAMP(r); \
|
||||
g = y1 - dG; \
|
||||
CLAMP(g); \
|
||||
b = y1 + dB; \
|
||||
CLAMP(b); \
|
||||
mach64->overlay_dat[x * 2] = (r << 16) | (g << 8) | b; \
|
||||
\
|
||||
r = y2 + dR; \
|
||||
CLAMP(r); \
|
||||
g = y2 - dG; \
|
||||
CLAMP(g); \
|
||||
b = y2 + dB; \
|
||||
CLAMP(b); \
|
||||
mach64->overlay_dat[(x * 2) + 1] = (r << 16) | (g << 8) | b; \
|
||||
} \
|
||||
} while (0)
|
||||
|
||||
#define DECODE_YUV12_PACKED() \
|
||||
do { \
|
||||
for (x = 0; x < src_w; x += 1) { \
|
||||
uint8_t y1, y2; \
|
||||
int8_t u, v; \
|
||||
int dR, dG, dB; \
|
||||
int r, g, b; \
|
||||
\
|
||||
u = uvsrc[3] - 0x80; \
|
||||
y1 = src[0]; \
|
||||
v = uvsrc[2] - 0x80; \
|
||||
y2 = src[1]; \
|
||||
src += 4; \
|
||||
uvsrc += 4; \
|
||||
\
|
||||
dR = (359 * v) >> 8; \
|
||||
dG = (88 * u + 183 * v) >> 8; \
|
||||
dB = (453 * u) >> 8; \
|
||||
\
|
||||
r = y1 + dR; \
|
||||
CLAMP(r); \
|
||||
g = y1 - dG; \
|
||||
CLAMP(g); \
|
||||
b = y1 + dB; \
|
||||
CLAMP(b); \
|
||||
mach64->overlay_dat[x * 2] = (r << 16) | (g << 8) | b; \
|
||||
\
|
||||
r = y2 + dR; \
|
||||
CLAMP(r); \
|
||||
g = y2 - dG; \
|
||||
CLAMP(g); \
|
||||
b = y2 + dB; \
|
||||
CLAMP(b); \
|
||||
mach64->overlay_dat[(x * 2) + 1] = (r << 16) | (g << 8) | b; \
|
||||
} \
|
||||
} while (0)
|
||||
|
||||
void
|
||||
@@ -4185,11 +4250,13 @@ mach64_overlay_draw(svga_t *svga, int displine)
|
||||
int x;
|
||||
int h_acc = 0;
|
||||
int h_max = (mach64->scaler_height_width >> 16) & 0x3ff;
|
||||
int src_w = h_max;
|
||||
int h_inc = mach64->overlay_scale_inc >> 16;
|
||||
int v_max = mach64->scaler_height_width & 0x3ff;
|
||||
int v_inc = mach64->overlay_scale_inc & 0xffff;
|
||||
uint32_t *p;
|
||||
uint8_t *src = &svga->vram[svga->overlay.addr];
|
||||
uint8_t *uvsrc = src;
|
||||
int old_y = mach64->overlay_v_acc;
|
||||
int y_diff;
|
||||
int video_key_fn = mach64->overlay_key_cntl & 5;
|
||||
@@ -4198,6 +4265,11 @@ mach64_overlay_draw(svga_t *svga, int displine)
|
||||
|
||||
p = &buffer32->line[displine][svga->x_add + mach64->svga.overlay_latch.x];
|
||||
|
||||
if (mach64->overlay_cur_y >= 2) {
|
||||
/* Avoid corrupt UV data on YUV12 packed modes */
|
||||
uvsrc = &svga->vram[mach64->overlay_base + svga->overlay.pitch * 2 * (!(mach64->overlay_cur_y & 1) ? (mach64->overlay_cur_y + 1) : mach64->overlay_cur_y)];
|
||||
}
|
||||
|
||||
if (mach64->scaler_update) {
|
||||
switch (mach64->scaler_format) {
|
||||
case 0x3:
|
||||
@@ -4209,6 +4281,9 @@ mach64_overlay_draw(svga_t *svga, int displine)
|
||||
case 0x6:
|
||||
DECODE_ARGB8888();
|
||||
break;
|
||||
case 0xa:
|
||||
DECODE_YUV12_PACKED();
|
||||
break;
|
||||
case 0xb:
|
||||
DECODE_VYUY422();
|
||||
break;
|
||||
@@ -4217,7 +4292,7 @@ mach64_overlay_draw(svga_t *svga, int displine)
|
||||
break;
|
||||
|
||||
default:
|
||||
mach64_log("Unknown Mach64 scaler format %x\n", mach64->scaler_format);
|
||||
pclog("Unknown Mach64 scaler format %x\n", mach64->scaler_format);
|
||||
/*Fill buffer with something recognisably wrong*/
|
||||
for (x = 0; x < mach64->svga.overlay_latch.cur_xsize; x++)
|
||||
mach64->overlay_dat[x] = 0xff00ff;
|
||||
@@ -4354,6 +4429,7 @@ mach64_overlay_draw(svga_t *svga, int displine)
|
||||
svga->overlay.addr += svga->overlay.pitch * 2 * y_diff;
|
||||
|
||||
mach64->scaler_update = y_diff;
|
||||
mach64->overlay_cur_y += y_diff;
|
||||
}
|
||||
|
||||
static void
|
||||
@@ -4389,7 +4465,7 @@ mach64_io_remove(mach64_t *mach64)
|
||||
io_removehandler(0x01ce, 0x0002, mach64_in, NULL, NULL, mach64_out, NULL, NULL, mach64);
|
||||
|
||||
if (mach64->block_decoded_io && mach64->block_decoded_io < 0x10000)
|
||||
io_removehandler(mach64->block_decoded_io, 0x0400, mach64_block_inb, mach64_block_inw, mach64_block_inl, mach64_block_outb, mach64_block_outw, mach64_block_outl, mach64);
|
||||
io_removehandler(mach64->block_decoded_io, 0x0100, mach64_block_inb, mach64_block_inw, mach64_block_inl, mach64_block_outb, mach64_block_outw, mach64_block_outl, mach64);
|
||||
}
|
||||
|
||||
static void
|
||||
@@ -4429,7 +4505,7 @@ mach64_io_set(mach64_t *mach64)
|
||||
io_sethandler(0x01ce, 0x0002, mach64_in, NULL, NULL, mach64_out, NULL, NULL, mach64);
|
||||
|
||||
if (mach64->use_block_decoded_io && mach64->block_decoded_io && mach64->block_decoded_io < 0x10000)
|
||||
io_sethandler(mach64->block_decoded_io, 0x0400, mach64_block_inb, mach64_block_inw, mach64_block_inl, mach64_block_outb, mach64_block_outw, mach64_block_outl, mach64);
|
||||
io_sethandler(mach64->block_decoded_io, 0x0100, mach64_block_inb, mach64_block_inw, mach64_block_inl, mach64_block_outb, mach64_block_outw, mach64_block_outl, mach64);
|
||||
}
|
||||
|
||||
static uint8_t
|
||||
@@ -4478,7 +4554,6 @@ static void
|
||||
mach64_write_linear(uint32_t addr, uint8_t val, void *priv)
|
||||
{
|
||||
svga_t *svga = (svga_t *) priv;
|
||||
|
||||
cycles -= svga->monitor->mon_video_timing_write_b;
|
||||
|
||||
addr &= svga->decode_mask;
|
||||
@@ -4507,10 +4582,38 @@ mach64_writew_linear(uint32_t addr, uint16_t val, void *priv)
|
||||
static void
|
||||
mach64_writel_linear(uint32_t addr, uint32_t val, void *priv)
|
||||
{
|
||||
svga_t *svga = (svga_t *) priv;
|
||||
svga_t *svga = (svga_t *) priv;
|
||||
mach64_t *mach64 = (mach64_t *) svga->priv;
|
||||
|
||||
cycles -= svga->monitor->mon_video_timing_write_l;
|
||||
|
||||
if (((mach64->scaler_yuv_aper >> 4) & 0xc) && !!(addr & 0x800000) == !(mach64->scaler_yuv_aper & 0x20)) {
|
||||
uint32_t offset_from_base = addr & 0x7FFFFF;
|
||||
if (addr & 0x800000) bswap32s(&val);
|
||||
if (((mach64->scaler_yuv_aper >> 4) & 0xc) == 0x4) { // Y plane
|
||||
offset_from_base <<= 1;
|
||||
svga->vram[offset_from_base & svga->vram_mask] = (val & 0xFF);
|
||||
svga->vram[(offset_from_base + 1) & svga->vram_mask] = ((val >> 8) & 0xFF);
|
||||
svga->vram[(offset_from_base + 4) & svga->vram_mask] = ((val >> 16) & 0xFF);
|
||||
svga->vram[(offset_from_base + 5) & svga->vram_mask] = ((val >> 24) & 0xFF);
|
||||
}
|
||||
else if (((mach64->scaler_yuv_aper >> 4) & 0xc) == 0x8 || ((mach64->scaler_yuv_aper >> 4) & 0xc) == 0xc) {
|
||||
offset_from_base <<= 2;
|
||||
if (((mach64->scaler_yuv_aper >> 4) & 0xc) == 0x8) { // U plane
|
||||
svga->vram[(offset_from_base + 3) & svga->vram_mask] = (val & 0xFF);
|
||||
svga->vram[(offset_from_base + 7) & svga->vram_mask] = ((val >> 8) & 0xFF);
|
||||
svga->vram[(offset_from_base + 11) & svga->vram_mask] = ((val >> 16) & 0xFF);
|
||||
svga->vram[(offset_from_base + 15) & svga->vram_mask] = ((val >> 24) & 0xFF);
|
||||
} else { // V plane
|
||||
svga->vram[(offset_from_base + 2) & svga->vram_mask] = (val & 0xFF);
|
||||
svga->vram[(offset_from_base + 6) & svga->vram_mask] = ((val >> 8) & 0xFF);
|
||||
svga->vram[(offset_from_base + 10) & svga->vram_mask] = ((val >> 16) & 0xFF);
|
||||
svga->vram[(offset_from_base + 14) & svga->vram_mask] = ((val >> 24) & 0xFF);
|
||||
}
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
addr &= svga->decode_mask;
|
||||
if (addr >= svga->vram_max)
|
||||
return;
|
||||
@@ -4519,6 +4622,42 @@ mach64_writel_linear(uint32_t addr, uint32_t val, void *priv)
|
||||
*(uint32_t *) &svga->vram[addr] = val;
|
||||
}
|
||||
|
||||
uint8_t
|
||||
mach64_readb_be(uint32_t addr, void *priv)
|
||||
{
|
||||
return mach64_read_linear(addr, priv);
|
||||
}
|
||||
|
||||
uint16_t
|
||||
mach64_readw_be(uint32_t addr, void *priv)
|
||||
{
|
||||
return bswap16(mach64_readw_linear(addr, priv));
|
||||
}
|
||||
|
||||
uint32_t
|
||||
mach64_readl_be(uint32_t addr, void *priv)
|
||||
{
|
||||
return bswap32(mach64_readl_linear(addr, priv));
|
||||
}
|
||||
|
||||
void
|
||||
mach64_writeb_be(uint32_t addr, uint8_t val, void *priv)
|
||||
{
|
||||
return mach64_write_linear(addr, val, priv);
|
||||
}
|
||||
|
||||
void
|
||||
mach64_writew_be(uint32_t addr, uint16_t val, void *priv)
|
||||
{
|
||||
return mach64_writew_linear(addr, bswap16(val), priv);
|
||||
}
|
||||
|
||||
void
|
||||
mach64_writel_be(uint32_t addr, uint32_t val, void *priv)
|
||||
{
|
||||
return mach64_writel_linear(addr, bswap32(val), priv);
|
||||
}
|
||||
|
||||
uint8_t
|
||||
mach64_pci_read(UNUSED(int func), int addr, void *priv)
|
||||
{
|
||||
@@ -4564,30 +4703,31 @@ mach64_pci_read(UNUSED(int func), int addr, void *priv)
|
||||
return mach64->linear_base >> 24;
|
||||
|
||||
case 0x14:
|
||||
if (mach64->type == MACH64_VT2)
|
||||
if (mach64->type >= MACH64_VT2)
|
||||
return 0x01; /*Block decoded IO address*/
|
||||
return 0x00;
|
||||
case 0x15:
|
||||
if (mach64->type == MACH64_VT2)
|
||||
if (mach64->type >= MACH64_VT2)
|
||||
return mach64->block_decoded_io >> 8;
|
||||
return 0x00;
|
||||
case 0x16:
|
||||
if (mach64->type == MACH64_VT2)
|
||||
if (mach64->type >= MACH64_VT2)
|
||||
return mach64->block_decoded_io >> 16;
|
||||
return 0x00;
|
||||
case 0x17:
|
||||
if (mach64->type == MACH64_VT2)
|
||||
if (mach64->type >= MACH64_VT2)
|
||||
return mach64->block_decoded_io >> 24;
|
||||
return 0x00;
|
||||
|
||||
|
||||
case 0x30:
|
||||
return mach64->pci_regs[0x30] & 0x01; /*BIOS ROM address*/
|
||||
return (mach64->on_board) ? 0 : (mach64->pci_regs[0x30] & 0x01); /*BIOS ROM address*/
|
||||
case 0x31:
|
||||
return 0x00;
|
||||
case 0x32:
|
||||
return mach64->pci_regs[0x32];
|
||||
return (mach64->on_board) ? 0 : mach64->pci_regs[0x32];
|
||||
case 0x33:
|
||||
return mach64->pci_regs[0x33];
|
||||
return (mach64->on_board) ? 0 : mach64->pci_regs[0x33];
|
||||
|
||||
case 0x3c:
|
||||
return mach64->int_line;
|
||||
@@ -4619,7 +4759,7 @@ mach64_pci_write(UNUSED(int func), int addr, uint8_t val, void *priv)
|
||||
break;
|
||||
|
||||
case 0x12:
|
||||
if (mach64->type == MACH64_VT2)
|
||||
if (mach64->type >= MACH64_VT2)
|
||||
val = 0;
|
||||
mach64->linear_base = (mach64->linear_base & 0xff000000) | ((val & 0x80) << 16);
|
||||
mach64_updatemapping(mach64);
|
||||
@@ -4630,16 +4770,16 @@ mach64_pci_write(UNUSED(int func), int addr, uint8_t val, void *priv)
|
||||
break;
|
||||
|
||||
case 0x15:
|
||||
if (mach64->type == MACH64_VT2) {
|
||||
if (mach64->type >= MACH64_VT2) {
|
||||
if (mach64->pci_regs[PCI_REG_COMMAND] & PCI_COMMAND_IO)
|
||||
mach64_io_remove(mach64);
|
||||
mach64->block_decoded_io = (mach64->block_decoded_io & 0xffff0000) | ((val & 0xfc) << 8);
|
||||
mach64->block_decoded_io = (mach64->block_decoded_io & 0xffff0000) | ((val & 0xff) << 8);
|
||||
if (mach64->pci_regs[PCI_REG_COMMAND] & PCI_COMMAND_IO)
|
||||
mach64_io_set(mach64);
|
||||
}
|
||||
break;
|
||||
case 0x16:
|
||||
if (mach64->type == MACH64_VT2) {
|
||||
if (mach64->type >= MACH64_VT2) {
|
||||
if (mach64->pci_regs[PCI_REG_COMMAND] & PCI_COMMAND_IO)
|
||||
mach64_io_remove(mach64);
|
||||
mach64->block_decoded_io = (mach64->block_decoded_io & 0xff00fc00) | (val << 16);
|
||||
@@ -4648,7 +4788,7 @@ mach64_pci_write(UNUSED(int func), int addr, uint8_t val, void *priv)
|
||||
}
|
||||
break;
|
||||
case 0x17:
|
||||
if (mach64->type == MACH64_VT2) {
|
||||
if (mach64->type >= MACH64_VT2) {
|
||||
if (mach64->pci_regs[PCI_REG_COMMAND] & PCI_COMMAND_IO)
|
||||
mach64_io_remove(mach64);
|
||||
mach64->block_decoded_io = (mach64->block_decoded_io & 0x00fffc00) | (val << 24);
|
||||
@@ -4660,6 +4800,7 @@ mach64_pci_write(UNUSED(int func), int addr, uint8_t val, void *priv)
|
||||
case 0x30:
|
||||
case 0x32:
|
||||
case 0x33:
|
||||
if (mach64->on_board) return;
|
||||
mach64->pci_regs[addr] = val;
|
||||
if (mach64->pci_regs[0x30] & 0x01) {
|
||||
uint32_t biosaddr = (mach64->pci_regs[0x32] << 16) | (mach64->pci_regs[0x33] << 24);
|
||||
@@ -4679,7 +4820,7 @@ mach64_pci_write(UNUSED(int func), int addr, uint8_t val, void *priv)
|
||||
if (mach64->pci_regs[PCI_REG_COMMAND] & PCI_COMMAND_IO)
|
||||
mach64_io_remove(mach64);
|
||||
mach64->io_base = val & 0x03;
|
||||
if (mach64->type == MACH64_VT2)
|
||||
if (mach64->type >= MACH64_VT2)
|
||||
mach64->use_block_decoded_io = val & 0x04;
|
||||
if (mach64->pci_regs[PCI_REG_COMMAND] & PCI_COMMAND_IO)
|
||||
mach64_io_set(mach64);
|
||||
@@ -4700,7 +4841,7 @@ mach64_common_init(const device_t *info)
|
||||
svga = &mach64->svga;
|
||||
|
||||
mach64->type = info->local & 0xff;
|
||||
mach64->vram_size = device_get_config_int("memory");
|
||||
mach64->vram_size = (info->local & (1 << 20)) ? 4 : device_get_config_int("memory");
|
||||
mach64->vram_mask = (mach64->vram_size << 20) - 1;
|
||||
|
||||
if (mach64->type > MACH64_GX)
|
||||
@@ -4717,9 +4858,10 @@ mach64_common_init(const device_t *info)
|
||||
mach64_overlay_draw);
|
||||
|
||||
mem_mapping_add(&mach64->linear_mapping, 0, 0, mach64_read_linear, mach64_readw_linear, mach64_readl_linear, mach64_write_linear, mach64_writew_linear, mach64_writel_linear, NULL, MEM_MAPPING_EXTERNAL, svga);
|
||||
mem_mapping_add(&mach64->linear_mapping_big_endian, 0, 0, mach64_readb_be, mach64_readw_be, mach64_readl_be, mach64_writeb_be, mach64_writew_be, mach64_writel_be, NULL, MEM_MAPPING_EXTERNAL, svga);
|
||||
mem_mapping_add(&mach64->mmio_linear_mapping, 0, 0, mach64_ext_readb, mach64_ext_readw, mach64_ext_readl, mach64_ext_writeb, mach64_ext_writew, mach64_ext_writel, NULL, MEM_MAPPING_EXTERNAL, mach64);
|
||||
mem_mapping_add(&mach64->mmio_linear_mapping_2, 0, 0, mach64_ext_readb, mach64_ext_readw, mach64_ext_readl, mach64_ext_writeb, mach64_ext_writew, mach64_ext_writel, NULL, MEM_MAPPING_EXTERNAL, mach64);
|
||||
mem_mapping_add(&mach64->mmio_mapping, 0xbc000, 0x04000, mach64_ext_readb, mach64_ext_readw, mach64_ext_readl, mach64_ext_writeb, mach64_ext_writew, mach64_ext_writel, NULL, MEM_MAPPING_EXTERNAL, mach64);
|
||||
mem_mapping_add(&mach64->mmio_mapping, 0xbf000, 0x1000, mach64_ext_readb, mach64_ext_readw, mach64_ext_readl, mach64_ext_writeb, mach64_ext_writew, mach64_ext_writel, NULL, MEM_MAPPING_EXTERNAL, mach64);
|
||||
mem_mapping_disable(&mach64->mmio_mapping);
|
||||
|
||||
mach64_io_set(mach64);
|
||||
|
||||
@@ -1952,9 +1952,9 @@ s3_virge_mmio_write_l(uint32_t addr, uint32_t val, void *priv)
|
||||
break;
|
||||
case 0x8190:
|
||||
virge->streams.sec_ctrl = val;
|
||||
virge->streams.dda_horiz_accumulator = val & 0xfff;
|
||||
if (val & 0x1000)
|
||||
virge->streams.dda_horiz_accumulator |= ~0xfff;
|
||||
virge->streams.dda_horiz_accumulator = val & 0x7ff;
|
||||
if (val & 0x800)
|
||||
virge->streams.dda_horiz_accumulator |= ~0x7ff;
|
||||
|
||||
virge->streams.sdif = (val >> 24) & 7;
|
||||
break;
|
||||
@@ -2030,9 +2030,9 @@ s3_virge_mmio_write_l(uint32_t addr, uint32_t val, void *priv)
|
||||
virge->streams.k2_vert_scale |= ~0x7ff;
|
||||
break;
|
||||
case 0x81e8:
|
||||
virge->streams.dda_vert_accumulator = val & 0xfff;
|
||||
if (val & 0x1000)
|
||||
virge->streams.dda_vert_accumulator |= ~0xfff;
|
||||
virge->streams.dda_vert_accumulator = val & 0x7ff;
|
||||
if (val & 0x800)
|
||||
virge->streams.dda_vert_accumulator |= ~0x7ff;
|
||||
|
||||
svga_recalctimings(svga);
|
||||
svga->fullchange = changeframecount;
|
||||
|
||||
Reference in New Issue
Block a user