Merge master

This commit is contained in:
Toni Riikonen
2025-09-27 22:29:23 +03:00
46 changed files with 1925 additions and 1223 deletions

View File

@@ -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/

View File

@@ -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 }}

View File

@@ -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 }}

View File

@@ -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 }}

View File

@@ -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.

View File

@@ -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)
{

File diff suppressed because it is too large Load Diff

View File

@@ -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

View File

@@ -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;

View File

@@ -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 */

View File

@@ -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*/

View File

@@ -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 *);

View File

@@ -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*/

View File

@@ -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);

View File

@@ -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);

View File

@@ -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,

View File

@@ -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) {

View File

@@ -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, &params);
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,

View File

@@ -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;

View File

@@ -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 widgets 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 deviceindependent 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();
}

View File

@@ -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

View File

@@ -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);

View File

@@ -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");

View File

@@ -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;

View File

@@ -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);

View File

@@ -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;
}
}

View File

@@ -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);

View File

@@ -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;