mirror of
https://github.com/86Box/86Box.git
synced 2026-02-28 01:44:22 -07:00
Merge branch '86Box:master' into master
This commit is contained in:
33
src/86box.c
33
src/86box.c
@@ -1870,6 +1870,27 @@ update_mouse_msg(void)
|
||||
(mouse_get_buttons() > 2) ? plat_get_string(STRING_MOUSE_RELEASE) : plat_get_string(STRING_MOUSE_RELEASE_MMB));
|
||||
swprintf(mouse_msg[2], sizeof_w(mouse_msg[2]), L"%ls v%ls - %%i%%%% - %ls - %ls/%ls",
|
||||
EMU_NAME_W, EMU_VERSION_FULL_W, wmachine, wcpufamily, wcpu);
|
||||
#else
|
||||
#ifdef __APPLE__
|
||||
/*
|
||||
* On macOS, BSD swprintf fails (returns -1) when the format string
|
||||
* or a %ls argument contains non-ASCII wide characters (e.g. the
|
||||
* native key symbols ⌘ U+2318, ⌫ U+232B) and the C locale is
|
||||
* active. Store just the message suffixes here; the title update
|
||||
* path in pc_render_monitor_dispatch() builds the full string
|
||||
* without swprintf.
|
||||
*/
|
||||
wcsncpy(mouse_msg[0], plat_get_string(STRING_MOUSE_CAPTURE), sizeof_w(mouse_msg[0]) - 1);
|
||||
mouse_msg[0][sizeof_w(mouse_msg[0]) - 1] = L'\0';
|
||||
|
||||
{
|
||||
wchar_t *rel = (mouse_get_buttons() > 2) ? plat_get_string(STRING_MOUSE_RELEASE)
|
||||
: plat_get_string(STRING_MOUSE_RELEASE_MMB);
|
||||
wcsncpy(mouse_msg[1], rel, sizeof_w(mouse_msg[1]) - 1);
|
||||
mouse_msg[1][sizeof_w(mouse_msg[1]) - 1] = L'\0';
|
||||
}
|
||||
|
||||
mouse_msg[2][0] = L'\0';
|
||||
#else
|
||||
swprintf(mouse_msg[0], sizeof_w(mouse_msg[0]), L"%%i%%%% - %ls",
|
||||
plat_get_string(STRING_MOUSE_CAPTURE));
|
||||
@@ -1877,6 +1898,7 @@ update_mouse_msg(void)
|
||||
(mouse_get_buttons() > 2) ? plat_get_string(STRING_MOUSE_RELEASE) : plat_get_string(STRING_MOUSE_RELEASE_MMB));
|
||||
wcsncpy(mouse_msg[2], L"%i%%", sizeof_w(mouse_msg[2]));
|
||||
#endif
|
||||
#endif
|
||||
}
|
||||
|
||||
void
|
||||
@@ -2009,11 +2031,20 @@ pc_run(void)
|
||||
else
|
||||
fps = ((fps + 20) / 50) * 50;
|
||||
#endif
|
||||
swprintf(temp, sizeof_w(temp), mouse_msg[mouse_msg_idx], fps / (force_10ms ? 1 : 10));
|
||||
#ifdef __APPLE__
|
||||
/*
|
||||
* mouse_msg[] stores suffixes only on macOS (see update_mouse_msg).
|
||||
* Build the title without passing non-ASCII chars through swprintf.
|
||||
*/
|
||||
swprintf(temp, sizeof_w(temp), L"%i%%", fps / (force_10ms ? 1 : 10));
|
||||
if (mouse_msg[mouse_msg_idx][0]) {
|
||||
wcsncat(temp, L" - ", sizeof_w(temp) - wcslen(temp) - 1);
|
||||
wcsncat(temp, mouse_msg[mouse_msg_idx], sizeof_w(temp) - wcslen(temp) - 1);
|
||||
}
|
||||
/* Needed due to modifying the UI on the non-main thread is a big no-no. */
|
||||
dispatch_async_f(dispatch_get_main_queue(), wcsdup((const wchar_t *) temp), _ui_window_title);
|
||||
#else
|
||||
swprintf(temp, sizeof_w(temp), mouse_msg[mouse_msg_idx], fps / (force_10ms ? 1 : 10));
|
||||
ui_window_title(temp);
|
||||
#endif
|
||||
title_update = 0;
|
||||
|
||||
@@ -84,7 +84,10 @@ opti499_recalc(opti499_t *dev)
|
||||
base = 0xd0000 + (i << 14);
|
||||
|
||||
if ((dev->regs[0x22] & ((base >= 0xe0000) ? 0x20 : 0x40)) && (dev->regs[0x23] & (1 << i))) {
|
||||
shflags = MEM_READ_INTERNAL;
|
||||
if (dev->regs[0x2d] & (1 << ((i >> 1) + 2)))
|
||||
shflags = MEM_READ_EXTANY;
|
||||
else
|
||||
shflags = MEM_READ_INTERNAL;
|
||||
shflags |= (dev->regs[0x22] & ((base >= 0xe0000) ? 0x08 : 0x10)) ? MEM_WRITE_DISABLED : MEM_WRITE_INTERNAL;
|
||||
} else {
|
||||
if (dev->regs[0x2d] & (1 << ((i >> 1) + 2)))
|
||||
|
||||
@@ -12,11 +12,17 @@
|
||||
*
|
||||
* Copyright 2020 Miran Grca.
|
||||
*/
|
||||
|
||||
#ifdef ENABLE_VL82C48X_LOG
|
||||
#include <stdarg.h>
|
||||
#endif
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdint.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <wchar.h>
|
||||
#define HAVE_STDARG_H
|
||||
#include <86box/86box.h>
|
||||
#include "cpu.h"
|
||||
#include <86box/timer.h>
|
||||
@@ -27,11 +33,31 @@
|
||||
#include <86box/nmi.h>
|
||||
#include <86box/port_92.h>
|
||||
#include <86box/chipset.h>
|
||||
#include <86box/log.h>
|
||||
|
||||
#ifdef ENABLE_VL82C48X_LOG
|
||||
int vl82c48x_do_log = ENABLE_VL82C48X_LOG;
|
||||
|
||||
static void
|
||||
vl82c48x_log(void *priv, const char *fmt, ...)
|
||||
{
|
||||
if (vl82c48x_do_log) {
|
||||
va_list ap;
|
||||
va_start(ap, fmt);
|
||||
log_out(priv, fmt, ap);
|
||||
va_end(ap);
|
||||
}
|
||||
}
|
||||
#else
|
||||
# define vl82c48x_log(fmt, ...)
|
||||
#endif
|
||||
|
||||
typedef struct vl82c480_t {
|
||||
uint8_t idx;
|
||||
uint8_t regs[256];
|
||||
uint32_t banks[4];
|
||||
|
||||
void * log; // New logging system
|
||||
} vl82c480_t;
|
||||
|
||||
static int
|
||||
@@ -77,6 +103,14 @@ vl82c480_recalc_shadow(vl82c480_t *dev)
|
||||
}
|
||||
}
|
||||
|
||||
/* Implement ROMCS# disable portion of ROMMOV behavior */
|
||||
if ((dev->regs[0x11] == 0x00) && ((dev->regs[0x0c] & 0x20) || (dev->regs[0x0c] & 0x10)))
|
||||
mem_set_mem_state(0xe0000, 0x10000, MEM_READ_EXTERNAL | MEM_WRITE_EXTERNAL);
|
||||
if (!(dev->regs[0x0f] & 0x0f) && !(dev->regs[0x0c] & 0x20))
|
||||
mem_set_mem_state(0xc0000, 0x8000, MEM_READ_EXTERNAL | MEM_WRITE_EXTERNAL);
|
||||
if (!(dev->regs[0x0f] & 0xf0) && !((dev->regs[0x0c] & 0x30) == 0x30))
|
||||
mem_set_mem_state(0xc8000, 0x8000, MEM_READ_EXTERNAL | MEM_WRITE_EXTERNAL);
|
||||
|
||||
flushmmucache();
|
||||
}
|
||||
|
||||
@@ -116,6 +150,8 @@ vl82c480_write(uint16_t addr, uint8_t val, void *priv)
|
||||
{
|
||||
vl82c480_t *dev = (vl82c480_t *) priv;
|
||||
|
||||
vl82c48x_log(dev->log, "[%04X:%08X] VL82c48x: [W] %04X = %02X\n", CS, cpu_state.pc, addr, val);
|
||||
|
||||
switch (addr) {
|
||||
case 0xec:
|
||||
dev->idx = val;
|
||||
@@ -146,6 +182,10 @@ vl82c480_write(uint16_t addr, uint8_t val, void *priv)
|
||||
case 0x07:
|
||||
dev->regs[dev->idx] = (dev->regs[dev->idx] & 0x40) | (val & 0xbf);
|
||||
break;
|
||||
case 0x0c:
|
||||
dev->regs[dev->idx] = val;
|
||||
vl82c480_recalc_shadow(dev);
|
||||
break;
|
||||
case 0x0d ... 0x12:
|
||||
dev->regs[dev->idx] = val;
|
||||
vl82c480_recalc_shadow(dev);
|
||||
@@ -195,6 +235,8 @@ vl82c480_read(uint16_t addr, void *priv)
|
||||
break;
|
||||
}
|
||||
|
||||
vl82c48x_log(dev->log, "[%04X:%08X] VL82c48x: [R] %04X = %02X\n", CS, cpu_state.pc, addr, ret);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
@@ -203,6 +245,11 @@ vl82c480_close(void *priv)
|
||||
{
|
||||
vl82c480_t *dev = (vl82c480_t *) priv;
|
||||
|
||||
if (dev->log != NULL) {
|
||||
log_close(dev->log);
|
||||
dev->log = NULL;
|
||||
}
|
||||
|
||||
free(dev);
|
||||
}
|
||||
|
||||
@@ -217,6 +264,8 @@ vl82c480_init(const device_t *info)
|
||||
uint8_t min_j = (machines[machine].init == machine_at_monsoon_init) ? 2 : 2;
|
||||
uint8_t max_j = (machines[machine].init == machine_at_monsoon_init) ? 7 : 7;
|
||||
|
||||
dev->log = log_open("VL82c48x");
|
||||
|
||||
dev->regs[0x00] = info->local;
|
||||
dev->regs[0x01] = 0xff;
|
||||
dev->regs[0x02] = 0x8a;
|
||||
|
||||
@@ -12,7 +12,7 @@
|
||||
* win2kgamer
|
||||
*
|
||||
* Copyright 2020-2025 Miran Grca.
|
||||
* Copyright 2025 win2kgamer
|
||||
* Copyright 2025-2026 win2kgamer
|
||||
*/
|
||||
#ifdef ENABLE_VL82C59X_LOG
|
||||
#include <stdarg.h>
|
||||
@@ -80,6 +80,9 @@ typedef struct vl82c59x_t {
|
||||
port_92_t *port_92;
|
||||
nvr_t *nvr;
|
||||
|
||||
uint32_t banks[4];
|
||||
uint8_t bankcfg[4];
|
||||
|
||||
void * log; /* New logging system */
|
||||
} vl82c59x_t;
|
||||
|
||||
@@ -207,6 +210,52 @@ vl82c59x_set_pm_io(void *priv)
|
||||
|
||||
}
|
||||
|
||||
void
|
||||
vl82c59x_recalc_banks(vl82c59x_t *dev)
|
||||
{
|
||||
uint32_t sizes[8] = { 2048, 4096, 8192, 16384, 32768, 65536, 131072, 262144 };
|
||||
uint8_t shifts[4] = { 0, 4, 0, 4 };
|
||||
uint8_t regs[4] = { 0x58, 0x58, 0x59, 0x59 };
|
||||
uint32_t total = 0;
|
||||
|
||||
for (uint8_t i = 0; i < 4; i++) {
|
||||
uint8_t shift = shifts[i];
|
||||
uint8_t reg = regs[i];
|
||||
uint8_t cfg = (dev->pci_conf[reg] >> shift) & 0x03; /* Module types */
|
||||
uint8_t dbl = ((dev->pci_conf[reg] >> shift) & 0x08) ? 1 : 0; /* Single/double sided */
|
||||
uint8_t conf = (cfg << 1) | (dbl & 0x01);
|
||||
uint32_t size = sizes[conf];
|
||||
|
||||
vl82c59x_log(dev->log, "VL82c59x DRAM recalc: bank %i, cfg = %02X, dbl = %i, conf = %02X, size = %i, RAMCTL0 = %02X\n", i, cfg, dbl, conf, size, dev->pci_conf[0x5c]);
|
||||
vl82c59x_log(dev->log, "VL82c59x DRAM recalc: bank %i size = %i\n", i, dev->banks[i]);
|
||||
|
||||
/* Handle case where the BIOS programs RAMCFGx for dual-sided/ranked memory when single-sided memory is installed */
|
||||
if (((dev->bankcfg[i] & 0x08) == 0x00) && dbl == 1) {
|
||||
size = sizes[conf - 1];
|
||||
vl82c59x_log(dev->log, "VL82c59x DRAM recalc: bank %i mismatch, bankcfg = %02X, reg = %02X\n", dev->bankcfg[i], dev->pci_conf[reg]);
|
||||
}
|
||||
|
||||
if (!(dev->pci_conf[0x5c] & (1 << i)))
|
||||
size = 0;
|
||||
|
||||
total += MIN(dev->banks[i], size);
|
||||
vl82c59x_log(dev->log, "VL82c59x DRAM recalc: bank %i, total = %i\n", i, total);
|
||||
}
|
||||
|
||||
if (total > 1024) {
|
||||
mem_mapping_set_addr(&ram_low_mapping, 0x00000000, 0x000a0000);
|
||||
mem_mapping_set_addr(&ram_high_mapping, 0x00100000, (total - 1024) << 10);
|
||||
} else {
|
||||
if (total >= 1024)
|
||||
mem_mapping_set_addr(&ram_low_mapping, 0x00000000, 0x000a0000);
|
||||
else
|
||||
mem_mapping_disable(&ram_low_mapping);
|
||||
mem_mapping_disable(&ram_high_mapping);
|
||||
}
|
||||
|
||||
flushmmucache();
|
||||
}
|
||||
|
||||
static void
|
||||
vl82c59x_write(int func, int addr, UNUSED(int len), uint8_t val, void *priv)
|
||||
{
|
||||
@@ -231,12 +280,21 @@ vl82c59x_write(int func, int addr, UNUSED(int len), uint8_t val, void *priv)
|
||||
case 0x58: /* RAMCFG0 */
|
||||
case 0x59: /* RAMCFG1 */
|
||||
dev->pci_conf[addr] = val;
|
||||
vl82c59x_log(dev->log, "VL82c59x: RAMCFGx write, RAMCFG0 = %02X, RAMCFG1 = %02X\n", dev->pci_conf[0x58], dev->pci_conf[0x59]);
|
||||
if (machines[machine].init == machine_at_bravoms586_init)
|
||||
vl82c59x_recalc_banks(dev);
|
||||
break;
|
||||
case 0x5a: /* Wildcat EDO RAM control */
|
||||
if (dev->type == 0x01)
|
||||
dev->pci_conf[addr] = val;
|
||||
break;
|
||||
case 0x5c ... 0x5e: /* RAMCTL0-RAMCTL2 */
|
||||
case 0x5c: /* RAMCTL0 */
|
||||
vl82c59x_log(dev->log, "VL82c59x: RAMCTL0 write\n");
|
||||
dev->pci_conf[addr] = val;
|
||||
if (machines[machine].init == machine_at_bravoms586_init)
|
||||
vl82c59x_recalc_banks(dev);
|
||||
break;
|
||||
case 0x5d ... 0x5e: /* RAMCTL1-RAMCTL2 */
|
||||
case 0x5f ... 0x60:
|
||||
case 0x62:
|
||||
/* Apricot XEN-PC Ruby/Jade BIOS requires bit 2 to be set or */
|
||||
@@ -483,6 +541,47 @@ vl82c59x_reset(void *priv)
|
||||
cpu_cache_int_enabled = 1;
|
||||
cpu_cache_ext_enabled = 1;
|
||||
cpu_update_waitstates();
|
||||
|
||||
/* Init DRAM bank registers */
|
||||
uint32_t sizes[8] = { 2048, 4096, 8192, 16384, 32768, 65536, 131072, 262144 };
|
||||
uint8_t reg_vals[8] = { 0x00, 0x08, 0x01, 0x09, 0x02, 0x0a, 0x03, 0x0b };
|
||||
uint32_t ms = mem_size;
|
||||
|
||||
dev->pci_conf[0x58] = 0x00; /* RAMCFG0 */
|
||||
dev->pci_conf[0x59] = 0x00; /* RAMCFG1 */
|
||||
dev->pci_conf[0x5c] = 0x00; /* RAMCTL0 */
|
||||
|
||||
|
||||
if (ms > 0) for (uint8_t i = 0; i < 4; i++ ) {
|
||||
for (uint8_t j = 0; j < 8; j++ ) {
|
||||
if (ms >= sizes[j] ) {
|
||||
dev->banks[i] = sizes[j];
|
||||
dev->bankcfg[i] = reg_vals[j];
|
||||
dev->pci_conf[0x5c] |= (1 << i);
|
||||
} else
|
||||
break;
|
||||
}
|
||||
|
||||
ms -= dev->banks[i];
|
||||
|
||||
if ((ms == 0 || dev->banks[i] == 0))
|
||||
break;
|
||||
}
|
||||
|
||||
for (uint8_t i = 0; i < 4; i++ ) {
|
||||
if (dev->banks[0] != 0)
|
||||
dev->pci_conf[0x58] = (dev->bankcfg[0] & 0x0f);
|
||||
if (dev->banks[1] != 0)
|
||||
dev->pci_conf[0x58] |= ((dev->bankcfg[1] & 0x0f) << 4);
|
||||
if (dev->banks[2] != 0)
|
||||
dev->pci_conf[0x59] = (dev->bankcfg[2] & 0x0f);
|
||||
if (dev->banks[3] != 0)
|
||||
dev->pci_conf[0x59] |= ((dev->bankcfg[3] & 0x0f) << 4);
|
||||
}
|
||||
|
||||
vl82c59x_log(dev->log, "VL82c59x: DRAM bank init, RAMCFG0 = %02X, RAMCFG1 = %02X, RAMCTL0 = %02X\n", dev->pci_conf[0x58], dev->pci_conf[0x59], dev->pci_conf[0x5c]);
|
||||
vl82c59x_log(dev->log, "VL82c59x: DRAM bank vals: %i, %i, %i, %i\n", dev->banks[0], dev->banks[1], dev->banks[2], dev->banks[3]);
|
||||
|
||||
}
|
||||
|
||||
static void
|
||||
|
||||
64
src/config.c
64
src/config.c
@@ -1016,27 +1016,37 @@ load_image_file(char *dest, char *p, uint8_t *ui_wp)
|
||||
int ret = 0;
|
||||
char *slash = NULL;
|
||||
char *above = NULL;
|
||||
char *above2 = NULL;
|
||||
char *use = NULL;
|
||||
|
||||
if ((slash = memrmem(usr_path + strlen(usr_path) - 2, usr_path, "/")) != NULL) {
|
||||
slash++;
|
||||
above = (char *) calloc(1, slash - usr_path + 1);
|
||||
memcpy(above, usr_path, slash - usr_path);
|
||||
|
||||
if ((slash = memrmem(above + strlen(above) - 2, above, "/")) != NULL) {
|
||||
slash++;
|
||||
above2 = (char *) calloc(1, slash - above + 1);
|
||||
memcpy(above2, above, slash - above);
|
||||
}
|
||||
}
|
||||
|
||||
if (strstr(p, "wp://") == p) {
|
||||
p += 5;
|
||||
prefix = "wp://";
|
||||
if (ui_wp != NULL)
|
||||
*ui_wp = 1;
|
||||
p += 5;
|
||||
prefix = "wp://";
|
||||
if (ui_wp != NULL)
|
||||
*ui_wp = 1;
|
||||
} else if ((ui_wp != NULL) && *ui_wp)
|
||||
prefix = "wp://";
|
||||
prefix = "wp://";
|
||||
|
||||
if (strstr(p, "ioctl://") == p) {
|
||||
if (strlen(p) > (MAX_IMAGE_PATH_LEN - 11))
|
||||
ret = 1;
|
||||
else
|
||||
snprintf(dest, MAX_IMAGE_PATH_LEN, "%s", p);
|
||||
if (strlen(p) > (MAX_IMAGE_PATH_LEN - 11))
|
||||
ret = 1;
|
||||
else
|
||||
snprintf(dest, MAX_IMAGE_PATH_LEN, "%s", p);
|
||||
|
||||
if (above2 != NULL)
|
||||
free(above2);
|
||||
|
||||
if (above != NULL)
|
||||
free(above);
|
||||
@@ -1051,6 +1061,13 @@ load_image_file(char *dest, char *p, uint8_t *ui_wp)
|
||||
else
|
||||
snprintf(dest, MAX_IMAGE_PATH_LEN, "%s%s%s%s", prefix, exe_path, path_get_slash(exe_path),
|
||||
p + strlen("<exe_path>/"));
|
||||
} else if (memcmp(p, "../../", strlen("../../")) == 0) {
|
||||
use = (above2 == NULL) ? usr_path : above2;
|
||||
if ((strlen(prefix) + strlen(use) + strlen(path_get_slash(use)) + strlen(p + strlen("../../"))) >
|
||||
(MAX_IMAGE_PATH_LEN - 11))
|
||||
ret = 1;
|
||||
else
|
||||
snprintf(dest, MAX_IMAGE_PATH_LEN, "%s%s%s%s", prefix, use, path_get_slash(use), p + strlen("../../"));
|
||||
} else if (memcmp(p, "../", strlen("../")) == 0) {
|
||||
use = (above == NULL) ? usr_path : above;
|
||||
if ((strlen(prefix) + strlen(use) + strlen(path_get_slash(use)) + strlen(p + strlen("../"))) >
|
||||
@@ -1072,6 +1089,9 @@ load_image_file(char *dest, char *p, uint8_t *ui_wp)
|
||||
|
||||
path_normalize(dest);
|
||||
|
||||
if (above2 != NULL)
|
||||
free(above2);
|
||||
|
||||
if (above != NULL)
|
||||
free(above);
|
||||
|
||||
@@ -3146,11 +3166,25 @@ save_image_file(char *cat, char *var, char *src)
|
||||
char *prefix = "";
|
||||
char *slash = NULL;
|
||||
char *above = NULL;
|
||||
char *above2 = NULL;
|
||||
char *above3 = NULL;
|
||||
|
||||
if ((slash = memrmem(usr_path + strlen(usr_path) - 2, usr_path, "/")) != NULL) {
|
||||
slash++;
|
||||
above = (char *) calloc(1, slash - usr_path + 1);
|
||||
memcpy(above, usr_path, slash - usr_path);
|
||||
|
||||
if ((slash = memrmem(above + strlen(above) - 2, above, "/")) != NULL) {
|
||||
slash++;
|
||||
above2 = (char *) calloc(1, slash - above + 1);
|
||||
memcpy(above2, above, slash - above);
|
||||
|
||||
if ((slash = memrmem(above2 + strlen(above2) - 2, above2, "/")) != NULL) {
|
||||
slash++;
|
||||
above3 = (char *) calloc(1, slash - above2 + 1);
|
||||
memcpy(above3, above2, slash - above2);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
path_normalize(src);
|
||||
@@ -3164,7 +3198,11 @@ save_image_file(char *cat, char *var, char *src)
|
||||
sprintf(temp, "%s", src);
|
||||
else if (!strnicmp(src, usr_path, strlen(usr_path)))
|
||||
sprintf(temp, "%s%s", prefix, &src[strlen(usr_path)]);
|
||||
else if ((above != NULL) && !strnicmp(src, above, strlen(above)))
|
||||
/* Do not relativize to root. */
|
||||
else if ((above2 != NULL) && (above3 != NULL) && !strnicmp(src, above2, strlen(above2)))
|
||||
sprintf(temp, "../../%s%s", prefix, &src[strlen(above2)]);
|
||||
/* Do not relativize to root. */
|
||||
else if ((above != NULL) && (above2 != NULL) && !strnicmp(src, above, strlen(above)))
|
||||
sprintf(temp, "../%s%s", prefix, &src[strlen(above)]);
|
||||
else if (!strnicmp(src, exe_path, strlen(exe_path)))
|
||||
sprintf(temp, "<exe_path>/%s%s", prefix, &src[strlen(exe_path)]);
|
||||
@@ -3173,6 +3211,12 @@ save_image_file(char *cat, char *var, char *src)
|
||||
|
||||
ini_section_set_string(cat, var, temp);
|
||||
|
||||
if (above3 != NULL)
|
||||
free(above3);
|
||||
|
||||
if (above2 != NULL)
|
||||
free(above2);
|
||||
|
||||
if (above != NULL)
|
||||
free(above);
|
||||
}
|
||||
|
||||
@@ -2184,7 +2184,7 @@ read_p1(atkbc_t *dev)
|
||||
-----------------
|
||||
IBM PS/1: xxxxxxxx
|
||||
IBM PS/2 MCA: xxxxx1xx
|
||||
IBM PS/2 Model 30-286: xxxxx1xx
|
||||
IBM PS/2 Model 30-286: x0xxx1xx
|
||||
Intel AMI Pentium BIOS'es with AMI MegaKey KB-5 keyboard controller: x1x1xxxx
|
||||
Acer: xxxxx0xx
|
||||
Packard Bell PB450: xxxxx1xx
|
||||
@@ -2199,7 +2199,8 @@ read_p1(atkbc_t *dev)
|
||||
Acer: Pull down bit 6 if primary display is MDA.
|
||||
Pull down bit 2 always (must be so to enable CMOS Setup).
|
||||
IBM PS/1: Pull down bit 6 if current floppy drive is 3.5".
|
||||
IBM PS/2 Model 30-286: Pull down bits 5 and 4 based on planar memory size.
|
||||
IBM PS/2 Model 30-286: Pull down bit 6 always (for 1.44M floppy).
|
||||
Pull down bits 5 and 4 based on planar memory size.
|
||||
Epson Action Tower 2600: Pull down bit 3 always (for Epson logo).
|
||||
NCR: Pull down bit 5 always (power-on default speed = high).
|
||||
Pull down bit 3 if there is no FPU.
|
||||
@@ -2215,6 +2216,7 @@ read_p1(atkbc_t *dev)
|
||||
Bit 6: Mostly, display: 0 = CGA, 1 = MDA, inverted on Xi8088 and Acer KBC's;
|
||||
Intel AMI MegaKey KB-5: Used for green features, SMM handler expects it to be set;
|
||||
IBM PS/1 Model 2011: 0 = current FDD is 3.5", 1 = current FDD is 5.25";
|
||||
IBM PS/2 Model 30-286: 0 = drive A is 1.44M, 1 = drive A is 720k;
|
||||
Compaq: 0 = Compaq dual-scan display, 1 = non-Compaq display.
|
||||
Bit 5: Mostly, manufacturing jumper: 0 = installed (infinite loop at POST), 1 = not installed;
|
||||
NCR: power-on default speed: 0 = high, 1 = low;
|
||||
|
||||
@@ -52,6 +52,14 @@
|
||||
Bit 0 = ????
|
||||
*/
|
||||
|
||||
/*
|
||||
Intel Monsoon bit meanings:
|
||||
Bit 5 = Password enable
|
||||
Bit 4 = Onboard video: 1 = disabled, 0 = enabled
|
||||
Bit 3 = CMOS Setup enable
|
||||
Bit 2 = CMOS clear: 1 = normal, 0 = clear CMOS
|
||||
*/
|
||||
|
||||
typedef struct phoenix_486_jumper_t {
|
||||
uint8_t type;
|
||||
uint8_t jumper;
|
||||
@@ -84,7 +92,11 @@ phoenix_486_jumper_write(UNUSED(uint16_t addr), uint8_t val, void *priv)
|
||||
dev->jumper = val & 0xbf;
|
||||
else if (dev->type == 2) /* PB600 */
|
||||
dev->jumper = ((val & 0xbf) | 0x02);
|
||||
else
|
||||
else if (dev->type == 3) { /* Intel Monsoon */
|
||||
dev->jumper = ((val & 0xef) | 0x2c);
|
||||
if (gfxcard[0] != 0x01)
|
||||
dev->jumper |= 0x10;
|
||||
} else
|
||||
dev->jumper = val;
|
||||
}
|
||||
|
||||
@@ -106,7 +118,11 @@ phoenix_486_jumper_reset(void *priv)
|
||||
dev->jumper = 0x00;
|
||||
else if (dev->type == 2) /* PB600 */
|
||||
dev->jumper = 0x02;
|
||||
else {
|
||||
else if (dev->type == 3) { /* Intel Monsoon */
|
||||
dev->jumper = 0x2c;
|
||||
if (gfxcard[0] != 0x01)
|
||||
dev->jumper |= 0x10;
|
||||
} else {
|
||||
dev->jumper = 0x9f;
|
||||
if (gfxcard[0] != 0x01)
|
||||
dev->jumper |= 0x40;
|
||||
@@ -176,3 +192,18 @@ const device_t phoenix_486_jumper_pci_pb600_device = {
|
||||
.force_redraw = NULL,
|
||||
.config = NULL
|
||||
};
|
||||
|
||||
const device_t phoenix_486_jumper_monsoon_device = {
|
||||
.name = "Phoenix 486 Jumper Readout (Monsoon)",
|
||||
.internal_name = "phoenix_486_jumper_monsoon",
|
||||
.flags = 0,
|
||||
.local = 3,
|
||||
.init = phoenix_486_jumper_init,
|
||||
.close = phoenix_486_jumper_close,
|
||||
.reset = phoenix_486_jumper_reset,
|
||||
.available = NULL,
|
||||
.speed_changed = NULL,
|
||||
.force_redraw = NULL,
|
||||
.config = NULL
|
||||
};
|
||||
|
||||
|
||||
@@ -381,6 +381,7 @@ typedef struct hdc_t {
|
||||
pc_timer_t timer;
|
||||
int8_t state; /* controller state */
|
||||
int8_t reset; /* reset state counter */
|
||||
int8_t ready; /* ready state counter */
|
||||
|
||||
/* Data transfer. */
|
||||
int16_t buf_idx; /* buffer index and pointer */
|
||||
@@ -723,6 +724,15 @@ hdc_callback(void *priv)
|
||||
uint8_t cmd = ccb->cmd & 0x0f;
|
||||
#endif
|
||||
|
||||
/* If we are returning from a RESET, handle this first. */
|
||||
if (dev->reset) {
|
||||
ps1_hdc_log("XTA reset.\n");
|
||||
dev->status &= ~ASR_BUSY;
|
||||
dev->reset = 0;
|
||||
do_finish(dev);
|
||||
return;
|
||||
}
|
||||
|
||||
/* Clear the SSB error bits. */
|
||||
dev->ssb.track_0 = 0;
|
||||
dev->ssb.cylinder_err = 0;
|
||||
@@ -754,6 +764,12 @@ hdc_callback(void *priv)
|
||||
return;
|
||||
}
|
||||
|
||||
if (!(dev->ready | no_data)) {
|
||||
/* Delay a bit, transfer not ready. */
|
||||
timer_advance_u64(&dev->timer, HDC_TIME);
|
||||
return;
|
||||
}
|
||||
|
||||
switch (dev->state) {
|
||||
case STATE_IDLE:
|
||||
/* Seek to cylinder if requested. */
|
||||
@@ -937,9 +953,6 @@ do_send:
|
||||
break;
|
||||
|
||||
case CMD_WRITE_VERIFY:
|
||||
no_data = 1;
|
||||
fallthrough;
|
||||
|
||||
case CMD_WRITE_SECTORS:
|
||||
if (!drive->present) {
|
||||
dev->ssb.not_ready = 1;
|
||||
@@ -947,6 +960,12 @@ do_send:
|
||||
return;
|
||||
}
|
||||
|
||||
if (!(dev->ready | no_data)) {
|
||||
/* Delay a bit, transfer not ready. */
|
||||
timer_advance_u64(&dev->timer, HDC_TIME);
|
||||
return;
|
||||
}
|
||||
|
||||
switch (dev->state) {
|
||||
case STATE_IDLE:
|
||||
/* Seek to cylinder if requested. */
|
||||
@@ -1231,24 +1250,21 @@ hdc_write(uint16_t port, uint8_t val, void *priv)
|
||||
if (val & ACR_INT_EN)
|
||||
set_intr(dev, 0); /* clear IRQ */
|
||||
|
||||
if (dev->reset != 0) {
|
||||
if (++dev->reset == 3) {
|
||||
dev->reset = 0;
|
||||
|
||||
set_intr(dev, 1);
|
||||
}
|
||||
break;
|
||||
if (val & ACR_RESET) {
|
||||
dev->reset = 1;
|
||||
dev->status |= ASR_BUSY;
|
||||
/* Schedule command execution. */
|
||||
timer_set_delay_u64(&dev->timer, HDC_TIME);
|
||||
}
|
||||
|
||||
if (val & ACR_RESET)
|
||||
dev->reset = 1;
|
||||
break;
|
||||
|
||||
case 4: /* ATTN */
|
||||
dev->status &= ~ASR_INT_REQ;
|
||||
if (val & ATT_DATA) {
|
||||
/* Dunno. Start PIO/DMA now? */
|
||||
}
|
||||
if (val & ATT_DATA)
|
||||
dev->ready = 1;
|
||||
else
|
||||
dev->ready = 0;
|
||||
|
||||
if (val & ATT_SSB) {
|
||||
if (dev->attn & ATT_CCB) {
|
||||
|
||||
@@ -234,6 +234,7 @@ extern const device_t nec_mate_unk_device;
|
||||
extern const device_t phoenix_486_jumper_device;
|
||||
extern const device_t phoenix_486_jumper_pci_device;
|
||||
extern const device_t phoenix_486_jumper_pci_pb600_device;
|
||||
extern const device_t phoenix_486_jumper_monsoon_device;
|
||||
|
||||
extern const device_t ast_readout_device;
|
||||
extern const device_t ast_nvr_device;
|
||||
|
||||
@@ -31,6 +31,43 @@
|
||||
#define PCI_REG_LATENCY_TIMER 0x0d
|
||||
#define PCI_REG_HEADER_TYPE 0x0e
|
||||
#define PCI_REG_BIST 0x0f
|
||||
#define PCI_REG_BAR0_BYTE0 0x10
|
||||
#define PCI_REG_BAR0_BYTE1 0x11
|
||||
#define PCI_REG_BAR0_BYTE2 0x12
|
||||
#define PCI_REG_BAR0_BYTE3 0x13
|
||||
#define PCI_REG_BAR1_BYTE0 0x14
|
||||
#define PCI_REG_BAR1_BYTE1 0x15
|
||||
#define PCI_REG_BAR1_BYTE2 0x16
|
||||
#define PCI_REG_BAR1_BYTE3 0x17
|
||||
#define PCI_REG_BAR2_BYTE0 0x18
|
||||
#define PCI_REG_BAR2_BYTE1 0x19
|
||||
#define PCI_REG_BAR2_BYTE2 0x1a
|
||||
#define PCI_REG_BAR2_BYTE3 0x1b
|
||||
#define PCI_REG_BAR3_BYTE0 0x1c
|
||||
#define PCI_REG_BAR3_BYTE1 0x1d
|
||||
#define PCI_REG_BAR3_BYTE2 0x1e
|
||||
#define PCI_REG_BAR3_BYTE3 0x1e
|
||||
#define PCI_REG_BAR4_BYTE0 0x20
|
||||
#define PCI_REG_BAR4_BYTE1 0x21
|
||||
#define PCI_REG_BAR4_BYTE2 0x22
|
||||
#define PCI_REG_BAR4_BYTE3 0x23
|
||||
#define PCI_REG_BAR5_BYTE0 0x24
|
||||
#define PCI_REG_BAR5_BYTE1 0x25
|
||||
#define PCI_REG_BAR5_BYTE2 0x26
|
||||
#define PCI_REG_BAR5_BYTE3 0x27
|
||||
#define PCI_REG_SUBVEN_ID_L 0x2c
|
||||
#define PCI_REG_SUBVEN_ID_H 0x2d
|
||||
#define PCI_REG_SUBSYS_ID_L 0x2e
|
||||
#define PCI_REG_SUBSYS_ID_H 0x2f
|
||||
#define PCI_REG_ROM_BAR_BYTE0 0x30
|
||||
#define PCI_REG_ROM_BAR_BYTE1 0x31
|
||||
#define PCI_REG_ROM_BAR_BYTE2 0x32
|
||||
#define PCI_REG_ROM_BAR_BYTE3 0x33
|
||||
#define PCI_REG_CAPS_PTR 0x34
|
||||
#define PCI_REG_INT_LINE 0x3c
|
||||
#define PCI_REG_INT_PIN 0x3d
|
||||
#define PCI_REG_MIN_GRANT 0x3e
|
||||
#define PCI_REG_MAX_LAT 0x3f
|
||||
|
||||
#define PCI_COMMAND_L_IO 0x01
|
||||
#define PCI_COMMAND_L_MEM 0x02
|
||||
|
||||
@@ -84,6 +84,7 @@ typedef struct ncr_t {
|
||||
int (*dma_send_ext)(void *priv, void *ext_priv);
|
||||
int (*dma_initiator_receive_ext)(void *priv, void *ext_priv);
|
||||
void (*timer)(void *ext_priv, double period);
|
||||
int (*irq_ena)(void *priv, void *ext_priv, int state);
|
||||
|
||||
scsi_bus_t scsibus;
|
||||
} ncr_t;
|
||||
|
||||
19
src/include/86box/scsi_qlogic.h
Normal file
19
src/include/86box/scsi_qlogic.h
Normal file
@@ -0,0 +1,19 @@
|
||||
/*
|
||||
* 86Box A hypervisor and IBM PC system emulator that specializes in
|
||||
* running old operating systems and software designed for IBM
|
||||
* PC systems and compatibles from 1981 through fairly recent
|
||||
* system designs based on the PCI bus.
|
||||
*
|
||||
* Emulation of QLogic QLA1x40/QLA1x80/QLA1x160 SCSI HBA.
|
||||
*
|
||||
* Authors: Dmitry Borisov, <di.sean@protonmail.com>
|
||||
*
|
||||
* Copyright 2026 Dmitry Borisov
|
||||
*/
|
||||
#pragma once
|
||||
|
||||
extern const device_t qla1040b_device;
|
||||
extern const device_t qla1080_device;
|
||||
extern const device_t qla1240_device;
|
||||
extern const device_t qla1280_device;
|
||||
extern const device_t qla12160a_device;
|
||||
@@ -15,7 +15,7 @@
|
||||
*
|
||||
* Copyright 2008-2018 Sarah Walker.
|
||||
* Copyright 2016-2018 Miran Grca.
|
||||
* Copyright 2024-2025 Jasmine Iwanek.
|
||||
* Copyright 2024-2026 Jasmine Iwanek.
|
||||
*/
|
||||
#ifndef SOUND_SND_SB_H
|
||||
#define SOUND_SND_SB_H
|
||||
@@ -28,12 +28,14 @@
|
||||
|
||||
enum {
|
||||
SADLIB = 1, /* No DSP */
|
||||
SB_DSP_105, /* DSP v1.05, Original CT1320 (Also known as CT1310) */
|
||||
SB_DSP_103, /* DSP v1.03, "killer card" prototype (Also known as CT1310) */
|
||||
SB_DSP_105, /* DSP v1.05, Original CT1320 */
|
||||
SB_DSP_200, /* DSP v2.00 */
|
||||
SB_DSP_201, /* DSP v2.01 - needed for high-speed DMA, Seen on CT1350B with CT1336 */
|
||||
SB_DSP_202, /* DSP v2.02 - Seen on CT1350B with CT1336A */
|
||||
SBPRO_DSP_300, /* DSP v3.00 */
|
||||
SBPRO2_DSP_302, /* DSP v3.02 + OPL3 */
|
||||
SBPRO_DSP_301, /* DSP v3.01 */
|
||||
SBPRO_DSP_302, /* DSP v3.02 */
|
||||
SB16_DSP_404, /* DSP v4.05 + OPL3 */
|
||||
SB16_DSP_405, /* DSP v4.05 + OPL3 */
|
||||
SB16_DSP_406, /* DSP v4.06 + OPL3 */
|
||||
|
||||
@@ -9,8 +9,9 @@
|
||||
#define SB_SUBTYPE_CLONE_AZT1605_0X0C 2 /* Aztech Sound Galaxy Nova 16 Extra /
|
||||
Packard Bell Forte 16, DSP 2.1 - SBPRO2 clone */
|
||||
#define SB_SUBTYPE_CLONE_AZTPR16_0X09 3 /* Aztech Sound Galaxy Pro 16 Extra */
|
||||
#define SB_SUBTYPE_ESS_ES688 4 /* ESS Technology ES688 */
|
||||
#define SB_SUBTYPE_ESS_ES1688 5 /* ESS Technology ES1688 */
|
||||
#define SB_SUBTYPE_MVD201 4 /* Mediavision MVD201, found on the thunderboard and PAS16 */
|
||||
#define SB_SUBTYPE_ESS_ES688 5 /* ESS Technology ES688 */
|
||||
#define SB_SUBTYPE_ESS_ES1688 6 /* ESS Technology ES1688 */
|
||||
|
||||
/* ESS-related */
|
||||
#define IS_ESS(dsp) ((dsp)->sb_subtype >= SB_SUBTYPE_ESS_ES688) /* Check for future ESS cards here */
|
||||
@@ -20,6 +21,9 @@
|
||||
#define IS_AZTECH(dsp) ((dsp)->sb_subtype == SB_SUBTYPE_CLONE_AZT2316A_0X11 || (dsp)->sb_subtype == SB_SUBTYPE_CLONE_AZT1605_0X0C || (dsp)->sb_subtype == SB_SUBTYPE_CLONE_AZTPR16_0X09) /* check for future AZT cards here */
|
||||
#define AZTECH_EEPROM_SIZE 36
|
||||
|
||||
/* MediaVision related */
|
||||
#define IS_MV201(dsp) ((dsp)->sb_subtype >= SB_SUBTYPE_MVD201)
|
||||
|
||||
typedef struct sb_dsp_t {
|
||||
int sb_type;
|
||||
int sb_subtype; /* which clone */
|
||||
@@ -102,6 +106,7 @@ typedef struct sb_dsp_t {
|
||||
int sbreset;
|
||||
uint8_t sbreaddat;
|
||||
uint8_t sb_command;
|
||||
uint8_t sb_last_command;
|
||||
uint8_t sb_test;
|
||||
int sb_timei;
|
||||
int sb_timeo;
|
||||
|
||||
@@ -228,6 +228,9 @@ extern const device_t entertainer_device;
|
||||
/* Mindscape Music Board */
|
||||
extern const device_t mmb_device;
|
||||
|
||||
/* MediaVision ThunderBoard */
|
||||
extern const device_t thunderboard_device;
|
||||
|
||||
/* OPTi 82c93x */
|
||||
extern const device_t acermagic_s20_device;
|
||||
extern const device_t mirosound_pcm10_device;
|
||||
|
||||
@@ -65,6 +65,7 @@ typedef union {
|
||||
|
||||
typedef struct ibm8514_t {
|
||||
rom_t bios_rom;
|
||||
rom_t bios_rom2;
|
||||
uint8_t *rom1;
|
||||
uint8_t *rom2;
|
||||
hwcursor8514_t hwcursor;
|
||||
@@ -187,6 +188,7 @@ typedef struct ibm8514_t {
|
||||
uint32_t dst_ge_offset;
|
||||
uint16_t src_pitch;
|
||||
uint16_t dst_pitch;
|
||||
uint16_t read_pixel;
|
||||
int64_t cur_x_24bpp;
|
||||
int64_t cur_y_24bpp;
|
||||
int64_t dest_x_24bpp;
|
||||
|
||||
@@ -1300,7 +1300,7 @@ voodoo_generate(uint8_t *code_block, voodoo_t *voodoo, voodoo_params_t *params,
|
||||
addbyte(0x35); /*XOR EAX, 0xff*/
|
||||
addlong(0xff);
|
||||
}
|
||||
addbyte(0x8e); /*ADD EAX, 1*/
|
||||
addbyte(0x83); /*ADD EAX, 1*/
|
||||
addbyte(0xc0);
|
||||
addbyte(1);
|
||||
addbyte(0x0f); /*IMUL EAX, EBX*/
|
||||
@@ -2327,7 +2327,7 @@ voodoo_generate(uint8_t *code_block, voodoo_t *voodoo, voodoo_params_t *params,
|
||||
addlong(offsetof(voodoo_state_t, z));
|
||||
addbyte(0xc1); /*SHR EAX, 12*/
|
||||
addbyte(0xe8);
|
||||
addbyte(12);
|
||||
addbyte(20);
|
||||
addbyte(0x25); /*AND EAX, 0xff*/
|
||||
addlong(0xff);
|
||||
#if 0
|
||||
|
||||
@@ -375,6 +375,7 @@ extern const device_t gd5401_isa_device;
|
||||
extern const device_t gd5401_onboard_device;
|
||||
extern const device_t gd5402_isa_device;
|
||||
extern const device_t gd5402_onboard_device;
|
||||
extern const device_t gd5402_onboard_commodore_device;
|
||||
extern const device_t gd5420_isa_device;
|
||||
extern const device_t gd5420_onboard_device;
|
||||
extern const device_t gd5422_isa_device;
|
||||
@@ -383,9 +384,11 @@ extern const device_t gd5424_onboard_device;
|
||||
extern const device_t gd5426_isa_device;
|
||||
extern const device_t gd5426_diamond_speedstar_pro_a1_isa_device;
|
||||
extern const device_t gd5426_vlb_device;
|
||||
extern const device_t gd5426_onboard_isa_device;
|
||||
extern const device_t gd5426_onboard_device;
|
||||
extern const device_t gd5428_isa_device;
|
||||
extern const device_t gd5428_vlb_onboard_device;
|
||||
extern const device_t gd5428_vlb_onboard_tandy_device;
|
||||
extern const device_t gd5428_vlb_device;
|
||||
extern const device_t gd5428_diamond_speedstar_pro_b1_vlb_device;
|
||||
extern const device_t gd5428_boca_isa_device;
|
||||
|
||||
@@ -586,7 +586,7 @@ machine_at_cmdsl386sx25_init(const machine_t *model)
|
||||
return ret;
|
||||
|
||||
if (gfxcard[0] == VID_INTERNAL)
|
||||
device_add(&gd5402_onboard_device);
|
||||
device_add(&gd5402_onboard_commodore_device);
|
||||
|
||||
machine_at_common_init_ex(model, 2);
|
||||
|
||||
|
||||
@@ -294,11 +294,13 @@ machine_at_vect486vl_init(const machine_t *model) // has HDC problems
|
||||
int ret;
|
||||
|
||||
ret = bios_load_linear("roms/machines/vect486vl/aa0500.ami",
|
||||
0x000e0000, 131072, 0);
|
||||
0x000c0000, 262144, 0);
|
||||
|
||||
if (bios_only || !ret)
|
||||
return ret;
|
||||
|
||||
memcpy(&rom[0x00020000], rom, 131072);
|
||||
|
||||
if (gfxcard[0] == VID_INTERNAL)
|
||||
device_add(machine_get_vid_device(machine));
|
||||
|
||||
@@ -311,6 +313,15 @@ machine_at_vect486vl_init(const machine_t *model) // has HDC problems
|
||||
device_add(&ide_isa_device);
|
||||
device_add_params(&fdc37c6xx_device, (void *) (FDC37C651 | FDC37C6XX_IDE_PRI));
|
||||
|
||||
video_reset(gfxcard[0]);
|
||||
|
||||
if (gfxcard[0] != VID_INTERNAL) {
|
||||
for (uint16_t i = 0; i < 32768; i++)
|
||||
rom[i] = mem_readb_phys(0x000c0000 + i);
|
||||
}
|
||||
mem_mapping_set_addr(&bios_mapping, 0x0c0000, 0x40000);
|
||||
mem_mapping_set_exec(&bios_mapping, rom);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
@@ -321,11 +332,13 @@ machine_at_d824_init(const machine_t *model)
|
||||
int ret;
|
||||
|
||||
ret = bios_load_linear("roms/machines/d824/fts-biosupdated824noflashbiosepromv320-320334-160.bin",
|
||||
0x000e0000, 131072, 0);
|
||||
0x000c0000, 262144, 0);
|
||||
|
||||
if (bios_only || !ret)
|
||||
return ret;
|
||||
|
||||
memcpy(&rom[0x00020000], rom, 131072);
|
||||
|
||||
if (gfxcard[0] == VID_INTERNAL)
|
||||
device_add(machine_get_vid_device(machine));
|
||||
|
||||
@@ -342,6 +355,15 @@ machine_at_d824_init(const machine_t *model)
|
||||
device_add(&ide_isa_device);
|
||||
device_add_params(&fdc37c6xx_device, (void *) FDC37C651);
|
||||
|
||||
video_reset(gfxcard[0]);
|
||||
|
||||
if (gfxcard[0] != VID_INTERNAL) {
|
||||
for (uint16_t i = 0; i < 32768; i++)
|
||||
rom[i] = mem_readb_phys(0x000c0000 + i);
|
||||
}
|
||||
mem_mapping_set_addr(&bios_mapping, 0x0c0000, 0x40000);
|
||||
mem_mapping_set_exec(&bios_mapping, rom);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
@@ -389,6 +389,7 @@ machine_at_monsoon_init(const machine_t *model)
|
||||
device_add_params(&fdc37c6xx_device, (void *) (FDC37C651 | FDC37C6XX_IDE_PRI));
|
||||
|
||||
device_add(&intel_flash_bxt_device);
|
||||
device_add(&phoenix_486_jumper_monsoon_device);
|
||||
|
||||
if (gfxcard[0] == VID_INTERNAL)
|
||||
device_add(machine_get_vid_device(machine));
|
||||
|
||||
@@ -59,12 +59,12 @@ machine_at_p5a_init(const machine_t *model)
|
||||
pci_register_slot(0x0F, PCI_CARD_SOUTHBRIDGE_IDE, 1, 2, 3, 4);
|
||||
pci_register_slot(0x03, PCI_CARD_SOUTHBRIDGE_PMU, 1, 2, 3, 4);
|
||||
pci_register_slot(0x02, PCI_CARD_SOUTHBRIDGE_USB, 1, 2, 3, 4);
|
||||
pci_register_slot(0x0C, PCI_CARD_NORMAL, 1, 2, 3, 4);
|
||||
pci_register_slot(0x0B, PCI_CARD_NORMAL, 2, 3, 4, 1);
|
||||
pci_register_slot(0x0A, PCI_CARD_NORMAL, 3, 4, 1, 2);
|
||||
pci_register_slot(0x09, PCI_CARD_NORMAL, 4, 1, 2, 3);
|
||||
pci_register_slot(0x0A, PCI_CARD_NORMAL, 3, 4, 1, 2);
|
||||
pci_register_slot(0x0B, PCI_CARD_NORMAL, 2, 3, 4, 1);
|
||||
pci_register_slot(0x0C, PCI_CARD_NORMAL, 1, 2, 3, 4);
|
||||
pci_register_slot(0x0D, PCI_CARD_NORMAL, 4, 1, 2, 3);
|
||||
pci_register_slot(0x06, PCI_CARD_NORMAL, 3, 4, 1, 2);
|
||||
pci_register_slot(0x06, PCI_CARD_SOUND, 3, 4, 1, 2);
|
||||
|
||||
device_add(&ali1541_device);
|
||||
device_add(&ali1543c_device); /* +0 */
|
||||
|
||||
@@ -264,18 +264,18 @@ machine_ps2_isa_p1_handler(void)
|
||||
|
||||
switch (mem_size / 1024) {
|
||||
case 0: /*256Kx2*/
|
||||
mem_p1 = 0xf0;
|
||||
mem_p1 = 0xb0;
|
||||
break;
|
||||
case 1: /*256Kx4*/
|
||||
mem_p1 = 0xe0;
|
||||
mem_p1 = 0xa0;
|
||||
break;
|
||||
case 2: /*1Mx2*/
|
||||
case 3:
|
||||
mem_p1 = 0xd0;
|
||||
mem_p1 = 0x90;
|
||||
break;
|
||||
case 4: /*1Mx4*/
|
||||
default:
|
||||
mem_p1 = 0xc0;
|
||||
mem_p1 = 0x80;
|
||||
break;
|
||||
}
|
||||
|
||||
|
||||
@@ -2167,7 +2167,7 @@ const machine_t machines[] = {
|
||||
.kbd_device = &keyboard_pc_xt_device,
|
||||
.fdc_device = NULL,
|
||||
.sio_device = NULL,
|
||||
.vid_device = &cga_device,
|
||||
.vid_device = &v6355d_device,
|
||||
.snd_device = NULL,
|
||||
.net_device = NULL
|
||||
},
|
||||
@@ -5905,7 +5905,7 @@ const machine_t machines[] = {
|
||||
.kbd_device = NULL,
|
||||
.fdc_device = NULL,
|
||||
.sio_device = NULL,
|
||||
.vid_device = &gd5402_onboard_device,
|
||||
.vid_device = &gd5402_onboard_commodore_device,
|
||||
.snd_device = NULL,
|
||||
.net_device = NULL
|
||||
},
|
||||
@@ -7779,7 +7779,7 @@ const machine_t machines[] = {
|
||||
.kbd_device = NULL,
|
||||
.fdc_device = NULL,
|
||||
.sio_device = NULL, /*Has SIO (sorta): VLSI VL82C113A SCAMP Combination I/O*/
|
||||
.vid_device = &gd5428_onboard_device,
|
||||
.vid_device = &gd5426_onboard_isa_device,
|
||||
.snd_device = NULL,
|
||||
.net_device = NULL
|
||||
},
|
||||
@@ -7893,7 +7893,7 @@ const machine_t machines[] = {
|
||||
.max_multi = 0
|
||||
},
|
||||
.bus_flags = MACHINE_PS2,
|
||||
.flags = MACHINE_IDE | MACHINE_SOUND | MACHINE_GAMEPORT | MACHINE_APM,
|
||||
.flags = MACHINE_IDE | MACHINE_SOUND | MACHINE_GAMEPORT,
|
||||
.ram = {
|
||||
.min = 2048,
|
||||
.max = 32768,
|
||||
@@ -8620,7 +8620,7 @@ const machine_t machines[] = {
|
||||
.kbd_device = NULL,
|
||||
.fdc_device = NULL,
|
||||
.sio_device = NULL,
|
||||
.vid_device = &gd5428_vlb_onboard_device,
|
||||
.vid_device = &gd5428_onboard_vlb_device,
|
||||
.snd_device = NULL,
|
||||
.net_device = NULL
|
||||
},
|
||||
@@ -8670,7 +8670,7 @@ const machine_t machines[] = {
|
||||
},
|
||||
/* Has a VLSI VL82C113A SCAMP Combination I/O which holds the KBC. */
|
||||
{
|
||||
.name = "[VLSI 82C486] Tandy Sensation! II (25-1651)/3100/MMPC",
|
||||
.name = "[VLSI 82C486] Tandy Sensation! II (25-1651)",
|
||||
.internal_name = "sensation2",
|
||||
.type = MACHINE_TYPE_486_S2,
|
||||
.chipset = MACHINE_CHIPSET_VLSI_VL82C486,
|
||||
@@ -8690,7 +8690,7 @@ const machine_t machines[] = {
|
||||
.max_multi = 0
|
||||
},
|
||||
.bus_flags = MACHINE_PS2,
|
||||
.flags = MACHINE_IDE | MACHINE_VIDEO | MACHINE_APM,
|
||||
.flags = MACHINE_IDE | MACHINE_VIDEO,
|
||||
.ram = {
|
||||
.min = 2048,
|
||||
.max = 65536,
|
||||
@@ -8708,7 +8708,7 @@ const machine_t machines[] = {
|
||||
.kbd_device = NULL,
|
||||
.fdc_device = NULL,
|
||||
.sio_device = NULL,
|
||||
.vid_device = &gd5428_vlb_onboard_device,
|
||||
.vid_device = &gd5428_vlb_onboard_tandy_device,
|
||||
.snd_device = NULL,
|
||||
.net_device = NULL
|
||||
},
|
||||
|
||||
@@ -348,8 +348,9 @@ endif()
|
||||
|
||||
if(WIN32)
|
||||
target_sources(plat PRIVATE win_cdrom_ioctl.c)
|
||||
elseif(UNIX AND NOT APPLE)
|
||||
target_sources(plat PRIVATE ../unix/linux_cdrom_ioctl.c)
|
||||
else()
|
||||
# Replace with proper *nix and mac handler files once they are done.
|
||||
target_sources(plat PRIVATE dummy_cdrom_ioctl.c)
|
||||
endif()
|
||||
|
||||
|
||||
Binary file not shown.
|
Before Width: | Height: | Size: 9.4 KiB After Width: | Height: | Size: 9.4 KiB |
@@ -1006,7 +1006,7 @@ msgid "About %1"
|
||||
msgstr "À propos de %1"
|
||||
|
||||
msgid "An emulator of old computers\n\nAuthors: Miran Grča (OBattler), RichardG867, Jasmine Iwanek, TC1995, coldbrewed, Teemu Korhonen (Manaatti), Joakim L. Gilje, Adrien Moulin (elyosh), Daniel Balsom (gloriouscow), Cacodemon345, Fred N. van Kempen (waltje), Tiseno100, reenigne, and others.\n\nWith previous core contributions from Sarah Walker, leilei, JohnElliott, greatpsycho, and others.\n\nReleased under the GNU General Public License version 2 or later. See LICENSE for more information."
|
||||
msgstr "Un émulateur d'ordinateurs du passé\n\nAuteurs : Miran Grča (OBattler), RichardG867, Jasmine Iwanek, TC1995, coldbrewed, Teemu Korhonen (Manaatti), Joakim L. Gilje, Adrien Moulin (elyosh), Daniel Balsom (gloriouscow), Cacodemon345, Fred N. van Kempen (waltje), Tiseno100, reenigne, and others.\n\nAvec les contributions de Sarah Walker, leilei, JohnElliott, greatpsycho et d'autres.\n\nLibéré sous la licence GNU General Public License version 2 ou ultérieure. Pour plus d'informations, voir le fichier LICENSE."
|
||||
msgstr "Un émulateur d'ordinateurs du passé\n\nAuteurs : Miran Grča (OBattler), RichardG867, Jasmine Iwanek, TC1995, coldbrewed, Teemu Korhonen (Manaatti), Joakim L. Gilje, Adrien Moulin (elyosh), Daniel Balsom (gloriouscow), Cacodemon345, Fred N. van Kempen (waltje), Tiseno100, reenigne et d'autres.\n\nAvec les contributions de Sarah Walker, leilei, JohnElliott, greatpsycho et d'autres.\n\nLibéré sous la licence GNU General Public License version 2 ou ultérieure. Pour plus d'informations, voir le fichier LICENSE."
|
||||
|
||||
msgid "Hardware not available"
|
||||
msgstr "Matériel non disponible"
|
||||
|
||||
@@ -55,10 +55,10 @@ msgid "&Resizeable window"
|
||||
msgstr "&Venster met aanpasbare grootte"
|
||||
|
||||
msgid "R&emember size && position"
|
||||
msgstr "&Onthoud grootte && positie"
|
||||
msgstr "&Onthoud grootte en positie"
|
||||
|
||||
msgid "Remember size && position"
|
||||
msgstr "Onthoud grootte && positie"
|
||||
msgstr "Onthoud grootte en positie"
|
||||
|
||||
msgid "Re&nderer"
|
||||
msgstr "Re&nderer"
|
||||
@@ -73,7 +73,7 @@ msgid "&VNC"
|
||||
msgstr "&VNC"
|
||||
|
||||
msgid "Specify &dimensions…"
|
||||
msgstr "Afmetingen opgeven…"
|
||||
msgstr "&Afmetingen opgeven…"
|
||||
|
||||
msgid "Force &4:3 display ratio"
|
||||
msgstr "Forceer &4:3 beeldverhouding"
|
||||
@@ -154,7 +154,7 @@ msgid "VGA screen &type"
|
||||
msgstr "VGA-scherm &type"
|
||||
|
||||
msgid "RGB &Color"
|
||||
msgstr "RGB &Kleur"
|
||||
msgstr "RGB &kleur"
|
||||
|
||||
msgid "RGB (no brown)"
|
||||
msgstr "RGN (geen bruin)"
|
||||
@@ -421,7 +421,7 @@ msgid "IBM 8514/A Graphics"
|
||||
msgstr "IBM 8514/A-graphics"
|
||||
|
||||
msgid "XGA Graphics"
|
||||
msgstr "XGA Graphics"
|
||||
msgstr "XGA-graphics"
|
||||
|
||||
msgid "IBM PS/55 Display Adapter Graphics"
|
||||
msgstr "IBM PS/55 Display Adapter Graphics"
|
||||
@@ -469,13 +469,13 @@ msgid "Sound card #4:"
|
||||
msgstr "Geluidskaart #4:"
|
||||
|
||||
msgid "MIDI Out Device:"
|
||||
msgstr "MIDI Uitvoerapparaat:"
|
||||
msgstr "MIDI uitvoerapparaat:"
|
||||
|
||||
msgid "MIDI In Device:"
|
||||
msgstr "MIDI Invoerapparaat:"
|
||||
msgstr "MIDI invoerapparaat:"
|
||||
|
||||
msgid "MIDI Out:"
|
||||
msgstr "Midi Uit:"
|
||||
msgstr "Midi uit:"
|
||||
|
||||
msgid "Standalone MPU-401"
|
||||
msgstr "Standalone MPU-401"
|
||||
@@ -580,7 +580,7 @@ msgid "Hard disks:"
|
||||
msgstr "Harde schijven:"
|
||||
|
||||
msgid "Firmware Version"
|
||||
msgstr "Firmware Versie"
|
||||
msgstr "Firmware versie"
|
||||
|
||||
msgid "&New…"
|
||||
msgstr "&Nieuw…"
|
||||
@@ -673,10 +673,10 @@ msgid "Generic ISA ROM Board"
|
||||
msgstr "Generieke ISA ROM-kaart"
|
||||
|
||||
msgid "Generic Dual ISA ROM Board"
|
||||
msgstr "Generieke Dubbele ISA ROM-kaart"
|
||||
msgstr "Generieke dubbele ISA ROM-kaart"
|
||||
|
||||
msgid "Generic Quad ISA ROM Board"
|
||||
msgstr "Generieke Viervoudige ISA ROM-kaart"
|
||||
msgstr "Generieke viervoudige ISA ROM-kaart"
|
||||
|
||||
msgid "ISABugger device"
|
||||
msgstr "ISABugger-apparaat"
|
||||
@@ -1006,7 +1006,7 @@ msgid "About %1"
|
||||
msgstr "Over %1"
|
||||
|
||||
msgid "An emulator of old computers\n\nAuthors: Miran Grča (OBattler), RichardG867, Jasmine Iwanek, TC1995, coldbrewed, Teemu Korhonen (Manaatti), Joakim L. Gilje, Adrien Moulin (elyosh), Daniel Balsom (gloriouscow), Cacodemon345, Fred N. van Kempen (waltje), Tiseno100, reenigne, and others.\n\nWith previous core contributions from Sarah Walker, leilei, JohnElliott, greatpsycho, and others.\n\nReleased under the GNU General Public License version 2 or later. See LICENSE for more information."
|
||||
msgstr "Een emulator van oude computers\n\nAuteurs: Miran Grča (OBattler), RichardG867, Jasmine Iwanek, TC1995, coldbrewed, Teemu Korhonen (Manaatti), Joakim L. Gilje, Adrien Moulin (elyosh), Daniel Balsom (gloriouscow), Cacodemon345, Fred N. van Kempen (waltje), Tiseno100, reenigne, and others.\n\nMet eerdere bijdragen van Sarah Walker, leilei, JohnElliott, greatpsycho en anderen.\n\nUitgebracht onder de GNU General Public License versie 2 of later. Zie LICENSE voor meer informatie."
|
||||
msgstr "Een emulator van oude computers\n\nAuteurs: Miran Grča (OBattler), RichardG867, Jasmine Iwanek, TC1995, coldbrewed, Teemu Korhonen (Manaatti), Joakim L. Gilje, Adrien Moulin (elyosh), Daniel Balsom (gloriouscow), Cacodemon345, Fred N. van Kempen (waltje), Tiseno100, reenigne, en anderen.\n\nMet eerdere bijdragen van Sarah Walker, leilei, JohnElliott, greatpsycho en anderen.\n\nUitgebracht onder de GNU General Public License versie 2 of later. Zie LICENSE voor meer informatie."
|
||||
|
||||
msgid "Hardware not available"
|
||||
msgstr "Hardware niet beschikbaar"
|
||||
@@ -1312,7 +1312,7 @@ msgid "An error has occurred while checking for updates: %1"
|
||||
msgstr "Er is een fout opgetreden tijdens het controleren op updates: %1"
|
||||
|
||||
msgid "<b>An update to 86Box is available!</b>"
|
||||
msgstr "<b> Een update van 86Box is beschikbaar!</b>"
|
||||
msgstr "<b>Een update van 86Box is beschikbaar!</b>"
|
||||
|
||||
msgid "Warning"
|
||||
msgstr "Waarschuwing"
|
||||
@@ -2065,7 +2065,7 @@ msgid "Dynamic Sample Loading"
|
||||
msgstr "Dynamische sample-lading"
|
||||
|
||||
msgid "Reverb Output Gain"
|
||||
msgstr "Reverbuitgang Versterking"
|
||||
msgstr "Reverbuitgang versterking"
|
||||
|
||||
msgid "Reversed stereo"
|
||||
msgstr "Omgekeerde stereo"
|
||||
@@ -2362,7 +2362,7 @@ msgid "Always at selected speed"
|
||||
msgstr "Altijd op geselecteerde snelheid"
|
||||
|
||||
msgid "BIOS setting + Hotkeys (off during POST)"
|
||||
msgstr "BIOS-instelling + Sneltoetsen (niet actief tijdens POST)"
|
||||
msgstr "BIOS-instelling + sneltoetsen (niet actief tijdens POST)"
|
||||
|
||||
msgid "64 KB starting from F0000"
|
||||
msgstr "64 KB vanaf F0000"
|
||||
@@ -2401,16 +2401,16 @@ msgid "Wheel"
|
||||
msgstr "Wiel"
|
||||
|
||||
msgid "Five + Wheel"
|
||||
msgstr "Vijf + Wiel"
|
||||
msgstr "Vijf + wiel"
|
||||
|
||||
msgid "Five + 2 Wheels"
|
||||
msgstr "Vijf + 2 Wielen"
|
||||
msgstr "Vijf + 2 wielen"
|
||||
|
||||
msgid "A3 - SMT2 Serial / SMT3(R)V"
|
||||
msgstr "A3 - SMT2 Serieel / SMT3(R)V"
|
||||
msgstr "A3 - SMT2 serieel / SMT3(R)V"
|
||||
|
||||
msgid "Q1 - SMT3(R) Serial"
|
||||
msgstr "Q1 - SMT3(R) Serieel"
|
||||
msgstr "Q1 - SMT3(R) serieel"
|
||||
|
||||
msgid "8 KB"
|
||||
msgstr "8 KB"
|
||||
@@ -2482,7 +2482,7 @@ msgid "Green Monochrome"
|
||||
msgstr "Groen monochroom"
|
||||
|
||||
msgid "Amber Monochrome"
|
||||
msgstr "Amber Monochroom"
|
||||
msgstr "Amber monochroom"
|
||||
|
||||
msgid "Gray Monochrome"
|
||||
msgstr "Grijs monochroom"
|
||||
@@ -2551,7 +2551,7 @@ msgid "Color"
|
||||
msgstr "Kleur"
|
||||
|
||||
msgid "U.S. English"
|
||||
msgstr "Amerikaans Engels"
|
||||
msgstr "Amerikaans engels"
|
||||
|
||||
msgid "Scandinavian"
|
||||
msgstr "Scandinavisch"
|
||||
@@ -2566,16 +2566,16 @@ msgid "Apply overscan deltas"
|
||||
msgstr "Overscan-delta’s toepassen"
|
||||
|
||||
msgid "Mono Interlaced"
|
||||
msgstr "Mono Interlaced"
|
||||
msgstr "Mono interlaced"
|
||||
|
||||
msgid "Mono Non-Interlaced"
|
||||
msgstr "Mono Niet-Interlaced"
|
||||
msgstr "Mono niet-interlaced"
|
||||
|
||||
msgid "Color Interlaced"
|
||||
msgstr "Kleur Interlaced"
|
||||
msgstr "Kleur interlaced"
|
||||
|
||||
msgid "Color Non-Interlaced"
|
||||
msgstr "Kleur Niet-Interlaced"
|
||||
msgstr "Kleur niet-interlaced"
|
||||
|
||||
msgid "3Dfx Voodoo Graphics"
|
||||
msgstr "3Dfx Voodoo Graphics"
|
||||
@@ -2635,7 +2635,7 @@ msgid "Passthrough Mode"
|
||||
msgstr "Doorgeefmodus"
|
||||
|
||||
msgid "Host Serial Device"
|
||||
msgstr "Host Serieel Apparaat"
|
||||
msgstr "Host serieel apparaat"
|
||||
|
||||
msgid "Name of pipe"
|
||||
msgstr "Naam van de pipe"
|
||||
@@ -2650,10 +2650,10 @@ msgid "Baud Rate of Passthrough"
|
||||
msgstr "Baud-snelheid van doorvoer"
|
||||
|
||||
msgid "Named Pipe (Server)"
|
||||
msgstr "Named Pipe (Server)"
|
||||
msgstr "Genoemd pipe (server)"
|
||||
|
||||
msgid "Named Pipe (Client)"
|
||||
msgstr "Named Pipe (Client)"
|
||||
msgstr "Genoemd pipe (client)"
|
||||
|
||||
msgid "Host Serial Passthrough"
|
||||
msgstr "Host seriële doorgave"
|
||||
@@ -2833,10 +2833,10 @@ msgid "SoundFont files"
|
||||
msgstr "SoundFont-bestanden"
|
||||
|
||||
msgid "Local Switch"
|
||||
msgstr "Lokale Switch"
|
||||
msgstr "Lokale-switch"
|
||||
|
||||
msgid "Remote Switch"
|
||||
msgstr "Externe Switch"
|
||||
msgstr "Externe-switch"
|
||||
|
||||
msgid "Shared secret:"
|
||||
msgstr "Gedeeld geheim:"
|
||||
@@ -2869,16 +2869,16 @@ msgid "An error occurred trying to wipe the NVRAM contents of the virtual machin
|
||||
msgstr "Fout bij Wissen van NVRAM-inhoud van de virtuele machine \"%1\""
|
||||
|
||||
msgid "%1 VM Manager"
|
||||
msgstr "%1 VM Beheerder"
|
||||
msgstr "%1 VM-beheerder"
|
||||
|
||||
msgid "%n disk(s)"
|
||||
msgstr "%n schijf/schijven"
|
||||
|
||||
msgid "Unknown Status"
|
||||
msgstr "Onbekende Status"
|
||||
msgstr "Onbekende status"
|
||||
|
||||
msgid "No Machines Found!"
|
||||
msgstr "Geen Machines Gevonden!"
|
||||
msgstr "Geen machines gevonden!"
|
||||
|
||||
msgid "Check for updates on startup"
|
||||
msgstr "Controleer op updates bij starten"
|
||||
@@ -2932,7 +2932,7 @@ msgid "Checking for updates…"
|
||||
msgstr "Controleren op updates…"
|
||||
|
||||
msgid "86Box Update"
|
||||
msgstr "86Box Update"
|
||||
msgstr "86Box-update"
|
||||
|
||||
msgid "Release notes:"
|
||||
msgstr "Release-opmerkingen:"
|
||||
|
||||
@@ -20,6 +20,7 @@
|
||||
#include "qt_machinestatus.hpp"
|
||||
|
||||
#include <QMenu>
|
||||
#include <QFile>
|
||||
#include <QFileDialog>
|
||||
#include <QMessageBox>
|
||||
#include <QStringBuilder>
|
||||
@@ -176,7 +177,15 @@ MediaMenu::refresh(QMenu *parentMenu)
|
||||
menu->addAction(QIcon(":/settings/qt/icons/cdrom_host.ico"), tr("&Host CD/DVD Drive (%1:)").arg(letter), [this, i, letter] { cdromMount(i, 2, QString(R"(\\.\%1:)").arg(letter)); })->setCheckable(false);
|
||||
}
|
||||
menu->addSeparator();
|
||||
#endif // Q_OS_WINDOWS
|
||||
#elif defined(Q_OS_LINUX)
|
||||
/* Enumerate Linux CD/DVD drives (/dev/sr0 .. /dev/sr15). */
|
||||
for (int sr = 0; sr < 16; sr++) {
|
||||
QString devPath = QString("/dev/sr%1").arg(sr);
|
||||
if (QFile::exists(devPath))
|
||||
menu->addAction(QIcon(":/settings/qt/icons/cdrom_host.ico"), tr("&Host CD/DVD Drive (%1)").arg(devPath), [this, i, devPath] { cdromMount(i, 2, devPath); })->setCheckable(false);
|
||||
}
|
||||
menu->addSeparator();
|
||||
#endif
|
||||
cdromEjectPos = menu->children().count();
|
||||
menu->addAction(tr("E&ject"), [this, i]() { cdromEject(i); })->setCheckable(false);
|
||||
cdromMenus[i] = menu;
|
||||
|
||||
@@ -1726,7 +1726,8 @@ OpenGLRenderer::render()
|
||||
glw.glFinish();
|
||||
glw.glReadPixels(window_rect.x, window_rect.y, width, height, GL_RGB, GL_UNSIGNED_BYTE, rgb);
|
||||
|
||||
QImage image((uchar*)rgb, width, height, width * 3, QImage::Format_RGB888);
|
||||
int pitch_adj = (4 - ((width * 3) & 3)) & 3;
|
||||
QImage image((uchar*)rgb, width, height, (width * 3) + pitch_adj, QImage::Format_RGB888);
|
||||
image.mirrored(false, true).save(path, "png");
|
||||
monitors[r_monitor_index].mon_screenshots--;
|
||||
free(rgb);
|
||||
@@ -1739,7 +1740,8 @@ OpenGLRenderer::render()
|
||||
glw.glFinish();
|
||||
glw.glReadPixels(window_rect.x, window_rect.y, width, height, GL_RGB, GL_UNSIGNED_BYTE, rgb);
|
||||
|
||||
QImage image((uchar*)rgb, width, height, width * 3, QImage::Format_RGB888);
|
||||
int pitch_adj = (4 - ((width * 3) & 3)) & 3;
|
||||
QImage image((uchar*)rgb, width, height, (width * 3) + pitch_adj, QImage::Format_RGB888);
|
||||
QClipboard *clipboard = QApplication::clipboard();
|
||||
clipboard->setImage(image.mirrored(false, true), QClipboard::Clipboard);
|
||||
monitors[r_monitor_index].mon_screenshots_clipboard--;
|
||||
|
||||
@@ -28,5 +28,6 @@ add_library(scsi OBJECT
|
||||
scsi_t128.c
|
||||
scsi_ncr53c8xx.c
|
||||
scsi_pcscsi.c
|
||||
scsi_ql1xxx.c
|
||||
scsi_spock.c
|
||||
)
|
||||
|
||||
@@ -38,6 +38,7 @@
|
||||
#include <86box/scsi_ncr5380.h>
|
||||
#include <86box/scsi_ncr53c8xx.h>
|
||||
#include <86box/scsi_pcscsi.h>
|
||||
#include <86box/scsi_qlogic.h>
|
||||
#include <86box/scsi_spock.h>
|
||||
|
||||
int scsi_card_current[SCSI_CARD_MAX] = { 0, 0, 0, 0 };
|
||||
@@ -91,6 +92,11 @@ static SCSI_CARD scsi_cards[] = {
|
||||
{ &ncr53c860_pci_device, },
|
||||
{ &ncr53c875_pci_device, },
|
||||
{ &dc390_pci_device, },
|
||||
{ &qla1040b_device, },
|
||||
{ &qla1080_device, },
|
||||
{ &qla1240_device, },
|
||||
{ &qla1280_device, },
|
||||
{ &qla12160a_device, },
|
||||
{ NULL, },
|
||||
// clang-format on
|
||||
};
|
||||
|
||||
@@ -62,13 +62,9 @@ void
|
||||
ncr5380_irq(ncr_t *ncr, int set_irq)
|
||||
{
|
||||
if (set_irq) {
|
||||
ncr->irq_state = 1;
|
||||
ncr->isr |= STATUS_INT;
|
||||
if (ncr->irq != -1)
|
||||
picint(1 << ncr->irq);
|
||||
} else {
|
||||
ncr->irq_state = 0;
|
||||
ncr->isr &= ~STATUS_INT;
|
||||
if (ncr->irq != 1)
|
||||
picintc(1 << ncr->irq);
|
||||
}
|
||||
@@ -104,7 +100,12 @@ ncr5380_reset(ncr_t *ncr)
|
||||
scsi_bus->data = 0;
|
||||
scsi_bus->command_issued = 0;
|
||||
|
||||
ncr5380_irq(ncr, 0);
|
||||
if (ncr->irq_ena)
|
||||
ncr->irq_ena(ncr, ncr->priv, 0);
|
||||
else
|
||||
ncr5380_irq(ncr, 0);
|
||||
|
||||
ncr->isr &= ~STATUS_INT;
|
||||
}
|
||||
|
||||
uint32_t
|
||||
@@ -164,7 +165,7 @@ ncr5380_write(uint16_t port, uint8_t val, ncr_t *ncr)
|
||||
if ((val & 0x80) && !(ncr->icr & 0x80)) {
|
||||
ncr5380_log("Resetting the 5380\n");
|
||||
ncr5380_reset(ncr);
|
||||
ncr5380_irq(ncr, 1);
|
||||
ncr->isr |= STATUS_INT;
|
||||
}
|
||||
ncr->icr = val;
|
||||
ncr5380_log("ICR WaitData=%d, ClearReq=%d.\n", scsi_bus->wait_data, scsi_bus->clear_req);
|
||||
@@ -301,7 +302,7 @@ ncr5380_read(uint16_t port, ncr_t *ncr)
|
||||
if (bus & BUS_MSG)
|
||||
bus_state |= TCR_MSG;
|
||||
if ((ncr->tcr & 7) != bus_state) {
|
||||
ncr5380_irq(ncr, 1);
|
||||
ncr->isr |= STATUS_INT;
|
||||
ncr5380_log("IRQ issued\n");
|
||||
}
|
||||
}
|
||||
@@ -321,7 +322,12 @@ ncr5380_read(uint16_t port, ncr_t *ncr)
|
||||
|
||||
case 7: /* reset Parity/Interrupt */
|
||||
ncr->isr &= ~(STATUS_BUSY_ERROR | 0x20);
|
||||
ncr5380_irq(ncr, 0);
|
||||
if (ncr->irq_ena)
|
||||
ncr->irq_ena(ncr, ncr->priv, 0);
|
||||
else
|
||||
ncr5380_irq(ncr, 0);
|
||||
|
||||
ncr->isr &= ~STATUS_INT;
|
||||
ncr5380_log("Reset Interrupt\n");
|
||||
break;
|
||||
|
||||
|
||||
@@ -72,6 +72,7 @@ typedef struct ncr53c400_t {
|
||||
int8_t type;
|
||||
uint8_t block_count;
|
||||
uint8_t status_ctrl;
|
||||
uint8_t irq_config;
|
||||
|
||||
int block_count_loaded;
|
||||
|
||||
@@ -103,6 +104,23 @@ ncr53c400_log(const char *fmt, ...)
|
||||
# define ncr53c400_log(fmt, ...)
|
||||
#endif
|
||||
|
||||
static int
|
||||
ncr53c400_irq_enable(void *priv, void *ext_priv, int state)
|
||||
{
|
||||
ncr53c400_t *ncr400 = (ncr53c400_t *) ext_priv;
|
||||
ncr_t *ncr = (ncr_t *) priv;
|
||||
|
||||
if (ncr->irq_state != state) {
|
||||
ncr->irq_state = state;
|
||||
ncr400->status_ctrl &= ~0x01;
|
||||
ncr400->status_ctrl |= (state << 0);
|
||||
ncr53c400_log("Status Control bit 4=%02x.\n", ncr400->status_ctrl);
|
||||
if (ncr400->status_ctrl & 0x10)
|
||||
ncr5380_irq(ncr, state);
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
static void
|
||||
ncr53c400_timer_on_auto(void *ext_priv, double period)
|
||||
{
|
||||
@@ -263,7 +281,8 @@ ncr53c400_read(uint32_t addr, void *priv)
|
||||
ncr->isr |= STATUS_END_OF_DMA;
|
||||
if (ncr->mode & MODE_ENA_EOP_INT) {
|
||||
ncr53c400_log("NCR read irq\n");
|
||||
ncr5380_irq(ncr, 1);
|
||||
ncr53c400_irq_enable(ncr, ncr400, 1);
|
||||
ncr->isr |= STATUS_INT;
|
||||
}
|
||||
} else if (!timer_is_enabled(&ncr400->timer)) {
|
||||
ncr53c400_log("Timer re-enabled.\n");
|
||||
@@ -277,15 +296,16 @@ ncr53c400_read(uint32_t addr, void *priv)
|
||||
case 0x3980:
|
||||
switch (addr) {
|
||||
case 0x3980: /* status */
|
||||
if (ncr400->reset) {
|
||||
ncr400->reset = 0;
|
||||
ncr53c400_irq_enable(ncr, ncr400, 1);
|
||||
}
|
||||
|
||||
ret = ncr400->status_ctrl;
|
||||
ncr53c400_log("NCR status ctrl read=%02x.\n", ncr400->status_ctrl & STATUS_BUFFER_NOT_READY);
|
||||
if (!ncr400->busy)
|
||||
ret |= STATUS_5380_ACCESSIBLE;
|
||||
|
||||
if (ncr400->reset) {
|
||||
ncr400->reset = 0;
|
||||
ret |= 0x01;
|
||||
}
|
||||
ncr53c400_log("NCR 53c400 status=%02x.\n", ret);
|
||||
break;
|
||||
|
||||
@@ -295,10 +315,7 @@ ncr53c400_read(uint32_t addr, void *priv)
|
||||
break;
|
||||
|
||||
case 0x3982: /* switch register read */
|
||||
if (ncr->irq != -1) {
|
||||
ret = 0xf8;
|
||||
ret += ncr->irq;
|
||||
}
|
||||
ret = ((ncr400->irq_config >> 5) & 7) | 0xf8;
|
||||
ncr53c400_log("Switches read=%02x.\n", ret);
|
||||
break;
|
||||
|
||||
@@ -519,7 +536,8 @@ ncr53c400_callback(void *priv)
|
||||
ncr->isr |= STATUS_END_OF_DMA;
|
||||
if (ncr->mode & MODE_ENA_EOP_INT) {
|
||||
ncr53c400_log("NCR 53c400 write irq\n");
|
||||
ncr5380_irq(ncr, 1);
|
||||
ncr53c400_irq_enable(ncr, ncr400, 1);
|
||||
ncr->isr |= STATUS_INT;
|
||||
}
|
||||
}
|
||||
break;
|
||||
@@ -573,7 +591,8 @@ ncr53c400_callback(void *priv)
|
||||
ncr->isr |= STATUS_END_OF_DMA;
|
||||
if (ncr->mode & MODE_ENA_EOP_INT) {
|
||||
ncr53c400_log("NCR read irq\n");
|
||||
ncr5380_irq(ncr, 1);
|
||||
ncr53c400_irq_enable(ncr, ncr400, 1);
|
||||
ncr->isr |= STATUS_INT;
|
||||
}
|
||||
} else
|
||||
timer_on_auto(&ncr400->timer, 1.0);
|
||||
@@ -675,7 +694,8 @@ ncr53c400_init(const device_t *info)
|
||||
switch (ncr400->type) {
|
||||
case ROM_LCS6821N: /* Longshine LCS6821N */
|
||||
ncr400->rom_addr = device_get_config_hex20("bios_addr");
|
||||
ncr->irq = device_get_config_int("irq");
|
||||
ncr400->irq_config = device_get_config_hex16("irq");
|
||||
ncr->irq = (ncr400->irq_config >> 5) & 7;
|
||||
|
||||
rom_init(&ncr400->bios_rom, LCS6821N_ROM,
|
||||
ncr400->rom_addr, 0x4000, 0x3fff, 0, MEM_MAPPING_EXTERNAL);
|
||||
@@ -689,7 +709,8 @@ ncr53c400_init(const device_t *info)
|
||||
|
||||
case ROM_LS2000: /* Corel LS2000 */
|
||||
ncr400->rom_addr = device_get_config_hex20("bios_addr");
|
||||
ncr->irq = device_get_config_int("irq");
|
||||
ncr400->irq_config = device_get_config_hex16("irq");
|
||||
ncr->irq = (ncr400->irq_config >> 5) & 7;
|
||||
|
||||
rom_init(&ncr400->bios_rom, COREL_LS2000_ROM,
|
||||
ncr400->rom_addr, 0x4000, 0x3fff, 0, MEM_MAPPING_EXTERNAL);
|
||||
@@ -702,7 +723,9 @@ ncr53c400_init(const device_t *info)
|
||||
|
||||
case ROM_RT1000B: /* Rancho RT1000B/MC */
|
||||
ncr400->rom_addr = device_get_config_hex20("bios_addr");
|
||||
ncr->irq = device_get_config_int("irq");
|
||||
ncr400->irq_config = device_get_config_hex16("irq");
|
||||
ncr->irq = (ncr400->irq_config >> 5) & 7;
|
||||
|
||||
if (info->flags & DEVICE_MCA) {
|
||||
rom_init(&ncr400->bios_rom, RT1000B_820R_ROM,
|
||||
0xd8000, 0x4000, 0x3fff, 0, MEM_MAPPING_EXTERNAL);
|
||||
@@ -729,7 +752,8 @@ ncr53c400_init(const device_t *info)
|
||||
case ROM_T130B: /* Trantor T130B */
|
||||
ncr400->rom_addr = device_get_config_hex20("bios_addr");
|
||||
ncr400->base = device_get_config_hex16("base");
|
||||
ncr->irq = device_get_config_int("irq");
|
||||
ncr400->irq_config = device_get_config_hex16("irq");
|
||||
ncr->irq = (ncr400->irq_config >> 5) & 7;
|
||||
|
||||
if (ncr400->rom_addr > 0x00000) {
|
||||
rom_init(&ncr400->bios_rom, T130B_ROM,
|
||||
@@ -754,6 +778,7 @@ ncr53c400_init(const device_t *info)
|
||||
ncr->dma_send_ext = NULL;
|
||||
ncr->dma_initiator_receive_ext = NULL;
|
||||
ncr->timer = ncr53c400_timer_on_auto;
|
||||
ncr->irq_ena = ncr53c400_irq_enable;
|
||||
scsi_bus->bus_device = ncr->bus;
|
||||
scsi_bus->timer = ncr->timer;
|
||||
scsi_bus->priv = ncr->priv;
|
||||
@@ -839,16 +864,16 @@ static const device_config_t ncr53c400_mmio_config[] = {
|
||||
{
|
||||
.name = "irq",
|
||||
.description = "IRQ",
|
||||
.type = CONFIG_SELECTION,
|
||||
.type = CONFIG_HEX16,
|
||||
.default_string = NULL,
|
||||
.default_int = 5,
|
||||
.default_int = 0xa0,
|
||||
.file_filter = NULL,
|
||||
.spinner = { 0 },
|
||||
.selection = {
|
||||
{ .description = "None", .value = -1 },
|
||||
{ .description = "IRQ 3", .value = 3 },
|
||||
{ .description = "IRQ 5", .value = 5 },
|
||||
{ .description = "IRQ 7", .value = 7 },
|
||||
{ .description = "IRQ 3", .value = 0x60 },
|
||||
{ .description = "IRQ 4", .value = 0x80 },
|
||||
{ .description = "IRQ 5", .value = 0xa0 },
|
||||
{ .description = "IRQ 7", .value = 0xe0 },
|
||||
{ .description = "" }
|
||||
},
|
||||
.bios = { { 0 } }
|
||||
@@ -910,16 +935,16 @@ static const device_config_t rt1000b_config[] = {
|
||||
{
|
||||
.name = "irq",
|
||||
.description = "IRQ",
|
||||
.type = CONFIG_SELECTION,
|
||||
.type = CONFIG_HEX16,
|
||||
.default_string = NULL,
|
||||
.default_int = 5,
|
||||
.default_int = 0xa0,
|
||||
.file_filter = NULL,
|
||||
.spinner = { 0 },
|
||||
.selection = {
|
||||
{ .description = "None", .value = -1 },
|
||||
{ .description = "IRQ 3", .value = 3 },
|
||||
{ .description = "IRQ 5", .value = 5 },
|
||||
{ .description = "IRQ 7", .value = 7 },
|
||||
{ .description = "IRQ 3", .value = 0x60 },
|
||||
{ .description = "IRQ 4", .value = 0x80 },
|
||||
{ .description = "IRQ 5", .value = 0xa0 },
|
||||
{ .description = "IRQ 7", .value = 0xe0 },
|
||||
{ .description = "" }
|
||||
},
|
||||
.bios = { { 0 } }
|
||||
@@ -931,16 +956,16 @@ static const device_config_t rt1000b_mc_config[] = {
|
||||
{
|
||||
.name = "irq",
|
||||
.description = "IRQ",
|
||||
.type = CONFIG_SELECTION,
|
||||
.type = CONFIG_HEX16,
|
||||
.default_string = NULL,
|
||||
.default_int = 5,
|
||||
.default_int = 0xa0,
|
||||
.file_filter = NULL,
|
||||
.spinner = { 0 },
|
||||
.selection = {
|
||||
{ .description = "None", .value = -1 },
|
||||
{ .description = "IRQ 3", .value = 3 },
|
||||
{ .description = "IRQ 5", .value = 5 },
|
||||
{ .description = "IRQ 7", .value = 7 },
|
||||
{ .description = "IRQ 3", .value = 0x60 },
|
||||
{ .description = "IRQ 4", .value = 0x80 },
|
||||
{ .description = "IRQ 5", .value = 0xa0 },
|
||||
{ .description = "IRQ 7", .value = 0xe0 },
|
||||
{ .description = "" }
|
||||
},
|
||||
.bios = { { 0 } }
|
||||
@@ -987,16 +1012,16 @@ static const device_config_t t130b_config[] = {
|
||||
{
|
||||
.name = "irq",
|
||||
.description = "IRQ",
|
||||
.type = CONFIG_SELECTION,
|
||||
.type = CONFIG_HEX16,
|
||||
.default_string = NULL,
|
||||
.default_int = 5,
|
||||
.default_int = 0xa0,
|
||||
.file_filter = NULL,
|
||||
.spinner = { 0 },
|
||||
.selection = {
|
||||
{ .description = "None", .value = -1 },
|
||||
{ .description = "IRQ 3", .value = 3 },
|
||||
{ .description = "IRQ 5", .value = 5 },
|
||||
{ .description = "IRQ 7", .value = 7 },
|
||||
{ .description = "IRQ 3", .value = 0x60 },
|
||||
{ .description = "IRQ 4", .value = 0x80 },
|
||||
{ .description = "IRQ 5", .value = 0xa0 },
|
||||
{ .description = "IRQ 7", .value = 0xe0 },
|
||||
{ .description = "" }
|
||||
},
|
||||
.bios = { { 0 } }
|
||||
|
||||
4580
src/scsi/scsi_ql1xxx.c
Normal file
4580
src/scsi/scsi_ql1xxx.c
Normal file
File diff suppressed because it is too large
Load Diff
@@ -27,7 +27,6 @@
|
||||
#define HAVE_STDARG_H
|
||||
#include <86box/86box.h>
|
||||
#include <86box/io.h>
|
||||
#include "cpu.h"
|
||||
#include <86box/timer.h>
|
||||
#include <86box/dma.h>
|
||||
#include <86box/pic.h>
|
||||
@@ -41,6 +40,7 @@
|
||||
#include <86box/scsi_device.h>
|
||||
#include <86box/scsi_ncr5380.h>
|
||||
#include <86box/scsi_t128.h>
|
||||
#include "cpu.h"
|
||||
|
||||
#define T128_ROM "roms/scsi/ncr5380/trantor_t128_bios_v1.12.bin"
|
||||
|
||||
@@ -75,7 +75,7 @@ t128_write(uint32_t addr, uint8_t val, void *priv)
|
||||
if ((addr >= 0x1800) && (addr < 0x1880))
|
||||
t128->ext_ram[addr & 0x7f] = val;
|
||||
else if ((addr >= 0x1c00) && (addr < 0x1c20)) {
|
||||
t128_log("T128 ctrl write=%02x, mode=%02x.\n", val, ncr->mode & MODE_DMA);
|
||||
t128_log("T128 ctrl write=%02x, mode=%02x.\n", val & 0x10, ncr->mode & MODE_DMA);
|
||||
t128->ctrl = val;
|
||||
} else if ((addr >= 0x1d00) && (addr < 0x1e00))
|
||||
ncr5380_write((addr - 0x1d00) >> 5, val, ncr);
|
||||
@@ -141,6 +141,7 @@ t128_read(uint32_t addr, void *priv)
|
||||
if (ncr->mode & MODE_ENA_EOP_INT) {
|
||||
t128_log("T128 read irq\n");
|
||||
ncr5380_irq(ncr, 1);
|
||||
ncr->isr |= STATUS_INT;
|
||||
}
|
||||
scsi_bus->bus_out |= BUS_CD;
|
||||
scsi_bus->tx_mode = PIO_TX_BUS;
|
||||
@@ -298,6 +299,7 @@ t128_callback(void *priv)
|
||||
if (ncr->mode & MODE_ENA_EOP_INT) {
|
||||
t128_log("T128 write irq\n");
|
||||
ncr5380_irq(ncr, 1);
|
||||
ncr->isr |= STATUS_INT;
|
||||
}
|
||||
scsi_bus->tx_mode = PIO_TX_BUS;
|
||||
timer_stop(&t128->timer);
|
||||
@@ -497,6 +499,7 @@ t128_init(const device_t *info)
|
||||
ncr->dma_send_ext = t128_dma_send_ext;
|
||||
ncr->dma_initiator_receive_ext = t128_dma_initiator_receive_ext;
|
||||
ncr->timer = t128_timer_on_auto;
|
||||
ncr->irq_ena = NULL;
|
||||
scsi_bus->bus_device = ncr->bus;
|
||||
scsi_bus->timer = ncr->timer;
|
||||
scsi_bus->priv = ncr->priv;
|
||||
@@ -566,12 +569,13 @@ static const device_config_t t128_config[] = {
|
||||
.description = "IRQ",
|
||||
.type = CONFIG_SELECTION,
|
||||
.default_string = NULL,
|
||||
.default_int = 5,
|
||||
.default_int = -1,
|
||||
.file_filter = NULL,
|
||||
.spinner = { 0 },
|
||||
.selection = {
|
||||
{ .description = "None", .value = -1 },
|
||||
{ .description = "IRQ 3", .value = 3 },
|
||||
{ .description = "IRQ 4", .value = 4 },
|
||||
{ .description = "IRQ 5", .value = 5 },
|
||||
{ .description = "IRQ 7", .value = 7 },
|
||||
{ .description = "IRQ 10", .value = 10 },
|
||||
|
||||
@@ -819,7 +819,7 @@ ad1816_init(const device_t *info)
|
||||
ad1816->sb->opl_enabled = 1;
|
||||
|
||||
sb_dsp_set_real_opl(&ad1816->sb->dsp, FM_YMF262);
|
||||
sb_dsp_init(&ad1816->sb->dsp, SBPRO2_DSP_302, SB_SUBTYPE_DEFAULT, ad1816);
|
||||
sb_dsp_init(&ad1816->sb->dsp, SBPRO_DSP_302, SB_SUBTYPE_DEFAULT, ad1816);
|
||||
sb_dsp_setaddr(&ad1816->sb->dsp, ad1816->cur_sb_addr);
|
||||
sb_dsp_setirq(&ad1816->sb->dsp, ad1816->cur_irq);
|
||||
sb_dsp_setirq(&ad1816->sb->dsp, ad1816->cur_dma);
|
||||
|
||||
@@ -1835,7 +1835,7 @@ azt_init(const device_t *info)
|
||||
fm_driver_get(FM_YMF262, &azt2316a->sb->opl);
|
||||
|
||||
sb_dsp_set_real_opl(&azt2316a->sb->dsp, 1);
|
||||
sb_dsp_init(&azt2316a->sb->dsp, SBPRO2_DSP_302, azt2316a->type, azt2316a);
|
||||
sb_dsp_init(&azt2316a->sb->dsp, SBPRO_DSP_302, azt2316a->type, azt2316a);
|
||||
sb_dsp_setaddr(&azt2316a->sb->dsp, azt2316a->cur_addr);
|
||||
sb_dsp_setirq(&azt2316a->sb->dsp, azt2316a->cur_irq);
|
||||
sb_dsp_setdma8(&azt2316a->sb->dsp, azt2316a->cur_dma);
|
||||
|
||||
@@ -877,7 +877,7 @@ cmi8x38_write(uint16_t addr, uint8_t val, void *priv)
|
||||
dev->sb->dsp.sbleftright_default = !!(val & 0x02);
|
||||
|
||||
/* Enable or disable SB16 mode. */
|
||||
dev->sb->dsp.sb_type = (val & 0x01) ? SBPRO2_DSP_302 : SB16_DSP_405;
|
||||
dev->sb->dsp.sb_type = (val & 0x01) ? SBPRO_DSP_302 : SB16_DSP_405;
|
||||
break;
|
||||
|
||||
case 0x22:
|
||||
|
||||
@@ -316,7 +316,9 @@ MPU401_Reset(mpu_t *mpu)
|
||||
mpu->ch_toref[i] = 4; /* Dummy reftable. */
|
||||
}
|
||||
|
||||
MPU401_ClrQueue(mpu);
|
||||
mpu->state.irq_pending = 0;
|
||||
MPU401_UpdateIRQ(mpu, 0);
|
||||
|
||||
mpu->state.data_onoff = -1;
|
||||
|
||||
mpu->state.req_mask = 0;
|
||||
|
||||
@@ -1095,7 +1095,7 @@ optimc_init(const device_t *info)
|
||||
optimc->fm_type = (info->local & OPTIMC_OPL4) ? FM_YMF278B : FM_YMF262;
|
||||
|
||||
sb_dsp_set_real_opl(&optimc->sb->dsp, optimc->fm_type != FM_YMF278B);
|
||||
sb_dsp_init(&optimc->sb->dsp, SBPRO2_DSP_302, SB_SUBTYPE_DEFAULT, optimc);
|
||||
sb_dsp_init(&optimc->sb->dsp, SBPRO_DSP_302, SB_SUBTYPE_DEFAULT, optimc);
|
||||
sb_dsp_setaddr(&optimc->sb->dsp, optimc->cur_addr);
|
||||
sb_dsp_setirq(&optimc->sb->dsp, optimc->cur_irq);
|
||||
sb_dsp_setdma8(&optimc->sb->dsp, optimc->cur_dma);
|
||||
|
||||
@@ -2327,7 +2327,7 @@ pas16_init(const device_t *info)
|
||||
pas16->has_scsi = (!pas16->type) || (pas16->type == 0x0f);
|
||||
fm_driver_get(FM_YMF262, &pas16->opl);
|
||||
sb_dsp_set_real_opl(&pas16->dsp, 1);
|
||||
sb_dsp_init(&pas16->dsp, SB_DSP_201, SB_SUBTYPE_DEFAULT, pas16);
|
||||
sb_dsp_init(&pas16->dsp, SB_DSP_200, SB_SUBTYPE_MVD201, pas16);
|
||||
pas16->mpu = (mpu_t *) calloc(1, sizeof(mpu_t));
|
||||
mpu401_init(pas16->mpu, 0, 0, M_UART, device_get_config_int("receive_input401"));
|
||||
sb_dsp_set_mpu(&pas16->dsp, pas16->mpu);
|
||||
|
||||
@@ -15,7 +15,7 @@
|
||||
*
|
||||
* Copyright 2008-2020 Sarah Walker.
|
||||
* Copyright 2016-2020 Miran Grca.
|
||||
* Copyright 2024-2025 Jasmine Iwanek.
|
||||
* Copyright 2024-2026 Jasmine Iwanek.
|
||||
*/
|
||||
#include <stdarg.h>
|
||||
#include <stdint.h>
|
||||
@@ -45,9 +45,10 @@
|
||||
#include <86box/plat_unused.h>
|
||||
#include <86box/snd_azt2316a.h>
|
||||
|
||||
#define SB_1 0
|
||||
#define SB_15 1
|
||||
#define SB_2 2
|
||||
#define SB_1 0
|
||||
#define SB_15 1
|
||||
#define SB_2 2
|
||||
#define THUNDERBOARD 3
|
||||
|
||||
#define SB_16_PNP_NOIDE 0
|
||||
#define SB_16_PNP_IDE 1
|
||||
@@ -2959,6 +2960,10 @@ sb_init(UNUSED(const device_t *info))
|
||||
sb->cms_enabled = device_get_config_int("cms");
|
||||
mixer_addr = device_get_config_int("mixaddr");
|
||||
break;
|
||||
case THUNDERBOARD:
|
||||
model = SB_DSP_200;
|
||||
sb->cms_enabled = 0;
|
||||
break;
|
||||
}
|
||||
|
||||
sb->opl_enabled = device_get_config_int("opl");
|
||||
@@ -3006,7 +3011,7 @@ sb_init(UNUSED(const device_t *info))
|
||||
&sb->cms);
|
||||
}
|
||||
|
||||
if (mixer_addr > 0x000) {
|
||||
if (mixer_addr > 0x0000) {
|
||||
sb->mixer_enabled = 1;
|
||||
io_sethandler(mixer_addr + 4, 0x0002,
|
||||
sb_ct1335_mixer_read, NULL, NULL,
|
||||
@@ -3026,6 +3031,58 @@ sb_init(UNUSED(const device_t *info))
|
||||
return sb;
|
||||
}
|
||||
|
||||
void *
|
||||
thunderboard_init(UNUSED(const device_t *info))
|
||||
{
|
||||
/* ThunderBoard port mappings, 210h to 260h in 10h steps
|
||||
2x6, 2xA, 2xC, 2xE -> DSP chip */
|
||||
sb_t *sb = calloc(1, sizeof(sb_t));
|
||||
const uint16_t addr = device_get_config_hex16("base");
|
||||
|
||||
sb->opl_enabled = device_get_config_int("opl");
|
||||
if (sb->opl_enabled)
|
||||
fm_driver_get(FM_YM3812, &sb->opl);
|
||||
|
||||
sb_dsp_set_real_opl(&sb->dsp, 0);
|
||||
sb_dsp_init(&sb->dsp, SB_DSP_200, SB_SUBTYPE_MVD201, sb);
|
||||
/* DSP I/O handler is activated in sb_dsp_setaddr */
|
||||
sb_dsp_setaddr(&sb->dsp, addr);
|
||||
sb_dsp_setirq(&sb->dsp, device_get_config_int("irq"));
|
||||
sb_dsp_setdma8(&sb->dsp, 1);
|
||||
|
||||
if (device_get_config_int("gameport")) {
|
||||
sb->gameport = gameport_add(&gameport_device);
|
||||
sb->gameport_addr = 0x200;
|
||||
gameport_remap(sb->gameport, sb->gameport_addr);
|
||||
}
|
||||
|
||||
/* DSP I/O handler is activated in sb_dsp_setaddr */
|
||||
if (sb->opl_enabled) {
|
||||
io_sethandler(addr, 0x0002,
|
||||
sb->opl.read, NULL, NULL,
|
||||
sb->opl.write, NULL, NULL,
|
||||
sb->opl.priv);
|
||||
io_sethandler(addr + 8, 0x0002,
|
||||
sb->opl.read, NULL, NULL,
|
||||
sb->opl.write, NULL, NULL,
|
||||
sb->opl.priv);
|
||||
io_sethandler(0x0388, 0x0002,
|
||||
sb->opl.read, NULL, NULL,
|
||||
sb->opl.write, NULL, NULL,
|
||||
sb->opl.priv);
|
||||
}
|
||||
|
||||
|
||||
sb->cms_enabled = 0;
|
||||
sb->mixer_enabled = 0;
|
||||
sound_add_handler(sb_get_buffer_sb2, sb);
|
||||
if (sb->opl_enabled)
|
||||
music_add_handler(sb_get_music_buffer_sb2, sb);
|
||||
sound_set_cd_audio_filter(sb2_filter_cd_audio, sb);
|
||||
|
||||
return sb;
|
||||
}
|
||||
|
||||
void *
|
||||
sb_mcv_init(UNUSED(const device_t *info))
|
||||
{
|
||||
@@ -3170,7 +3227,7 @@ sb_pro_v2_init(UNUSED(const device_t *info))
|
||||
fm_driver_get(FM_YMF262, &sb->opl);
|
||||
|
||||
sb_dsp_set_real_opl(&sb->dsp, 1);
|
||||
sb_dsp_init(&sb->dsp, SBPRO2_DSP_302, SB_SUBTYPE_DEFAULT, sb);
|
||||
sb_dsp_init(&sb->dsp, SBPRO_DSP_302, SB_SUBTYPE_DEFAULT, sb);
|
||||
sb_dsp_setaddr(&sb->dsp, addr);
|
||||
sb_dsp_setirq(&sb->dsp, device_get_config_int("irq"));
|
||||
sb_dsp_setdma8(&sb->dsp, device_get_config_int("dma"));
|
||||
@@ -3226,7 +3283,7 @@ sb_pro_mcv_init(UNUSED(const device_t *info))
|
||||
fm_driver_get(FM_YMF262, &sb->opl);
|
||||
|
||||
sb_dsp_set_real_opl(&sb->dsp, 1);
|
||||
sb_dsp_init(&sb->dsp, SBPRO2_DSP_302, SB_SUBTYPE_DEFAULT, sb);
|
||||
sb_dsp_init(&sb->dsp, SBPRO_DSP_302, SB_SUBTYPE_DEFAULT, sb);
|
||||
sb_ct1345_mixer_reset(sb);
|
||||
|
||||
sb->mixer_enabled = 1;
|
||||
@@ -3258,7 +3315,7 @@ sb_pro_compat_init(UNUSED(const device_t *info))
|
||||
fm_driver_get(FM_YMF262, &sb->opl);
|
||||
|
||||
sb_dsp_set_real_opl(&sb->dsp, 1);
|
||||
sb_dsp_init(&sb->dsp, SBPRO2_DSP_302, SB_SUBTYPE_DEFAULT, sb);
|
||||
sb_dsp_init(&sb->dsp, SBPRO_DSP_302, SB_SUBTYPE_DEFAULT, sb);
|
||||
sb_ct1345_mixer_reset(sb);
|
||||
|
||||
sb->mixer_enabled = 1;
|
||||
@@ -3938,7 +3995,7 @@ ess_x688_init(UNUSED(const device_t *info))
|
||||
fm_driver_get(info->local ? FM_ESFM : FM_YMF262, &ess->opl);
|
||||
|
||||
sb_dsp_set_real_opl(&ess->dsp, 1);
|
||||
sb_dsp_init(&ess->dsp, SBPRO2_DSP_302, info->local ? SB_SUBTYPE_ESS_ES1688 : SB_SUBTYPE_ESS_ES688, ess);
|
||||
sb_dsp_init(&ess->dsp, SBPRO_DSP_301, info->local ? SB_SUBTYPE_ESS_ES1688 : SB_SUBTYPE_ESS_ES688, ess);
|
||||
sb_dsp_setaddr(&ess->dsp, addr);
|
||||
sb_dsp_setirq(&ess->dsp, device_get_config_int("irq"));
|
||||
sb_dsp_setdma8(&ess->dsp, device_get_config_int("dma"));
|
||||
@@ -4050,7 +4107,7 @@ ess_x688_pnp_init(UNUSED(const device_t *info))
|
||||
fm_driver_get(info->local ? FM_ESFM : FM_YMF262, &ess->opl);
|
||||
|
||||
sb_dsp_set_real_opl(&ess->dsp, 1);
|
||||
sb_dsp_init(&ess->dsp, SBPRO2_DSP_302, info->local ? SB_SUBTYPE_ESS_ES1688 : SB_SUBTYPE_ESS_ES688, ess);
|
||||
sb_dsp_init(&ess->dsp, SBPRO_DSP_301, info->local ? SB_SUBTYPE_ESS_ES1688 : SB_SUBTYPE_ESS_ES688, ess);
|
||||
sb_dsp_setdma16_supported(&ess->dsp, 0);
|
||||
ess_mixer_reset(ess);
|
||||
|
||||
@@ -4136,7 +4193,7 @@ ess_x688_mca_init(UNUSED(const device_t *info))
|
||||
fm_driver_get(info->local ? FM_ESFM : FM_YMF262, &ess->opl);
|
||||
|
||||
sb_dsp_set_real_opl(&ess->dsp, 1);
|
||||
sb_dsp_init(&ess->dsp, SBPRO2_DSP_302, info->local ? SB_SUBTYPE_ESS_ES1688 : SB_SUBTYPE_ESS_ES688, ess);
|
||||
sb_dsp_init(&ess->dsp, SBPRO_DSP_301, info->local ? SB_SUBTYPE_ESS_ES1688 : SB_SUBTYPE_ESS_ES688, ess);
|
||||
sb_dsp_setdma16_supported(&ess->dsp, 0);
|
||||
ess_mixer_reset(ess);
|
||||
|
||||
@@ -4288,6 +4345,68 @@ static const device_config_t sb_config[] = {
|
||||
{ .name = "", .description = "", .type = CONFIG_END }
|
||||
};
|
||||
|
||||
static const device_config_t thunderboard_config[] = {
|
||||
{
|
||||
.name = "base",
|
||||
.description = "Address",
|
||||
.type = CONFIG_HEX16,
|
||||
.default_string = NULL,
|
||||
.default_int = 0x220,
|
||||
.file_filter = NULL,
|
||||
.spinner = { 0 },
|
||||
.selection = {
|
||||
{ .description = "0x210", .value = 0x210 },
|
||||
{ .description = "0x220", .value = 0x220 },
|
||||
{ .description = "0x230", .value = 0x230 },
|
||||
{ .description = "0x240", .value = 0x240 },
|
||||
{ .description = "0x250", .value = 0x250 },
|
||||
{ .description = "0x260", .value = 0x260 },
|
||||
{ .description = "" }
|
||||
},
|
||||
.bios = { { 0 } }
|
||||
},
|
||||
{
|
||||
.name = "irq",
|
||||
.description = "IRQ",
|
||||
.type = CONFIG_SELECTION,
|
||||
.default_string = NULL,
|
||||
.default_int = 7,
|
||||
.file_filter = NULL,
|
||||
.spinner = { 0 },
|
||||
.selection = {
|
||||
{ .description = "IRQ 2", .value = 2 },
|
||||
{ .description = "IRQ 3", .value = 3 },
|
||||
{ .description = "IRQ 5", .value = 5 },
|
||||
{ .description = "IRQ 7", .value = 7 },
|
||||
{ .description = "" }
|
||||
},
|
||||
.bios = { { 0 } }
|
||||
},
|
||||
{
|
||||
.name = "gameport",
|
||||
.description = "Enable Game port",
|
||||
.type = CONFIG_BINARY,
|
||||
.default_string = NULL,
|
||||
.default_int = 0,
|
||||
.file_filter = NULL,
|
||||
.spinner = { 0 },
|
||||
.selection = { { 0 } },
|
||||
.bios = { { 0 } }
|
||||
},
|
||||
{
|
||||
.name = "opl",
|
||||
.description = "Enable OPL",
|
||||
.type = CONFIG_BINARY,
|
||||
.default_string = NULL,
|
||||
.default_int = 1,
|
||||
.file_filter = NULL,
|
||||
.spinner = { 0 },
|
||||
.selection = { { 0 } },
|
||||
.bios = { { 0 } }
|
||||
},
|
||||
{ .name = "", .description = "", .type = CONFIG_END }
|
||||
};
|
||||
|
||||
static const device_config_t sb15_config[] = {
|
||||
{
|
||||
.name = "base",
|
||||
@@ -5576,6 +5695,20 @@ static const device_config_t ess_1688_pnp_config[] = {
|
||||
};
|
||||
// clang-format on
|
||||
|
||||
const device_t thunderboard_device = {
|
||||
.name = "MediaVision ThunderBoard",
|
||||
.internal_name = "thunderboard",
|
||||
.flags = DEVICE_ISA,
|
||||
.local = THUNDERBOARD,
|
||||
.init = thunderboard_init,
|
||||
.close = sb_close,
|
||||
.reset = NULL,
|
||||
.available = NULL,
|
||||
.speed_changed = sb_speed_changed,
|
||||
.force_redraw = NULL,
|
||||
.config = thunderboard_config
|
||||
};
|
||||
|
||||
const device_t sb_1_device = {
|
||||
.name = "Sound Blaster v1.0",
|
||||
.internal_name = "sb",
|
||||
|
||||
@@ -85,20 +85,22 @@ char sb202_copyright[] = "COPYRIGHT(C) CREATIVE TECHNOLOGY PTE. LTD. (1991)
|
||||
char sb16_copyright[] = "COPYRIGHT (C) CREATIVE TECHNOLOGY LTD, 1992.";
|
||||
uint16_t sb_dsp_versions[] = {
|
||||
0, /* Pad */
|
||||
0, /* SADLIB - No DSP */
|
||||
0, /* SADLIB - No DSP */
|
||||
0x103, /* SB_DSP_103 - SB "killer card" prototype, DSP v1.03 */
|
||||
0x105, /* SB_DSP_105 - SB1/1.5, DSP v1.05 */
|
||||
0x200, /* SB_DSP_200 - SB1.5/2, DSP v2.00 */
|
||||
0x201, /* SB_DSP_201 - SB1.5/2, DSP v2.01 - needed for high-speed DMA */
|
||||
0x202, /* SB_DSP_202 - SB2, DSP v2.02 */
|
||||
0x300, /* SB_PRO_DSP_300 - SB Pro, DSP v3.00 */
|
||||
0x302, /* SBPRO2_DSP_302 - SB Pro 2, DSP v3.02 + OPL3 */
|
||||
0x404, /* SB16_DSP_404 - DSP v4.04 + OPL3 */
|
||||
0x405, /* SB16_405 - DSP v4.05 + OPL3 */
|
||||
0x406, /* SB16_406 - DSP v4.06 + OPL3 */
|
||||
0x40b, /* SB16_411 - DSP v4.11 + OPL3 */
|
||||
0x40c, /* SBAWE32 - DSP v4.12 + OPL3 */
|
||||
0x40d, /* SBAWE32PNP - DSP v4.13 + OPL3 */
|
||||
0x410 /* SBAWE64 - DSP v4.16 + OPL3 */
|
||||
0x300, /* SBPRO_DSP_300 - SB Pro, DSP v3.00 */
|
||||
0x301, /* SBPRO_DSP_301 - SB Pro/Pro 2, DSP v3.01 */
|
||||
0x302, /* SBPRO_DSP_302 - SB Pro/Pro 2, DSP v3.02 */
|
||||
0x404, /* SB16_DSP_404 - DSP v4.04 + OPL3 */
|
||||
0x405, /* SB16_DSP_405 - DSP v4.05 + OPL3 */
|
||||
0x406, /* SB16_DSP_406 - DSP v4.06 + OPL3 */
|
||||
0x40b, /* SB16_DSP_411 - DSP v4.11 + OPL3 */
|
||||
0x40c, /* SBAWE32_DSP_412 - DSP v4.12 + OPL3 */
|
||||
0x40d, /* SBAWE32_DSP_413 - DSP v4.13 + OPL3 */
|
||||
0x410 /* SBAWE64_DSP_416 - DSP v4.16 + OPL3 */
|
||||
};
|
||||
|
||||
/*These tables were 'borrowed' from DOSBox*/
|
||||
@@ -1614,7 +1616,7 @@ sb_exec_command(sb_dsp_t *dsp)
|
||||
break;
|
||||
case 0xA0: /* Set input mode to mono */
|
||||
case 0xA8: /* Set input mode to stereo */
|
||||
if ((dsp->sb_type < SBPRO_DSP_300) || (dsp->sb_type > SBPRO2_DSP_302))
|
||||
if ((dsp->sb_type < SBPRO_DSP_300) || (dsp->sb_type > SBPRO_DSP_302))
|
||||
break;
|
||||
/* TODO: Implement. 3.xx-only command. */
|
||||
break;
|
||||
@@ -1730,6 +1732,18 @@ sb_exec_command(sb_dsp_t *dsp)
|
||||
sb_add_data(dsp, ~dsp->sb_data[0]);
|
||||
break;
|
||||
case 0xE1: /* Get DSP version */
|
||||
if (IS_MV201(dsp)) {
|
||||
if (dsp->sb_last_command == 0xE1) {
|
||||
sb_add_data(dsp, 0x01);
|
||||
sb_add_data(dsp, 0x30);
|
||||
dsp->sb_last_command = 0x00;
|
||||
} else {
|
||||
sb_add_data(dsp, 0x02);
|
||||
sb_add_data(dsp, 0x00);
|
||||
dsp->sb_last_command = 0xE1;
|
||||
}
|
||||
break;
|
||||
}
|
||||
if (IS_ESS(dsp)) {
|
||||
/*
|
||||
0x03 0x01 (Sound Blaster Pro compatibility) confirmed by both the
|
||||
@@ -1859,12 +1873,12 @@ sb_exec_command(sb_dsp_t *dsp)
|
||||
* 059h Fetches the samples and then immediately plays them back. SB???
|
||||
* 078h Auto-init DMA ADPCM SB2???
|
||||
* 07Ah 2.6-bit ADPCM SB???
|
||||
* 0E3h DSP Copyright SBPro2??? (SBPRO2_DSP_302)
|
||||
* 0F0h Sine Generator SB (SB_DSP_105, DSP20x)
|
||||
* 0F1h DSP Auxiliary Status (Obsolete) SB-Pro2 (DSP20x, SBPRO2_DSP_302)
|
||||
* 0F2h IRQ Request, 8-bit SB (SB_DSP_105, DSP20x)
|
||||
* 0E3h DSP Copyright SBPro2??? (SBPRO_DSP_302)
|
||||
* 0F0h Sine Generator SB (SB_DSP_105, SB_DSP_20x)
|
||||
* 0F1h DSP Auxiliary Status (Obsolete) SB-Pro2 (SB_DSP_20x, SBPRO_DSP_302)
|
||||
* 0F2h IRQ Request, 8-bit SB (SB_DSP_105, SB_DSP_20x)
|
||||
* 0F3h IRQ Request, 16-bit SB16
|
||||
* 0F4h Perform ROM checksum SB (SB_DSP_105, DSP20x)
|
||||
* 0F4h Perform ROM checksum SB (SB_DSP_105, SB_DSP_20x)
|
||||
* 0FBh DSP Status SB16
|
||||
* 0FCh DSP Auxiliary Status SB16
|
||||
* 0FDh DSP Command Status SB16
|
||||
@@ -2236,7 +2250,7 @@ sb_dsp_init(sb_dsp_t *dsp, int type, int subtype, void *parent)
|
||||
a set frequency command is sent. */
|
||||
recalc_sb16_filter(0, 3200 * 2);
|
||||
}
|
||||
if (IS_ESS(dsp) || (dsp->sb_type >= SBPRO2_DSP_302)) {
|
||||
if (IS_ESS(dsp) || (dsp->sb_type >= SBPRO_DSP_302)) {
|
||||
/* OPL3 or dual OPL2 is stereo. */
|
||||
if (dsp->sb_has_real_opl)
|
||||
recalc_opl_filter(FREQ_49716 * 2);
|
||||
|
||||
@@ -808,6 +808,7 @@ sensation_visdac_read(uint16_t port, void *priv)
|
||||
sensation_t *visdac = (sensation_t *) priv;
|
||||
|
||||
uint8_t ret;
|
||||
ret = 0xff;
|
||||
|
||||
switch (port & 0xF) {
|
||||
case 0x00:
|
||||
|
||||
@@ -419,7 +419,7 @@ ymf701_init(const device_t *info)
|
||||
ymf701->sb->opl_enabled = 1;
|
||||
|
||||
sb_dsp_set_real_opl(&ymf701->sb->dsp, 1);
|
||||
sb_dsp_init(&ymf701->sb->dsp, SBPRO2_DSP_302, SB_SUBTYPE_DEFAULT, ymf701);
|
||||
sb_dsp_init(&ymf701->sb->dsp, SBPRO_DSP_302, SB_SUBTYPE_DEFAULT, ymf701);
|
||||
sb_dsp_setaddr(&ymf701->sb->dsp, ymf701->cur_sb_addr);
|
||||
sb_dsp_setirq(&ymf701->sb->dsp, ymf701->cur_sb_irq);
|
||||
sb_dsp_setdma8(&ymf701->sb->dsp, ymf701->cur_sb_dma);
|
||||
|
||||
@@ -712,7 +712,7 @@ ymf71x_init(const device_t *info)
|
||||
ymf71x->sb->opl_enabled = 1;
|
||||
|
||||
sb_dsp_set_real_opl(&ymf71x->sb->dsp, 1);
|
||||
sb_dsp_init(&ymf71x->sb->dsp, SBPRO2_DSP_302, SB_SUBTYPE_DEFAULT, ymf71x);
|
||||
sb_dsp_init(&ymf71x->sb->dsp, SBPRO_DSP_302, SB_SUBTYPE_DEFAULT, ymf71x);
|
||||
sb_ct1345_mixer_reset(ymf71x->sb);
|
||||
|
||||
ymf71x->sb->opl_mixer = ymf71x;
|
||||
|
||||
@@ -126,6 +126,7 @@ static const SOUND_CARD sound_cards[] = {
|
||||
#ifdef USE_LIBSERIALPORT /*The following devices required LIBSERIALPORT*/
|
||||
{ &opl2board_device },
|
||||
#endif
|
||||
{ &thunderboard_device },
|
||||
{ &pasplus_device },
|
||||
{ &sb_1_device },
|
||||
{ &sb_15_device },
|
||||
|
||||
@@ -47,8 +47,12 @@ add_library(ui OBJECT
|
||||
unix_sdl.c
|
||||
unix_osd.c
|
||||
unix_cdrom.c
|
||||
dummy_cdrom_ioctl.c
|
||||
)
|
||||
if(APPLE)
|
||||
target_sources(ui PRIVATE dummy_cdrom_ioctl.c)
|
||||
else()
|
||||
target_sources(ui PRIVATE linux_cdrom_ioctl.c)
|
||||
endif()
|
||||
target_compile_definitions(ui PUBLIC _FILE_OFFSET_BITS=64)
|
||||
target_link_libraries(ui ${CMAKE_DL_LIBS})
|
||||
|
||||
|
||||
875
src/unix/linux_cdrom_ioctl.c
Normal file
875
src/unix/linux_cdrom_ioctl.c
Normal file
@@ -0,0 +1,875 @@
|
||||
/*
|
||||
* 86Box A hypervisor and IBM PC system emulator that specializes in
|
||||
* running old operating systems and software designed for IBM
|
||||
* PC systems and compatibles from 1981 through fairly recent
|
||||
* system designs based on the PCI bus.
|
||||
*
|
||||
* This file is part of the 86Box distribution.
|
||||
*
|
||||
* Linux CD-ROM support via IOCTL (SG_IO).
|
||||
*
|
||||
* Authors: Miran Grca, <mgrca8@gmail.com>
|
||||
* TheCollector1995, <mariogplayer@gmail.com>
|
||||
*
|
||||
* Copyright 2023 TheCollector1995.
|
||||
* Copyright 2023 Miran Grca.
|
||||
* Copyright 2025 86Box contributors.
|
||||
*/
|
||||
#include <inttypes.h>
|
||||
#ifdef ENABLE_IOCTL_LOG
|
||||
#include <stdarg.h>
|
||||
#endif
|
||||
#include <stdio.h>
|
||||
#include <stdint.h>
|
||||
#include <string.h>
|
||||
#include <stdlib.h>
|
||||
#include <stddef.h>
|
||||
#include <unistd.h>
|
||||
#include <fcntl.h>
|
||||
#include <errno.h>
|
||||
#include <pthread.h>
|
||||
#include <sys/ioctl.h>
|
||||
#include <scsi/sg.h>
|
||||
#include <linux/cdrom.h>
|
||||
#define HAVE_STDARG_H
|
||||
#include <86box/86box.h>
|
||||
#include <86box/cdrom.h>
|
||||
#include <86box/log.h>
|
||||
#include <86box/plat_cdrom_ioctl.h>
|
||||
#include <86box/scsi_device.h>
|
||||
|
||||
typedef struct ioctl_t {
|
||||
cdrom_t *dev;
|
||||
void *log;
|
||||
int fd;
|
||||
int is_dvd;
|
||||
int has_audio;
|
||||
int blocks_num;
|
||||
uint8_t cur_rti[65536];
|
||||
char path[256];
|
||||
pthread_t poll_tid;
|
||||
int poll_active;
|
||||
} ioctl_t;
|
||||
|
||||
static int ioctl_read_dvd_structure(const void *local, uint8_t layer, uint8_t format,
|
||||
uint8_t *buffer, uint32_t *info);
|
||||
static int ioctl_is_empty(const void *local);
|
||||
|
||||
/*
|
||||
* Wrapper for the system ioctl() call to avoid naming collisions
|
||||
* with the local 'ioctl' variable of type ioctl_t*.
|
||||
*/
|
||||
static inline int
|
||||
sys_ioctl(int fd, unsigned long request, void *arg)
|
||||
{
|
||||
return ioctl(fd, request, arg);
|
||||
}
|
||||
|
||||
#ifdef ENABLE_IOCTL_LOG
|
||||
int ioctl_do_log = ENABLE_IOCTL_LOG;
|
||||
|
||||
void
|
||||
ioctl_log(void *priv, const char *fmt, ...)
|
||||
{
|
||||
if (ioctl_do_log) {
|
||||
va_list ap;
|
||||
va_start(ap, fmt);
|
||||
log_out(priv, fmt, ap);
|
||||
va_end(ap);
|
||||
}
|
||||
}
|
||||
#else
|
||||
# define ioctl_log(priv, fmt, ...)
|
||||
#endif
|
||||
|
||||
/* Internal functions. */
|
||||
static void
|
||||
ioctl_close_handle(const ioctl_t *ioctl)
|
||||
{
|
||||
if (ioctl->fd >= 0)
|
||||
close(ioctl->fd);
|
||||
}
|
||||
|
||||
static int
|
||||
ioctl_open_handle(ioctl_t *ioctl)
|
||||
{
|
||||
ioctl_log(ioctl->log, "ioctl->path = \"%s\"\n", ioctl->path);
|
||||
ioctl->fd = open(ioctl->path, O_RDONLY | O_NONBLOCK);
|
||||
|
||||
ioctl_log(ioctl->log, "fd=%d, errno=%d\n", ioctl->fd, errno);
|
||||
|
||||
return (ioctl->fd >= 0);
|
||||
}
|
||||
|
||||
/*
|
||||
* Execute a SCSI command via the Linux SG_IO interface.
|
||||
* Returns 1 on success, 0 on failure.
|
||||
* sense_buf should be at least 64 bytes, sense_len receives actual sense length.
|
||||
*/
|
||||
static int
|
||||
sg_io_cmd(int fd, const uint8_t *cdb, int cdb_len,
|
||||
uint8_t *data_buf, int data_len, int direction,
|
||||
uint8_t *sense_buf, int *sense_len)
|
||||
{
|
||||
sg_io_hdr_t io_hdr;
|
||||
|
||||
memset(&io_hdr, 0, sizeof(sg_io_hdr_t));
|
||||
io_hdr.interface_id = 'S';
|
||||
io_hdr.cmd_len = cdb_len;
|
||||
io_hdr.mx_sb_len = 64;
|
||||
io_hdr.dxfer_direction = direction;
|
||||
io_hdr.dxfer_len = data_len;
|
||||
io_hdr.dxferp = data_buf;
|
||||
io_hdr.cmdp = (unsigned char *) cdb;
|
||||
io_hdr.sbp = sense_buf;
|
||||
io_hdr.timeout = 6000; /* 6 seconds, matching Windows */
|
||||
|
||||
if (ioctl(fd, SG_IO, &io_hdr) < 0)
|
||||
return 0;
|
||||
|
||||
if (sense_len != NULL)
|
||||
*sense_len = io_hdr.sb_len_wr;
|
||||
|
||||
/* Check for SCSI errors. */
|
||||
if ((io_hdr.info & SG_INFO_OK_MASK) != SG_INFO_OK) {
|
||||
if (io_hdr.sb_len_wr > 0) {
|
||||
if (sense_len != NULL)
|
||||
*sense_len = io_hdr.sb_len_wr;
|
||||
return 0;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int
|
||||
ioctl_read_normal_toc(ioctl_t *ioctl, uint8_t *toc_buf, int32_t *tracks_num)
|
||||
{
|
||||
struct cdrom_tochdr tochdr;
|
||||
struct cdrom_tocentry tocentry;
|
||||
int status;
|
||||
|
||||
*tracks_num = 0;
|
||||
memset(toc_buf, 0x00, 65536);
|
||||
|
||||
status = sys_ioctl(ioctl->fd, CDROMREADTOCHDR, &tochdr);
|
||||
if (status < 0)
|
||||
return 0;
|
||||
|
||||
ioctl_log(ioctl->log, "TOC: first=%d, last=%d\n",
|
||||
tochdr.cdth_trk0, tochdr.cdth_trk1);
|
||||
|
||||
/*
|
||||
* Build a cooked TOC buffer in the same format as the Windows
|
||||
* CDROM_TOC structure:
|
||||
* [0..1] = length (big-endian)
|
||||
* [2] = first track
|
||||
* [3] = last track
|
||||
* [4..] = 8-byte track descriptors
|
||||
*
|
||||
* Each track descriptor:
|
||||
* [0] = reserved
|
||||
* [1] = Adr/Control
|
||||
* [2] = track number
|
||||
* [3] = reserved
|
||||
* [4..7] = MSF address (0, M, S, F)
|
||||
*/
|
||||
toc_buf[2] = tochdr.cdth_trk0;
|
||||
toc_buf[3] = tochdr.cdth_trk1;
|
||||
|
||||
int count = 0;
|
||||
for (int i = tochdr.cdth_trk0; i <= tochdr.cdth_trk1; i++) {
|
||||
memset(&tocentry, 0, sizeof(tocentry));
|
||||
tocentry.cdte_track = i;
|
||||
tocentry.cdte_format = CDROM_MSF;
|
||||
|
||||
if (sys_ioctl(ioctl->fd, CDROMREADTOCENTRY, &tocentry) < 0)
|
||||
continue;
|
||||
|
||||
uint8_t *t = &toc_buf[4 + count * 8];
|
||||
t[0] = 0;
|
||||
t[1] = ((tocentry.cdte_adr & 0xf) << 4) | (tocentry.cdte_ctrl & 0xf);
|
||||
t[2] = i;
|
||||
t[3] = 0;
|
||||
t[4] = 0;
|
||||
t[5] = tocentry.cdte_addr.msf.minute;
|
||||
t[6] = tocentry.cdte_addr.msf.second;
|
||||
t[7] = tocentry.cdte_addr.msf.frame;
|
||||
count++;
|
||||
}
|
||||
|
||||
/* Lead-out (track 0xAA). */
|
||||
memset(&tocentry, 0, sizeof(tocentry));
|
||||
tocentry.cdte_track = CDROM_LEADOUT;
|
||||
tocentry.cdte_format = CDROM_MSF;
|
||||
|
||||
if (sys_ioctl(ioctl->fd, CDROMREADTOCENTRY, &tocentry) >= 0) {
|
||||
uint8_t *t = &toc_buf[4 + count * 8];
|
||||
t[0] = 0;
|
||||
t[1] = ((tocentry.cdte_adr & 0xf) << 4) | (tocentry.cdte_ctrl & 0xf);
|
||||
t[2] = 0xAA;
|
||||
t[3] = 0;
|
||||
t[4] = 0;
|
||||
t[5] = tocentry.cdte_addr.msf.minute;
|
||||
t[6] = tocentry.cdte_addr.msf.second;
|
||||
t[7] = tocentry.cdte_addr.msf.frame;
|
||||
count++;
|
||||
}
|
||||
|
||||
/* Set the length field (big-endian). */
|
||||
int length = 2 + count * 8;
|
||||
toc_buf[0] = (length >> 8) & 0xff;
|
||||
toc_buf[1] = length & 0xff;
|
||||
*tracks_num = count;
|
||||
|
||||
ioctl_log(ioctl->log, "%i tracks\n", *tracks_num);
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
static void
|
||||
ioctl_read_raw_toc(ioctl_t *ioctl)
|
||||
{
|
||||
raw_track_info_t *rti = (raw_track_info_t *) ioctl->cur_rti;
|
||||
uint8_t *buffer = (uint8_t *) calloc(1, 2052);
|
||||
int status = 0;
|
||||
|
||||
ioctl->is_dvd = (ioctl_read_dvd_structure(ioctl, 0, 0, buffer, NULL) > 0);
|
||||
free(buffer);
|
||||
|
||||
ioctl->has_audio = 0;
|
||||
ioctl->blocks_num = 0;
|
||||
memset(ioctl->cur_rti, 0x00, 65536);
|
||||
|
||||
if (!ioctl->is_dvd) {
|
||||
/* Try SG_IO with READ TOC command, Format=2 (full/raw TOC). */
|
||||
uint8_t cdb[12];
|
||||
uint8_t sense[64];
|
||||
uint8_t *raw_buf = (uint8_t *) calloc(1, 65536);
|
||||
int sense_len = 0;
|
||||
|
||||
memset(cdb, 0, sizeof(cdb));
|
||||
cdb[0] = 0x43; /* READ TOC */
|
||||
cdb[1] = 0x02; /* MSF */
|
||||
cdb[2] = 0x02; /* Format = Full TOC (raw) */
|
||||
cdb[6] = 0x01; /* Session = 1 */
|
||||
cdb[7] = 0xff; /* Allocation length high */
|
||||
cdb[8] = 0xff; /* Allocation length low */
|
||||
|
||||
memset(sense, 0, sizeof(sense));
|
||||
status = sg_io_cmd(ioctl->fd, cdb, 10, raw_buf, 65535,
|
||||
SG_DXFER_FROM_DEV, sense, &sense_len);
|
||||
|
||||
if (status && sense_len == 0) {
|
||||
int length = ((raw_buf[0] << 8) | raw_buf[1]) - 2;
|
||||
ioctl->blocks_num = length / 11;
|
||||
if (ioctl->blocks_num > 0)
|
||||
memcpy(ioctl->cur_rti, &raw_buf[4], ioctl->blocks_num * 11);
|
||||
} else {
|
||||
status = 0;
|
||||
}
|
||||
|
||||
free(raw_buf);
|
||||
}
|
||||
|
||||
if (status == 0) {
|
||||
/*
|
||||
* Raw TOC read failed (or this is a DVD). Fall back to the
|
||||
* cooked TOC, and construct raw_track_info_t entries from it,
|
||||
* mirroring the Windows fallback path.
|
||||
*/
|
||||
uint8_t cur_toc[65536] = { 0 };
|
||||
int32_t tracks_num = 0;
|
||||
|
||||
status = ioctl_read_normal_toc(ioctl, cur_toc, &tracks_num);
|
||||
|
||||
if ((status > 0) && (tracks_num >= 1)) {
|
||||
/* Last real entry (the lead-out). */
|
||||
const uint8_t *ct = &cur_toc[4 + (tracks_num - 1) * 8];
|
||||
|
||||
rti[0].adr_ctl = ct[1];
|
||||
rti[0].point = 0xa0;
|
||||
rti[0].pm = cur_toc[2]; /* FirstTrack */
|
||||
|
||||
rti[1].adr_ctl = rti[0].adr_ctl;
|
||||
rti[1].point = 0xa1;
|
||||
rti[1].pm = cur_toc[3]; /* LastTrack */
|
||||
|
||||
rti[2].adr_ctl = rti[0].adr_ctl;
|
||||
rti[2].point = 0xa2;
|
||||
rti[2].pm = ct[5]; /* M */
|
||||
rti[2].ps = ct[6]; /* S */
|
||||
rti[2].pf = ct[7]; /* F */
|
||||
|
||||
ioctl->blocks_num = 3;
|
||||
|
||||
for (int i = 0; i < (tracks_num - 1); i++) {
|
||||
raw_track_info_t *crt = &(rti[ioctl->blocks_num]);
|
||||
|
||||
ct = &cur_toc[4 + i * 8];
|
||||
|
||||
crt->adr_ctl = ct[1];
|
||||
crt->point = ct[2];
|
||||
crt->pm = ct[5];
|
||||
crt->ps = ct[6];
|
||||
crt->pf = ct[7];
|
||||
|
||||
ioctl->blocks_num++;
|
||||
}
|
||||
} else if (status > 0)
|
||||
/* Announce that we've had a failure. */
|
||||
status = 0;
|
||||
}
|
||||
|
||||
if (ioctl->blocks_num) for (int i = 0; i < ioctl->blocks_num; i++) {
|
||||
const raw_track_info_t *crt = &(rti[i]);
|
||||
|
||||
if ((crt->point >= 1) && (crt->point <= 99) && !(crt->adr_ctl & 0x04)) {
|
||||
ioctl->has_audio = 1;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef ENABLE_IOCTL_LOG
|
||||
ioctl_log(ioctl->log, "%i blocks\n", ioctl->blocks_num);
|
||||
|
||||
for (int i = 0; i < ioctl->blocks_num; i++) {
|
||||
uint8_t *t = (uint8_t *) &rti[i];
|
||||
ioctl_log(ioctl->log, "Block %03i: %02X %02X %02X %02X %02X %02X %02X %02X "
|
||||
"%02X %02X %02X\n",
|
||||
i, t[0], t[1], t[2], t[3], t[4], t[5], t[6], t[7], t[8],
|
||||
t[9], t[10]);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
static int
|
||||
ioctl_get_track(const ioctl_t *ioctl, const uint32_t sector)
|
||||
{
|
||||
raw_track_info_t *rti = (raw_track_info_t *) ioctl->cur_rti;
|
||||
int track = -1;
|
||||
|
||||
for (int i = (ioctl->blocks_num - 1); i >= 0; i--) {
|
||||
const raw_track_info_t *ct = &(rti[i]);
|
||||
const uint32_t start = (ct->pm * 60 * 75) + (ct->ps * 75) + ct->pf - 150;
|
||||
|
||||
ioctl_log(ioctl->log, "ioctl_get_track(): ct: %02X, %08X\n",
|
||||
ct->point, start);
|
||||
|
||||
if ((ct->point >= 1) && (ct->point <= 99) && (sector >= start)) {
|
||||
track = i;
|
||||
ioctl_log(ioctl->log, "ioctl_get_track(): found track: %i\n", i);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return track;
|
||||
}
|
||||
|
||||
static int
|
||||
ioctl_is_track_audio(const ioctl_t *ioctl, const uint32_t pos)
|
||||
{
|
||||
const raw_track_info_t *rti = (const raw_track_info_t *) ioctl->cur_rti;
|
||||
int ret = 0;
|
||||
|
||||
if (ioctl->has_audio && !ioctl->is_dvd) {
|
||||
const int track = ioctl_get_track(ioctl, pos);
|
||||
const int control = rti[track].adr_ctl;
|
||||
|
||||
ret = !(control & 0x04);
|
||||
|
||||
ioctl_log(ioctl->log, "ioctl_is_track_audio(%08X, %02X): %i\n", pos, track, ret);
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
/* Shared functions (cdrom_ops_t interface). */
|
||||
static int
|
||||
ioctl_get_track_info(const void *local, const uint32_t track,
|
||||
int end, track_info_t *ti)
|
||||
{
|
||||
const ioctl_t *ioctl = (const ioctl_t *) local;
|
||||
const raw_track_info_t *rti = (const raw_track_info_t *) ioctl->cur_rti;
|
||||
int ret = 1;
|
||||
int trk = -1;
|
||||
int next = -1;
|
||||
|
||||
if ((track >= 1) && (track < 99))
|
||||
for (int i = 0; i < ioctl->blocks_num; i++)
|
||||
if (rti[i].point == track) {
|
||||
trk = i;
|
||||
break;
|
||||
}
|
||||
|
||||
if ((track >= 1) && (track < 98))
|
||||
for (int i = 0; i < ioctl->blocks_num; i++)
|
||||
if ((rti[i].point == (track + 1)) && (rti[i].session == rti[trk].session)) {
|
||||
next = i;
|
||||
break;
|
||||
}
|
||||
|
||||
if ((track >= 1) && (track < 99) && (trk != -1) && (next == -1))
|
||||
for (int i = 0; i < ioctl->blocks_num; i++)
|
||||
if ((rti[i].point == 0xa2) && (rti[i].session == rti[trk].session)) {
|
||||
next = i;
|
||||
break;
|
||||
}
|
||||
|
||||
if ((track == 0xaa) || (trk == -1)) {
|
||||
ioctl_log(ioctl->log, "ioctl_get_track_info(%02i)\n", track);
|
||||
ret = 0;
|
||||
} else {
|
||||
if (end) {
|
||||
if (next != -1) {
|
||||
ti->m = rti[next].pm;
|
||||
ti->s = rti[next].ps;
|
||||
ti->f = rti[next].pf;
|
||||
}
|
||||
} else {
|
||||
ti->m = rti[trk].pm;
|
||||
ti->s = rti[trk].ps;
|
||||
ti->f = rti[trk].pf;
|
||||
}
|
||||
|
||||
ti->number = rti[trk].point;
|
||||
ti->attr = rti[trk].adr_ctl;
|
||||
|
||||
ioctl_log(ioctl->log, "ioctl_get_track_info(%02i): %02i:%02i:%02i, %02i, %02X\n",
|
||||
track, ti->m, ti->s, ti->f, ti->number, ti->attr);
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static void
|
||||
ioctl_get_raw_track_info(const void *local, int *num, uint8_t *rti)
|
||||
{
|
||||
const ioctl_t *ioctl = (const ioctl_t *) local;
|
||||
|
||||
*num = ioctl->blocks_num;
|
||||
memcpy(rti, ioctl->cur_rti, ioctl->blocks_num * 11);
|
||||
}
|
||||
|
||||
static int
|
||||
ioctl_is_track_pre(const void *local, const uint32_t sector)
|
||||
{
|
||||
const ioctl_t *ioctl = (const ioctl_t *) local;
|
||||
const raw_track_info_t *rti = (const raw_track_info_t *) ioctl->cur_rti;
|
||||
int ret = 0;
|
||||
|
||||
if (ioctl->has_audio && !ioctl->is_dvd) {
|
||||
const int track = ioctl_get_track(ioctl, sector);
|
||||
const int control = rti[track].adr_ctl;
|
||||
|
||||
ret = control & 0x01;
|
||||
|
||||
ioctl_log(ioctl->log, "ioctl_is_track_pre(%08X, %02X): %i\n", sector, track, ret);
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int
|
||||
ioctl_read_sector(const void *local, uint8_t *buffer, uint32_t const sector)
|
||||
{
|
||||
const ioctl_t *ioctl = (const ioctl_t *) local;
|
||||
const raw_track_info_t *rti = (raw_track_info_t *) ioctl->cur_rti;
|
||||
const int sc_offs = (sector == 0xffffffff) ? 0 : 2352;
|
||||
int len = (sector == 0xffffffff) ? 16 : 2368;
|
||||
int m = 0;
|
||||
int s = 0;
|
||||
int f = 0;
|
||||
uint32_t lba = sector;
|
||||
int ret;
|
||||
int data_len = 0;
|
||||
|
||||
if (ioctl->is_dvd) {
|
||||
int track;
|
||||
|
||||
data_len = 0;
|
||||
ret = 0;
|
||||
|
||||
if (lba == 0xffffffff) {
|
||||
lba = ioctl->dev->seek_pos;
|
||||
track = ioctl_get_track(ioctl, lba);
|
||||
|
||||
if (track != -1) {
|
||||
data_len = len;
|
||||
ret = 1;
|
||||
}
|
||||
} else {
|
||||
len = COOKED_SECTOR_SIZE;
|
||||
track = ioctl_get_track(ioctl, lba);
|
||||
|
||||
if (track != -1) {
|
||||
ssize_t nread = pread(ioctl->fd, &(buffer[16]),
|
||||
COOKED_SECTOR_SIZE,
|
||||
(off_t) lba * COOKED_SECTOR_SIZE);
|
||||
if (nread > 0) {
|
||||
data_len = (int) nread;
|
||||
ret = 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (ret && (data_len >= len) && (track != -1)) {
|
||||
const raw_track_info_t *ct = &(rti[track]);
|
||||
const uint32_t start = (ct->pm * 60 * 75) + (ct->ps * 75) + ct->pf;
|
||||
|
||||
m = s = f = 0;
|
||||
|
||||
/* Construct sector header and sub-header. */
|
||||
if (sector != 0xffffffff) {
|
||||
/* Sync bytes. */
|
||||
buffer[0] = 0x00;
|
||||
memset(&(buffer[1]), 0xff, 10);
|
||||
buffer[11] = 0x00;
|
||||
|
||||
/* Sector header. */
|
||||
FRAMES_TO_MSF(lba + 150, &m, &s, &f);
|
||||
buffer[12] = bin2bcd(m);
|
||||
buffer[13] = bin2bcd(s);
|
||||
buffer[14] = bin2bcd(f);
|
||||
|
||||
/* Mode 1 data. */
|
||||
buffer[15] = 0x01;
|
||||
}
|
||||
|
||||
/* Construct Q. */
|
||||
buffer[sc_offs + 0] = (ct->adr_ctl >> 4) | ((ct->adr_ctl & 0xf) << 4);
|
||||
buffer[sc_offs + 1] = bin2bcd(ct->point);
|
||||
buffer[sc_offs + 2] = 1;
|
||||
FRAMES_TO_MSF((int32_t) (lba + 150 - start), &m, &s, &f);
|
||||
buffer[sc_offs + 3] = bin2bcd(m);
|
||||
buffer[sc_offs + 4] = bin2bcd(s);
|
||||
buffer[sc_offs + 5] = bin2bcd(f);
|
||||
FRAMES_TO_MSF(lba + 150, &m, &s, &f);
|
||||
buffer[sc_offs + 7] = bin2bcd(m);
|
||||
buffer[sc_offs + 8] = bin2bcd(s);
|
||||
buffer[sc_offs + 9] = bin2bcd(f);
|
||||
}
|
||||
} else {
|
||||
/* CD: use SG_IO with READ CD (0xBE). */
|
||||
uint8_t cdb[12];
|
||||
uint8_t sense[64];
|
||||
int sense_len = 0;
|
||||
|
||||
memset(cdb, 0, sizeof(cdb));
|
||||
cdb[0] = 0xbe; /* READ CD */
|
||||
cdb[1] = 0x00;
|
||||
cdb[2] = (sector >> 24) & 0xff;
|
||||
cdb[3] = (sector >> 16) & 0xff;
|
||||
cdb[4] = (sector >> 8) & 0xff;
|
||||
cdb[5] = sector & 0xff; /* Starting LBA */
|
||||
cdb[6] = 0x00;
|
||||
cdb[7] = 0x00;
|
||||
cdb[8] = 0x01; /* Transfer Length = 1 */
|
||||
/* If sector is FFFFFFFF, only return the subchannel. */
|
||||
cdb[9] = (sector == 0xffffffff) ? 0x00 : 0xf8;
|
||||
cdb[10] = 0x02;
|
||||
cdb[11] = 0x00;
|
||||
|
||||
#ifdef ENABLE_IOCTL_LOG
|
||||
ioctl_log(ioctl->log, "Host CDB: %02X %02X %02X %02X %02X %02X "
|
||||
"%02X %02X %02X %02X %02X %02X\n",
|
||||
cdb[0], cdb[1], cdb[2], cdb[3], cdb[4], cdb[5],
|
||||
cdb[6], cdb[7], cdb[8], cdb[9], cdb[10], cdb[11]);
|
||||
#endif
|
||||
|
||||
memset(sense, 0, sizeof(sense));
|
||||
ret = sg_io_cmd(ioctl->fd, cdb, 12, buffer, len,
|
||||
SG_DXFER_FROM_DEV, sense, &sense_len);
|
||||
|
||||
ioctl_log(ioctl->log, "ioctl_read_sector: ret = %d, sense_len = %d\n",
|
||||
ret, sense_len);
|
||||
|
||||
if (sense_len >= 16) {
|
||||
if ((sense[2] == 0x03) && (sense[12] == 0x11))
|
||||
/* Treat this as an error to correctly indicate CIRC error to the guest. */
|
||||
ret = 0;
|
||||
ioctl_log(ioctl->log, "Host sense: %02X %02X %02X %02X %02X %02X %02X %02X\n",
|
||||
sense[0], sense[1], sense[2], sense[3],
|
||||
sense[4], sense[5], sense[6], sense[7]);
|
||||
ioctl_log(ioctl->log, " %02X %02X %02X %02X %02X %02X %02X %02X\n",
|
||||
sense[8], sense[9], sense[10], sense[11],
|
||||
sense[12], sense[13], sense[14], sense[15]);
|
||||
}
|
||||
|
||||
ret = ret ? 1 : -1;
|
||||
data_len = len; /* sg_io_cmd handles this internally */
|
||||
}
|
||||
|
||||
ioctl_log(ioctl->log, "ioctl_read_sector: final ret = %i\n", ret);
|
||||
|
||||
/* Construct raw subchannel data from Q only. */
|
||||
if ((ret > 0) && !ioctl->is_dvd)
|
||||
for (int i = 11; i >= 0; i--)
|
||||
for (int j = 7; j >= 0; j--)
|
||||
buffer[2352 + (i * 8) + j] = ((buffer[sc_offs + i] >> (7 - j)) & 0x01) << 6;
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static uint8_t
|
||||
ioctl_get_track_type(const void *local, const uint32_t sector)
|
||||
{
|
||||
ioctl_t *ioctl = (ioctl_t *) local;
|
||||
int track = ioctl_get_track(ioctl, sector);
|
||||
raw_track_info_t *rti = (raw_track_info_t *) ioctl->cur_rti;
|
||||
const raw_track_info_t *trk = &(rti[track]);
|
||||
uint8_t ret = 0x00;
|
||||
|
||||
if (ioctl_is_track_audio(ioctl, sector))
|
||||
ret = CD_TRACK_AUDIO;
|
||||
else if (track != -1) for (int i = 0; i < ioctl->blocks_num; i++) {
|
||||
const raw_track_info_t *ct = &(rti[i]);
|
||||
const raw_track_info_t *nt = &(rti[i + 1]);
|
||||
|
||||
if (ct->point == 0xa0) {
|
||||
uint8_t first = ct->pm;
|
||||
uint8_t last = nt->pm;
|
||||
|
||||
if ((trk->point >= first) && (trk->point <= last)) {
|
||||
ret = ct->ps;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static uint32_t
|
||||
ioctl_get_last_block(const void *local)
|
||||
{
|
||||
const ioctl_t *ioctl = (const ioctl_t *) local;
|
||||
raw_track_info_t *rti = (raw_track_info_t *) ioctl->cur_rti;
|
||||
uint32_t lb = 0;
|
||||
|
||||
for (int i = (ioctl->blocks_num - 1); i >= 0; i--)
|
||||
if (rti[i].point == 0xa2) {
|
||||
lb = MSFtoLBA(rti[i].pm, rti[i].ps, rti[i].pf) - 151;
|
||||
break;
|
||||
}
|
||||
|
||||
ioctl_log(ioctl->log, "LBCapacity=%d\n", lb);
|
||||
|
||||
return lb;
|
||||
}
|
||||
|
||||
static int
|
||||
ioctl_read_dvd_structure(const void *local, const uint8_t layer, const uint8_t format,
|
||||
uint8_t *buffer, uint32_t *info)
|
||||
{
|
||||
const ioctl_t *ioctl = (const ioctl_t *) local;
|
||||
const int len = 2052;
|
||||
uint8_t cdb[12];
|
||||
uint8_t sense[64];
|
||||
int sense_len = 0;
|
||||
|
||||
memset(cdb, 0, sizeof(cdb));
|
||||
cdb[0] = 0xad; /* READ DVD STRUCTURE */
|
||||
cdb[6] = layer; /* Layer Number */
|
||||
cdb[7] = format; /* Format */
|
||||
cdb[8] = 0x08; /* Allocation Length high */
|
||||
cdb[9] = 0x04; /* Allocation Length low */
|
||||
|
||||
#ifdef ENABLE_IOCTL_LOG
|
||||
ioctl_log(ioctl->log, "Host CDB: %02X %02X %02X %02X %02X %02X "
|
||||
"%02X %02X %02X %02X %02X %02X\n",
|
||||
cdb[0], cdb[1], cdb[2], cdb[3], cdb[4], cdb[5],
|
||||
cdb[6], cdb[7], cdb[8], cdb[9], cdb[10], cdb[11]);
|
||||
#endif
|
||||
|
||||
memset(sense, 0, sizeof(sense));
|
||||
int ret = sg_io_cmd(ioctl->fd, cdb, 12, buffer, len,
|
||||
SG_DXFER_FROM_DEV, sense, &sense_len);
|
||||
|
||||
ioctl_log(ioctl->log, "ioctl_read_dvd_structure(): ret = %d, sense_len = %d\n",
|
||||
ret, sense_len);
|
||||
|
||||
if (sense_len >= 16) {
|
||||
/* Return sense to the host as is. */
|
||||
ret = -((sense[2] << 16) | (sense[12] << 8) | sense[13]);
|
||||
if (info != NULL)
|
||||
*info = *(uint32_t *) &(sense[3]);
|
||||
ioctl_log(ioctl->log, "Host sense: %02X %02X %02X %02X %02X %02X %02X %02X\n",
|
||||
sense[0], sense[1], sense[2], sense[3],
|
||||
sense[4], sense[5], sense[6], sense[7]);
|
||||
ioctl_log(ioctl->log, " %02X %02X %02X %02X %02X %02X %02X %02X\n",
|
||||
sense[8], sense[9], sense[10], sense[11],
|
||||
sense[12], sense[13], sense[14], sense[15]);
|
||||
} else
|
||||
ret = ret ? 1 : 0;
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int
|
||||
ioctl_is_dvd(const void *local)
|
||||
{
|
||||
const ioctl_t *ioctl = (const ioctl_t *) local;
|
||||
|
||||
return ioctl->is_dvd;
|
||||
}
|
||||
|
||||
static int
|
||||
ioctl_has_audio(const void *local)
|
||||
{
|
||||
const ioctl_t *ioctl = (const ioctl_t *) local;
|
||||
|
||||
return ioctl->has_audio;
|
||||
}
|
||||
|
||||
static int
|
||||
ioctl_is_empty(const void *local)
|
||||
{
|
||||
const ioctl_t *ioctl = (const ioctl_t *) local;
|
||||
uint8_t cdb[12];
|
||||
uint8_t sense[64];
|
||||
int sense_len = 0;
|
||||
|
||||
/* TEST UNIT READY */
|
||||
memset(cdb, 0, sizeof(cdb));
|
||||
cdb[0] = 0x00;
|
||||
|
||||
#ifdef ENABLE_IOCTL_LOG
|
||||
ioctl_log(ioctl->log, "Host CDB: %02X %02X %02X %02X %02X %02X "
|
||||
"%02X %02X %02X %02X %02X %02X\n",
|
||||
cdb[0], cdb[1], cdb[2], cdb[3], cdb[4], cdb[5],
|
||||
cdb[6], cdb[7], cdb[8], cdb[9], cdb[10], cdb[11]);
|
||||
#endif
|
||||
|
||||
memset(sense, 0, sizeof(sense));
|
||||
int ret = sg_io_cmd(ioctl->fd, cdb, 6, NULL, 0,
|
||||
SG_DXFER_NONE, sense, &sense_len);
|
||||
|
||||
ioctl_log(ioctl->log, "ioctl_is_empty(): ret = %d, sense_len = %d\n",
|
||||
ret, sense_len);
|
||||
|
||||
if (sense_len >= 16) {
|
||||
/* Check for NOT READY + MEDIUM NOT PRESENT. */
|
||||
ret = ((sense[2] == SENSE_NOT_READY) && (sense[12] == ASC_MEDIUM_NOT_PRESENT));
|
||||
ioctl_log(ioctl->log, "Host sense: %02X %02X %02X %02X %02X %02X %02X %02X\n",
|
||||
sense[0], sense[1], sense[2], sense[3],
|
||||
sense[4], sense[5], sense[6], sense[7]);
|
||||
ioctl_log(ioctl->log, " %02X %02X %02X %02X %02X %02X %02X %02X\n",
|
||||
sense[8], sense[9], sense[10], sense[11],
|
||||
sense[12], sense[13], sense[14], sense[15]);
|
||||
} else if (!ret)
|
||||
ret = 1; /* SG_IO itself failed, assume empty */
|
||||
else
|
||||
ret = 0; /* No sense data and command succeeded = media present */
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
/* Disc change polling thread. */
|
||||
static void *
|
||||
ioctl_poll_thread(void *arg)
|
||||
{
|
||||
ioctl_t *ioctl = (ioctl_t *) arg;
|
||||
int was_empty = ioctl_is_empty(ioctl);
|
||||
|
||||
while (ioctl->poll_active) {
|
||||
sleep(2); /* Poll every 2 seconds. */
|
||||
if (!ioctl->poll_active)
|
||||
break;
|
||||
|
||||
int now_empty = ioctl_is_empty(ioctl);
|
||||
if (now_empty != was_empty) {
|
||||
if (now_empty)
|
||||
cdrom_set_empty(ioctl->dev);
|
||||
else
|
||||
cdrom_update_status(ioctl->dev);
|
||||
was_empty = now_empty;
|
||||
}
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static void
|
||||
ioctl_close(void *local)
|
||||
{
|
||||
ioctl_t *ioctl = (ioctl_t *) local;
|
||||
|
||||
/* Stop the polling thread. */
|
||||
if (ioctl->poll_active) {
|
||||
ioctl->poll_active = 0;
|
||||
pthread_join(ioctl->poll_tid, NULL);
|
||||
}
|
||||
|
||||
ioctl_close_handle(ioctl);
|
||||
ioctl->fd = -1;
|
||||
|
||||
ioctl_log(ioctl->log, "Log closed\n");
|
||||
|
||||
log_close(ioctl->log);
|
||||
ioctl->log = NULL;
|
||||
|
||||
free(ioctl);
|
||||
}
|
||||
|
||||
static void
|
||||
ioctl_load(const void *local)
|
||||
{
|
||||
ioctl_t *ioctl = (ioctl_t *) local;
|
||||
|
||||
if ((ioctl->fd >= 0) || ioctl_open_handle(ioctl)) {
|
||||
/* Try to close the tray. */
|
||||
(void) sys_ioctl(ioctl->fd, CDROMCLOSETRAY, NULL);
|
||||
|
||||
ioctl_read_raw_toc(ioctl);
|
||||
}
|
||||
}
|
||||
|
||||
static const cdrom_ops_t ioctl_ops = {
|
||||
ioctl_get_track_info,
|
||||
ioctl_get_raw_track_info,
|
||||
ioctl_is_track_pre,
|
||||
ioctl_read_sector,
|
||||
ioctl_get_track_type,
|
||||
ioctl_get_last_block,
|
||||
ioctl_read_dvd_structure,
|
||||
ioctl_is_dvd,
|
||||
ioctl_has_audio,
|
||||
ioctl_is_empty,
|
||||
ioctl_close,
|
||||
ioctl_load
|
||||
};
|
||||
|
||||
/* Public functions. */
|
||||
void *
|
||||
ioctl_open(cdrom_t *dev, const char *drv)
|
||||
{
|
||||
ioctl_t *ioctl = (ioctl_t *) calloc(1, sizeof(ioctl_t));
|
||||
|
||||
if (ioctl != NULL) {
|
||||
char n[1024] = { 0 };
|
||||
|
||||
sprintf(n, "CD-ROM %i IOCtl", dev->id + 1);
|
||||
ioctl->log = log_open(n);
|
||||
|
||||
memset(ioctl->path, 0x00, sizeof(ioctl->path));
|
||||
ioctl->fd = -1;
|
||||
|
||||
/* drv is "ioctl:///dev/sr0", extract the path part. */
|
||||
snprintf(ioctl->path, sizeof(ioctl->path), "%s", &(drv[8]));
|
||||
ioctl_log(ioctl->log, "Path is %s\n", ioctl->path);
|
||||
|
||||
ioctl->dev = dev;
|
||||
dev->ops = &ioctl_ops;
|
||||
|
||||
ioctl_load(ioctl);
|
||||
|
||||
/* Start the disc change polling thread. */
|
||||
ioctl->poll_active = 1;
|
||||
if (pthread_create(&ioctl->poll_tid, NULL, ioctl_poll_thread, ioctl) != 0)
|
||||
ioctl->poll_active = 0;
|
||||
}
|
||||
|
||||
return ioctl;
|
||||
}
|
||||
@@ -1121,83 +1121,159 @@ ibm8514_accel_start(int count, int cpu_input, uint32_t mix_dat, uint32_t cpu_dat
|
||||
|
||||
if (pixcntl == 1) {
|
||||
mix_dat = 0;
|
||||
if (and3 == 3) {
|
||||
if (dev->accel.multifunc[8] & 0x02)
|
||||
mix_dat |= 0x08;
|
||||
if (dev->accel.multifunc[8] & 0x04)
|
||||
mix_dat |= 0x10;
|
||||
if (dev->accel.multifunc[8] & 0x08)
|
||||
mix_dat |= 0x20;
|
||||
if (dev->accel.multifunc[8] & 0x10)
|
||||
mix_dat |= 0x40;
|
||||
if (dev->accel.multifunc[9] & 0x02)
|
||||
mix_dat |= 0x80;
|
||||
if (dev->accel.multifunc[9] & 0x04)
|
||||
mix_dat |= 0x01;
|
||||
if (dev->accel.multifunc[9] & 0x08)
|
||||
mix_dat |= 0x02;
|
||||
if (dev->accel.multifunc[9] & 0x10)
|
||||
mix_dat |= 0x04;
|
||||
}
|
||||
if (and3 == 2) {
|
||||
if (dev->accel.multifunc[8] & 0x02)
|
||||
mix_dat |= 0x04;
|
||||
if (dev->accel.multifunc[8] & 0x04)
|
||||
mix_dat |= 0x08;
|
||||
if (dev->accel.multifunc[8] & 0x08)
|
||||
mix_dat |= 0x10;
|
||||
if (dev->accel.multifunc[8] & 0x10)
|
||||
mix_dat |= 0x20;
|
||||
if (dev->accel.multifunc[9] & 0x02)
|
||||
mix_dat |= 0x40;
|
||||
if (dev->accel.multifunc[9] & 0x04)
|
||||
mix_dat |= 0x80;
|
||||
if (dev->accel.multifunc[9] & 0x08)
|
||||
mix_dat |= 0x01;
|
||||
if (dev->accel.multifunc[9] & 0x10)
|
||||
mix_dat |= 0x02;
|
||||
}
|
||||
if (and3 == 1) {
|
||||
if (dev->accel.multifunc[8] & 0x02)
|
||||
mix_dat |= 0x02;
|
||||
if (dev->accel.multifunc[8] & 0x04)
|
||||
mix_dat |= 0x04;
|
||||
if (dev->accel.multifunc[8] & 0x08)
|
||||
mix_dat |= 0x08;
|
||||
if (dev->accel.multifunc[8] & 0x10)
|
||||
mix_dat |= 0x10;
|
||||
if (dev->accel.multifunc[9] & 0x02)
|
||||
mix_dat |= 0x20;
|
||||
if (dev->accel.multifunc[9] & 0x04)
|
||||
mix_dat |= 0x40;
|
||||
if (dev->accel.multifunc[9] & 0x08)
|
||||
mix_dat |= 0x80;
|
||||
if (dev->accel.multifunc[9] & 0x10)
|
||||
mix_dat |= 0x01;
|
||||
}
|
||||
if (and3 == 0) {
|
||||
if (dev->accel.multifunc[8] & 0x02)
|
||||
mix_dat |= 0x01;
|
||||
if (dev->accel.multifunc[8] & 0x04)
|
||||
mix_dat |= 0x02;
|
||||
if (dev->accel.multifunc[8] & 0x08)
|
||||
mix_dat |= 0x04;
|
||||
if (dev->accel.multifunc[8] & 0x10)
|
||||
mix_dat |= 0x08;
|
||||
if (dev->accel.multifunc[9] & 0x02)
|
||||
mix_dat |= 0x10;
|
||||
if (dev->accel.multifunc[9] & 0x04)
|
||||
mix_dat |= 0x20;
|
||||
if (dev->accel.multifunc[9] & 0x08)
|
||||
mix_dat |= 0x40;
|
||||
if (dev->accel.multifunc[9] & 0x10)
|
||||
mix_dat |= 0x80;
|
||||
if (cmd == 6) {
|
||||
if (and3_blt == 3) {
|
||||
if (dev->accel.multifunc[8] & 0x02)
|
||||
mix_dat |= 0x08;
|
||||
if (dev->accel.multifunc[8] & 0x04)
|
||||
mix_dat |= 0x10;
|
||||
if (dev->accel.multifunc[8] & 0x08)
|
||||
mix_dat |= 0x20;
|
||||
if (dev->accel.multifunc[8] & 0x10)
|
||||
mix_dat |= 0x40;
|
||||
if (dev->accel.multifunc[9] & 0x02)
|
||||
mix_dat |= 0x80;
|
||||
if (dev->accel.multifunc[9] & 0x04)
|
||||
mix_dat |= 0x01;
|
||||
if (dev->accel.multifunc[9] & 0x08)
|
||||
mix_dat |= 0x02;
|
||||
if (dev->accel.multifunc[9] & 0x10)
|
||||
mix_dat |= 0x04;
|
||||
}
|
||||
if (and3_blt == 2) {
|
||||
if (dev->accel.multifunc[8] & 0x02)
|
||||
mix_dat |= 0x04;
|
||||
if (dev->accel.multifunc[8] & 0x04)
|
||||
mix_dat |= 0x08;
|
||||
if (dev->accel.multifunc[8] & 0x08)
|
||||
mix_dat |= 0x10;
|
||||
if (dev->accel.multifunc[8] & 0x10)
|
||||
mix_dat |= 0x20;
|
||||
if (dev->accel.multifunc[9] & 0x02)
|
||||
mix_dat |= 0x40;
|
||||
if (dev->accel.multifunc[9] & 0x04)
|
||||
mix_dat |= 0x80;
|
||||
if (dev->accel.multifunc[9] & 0x08)
|
||||
mix_dat |= 0x01;
|
||||
if (dev->accel.multifunc[9] & 0x10)
|
||||
mix_dat |= 0x02;
|
||||
}
|
||||
if (and3_blt == 1) {
|
||||
if (dev->accel.multifunc[8] & 0x02)
|
||||
mix_dat |= 0x02;
|
||||
if (dev->accel.multifunc[8] & 0x04)
|
||||
mix_dat |= 0x04;
|
||||
if (dev->accel.multifunc[8] & 0x08)
|
||||
mix_dat |= 0x08;
|
||||
if (dev->accel.multifunc[8] & 0x10)
|
||||
mix_dat |= 0x10;
|
||||
if (dev->accel.multifunc[9] & 0x02)
|
||||
mix_dat |= 0x20;
|
||||
if (dev->accel.multifunc[9] & 0x04)
|
||||
mix_dat |= 0x40;
|
||||
if (dev->accel.multifunc[9] & 0x08)
|
||||
mix_dat |= 0x80;
|
||||
if (dev->accel.multifunc[9] & 0x10)
|
||||
mix_dat |= 0x01;
|
||||
}
|
||||
if (and3_blt == 0) {
|
||||
if (dev->accel.multifunc[8] & 0x02)
|
||||
mix_dat |= 0x01;
|
||||
if (dev->accel.multifunc[8] & 0x04)
|
||||
mix_dat |= 0x02;
|
||||
if (dev->accel.multifunc[8] & 0x08)
|
||||
mix_dat |= 0x04;
|
||||
if (dev->accel.multifunc[8] & 0x10)
|
||||
mix_dat |= 0x08;
|
||||
if (dev->accel.multifunc[9] & 0x02)
|
||||
mix_dat |= 0x10;
|
||||
if (dev->accel.multifunc[9] & 0x04)
|
||||
mix_dat |= 0x20;
|
||||
if (dev->accel.multifunc[9] & 0x08)
|
||||
mix_dat |= 0x40;
|
||||
if (dev->accel.multifunc[9] & 0x10)
|
||||
mix_dat |= 0x80;
|
||||
}
|
||||
} else {
|
||||
if (and3 == 3) {
|
||||
if (dev->accel.multifunc[8] & 0x02)
|
||||
mix_dat |= 0x08;
|
||||
if (dev->accel.multifunc[8] & 0x04)
|
||||
mix_dat |= 0x10;
|
||||
if (dev->accel.multifunc[8] & 0x08)
|
||||
mix_dat |= 0x20;
|
||||
if (dev->accel.multifunc[8] & 0x10)
|
||||
mix_dat |= 0x40;
|
||||
if (dev->accel.multifunc[9] & 0x02)
|
||||
mix_dat |= 0x80;
|
||||
if (dev->accel.multifunc[9] & 0x04)
|
||||
mix_dat |= 0x01;
|
||||
if (dev->accel.multifunc[9] & 0x08)
|
||||
mix_dat |= 0x02;
|
||||
if (dev->accel.multifunc[9] & 0x10)
|
||||
mix_dat |= 0x04;
|
||||
}
|
||||
if (and3 == 2) {
|
||||
if (dev->accel.multifunc[8] & 0x02)
|
||||
mix_dat |= 0x04;
|
||||
if (dev->accel.multifunc[8] & 0x04)
|
||||
mix_dat |= 0x08;
|
||||
if (dev->accel.multifunc[8] & 0x08)
|
||||
mix_dat |= 0x10;
|
||||
if (dev->accel.multifunc[8] & 0x10)
|
||||
mix_dat |= 0x20;
|
||||
if (dev->accel.multifunc[9] & 0x02)
|
||||
mix_dat |= 0x40;
|
||||
if (dev->accel.multifunc[9] & 0x04)
|
||||
mix_dat |= 0x80;
|
||||
if (dev->accel.multifunc[9] & 0x08)
|
||||
mix_dat |= 0x01;
|
||||
if (dev->accel.multifunc[9] & 0x10)
|
||||
mix_dat |= 0x02;
|
||||
}
|
||||
if (and3 == 1) {
|
||||
if (dev->accel.multifunc[8] & 0x02)
|
||||
mix_dat |= 0x02;
|
||||
if (dev->accel.multifunc[8] & 0x04)
|
||||
mix_dat |= 0x04;
|
||||
if (dev->accel.multifunc[8] & 0x08)
|
||||
mix_dat |= 0x08;
|
||||
if (dev->accel.multifunc[8] & 0x10)
|
||||
mix_dat |= 0x10;
|
||||
if (dev->accel.multifunc[9] & 0x02)
|
||||
mix_dat |= 0x20;
|
||||
if (dev->accel.multifunc[9] & 0x04)
|
||||
mix_dat |= 0x40;
|
||||
if (dev->accel.multifunc[9] & 0x08)
|
||||
mix_dat |= 0x80;
|
||||
if (dev->accel.multifunc[9] & 0x10)
|
||||
mix_dat |= 0x01;
|
||||
}
|
||||
if (and3 == 0) {
|
||||
if (dev->accel.multifunc[8] & 0x02)
|
||||
mix_dat |= 0x01;
|
||||
if (dev->accel.multifunc[8] & 0x04)
|
||||
mix_dat |= 0x02;
|
||||
if (dev->accel.multifunc[8] & 0x08)
|
||||
mix_dat |= 0x04;
|
||||
if (dev->accel.multifunc[8] & 0x10)
|
||||
mix_dat |= 0x08;
|
||||
if (dev->accel.multifunc[9] & 0x02)
|
||||
mix_dat |= 0x10;
|
||||
if (dev->accel.multifunc[9] & 0x04)
|
||||
mix_dat |= 0x20;
|
||||
if (dev->accel.multifunc[9] & 0x08)
|
||||
mix_dat |= 0x40;
|
||||
if (dev->accel.multifunc[9] & 0x10)
|
||||
mix_dat |= 0x80;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
old_mix_dat = mix_dat;
|
||||
|
||||
ibm8514_log("CMD=%d, full=%04x, pixcntl=%d, filling=%02x, ssvdraw=%02x.\n", cmd, dev->accel.cmd, pixcntl, dev->accel.multifunc[0x0a] & 0x06, dev->accel.ssv_draw);
|
||||
if (!(dev->accel.cmd & 0x01))
|
||||
ibm8514_log("CMD=%d, full=%04x, pixcntl=%d, filling=%02x, ssvdraw=%02x.\n", cmd, dev->accel.cmd, pixcntl, dev->accel.multifunc[0x0a] & 0x06, dev->accel.ssv_draw);
|
||||
|
||||
/*Bit 4 of the Command register is the draw yes bit, which enables writing to memory/reading from memory when enabled.
|
||||
When this bit is disabled, no writing to memory/reading from memory is allowed. (This bit is almost meaningless on
|
||||
|
||||
@@ -3021,8 +3021,10 @@ ati8514_recalctimings(svga_t *svga)
|
||||
if (dev->ven_clock & 0x40)
|
||||
svga->clock_8514 *= 2.0;
|
||||
|
||||
if (dev->interlace)
|
||||
if (dev->interlace) {
|
||||
dev->dispend >>= 1;
|
||||
svga->clock_8514 /= 2.0;
|
||||
}
|
||||
|
||||
mach_log("cntl=%d, hv(%d,%d), pitch=%d, rowoffset=%d, gextconfig=%03x, shadow=%x interlace=%d.\n",
|
||||
dev->accel.advfunc_cntl & 0x04, dev->h_disp, dev->dispend, dev->pitch, dev->rowoffset,
|
||||
@@ -3183,8 +3185,10 @@ mach_recalctimings(svga_t *svga)
|
||||
|
||||
mach_log("8514/A modes=%d, clocksel=%02x, clkselmode=%02x, divide reg ibm=%02x, divide reg vga=%02x, vgainterlace=%x, interlace=%x, htotal=%02x.\n", _8514_modes, mach->accel.clock_sel & 0xfe, mach->accel.clock_sel_mode & 0xfe, mach->accel.clock_sel & 0x40, mach->regs[0xb8] & 0x40, svga->interlace, dev->interlace, dev->htotal);
|
||||
|
||||
if (dev->interlace)
|
||||
if (dev->interlace) {
|
||||
dev->dispend >>= 1;
|
||||
svga->clock_8514 /= 2.0;
|
||||
}
|
||||
|
||||
if (ATI_MACH32) {
|
||||
switch ((mach->shadow_set >> 8) & 0x03) {
|
||||
|
||||
@@ -53,6 +53,7 @@
|
||||
#define BIOS_GD5428_DIAMOND_B1_VLB_PATH "roms/video/cirruslogic/Diamond SpeedStar PRO VLB v3.04.bin"
|
||||
#define BIOS_GD5428_ISA_PATH "roms/video/cirruslogic/5428.bin"
|
||||
#define BIOS_GD5428_MCA_PATH "roms/video/cirruslogic/SVGA141.ROM"
|
||||
#define BIOS_GD5428_ONBOARD_ACER_PATH "roms/machines/acera1g/4alo001.bin"
|
||||
#define BIOS_GD5428_PATH "roms/video/cirruslogic/vlbusjapan.BIN"
|
||||
#define BIOS_GD5428_BOCA_ISA_PATH_1 "roms/video/cirruslogic/boca_gd5428_1.30b_1.bin"
|
||||
#define BIOS_GD5428_BOCA_ISA_PATH_2 "roms/video/cirruslogic/boca_gd5428_1.30b_2.bin"
|
||||
@@ -1327,7 +1328,10 @@ gd54xx_in(uint16_t addr, void *priv)
|
||||
/* Scratch Pad 1 (Memory size for 5402/542x) */
|
||||
ret = svga->seqregs[0x0a] & ~0x1a;
|
||||
if (svga->crtc[0x27] == CIRRUS_ID_CLGD5402) {
|
||||
ret |= 0x01; /*512K of memory*/
|
||||
if ((gd54xx->vram_size >> 10) == 512)
|
||||
ret |= 0x01; /*512K of memory*/
|
||||
else
|
||||
ret &= 0xfe; /*256K of memory*/
|
||||
} else if (svga->crtc[0x27] > CIRRUS_ID_CLGD5402) {
|
||||
switch (gd54xx->vram_size >> 10) {
|
||||
case 512:
|
||||
@@ -4284,6 +4288,8 @@ gd54xx_init(const device_t *info)
|
||||
|
||||
case CIRRUS_ID_CLGD5402:
|
||||
if (info->local & 0x200)
|
||||
romfn = NULL;
|
||||
else if (info->local & 0x100)
|
||||
romfn = BIOS_GD5402_ONBOARD_PATH;
|
||||
else
|
||||
romfn = BIOS_GD5402_PATH;
|
||||
@@ -4326,7 +4332,10 @@ gd54xx_init(const device_t *info)
|
||||
|
||||
case CIRRUS_ID_CLGD5428:
|
||||
if (info->local & 0x200) {
|
||||
romfn = NULL;
|
||||
if (machines[machine].init == machine_at_acera1g_init)
|
||||
romfn = BIOS_GD5428_ONBOARD_ACER_PATH;
|
||||
else
|
||||
romfn = NULL;
|
||||
gd54xx->has_bios = 0;
|
||||
} else if (info->local & 0x100)
|
||||
if (gd54xx->vlb)
|
||||
@@ -4427,12 +4436,12 @@ gd54xx_init(const device_t *info)
|
||||
gd54xx->vram_size = vram << 10;
|
||||
} else {
|
||||
if (id <= CIRRUS_ID_CLGD5428) {
|
||||
if ((id == CIRRUS_ID_CLGD5426) && (info->local & 0x200))
|
||||
if ((id == CIRRUS_ID_CLGD5428) && (info->local & 0x200) && (info->local & 0x1000))
|
||||
vram = 1024;
|
||||
else if ((id == CIRRUS_ID_CLGD5426) && (info->local & 0x200) && (info->local & 0x1000))
|
||||
vram = 1024;
|
||||
else if (id == CIRRUS_ID_CLGD5401)
|
||||
vram = 256;
|
||||
else if (id == CIRRUS_ID_CLGD5402)
|
||||
vram = 512;
|
||||
else
|
||||
vram = device_get_config_int("memory");
|
||||
|
||||
@@ -4768,6 +4777,25 @@ gd54xx_force_redraw(void *priv)
|
||||
}
|
||||
|
||||
// clang-format off
|
||||
static const device_config_t gd5402_config[] = {
|
||||
{
|
||||
.name = "memory",
|
||||
.description = "Memory size",
|
||||
.type = CONFIG_SELECTION,
|
||||
.default_string = NULL,
|
||||
.default_int = 512,
|
||||
.file_filter = NULL,
|
||||
.spinner = { 0 },
|
||||
.selection = {
|
||||
{ .description = "256 KB", .value = 256 },
|
||||
{ .description = "512 KB", .value = 512 },
|
||||
{ .description = "" }
|
||||
},
|
||||
.bios = { { 0 } }
|
||||
},
|
||||
{ .name = "", .description = "", .type = CONFIG_END }
|
||||
};
|
||||
|
||||
static const device_config_t gd542x_config[] = {
|
||||
{
|
||||
.name = "memory",
|
||||
@@ -5015,7 +5043,7 @@ const device_t gd5402_isa_device = {
|
||||
.available = gd5402_available,
|
||||
.speed_changed = gd54xx_speed_changed,
|
||||
.force_redraw = gd54xx_force_redraw,
|
||||
.config = NULL,
|
||||
.config = gd5402_config,
|
||||
};
|
||||
|
||||
const device_t gd5402_onboard_device = {
|
||||
@@ -5029,7 +5057,21 @@ const device_t gd5402_onboard_device = {
|
||||
.available = NULL,
|
||||
.speed_changed = gd54xx_speed_changed,
|
||||
.force_redraw = gd54xx_force_redraw,
|
||||
.config = NULL,
|
||||
.config = gd5402_config,
|
||||
};
|
||||
|
||||
const device_t gd5402_onboard_commodore_device = {
|
||||
.name = "Cirrus Logic GD5402 (ISA) (ACUMOS AVGA2) (On-Board) (Commodore)",
|
||||
.internal_name = "cl_gd5402_onboard_commodore",
|
||||
.flags = DEVICE_ISA16,
|
||||
.local = CIRRUS_ID_CLGD5402 | 0x100,
|
||||
.init = gd54xx_init,
|
||||
.close = gd54xx_close,
|
||||
.reset = gd54xx_reset,
|
||||
.available = NULL,
|
||||
.speed_changed = gd54xx_speed_changed,
|
||||
.force_redraw = gd54xx_force_redraw,
|
||||
.config = gd5402_config,
|
||||
};
|
||||
|
||||
const device_t gd5420_isa_device = {
|
||||
@@ -5145,11 +5187,25 @@ const device_t gd5426_vlb_device = {
|
||||
.config = gd5426_config
|
||||
};
|
||||
|
||||
const device_t gd5426_onboard_isa_device = {
|
||||
.name = "Cirrus Logic GD5426 (ISA) (On-Board)",
|
||||
.internal_name = "cl_gd5426_onboard",
|
||||
.flags = DEVICE_ISA16,
|
||||
.local = CIRRUS_ID_CLGD5426 | 0x200,
|
||||
.init = gd54xx_init,
|
||||
.close = gd54xx_close,
|
||||
.reset = gd54xx_reset,
|
||||
.available = gd5428_isa_available,
|
||||
.speed_changed = gd54xx_speed_changed,
|
||||
.force_redraw = gd54xx_force_redraw,
|
||||
.config = gd542x_config
|
||||
};
|
||||
|
||||
const device_t gd5426_onboard_device = {
|
||||
.name = "Cirrus Logic GD5426 (VLB) (On-Board)",
|
||||
.internal_name = "cl_gd5426_onboard",
|
||||
.flags = DEVICE_VLB,
|
||||
.local = CIRRUS_ID_CLGD5426 | 0x200,
|
||||
.local = CIRRUS_ID_CLGD5426 | 0x200 | 0x1000,
|
||||
.init = gd54xx_init,
|
||||
.close = gd54xx_close,
|
||||
.reset = gd54xx_reset,
|
||||
@@ -5248,21 +5304,21 @@ const device_t gd5428_onboard_device = {
|
||||
.name = "Cirrus Logic GD5428 (ISA) (On-Board)",
|
||||
.internal_name = "cl_gd5428_onboard",
|
||||
.flags = DEVICE_ISA16,
|
||||
.local = CIRRUS_ID_CLGD5428,
|
||||
.local = CIRRUS_ID_CLGD5428 | 0x200,
|
||||
.init = gd54xx_init,
|
||||
.close = gd54xx_close,
|
||||
.reset = gd54xx_reset,
|
||||
.available = gd5428_isa_available,
|
||||
.speed_changed = gd54xx_speed_changed,
|
||||
.force_redraw = gd54xx_force_redraw,
|
||||
.config = gd5426_config
|
||||
.config = gd542x_config
|
||||
};
|
||||
|
||||
const device_t gd5428_vlb_onboard_device = {
|
||||
.name = "Cirrus Logic GD5428 (VLB) (On-Board)",
|
||||
.internal_name = "cl_gd5428_vlb_onboard",
|
||||
.flags = DEVICE_VLB,
|
||||
.local = CIRRUS_ID_CLGD5428,
|
||||
.local = CIRRUS_ID_CLGD5428 | 0x200,
|
||||
.init = gd54xx_init,
|
||||
.close = gd54xx_close,
|
||||
.reset = gd54xx_reset,
|
||||
@@ -5273,7 +5329,7 @@ const device_t gd5428_vlb_onboard_device = {
|
||||
};
|
||||
|
||||
const device_t gd5428_onboard_vlb_device = {
|
||||
.name = "Cirrus Logic GD5428 (VLB) (On-Board) (Dell)",
|
||||
.name = "Cirrus Logic GD5428 (VLB) (On-Board) (1MB)",
|
||||
.internal_name = "cl_gd5428_onboard_vlb",
|
||||
.flags = DEVICE_VLB,
|
||||
.local = CIRRUS_ID_CLGD5428 | 0x200,
|
||||
@@ -5286,6 +5342,20 @@ const device_t gd5428_onboard_vlb_device = {
|
||||
.config = gd542x_config
|
||||
};
|
||||
|
||||
const device_t gd5428_vlb_onboard_tandy_device = {
|
||||
.name = "Cirrus Logic GD5428 (VLB) (On-Board) (Tandy)",
|
||||
.internal_name = "cl_gd5428_vlb_onboard_tandy",
|
||||
.flags = DEVICE_VLB,
|
||||
.local = CIRRUS_ID_CLGD5428 | 0x200 | 0x1000,
|
||||
.init = gd54xx_init,
|
||||
.close = gd54xx_close,
|
||||
.reset = gd54xx_reset,
|
||||
.available = NULL,
|
||||
.speed_changed = gd54xx_speed_changed,
|
||||
.force_redraw = gd54xx_force_redraw,
|
||||
.config = NULL
|
||||
};
|
||||
|
||||
const device_t gd5429_isa_device = {
|
||||
.name = "Cirrus Logic GD5429 (ISA)",
|
||||
.internal_name = "cl_gd5429_isa",
|
||||
|
||||
Reference in New Issue
Block a user