mirror of
https://github.com/86Box/86Box.git
synced 2026-02-24 02:18:20 -07:00
Merge branch '86Box:master' into master
This commit is contained in:
@@ -149,6 +149,18 @@ else()
|
||||
option(NEW_DYNAREC "Use the PCem v15 (\"new\") dynamic recompiler" OFF)
|
||||
endif()
|
||||
|
||||
if(CMAKE_SYSTEM_NAME STREQUAL "NetBSD")
|
||||
option(AUDIO4 "Use audio(4) as sound backend" ON)
|
||||
else()
|
||||
set(AUDIO4 OFF)
|
||||
endif()
|
||||
|
||||
if(CMAKE_SYSTEM_NAME STREQUAL "OpenBSD")
|
||||
option(SNDIO "Use sndio as sound backend" ON)
|
||||
else()
|
||||
set(SNDIO OFF)
|
||||
endif()
|
||||
|
||||
if(WIN32)
|
||||
set(QT ON)
|
||||
option(CPPTHREADS "C++11 threads" OFF)
|
||||
|
||||
@@ -53,6 +53,7 @@
|
||||
|
||||
#define REG_RA1 0x61 /* Command Delay */
|
||||
#define RA1_MASK 0xff /* 1111 1111 */
|
||||
#define RA1_MASK_SX 0xbf /* 1X11 1111 */
|
||||
#define RA1_BUSDLY 0x03 /* AT BUS command delay */
|
||||
#define RA1_BUSDLY_SH 0
|
||||
#define RA1_BUS8DLY 0x0c /* AT BUS 8bit command delay */
|
||||
@@ -81,6 +82,7 @@
|
||||
#define ATWS_3 1 /* 3 wait states */
|
||||
#define ATWS_4 2 /* 4 wait states */
|
||||
#define ATWS_5 4 /* 5 wait states */
|
||||
#define RA2_387SX 0x80
|
||||
|
||||
/* CS8221 82C212 controller registers. */
|
||||
#define REG_RB0 0x64 /* Version ID */
|
||||
@@ -103,6 +105,9 @@
|
||||
|
||||
#define REG_RB2 0x66 /* Memory Enable 1 */
|
||||
#define RB2_MASK 0x80 /* 1XXX XXXX */
|
||||
#define RB2_MASK_SX 0xe0 /* 111X XXXX */
|
||||
#define RB2_BOT256 0x20 /* bottom 256K is on sysboard (1) */
|
||||
#define RB2_MID256 0x40 /* middle 256K is on sysboard (1) */
|
||||
#define RB2_TOP128 0x80 /* top 128K is on sysboard (1) */
|
||||
|
||||
#define REG_RB3 0x67 /* Memory Enable 2 */
|
||||
@@ -198,6 +203,7 @@
|
||||
|
||||
#define REG_RB12 0x6f /* Miscellaneous */
|
||||
#define RB12_MASK 0xe6 /* 111R R11R */
|
||||
#define RB12_MASK_SX 0xf6 /* 1111 R11R */
|
||||
#define RB12_GA20 0x02 /* gate for A20 */
|
||||
#define RB12_RASTMO 0x04 /* enable RAS timeout counter */
|
||||
#define RB12_EMSLEN 0xe0 /* EMS memory chunk size */
|
||||
@@ -221,11 +227,10 @@ typedef struct ram_page_t {
|
||||
} ram_page_t;
|
||||
|
||||
typedef struct neat_t {
|
||||
uint8_t mem_flags[32];
|
||||
uint8_t mem_flags[64];
|
||||
uint8_t regs[128]; /* all the CS8221 registers */
|
||||
uint8_t indx; /* programmed index into registers */
|
||||
|
||||
char pad;
|
||||
uint8_t sx;
|
||||
|
||||
uint16_t ems_base; /* configured base address */
|
||||
uint32_t ems_frame; /* configured frame address */
|
||||
@@ -238,8 +243,19 @@ typedef struct neat_t {
|
||||
ram_page_t shadow[32]; /* Shadow RAM pages */
|
||||
} neat_t;
|
||||
|
||||
static uint8_t defaults[16] = { 0x0a, 0x45, 0xfc, 0x00, 0x00, 0xfe, 0x00, 0x00,
|
||||
0x00, 0x00, 0xa0, 0x63, 0x10, 0x00, 0x00, 0x12 };
|
||||
static uint8_t defaults[2][16] = { { 0x0a, 0x45, 0xfc, 0x00, 0x00, 0x0e, 0x00, 0x00,
|
||||
0x00, 0x00, 0x80, 0x43, 0x10, 0x00, 0x00, 0x12 },
|
||||
{ 0x0a, 0x45, 0x7c, 0x00, 0x00, 0x0e, 0x00, 0x00,
|
||||
0x00, 0x00, 0x80, 0x43, 0x00, 0x00, 0x00, 0x08 } };
|
||||
|
||||
static uint8_t reg_masks[2][16] = { { RA0_MASK, RA1_MASK, RA2_MASK, 0x00,
|
||||
RB0_MASK, RB1_MASK, RB2_MASK, RB3_MASK,
|
||||
RB4_MASK, RB4_MASK, RB4_MASK, RB4_MASK,
|
||||
RB8_MASK, RB9_MASK, RB10_MASK, RB12_MASK },
|
||||
{ RA0_MASK, RA1_MASK_SX, RA2_MASK, 0x00,
|
||||
RB0_MASK, RB1_MASK, RB2_MASK_SX, RB3_MASK,
|
||||
RB4_MASK, RB4_MASK, RB4_MASK, RB4_MASK,
|
||||
RB8_MASK, RB9_MASK, RB10_MASK, RB12_MASK_SX } };
|
||||
|
||||
static uint8_t masks[4] = { RB10_P0EXT, RB10_P1EXT, RB10_P2EXT, RB10_P3EXT };
|
||||
static uint8_t shifts[4] = { RB10_P0EXT_SH, RB10_P1EXT_SH, RB10_P2EXT_SH, RB10_P3EXT_SH };
|
||||
@@ -405,12 +421,12 @@ ems_writew(uint32_t addr, uint16_t val, void *priv)
|
||||
static void
|
||||
neat_mem_update_state(neat_t *dev, uint32_t addr, uint32_t size, uint8_t new_flags, uint8_t mask)
|
||||
{
|
||||
if ((addr >= 0x00080000) && (addr < 0x00100000) &&
|
||||
((new_flags ^ dev->mem_flags[(addr - 0x00080000) / EMS_PGSIZE]) & mask)) {
|
||||
dev->mem_flags[(addr - 0x00080000) / EMS_PGSIZE] &= ~mask;
|
||||
dev->mem_flags[(addr - 0x00080000) / EMS_PGSIZE] |= new_flags;
|
||||
if ((addr < 0x00100000) &&
|
||||
((new_flags ^ dev->mem_flags[addr / EMS_PGSIZE]) & mask)) {
|
||||
dev->mem_flags[addr / EMS_PGSIZE] &= ~mask;
|
||||
dev->mem_flags[addr / EMS_PGSIZE] |= new_flags;
|
||||
|
||||
new_flags = dev->mem_flags[(addr - 0x00080000) / EMS_PGSIZE];
|
||||
new_flags = dev->mem_flags[addr / EMS_PGSIZE];
|
||||
|
||||
if (new_flags & MEM_FLAG_ROMCS) {
|
||||
neat_log("neat_mem_update_state(): %08X-%08X: %02X (ROMCS)\n", addr, addr + size - 1, new_flags);
|
||||
@@ -691,6 +707,7 @@ neat_write(uint16_t port, uint8_t val, void *priv)
|
||||
uint8_t xval;
|
||||
uint8_t j;
|
||||
uint8_t *reg;
|
||||
uint8_t mask;
|
||||
int i;
|
||||
|
||||
#if defined(ENABLE_NEAT_LOG) && (ENABLE_NEAT_LOG == 2)
|
||||
@@ -705,10 +722,11 @@ neat_write(uint16_t port, uint8_t val, void *priv)
|
||||
case 0x23:
|
||||
reg = &dev->regs[dev->indx];
|
||||
xval = *reg ^ val;
|
||||
mask = reg_masks[dev->sx][dev->indx & REG_MASK];
|
||||
switch (dev->indx) {
|
||||
case REG_RA0:
|
||||
val &= RA0_MASK;
|
||||
*reg = (*reg & ~RA0_MASK) | val | (RA0_REV_ID << RA0_REV_SH);
|
||||
val &= mask;
|
||||
*reg = (*reg & ~mask) | val | (RA0_REV_ID << RA0_REV_SH);
|
||||
if ((xval & 0x20) && (val & 0x20))
|
||||
outb(0x64, 0xfe);
|
||||
#if defined(ENABLE_NEAT_LOG) && (ENABLE_NEAT_LOG == 2)
|
||||
@@ -717,32 +735,32 @@ neat_write(uint16_t port, uint8_t val, void *priv)
|
||||
break;
|
||||
|
||||
case REG_RA1:
|
||||
val &= RA1_MASK;
|
||||
*reg = (*reg & ~RA1_MASK) | val;
|
||||
val &= mask;
|
||||
*reg = (*reg & ~mask) | val;
|
||||
#if defined(ENABLE_NEAT_LOG) && (ENABLE_NEAT_LOG == 2)
|
||||
neat_log("NEAT: RA1=%02x(%02x)\n", val, *reg);
|
||||
#endif
|
||||
break;
|
||||
|
||||
case REG_RA2:
|
||||
val &= RA2_MASK;
|
||||
*reg = (*reg & ~RA2_MASK) | val;
|
||||
val &= mask;
|
||||
*reg = (*reg & ~mask) | val;
|
||||
#if defined(ENABLE_NEAT_LOG) && (ENABLE_NEAT_LOG == 2)
|
||||
neat_log("NEAT: RA2=%02x(%02x)\n", val, *reg);
|
||||
#endif
|
||||
break;
|
||||
|
||||
case REG_RB0:
|
||||
val &= RB0_MASK;
|
||||
*reg = (*reg & ~RB0_MASK) | val | (RB0_REV_ID << RB0_REV_SH);
|
||||
val &= mask;
|
||||
*reg = (*reg & ~mask) | val | (RB0_REV_ID << RB0_REV_SH);
|
||||
#if defined(ENABLE_NEAT_LOG) && (ENABLE_NEAT_LOG == 2)
|
||||
neat_log("NEAT: RB0=%02x(%02x)\n", val, *reg);
|
||||
#endif
|
||||
break;
|
||||
|
||||
case REG_RB1:
|
||||
val &= RB1_MASK;
|
||||
*reg = (*reg & ~RB1_MASK) | val;
|
||||
val &= mask;
|
||||
*reg = (*reg & ~mask) | val;
|
||||
shadow_recalc(dev);
|
||||
#if defined(ENABLE_NEAT_LOG) && (ENABLE_NEAT_LOG == 2)
|
||||
neat_log("NEAT: RB1=%02x(%02x)\n", val, *reg);
|
||||
@@ -750,20 +768,37 @@ neat_write(uint16_t port, uint8_t val, void *priv)
|
||||
break;
|
||||
|
||||
case REG_RB2:
|
||||
val &= RB2_MASK;
|
||||
*reg = (*reg & ~RB2_MASK) | val;
|
||||
val &= mask;
|
||||
*reg = (*reg & ~mask) | val;
|
||||
if (dev->sx) {
|
||||
if (val & RB2_BOT256)
|
||||
neat_mem_update_state(dev, 0x00000000, 0x00040000,
|
||||
MEM_FLAG_READ | MEM_FLAG_WRITE, MEM_FMASK_SHADOW);
|
||||
else
|
||||
neat_mem_update_state(dev, 0x00000000, 0x00040000,
|
||||
0x00, MEM_FMASK_SHADOW);
|
||||
|
||||
if (val & RB2_MID256)
|
||||
neat_mem_update_state(dev, 0x00040000, 0x00040000,
|
||||
MEM_FLAG_READ | MEM_FLAG_WRITE, MEM_FMASK_SHADOW);
|
||||
else
|
||||
neat_mem_update_state(dev, 0x00040000, 0x00040000,
|
||||
0x00, MEM_FMASK_SHADOW);
|
||||
}
|
||||
if (val & RB2_TOP128)
|
||||
neat_mem_update_state(dev, 0x00080000, 0x00020000, MEM_FLAG_READ | MEM_FLAG_WRITE, MEM_FMASK_SHADOW);
|
||||
neat_mem_update_state(dev, 0x00080000, 0x00020000,
|
||||
MEM_FLAG_READ | MEM_FLAG_WRITE, MEM_FMASK_SHADOW);
|
||||
else
|
||||
neat_mem_update_state(dev, 0x00080000, 0x00020000, 0x00, MEM_FMASK_SHADOW);
|
||||
neat_mem_update_state(dev, 0x00080000, 0x00020000,
|
||||
0x00, MEM_FMASK_SHADOW);
|
||||
#if defined(ENABLE_NEAT_LOG) && (ENABLE_NEAT_LOG == 2)
|
||||
neat_log("NEAT: RB2=%02x(%02x)\n", val, *reg);
|
||||
#endif
|
||||
break;
|
||||
|
||||
case REG_RB3:
|
||||
val &= RB3_MASK;
|
||||
*reg = (*reg & ~RB3_MASK) | val;
|
||||
val &= mask;
|
||||
*reg = (*reg & ~mask) | val;
|
||||
shadow_recalc(dev);
|
||||
#if defined(ENABLE_NEAT_LOG) && (ENABLE_NEAT_LOG == 2)
|
||||
neat_log("NEAT: RB3=%02x(%02x)\n", val, *reg);
|
||||
@@ -771,8 +806,8 @@ neat_write(uint16_t port, uint8_t val, void *priv)
|
||||
break;
|
||||
|
||||
case REG_RB4:
|
||||
val &= RB4_MASK;
|
||||
*reg = (*reg & ~RB4_MASK) | val;
|
||||
val &= mask;
|
||||
*reg = (*reg & ~mask) | val;
|
||||
shadow_recalc(dev);
|
||||
#if defined(ENABLE_NEAT_LOG) && (ENABLE_NEAT_LOG == 2)
|
||||
neat_log("NEAT: RB4=%02x(%02x)\n", val, *reg);
|
||||
@@ -780,8 +815,8 @@ neat_write(uint16_t port, uint8_t val, void *priv)
|
||||
break;
|
||||
|
||||
case REG_RB5:
|
||||
val &= RB5_MASK;
|
||||
*reg = (*reg & ~RB5_MASK) | val;
|
||||
val &= mask;
|
||||
*reg = (*reg & ~mask) | val;
|
||||
shadow_recalc(dev);
|
||||
#if defined(ENABLE_NEAT_LOG) && (ENABLE_NEAT_LOG == 2)
|
||||
neat_log("NEAT: RB5=%02x(%02x)\n", val, *reg);
|
||||
@@ -789,20 +824,20 @@ neat_write(uint16_t port, uint8_t val, void *priv)
|
||||
break;
|
||||
|
||||
case REG_RB6:
|
||||
val &= RB6_MASK;
|
||||
*reg = (*reg & ~RB6_MASK) | val;
|
||||
val &= mask;
|
||||
*reg = (*reg & ~mask) | val;
|
||||
#if defined(ENABLE_NEAT_LOG) && (ENABLE_NEAT_LOG == 2)
|
||||
neat_log("NEAT: RB6=%02x(%02x)\n", val, *reg);
|
||||
#endif
|
||||
break;
|
||||
|
||||
case REG_RB7:
|
||||
val &= RB7_MASK;
|
||||
val &= mask;
|
||||
|
||||
if (xval & (RB7_EMSEN | RB7_UMAREL))
|
||||
remap_update(dev, val);
|
||||
|
||||
dev->regs[REG_RB7] = val;
|
||||
*reg = (*reg & ~mask) | val;
|
||||
|
||||
if (xval & RB7_EMSEN)
|
||||
ems_remove_handlers(dev);
|
||||
@@ -816,16 +851,16 @@ neat_write(uint16_t port, uint8_t val, void *priv)
|
||||
break;
|
||||
|
||||
case REG_RB8:
|
||||
val &= RB8_MASK;
|
||||
*reg = (*reg & ~RB8_MASK) | val;
|
||||
val &= mask;
|
||||
*reg = (*reg & ~mask) | val;
|
||||
#if defined(ENABLE_NEAT_LOG) && (ENABLE_NEAT_LOG == 2)
|
||||
neat_log("NEAT: RB8=%02x(%02x)\n", val, *reg);
|
||||
#endif
|
||||
break;
|
||||
|
||||
case REG_RB9:
|
||||
val &= RB9_MASK;
|
||||
*reg = (*reg & ~RB9_MASK) | val;
|
||||
val &= mask;
|
||||
*reg = (*reg & ~mask) | val;
|
||||
#if defined(ENABLE_NEAT_LOG) && (ENABLE_NEAT_LOG == 2)
|
||||
neat_log("NEAT: RB9=%02x(%02x)\n", val, *reg);
|
||||
#endif
|
||||
@@ -847,8 +882,8 @@ neat_write(uint16_t port, uint8_t val, void *priv)
|
||||
break;
|
||||
|
||||
case REG_RB10:
|
||||
val &= RB10_MASK;
|
||||
*reg = (*reg & ~RB10_MASK) | val;
|
||||
val &= mask;
|
||||
*reg = (*reg & ~mask) | val;
|
||||
#if defined(ENABLE_NEAT_LOG) && (ENABLE_NEAT_LOG == 2)
|
||||
neat_log("NEAT: RB10=%02x(%02x)\n", val, *reg);
|
||||
#endif
|
||||
@@ -882,8 +917,8 @@ neat_write(uint16_t port, uint8_t val, void *priv)
|
||||
break;
|
||||
|
||||
case REG_RB12:
|
||||
val &= RB12_MASK;
|
||||
*reg = (*reg & ~RB12_MASK) | val;
|
||||
val &= mask;
|
||||
*reg = (*reg & ~mask) | val;
|
||||
#if defined(ENABLE_NEAT_LOG) && (ENABLE_NEAT_LOG == 2)
|
||||
neat_log("NEAT: RB12=%02x(%02x)\n", val, *reg);
|
||||
#endif
|
||||
@@ -976,6 +1011,8 @@ neat_init(UNUSED(const device_t *info))
|
||||
/* Create an instance. */
|
||||
dev = (neat_t *) calloc(1, sizeof(neat_t));
|
||||
|
||||
dev->sx = info->local;
|
||||
|
||||
if (mem_size > 1024) {
|
||||
mem_mapping_set_handler(&ram_high_mapping, neat_read_ram, neat_read_ramw, NULL,
|
||||
neat_write_ram, neat_write_ramw, NULL);
|
||||
@@ -1002,7 +1039,7 @@ neat_init(UNUSED(const device_t *info))
|
||||
neat_mem_update_state(dev, 0x000a0000 + (i * EMS_PGSIZE), EMS_PGSIZE, MEM_FLAG_ROMCS, MEM_FMASK_SHADOW);
|
||||
else {
|
||||
/* This is needed to actually trigger an update. */
|
||||
dev->mem_flags[i + 8] = MEM_FLAG_ROMCS;
|
||||
dev->mem_flags[i + 40] = MEM_FLAG_ROMCS;
|
||||
neat_mem_update_state(dev, 0x000a0000 + (i * EMS_PGSIZE), EMS_PGSIZE, 0x00, MEM_FMASK_SHADOW);
|
||||
}
|
||||
}
|
||||
@@ -1045,7 +1082,10 @@ neat_init(UNUSED(const device_t *info))
|
||||
/* Initialize some of the registers to specific defaults. */
|
||||
for (uint8_t i = REG_RA0; i <= REG_RB12; i++) {
|
||||
dev->indx = i;
|
||||
neat_write(0x0023, defaults[i & REG_MASK], dev);
|
||||
uint8_t def = defaults[dev->sx][i & REG_MASK];
|
||||
if ((i == REG_RA2) && (fpu_type == FPU_387))
|
||||
def |= RA2_387SX;
|
||||
neat_write(0x0023, def, dev);
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -1190,7 +1230,7 @@ neat_init(UNUSED(const device_t *info))
|
||||
}
|
||||
|
||||
const device_t neat_device = {
|
||||
.name = "C&T CS8121 (NEAT)",
|
||||
.name = "C&T CS8221 (NEAT)",
|
||||
.internal_name = "neat",
|
||||
.flags = 0,
|
||||
.local = 0,
|
||||
@@ -1202,3 +1242,17 @@ const device_t neat_device = {
|
||||
.force_redraw = NULL,
|
||||
.config = NULL
|
||||
};
|
||||
|
||||
const device_t neat_sx_device = {
|
||||
.name = "C&T CS8281 (NEATsx)",
|
||||
.internal_name = "neat_sx",
|
||||
.flags = 0,
|
||||
.local = 1,
|
||||
.init = neat_init,
|
||||
.close = neat_close,
|
||||
.reset = NULL,
|
||||
.available = NULL,
|
||||
.speed_changed = NULL,
|
||||
.force_redraw = NULL,
|
||||
.config = NULL
|
||||
};
|
||||
|
||||
@@ -1577,21 +1577,35 @@ write64_phoenix(void *priv, uint8_t val)
|
||||
revision level and proper CPU bits. */
|
||||
case 0xd5: /* Read MultiKey code revision level */
|
||||
kbc_at_log("ATkbc: Phoenix - Read MultiKey code revision level\n");
|
||||
kbc_at_queue_add(dev, 0x04);
|
||||
kbc_at_queue_add(dev, 0x16);
|
||||
if (dev->misc_flags & FLAG_PS2) {
|
||||
kbc_at_queue_add(dev, 0x04);
|
||||
kbc_at_queue_add(dev, 0x16);
|
||||
} else {
|
||||
kbc_at_queue_add(dev, 0x01);
|
||||
kbc_at_queue_add(dev, 0x29);
|
||||
}
|
||||
return 0;
|
||||
|
||||
case 0xd6: /* Read Version Information */
|
||||
kbc_at_log("ATkbc: Phoenix - Read Version Information\n");
|
||||
kbc_at_queue_add(dev, 0x81);
|
||||
kbc_at_queue_add(dev, 0xac);
|
||||
if (dev->misc_flags & FLAG_PS2)
|
||||
kbc_at_queue_add(dev, 0xac);
|
||||
else
|
||||
kbc_at_queue_add(dev, 0xaa);
|
||||
return 0;
|
||||
|
||||
case 0xd7: /* Read MultiKey model numbers */
|
||||
kbc_at_log("ATkbc: Phoenix - Read MultiKey model numbers\n");
|
||||
kbc_at_queue_add(dev, 0x02);
|
||||
kbc_at_queue_add(dev, 0x87);
|
||||
kbc_at_queue_add(dev, 0x02);
|
||||
if (dev->misc_flags & FLAG_PS2) {
|
||||
kbc_at_queue_add(dev, 0x02);
|
||||
kbc_at_queue_add(dev, 0x87);
|
||||
kbc_at_queue_add(dev, 0x02);
|
||||
} else {
|
||||
kbc_at_queue_add(dev, 0x90);
|
||||
kbc_at_queue_add(dev, 0x88);
|
||||
kbc_at_queue_add(dev, 0xd0);
|
||||
}
|
||||
return 0;
|
||||
|
||||
default:
|
||||
@@ -2510,6 +2524,20 @@ const device_t keyboard_at_compaq_device = {
|
||||
.config = NULL
|
||||
};
|
||||
|
||||
const device_t keyboard_at_phoenix_device = {
|
||||
.name = "PC/AT Keyboard (Phoenix)",
|
||||
.internal_name = "keyboard_at_phoenix",
|
||||
.flags = DEVICE_KBC,
|
||||
.local = KBC_TYPE_ISA | KBC_VEN_PHOENIX,
|
||||
.init = kbc_at_init,
|
||||
.close = kbc_at_close,
|
||||
.reset = kbc_at_reset,
|
||||
.available = NULL,
|
||||
.speed_changed = NULL,
|
||||
.force_redraw = NULL,
|
||||
.config = NULL
|
||||
};
|
||||
|
||||
const device_t keyboard_ps2_device = {
|
||||
.name = "PS/2 Keyboard",
|
||||
.internal_name = "keyboard_ps2",
|
||||
|
||||
@@ -20,8 +20,8 @@
|
||||
#ifndef EMU_86BOX_H
|
||||
#define EMU_86BOX_H
|
||||
|
||||
#ifdef __NetBSD__
|
||||
/* Doesn't compile on NetBSD without this include */
|
||||
#if defined(__NetBSD__) || defined(__OpenBSD__)
|
||||
/* Doesn't compile on NetBSD/OpenBSD without this include */
|
||||
#include <stdarg.h>
|
||||
#endif
|
||||
|
||||
|
||||
@@ -48,6 +48,7 @@ extern const device_t contaq_82c597_device;
|
||||
/* C&T */
|
||||
extern const device_t ct_82c100_device;
|
||||
extern const device_t neat_device;
|
||||
extern const device_t neat_sx_device;
|
||||
extern const device_t scat_device;
|
||||
extern const device_t scat_4_device;
|
||||
extern const device_t scat_sx_device;
|
||||
|
||||
@@ -234,6 +234,7 @@ extern const device_t keyboard_xtclone_device;
|
||||
extern const device_t keyboard_at_device;
|
||||
extern const device_t keyboard_at_ami_device;
|
||||
extern const device_t keyboard_at_compaq_device;
|
||||
extern const device_t keyboard_at_phoenix_device;
|
||||
extern const device_t keyboard_at_ncr_device;
|
||||
extern const device_t keyboard_at_olivetti_device;
|
||||
extern const device_t keyboard_at_siemens_device;
|
||||
|
||||
@@ -208,7 +208,9 @@ enum {
|
||||
MACHINE_CHIPSET_ALI_ALADDIN_V,
|
||||
MACHINE_CHIPSET_ALI_ALADDIN_PRO_II,
|
||||
MACHINE_CHIPSET_SCAT,
|
||||
MACHINE_CHIPSET_SCAT_SX,
|
||||
MACHINE_CHIPSET_NEAT,
|
||||
MACHINE_CHIPSET_NEAT_SX,
|
||||
MACHINE_CHIPSET_CT_386,
|
||||
MACHINE_CHIPSET_CT_CS4031,
|
||||
MACHINE_CHIPSET_CONTAQ_82C596,
|
||||
@@ -483,6 +485,7 @@ extern int machine_at_adi386sx_init(const machine_t *);
|
||||
extern int machine_at_cmdsl386sx16_init(const machine_t *);
|
||||
extern int machine_at_cmdsl386sx25_init(const machine_t *);
|
||||
extern int machine_at_dataexpert386sx_init(const machine_t *);
|
||||
extern int machine_at_if386sx_init(const machine_t *);
|
||||
extern int machine_at_spc6033p_init(const machine_t *);
|
||||
extern int machine_at_wd76c10_init(const machine_t *);
|
||||
extern int machine_at_arb1374_init(const machine_t *);
|
||||
|
||||
@@ -456,6 +456,9 @@ extern const device_t millennium_ii_device;
|
||||
extern const device_t productiva_g100_device;
|
||||
#endif /* USE_G100 */
|
||||
|
||||
/* JEGA */
|
||||
extern const device_t if386jega_device;
|
||||
|
||||
/* Oak OTI-0x7 */
|
||||
extern const device_t oti037c_device;
|
||||
extern const device_t oti067_device;
|
||||
|
||||
@@ -641,6 +641,31 @@ machine_at_cmdsl386sx16_init(const machine_t *model)
|
||||
return ret;
|
||||
}
|
||||
|
||||
int
|
||||
machine_at_if386sx_init(const machine_t *model)
|
||||
{
|
||||
int ret;
|
||||
|
||||
ret = bios_load_interleaved("roms/machines/if386sx/OKI_IF386SX_odd.bin",
|
||||
"roms/machines/if386sx/OKI_IF386SX_even.bin",
|
||||
0x000f0000, 65536, 0);
|
||||
|
||||
if (bios_only || !ret)
|
||||
return ret;
|
||||
|
||||
machine_at_common_init(model);
|
||||
device_add(&keyboard_at_phoenix_device);
|
||||
|
||||
device_add(&neat_sx_device);
|
||||
|
||||
if (gfxcard[0] == VID_INTERNAL)
|
||||
device_add(&if386jega_device);
|
||||
if (fdc_current[0] == FDC_INTERNAL)
|
||||
device_add(&fdc_at_device);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static void
|
||||
machine_at_scamp_common_init(const machine_t *model, int is_ps2)
|
||||
{
|
||||
|
||||
@@ -115,7 +115,9 @@ const machine_filter_t machine_chipsets[] = {
|
||||
{ "ALi ALADDiN V", MACHINE_CHIPSET_ALI_ALADDIN_V },
|
||||
{ "ALi ALADDiN-PRO II", MACHINE_CHIPSET_ALI_ALADDIN_PRO_II },
|
||||
{ "C&T 82C235 SCAT", MACHINE_CHIPSET_SCAT },
|
||||
{ "C&T CS8121 NEAT", MACHINE_CHIPSET_NEAT },
|
||||
{ "C&T 82C236 SCATsx", MACHINE_CHIPSET_SCAT_SX },
|
||||
{ "C&T CS8221 NEAT", MACHINE_CHIPSET_NEAT },
|
||||
{ "C&T CS8281 NEATsx", MACHINE_CHIPSET_NEAT_SX },
|
||||
{ "C&T 386", MACHINE_CHIPSET_CT_386 },
|
||||
{ "C&T CS4031", MACHINE_CHIPSET_CT_CS4031 },
|
||||
{ "Contaq 82C596", MACHINE_CHIPSET_CONTAQ_82C596 },
|
||||
@@ -1760,7 +1762,7 @@ const machine_t machines[] = {
|
||||
.available_flag = MACHINE_AVAILABLE,
|
||||
.gpio_acpi_handler = NULL,
|
||||
.cpu = {
|
||||
.package = CPU_PKG_8088,
|
||||
.package = CPU_PKG_8088_VTECH,
|
||||
.block = CPU_BLOCK_NONE,
|
||||
.min_bus = 0,
|
||||
.max_bus = 0,
|
||||
@@ -2623,7 +2625,7 @@ const machine_t machines[] = {
|
||||
.available_flag = MACHINE_AVAILABLE,
|
||||
.gpio_acpi_handler = NULL,
|
||||
.cpu = {
|
||||
.package = CPU_PKG_8086,
|
||||
.package = CPU_PKG_8086_VTECH,
|
||||
.block = CPU_BLOCK_NONE,
|
||||
.min_bus = 0,
|
||||
.max_bus = 0,
|
||||
@@ -2758,9 +2760,9 @@ const machine_t machines[] = {
|
||||
.bus_flags = MACHINE_PS2,
|
||||
.flags = MACHINE_XTA | MACHINE_VIDEO_FIXED,
|
||||
.ram = {
|
||||
.min = 1024,
|
||||
.min = 512,
|
||||
.max = 16384,
|
||||
.step = 1024
|
||||
.step = 512
|
||||
},
|
||||
.nvrmask = 127,
|
||||
.kbc_device = NULL,
|
||||
@@ -4746,6 +4748,44 @@ const machine_t machines[] = {
|
||||
.snd_device = NULL,
|
||||
.net_device = NULL
|
||||
},
|
||||
{ .name = "[NEATsx] OKI if386AX30L",
|
||||
.internal_name = "if386sx",
|
||||
.type = MACHINE_TYPE_386SX,
|
||||
.chipset = MACHINE_CHIPSET_NEAT_SX,
|
||||
.init = machine_at_if386sx_init,
|
||||
.p1_handler = NULL,
|
||||
.gpio_handler = NULL,
|
||||
.available_flag = MACHINE_AVAILABLE,
|
||||
.gpio_acpi_handler = NULL,
|
||||
.cpu = {
|
||||
.package = CPU_PKG_386SX,
|
||||
.block = CPU_BLOCK_NONE,
|
||||
.min_bus = 0,
|
||||
.max_bus = 0,
|
||||
.min_voltage = 0,
|
||||
.max_voltage = 0,
|
||||
.min_multi = 0,
|
||||
.max_multi = 0
|
||||
},
|
||||
.bus_flags = MACHINE_AT,
|
||||
.flags = MACHINE_VIDEO,
|
||||
.ram = {
|
||||
.min = 1024,
|
||||
.max = 4096,
|
||||
.step = 1024
|
||||
},
|
||||
.nvrmask = 127,
|
||||
.kbc_device = NULL,
|
||||
.kbc_p1 = 0xff,
|
||||
.gpio = 0xffffffff,
|
||||
.gpio_acpi = 0xffffffff,
|
||||
.device = NULL,
|
||||
.fdc_device = NULL,
|
||||
.sio_device = NULL,
|
||||
.vid_device = NULL,
|
||||
.snd_device = NULL,
|
||||
.net_device = NULL
|
||||
},
|
||||
/* Has IBM AT KBC firmware. */
|
||||
{
|
||||
.name = "[OPTi 291] DTK PPM-3333P",
|
||||
@@ -4913,10 +4953,10 @@ const machine_t machines[] = {
|
||||
/* Has an unknown AMI KBC firmware, I'm going to assume 'F' until a
|
||||
photo or real hardware BIOS string is found. */
|
||||
{
|
||||
.name = "[SCAT] Kaimei KMX-C-02",
|
||||
.name = "[SCATsx] Kaimei KMX-C-02",
|
||||
.internal_name = "kmxc02",
|
||||
.type = MACHINE_TYPE_386SX,
|
||||
.chipset = MACHINE_CHIPSET_SCAT,
|
||||
.chipset = MACHINE_CHIPSET_SCAT_SX,
|
||||
.init = machine_at_kmxc02_init,
|
||||
.p1_handler = NULL,
|
||||
.gpio_handler = NULL,
|
||||
|
||||
@@ -971,7 +971,8 @@ tulip_write(uint32_t addr, uint32_t data, void *opaque)
|
||||
|
||||
case CSR(7):
|
||||
s->csr[7] = data;
|
||||
tulip_update_int(s);
|
||||
if (s->device_info->local)
|
||||
tulip_update_int(s);
|
||||
break;
|
||||
|
||||
case CSR(8):
|
||||
@@ -1006,7 +1007,7 @@ tulip_write(uint32_t addr, uint32_t data, void *opaque)
|
||||
|
||||
case CSR(13):
|
||||
s->csr[13] = data;
|
||||
if (s->device_info->local == 3 && (data & 0x4)) {
|
||||
if ((s->device_info->local == 3) && (data & 0x4)) {
|
||||
s->csr[13] = 0x8f01;
|
||||
s->csr[14] = 0xfffd;
|
||||
s->csr[15] = 0;
|
||||
@@ -1407,7 +1408,7 @@ nic_init(const device_t *info)
|
||||
if (!s)
|
||||
return NULL;
|
||||
|
||||
if (info->local && info->local != 3) {
|
||||
if (info->local && (info->local != 3)) {
|
||||
s->bios_addr = 0xD0000;
|
||||
s->has_bios = device_get_config_int("bios");
|
||||
} else {
|
||||
@@ -1434,7 +1435,7 @@ nic_init(const device_t *info)
|
||||
s->eeprom_data[2] = 0x14;
|
||||
s->eeprom_data[3] = 0x21;
|
||||
} else {
|
||||
/*Subsystem Vendor ID*/
|
||||
/*Subsystem Vendor ID*/
|
||||
s->eeprom_data[0] = info->local ? 0x25 : 0x11;
|
||||
s->eeprom_data[1] = 0x10;
|
||||
|
||||
@@ -1549,23 +1550,40 @@ nic_init(const device_t *info)
|
||||
/*Block Count*/
|
||||
s->eeprom_data[32] = 0x01;
|
||||
|
||||
/*Extended Format - Block Type 2 for 21142/21143*/
|
||||
/*Extended Format - Block Type 3 for 21142/21143*/
|
||||
/*Length (0:6) and Format Indicator (7)*/
|
||||
s->eeprom_data[33] = 0x86;
|
||||
s->eeprom_data[33] = 0x8d;
|
||||
|
||||
/*Block Type*/
|
||||
s->eeprom_data[34] = 0x02;
|
||||
s->eeprom_data[34] = 0x03;
|
||||
|
||||
/*Media Code (0:5), EXT (6), Reserved (7)*/
|
||||
s->eeprom_data[35] = 0x01;
|
||||
/*PHY Number*/
|
||||
s->eeprom_data[35] = 0x00;
|
||||
|
||||
/*General Purpose Control*/
|
||||
s->eeprom_data[36] = 0xff;
|
||||
s->eeprom_data[37] = 0xff;
|
||||
/*GPR Length*/
|
||||
s->eeprom_data[36] = 0x00;
|
||||
|
||||
/*General Purpose Data*/
|
||||
/*Reset Length*/
|
||||
s->eeprom_data[37] = 0x00;
|
||||
|
||||
/*Media Capabilities*/
|
||||
s->eeprom_data[38] = 0x00;
|
||||
s->eeprom_data[39] = 0x00;
|
||||
s->eeprom_data[39] = 0x78;
|
||||
|
||||
/*Nway Advertisement*/
|
||||
s->eeprom_data[40] = 0xe0;
|
||||
s->eeprom_data[41] = 0x01;
|
||||
|
||||
/*FDX Bit Map*/
|
||||
s->eeprom_data[42] = 0x00;
|
||||
s->eeprom_data[43] = 0x50;
|
||||
|
||||
/*TTM Bit Map*/
|
||||
s->eeprom_data[44] = 0x00;
|
||||
s->eeprom_data[45] = 0x18;
|
||||
|
||||
/*MII PHY Insertion/removal Indication*/
|
||||
s->eeprom_data[46] = 0x00;
|
||||
}
|
||||
|
||||
s->eeprom_data[126] = tulip_srom_crc(s->eeprom_data) & 0xff;
|
||||
@@ -1608,7 +1626,7 @@ nic_init(const device_t *info)
|
||||
checksum *= 2;
|
||||
if (checksum > 65535)
|
||||
checksum = checksum % 65535;
|
||||
|
||||
|
||||
/* 3rd pair. */
|
||||
checksum += (s->eeprom_data[4] * 256) | s->eeprom_data[5];
|
||||
if (checksum > 65535)
|
||||
@@ -1616,7 +1634,7 @@ nic_init(const device_t *info)
|
||||
|
||||
if (checksum >= 65535)
|
||||
checksum = 0;
|
||||
|
||||
|
||||
s->eeprom_data[6] = (checksum >> 8) & 0xFF;
|
||||
s->eeprom_data[7] = checksum & 0xFF;
|
||||
}
|
||||
|
||||
@@ -970,10 +970,17 @@ VulkanRenderer2::startNextFrame()
|
||||
m_devFuncs->vkCmdBindVertexBuffers(cb, 0, 1, &m_buf, &vbOffset);
|
||||
|
||||
VkViewport viewport;
|
||||
viewport.x = destination.x() * m_window->devicePixelRatio();
|
||||
viewport.y = destination.y() * m_window->devicePixelRatio();
|
||||
viewport.width = destination.width() * m_window->devicePixelRatio();
|
||||
viewport.height = destination.height() * m_window->devicePixelRatio();
|
||||
if (dpi_scale) {
|
||||
viewport.x = destination.x() * m_window->devicePixelRatio();
|
||||
viewport.y = destination.y() * m_window->devicePixelRatio();
|
||||
viewport.width = destination.width() * m_window->devicePixelRatio();
|
||||
viewport.height = destination.height() * m_window->devicePixelRatio();
|
||||
} else {
|
||||
viewport.x = destination.x();
|
||||
viewport.y = destination.y();
|
||||
viewport.width = destination.width();
|
||||
viewport.height = destination.height();
|
||||
}
|
||||
viewport.minDepth = 0;
|
||||
viewport.maxDepth = 1;
|
||||
m_devFuncs->vkCmdSetViewport(cb, 0, 1, &viewport);
|
||||
|
||||
@@ -53,7 +53,25 @@ add_library(snd OBJECT
|
||||
snd_opl_esfm.c
|
||||
)
|
||||
|
||||
if(OPENAL)
|
||||
# TODO: Should platform-specific audio driver be here?
|
||||
if(AUDIO4)
|
||||
target_sources(snd PRIVATE audio4.c)
|
||||
elseif(SNDIO)
|
||||
target_sources(snd PRIVATE sndio.c)
|
||||
find_package(PkgConfig REQUIRED)
|
||||
|
||||
pkg_check_modules(SNDIO IMPORTED_TARGET sndio)
|
||||
if(SNDIO_FOUND)
|
||||
target_link_libraries(86Box PkgConfig::SNDIO)
|
||||
else()
|
||||
find_path(SNDIO_INCLUDE_DIR NAMES "sndio.h")
|
||||
find_library(SNDIO_LIBRARY sndio)
|
||||
|
||||
target_link_libraries(86Box ${SNDIO_LIBRARY})
|
||||
endif()
|
||||
|
||||
include_directories(${SNDIO_INCLUDE_DIRS})
|
||||
elseif(OPENAL)
|
||||
if(VCPKG_TOOLCHAIN)
|
||||
find_package(OpenAL CONFIG REQUIRED)
|
||||
elseif(MINGW)
|
||||
|
||||
161
src/sound/audio4.c
Normal file
161
src/sound/audio4.c
Normal file
@@ -0,0 +1,161 @@
|
||||
/*
|
||||
* 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.
|
||||
*
|
||||
* Interface to audio(4) for NetBSD/OpenBSD.
|
||||
*
|
||||
*
|
||||
* Authors: Nishi
|
||||
*
|
||||
* Copyright 2025 Nishi.
|
||||
*/
|
||||
#include <stdint.h>
|
||||
#include <fcntl.h>
|
||||
#include <unistd.h>
|
||||
#include <sys/ioctl.h>
|
||||
#include <string.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <math.h>
|
||||
|
||||
#include <sys/audioio.h>
|
||||
#include <sys/param.h>
|
||||
|
||||
#include <86box/86box.h>
|
||||
#include <86box/sound.h>
|
||||
#include <86box/plat_unused.h>
|
||||
|
||||
#if defined(OpenBSD) && OpenBSD >= 201709
|
||||
#define USE_NEW_API
|
||||
#endif
|
||||
|
||||
#define I_NORMAL 0
|
||||
#define I_MUSIC 1
|
||||
#define I_WT 2
|
||||
#define I_CD 3
|
||||
#define I_MIDI 4
|
||||
|
||||
static int audio[5] = {-1, -1, -1, -1, -1};
|
||||
#ifdef USE_NEW_API
|
||||
static struct audio_swpar info[5];
|
||||
#else
|
||||
static audio_info_t info[5];
|
||||
#endif
|
||||
static int freqs[5] = {SOUND_FREQ, MUSIC_FREQ, WT_FREQ, CD_FREQ, 0};
|
||||
|
||||
void closeal(void){
|
||||
int i;
|
||||
for(i = 0; i < sizeof(audio) / sizeof(audio[0]); i++){
|
||||
if(audio[i] != -1){
|
||||
close(audio[i]);
|
||||
}
|
||||
audio[i] = -1;
|
||||
}
|
||||
}
|
||||
|
||||
void inital(void){
|
||||
int i;
|
||||
for(i = 0; i < sizeof(audio) / sizeof(audio[0]); i++){
|
||||
audio[i] = open("/dev/audio", O_WRONLY);
|
||||
if(audio[i] == -1) audio[i] = open("/dev/audio0", O_WRONLY);
|
||||
if(audio[i] != -1){
|
||||
#ifdef USE_NEW_API
|
||||
AUDIO_INITPAR(&info[i]);
|
||||
ioctl(audio[i], AUDIO_GETPAR, &info[i]);
|
||||
info[i].sig = 1;
|
||||
info[i].bits = 16;
|
||||
info[i].pchan = 2;
|
||||
info[i].bps = 2;
|
||||
ioctl(audio[i], AUDIO_SETPAR, &info[i]);
|
||||
#else
|
||||
AUDIO_INITINFO(&info[i]);
|
||||
#if defined(__NetBSD__) && (__NetBSD_Version__ >= 900000000)
|
||||
ioctl(audio[i], AUDIO_GETFORMAT, &info[i]);
|
||||
#else
|
||||
ioctl(audio[i], AUDIO_GETINFO, &info[i]);
|
||||
#endif
|
||||
info[i].play.channels = 2;
|
||||
info[i].play.precision = 16;
|
||||
info[i].play.encoding = AUDIO_ENCODING_SLINEAR;
|
||||
info[i].hiwat = 5;
|
||||
info[i].lowat = 3;
|
||||
ioctl(audio[i], AUDIO_SETINFO, &info[i]);
|
||||
#endif
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void givealbuffer_common(const void *buf, const uint8_t src, const int size){
|
||||
const int freq = freqs[src];
|
||||
int16_t* output;
|
||||
int output_size;
|
||||
int16_t* conv;
|
||||
int conv_size;
|
||||
int i;
|
||||
double gain;
|
||||
int target_rate;
|
||||
if(audio[src] == -1) return;
|
||||
|
||||
gain = sound_muted ? 0.0 : pow(10.0, (double) sound_gain / 20.0);
|
||||
|
||||
if(sound_is_float){
|
||||
float* input = (float*)buf;
|
||||
conv_size = sizeof(int16_t) * size;
|
||||
conv = malloc(conv_size);
|
||||
for(i = 0; i < conv_size / sizeof(int16_t); i++){
|
||||
conv[i] = 32767 * input[i];
|
||||
}
|
||||
}else{
|
||||
conv_size = size * sizeof(int16_t);
|
||||
conv = malloc(conv_size);
|
||||
memcpy(conv, buf, conv_size);
|
||||
}
|
||||
|
||||
#ifdef USE_NEW_API
|
||||
target_rate = info[src].rate;
|
||||
#else
|
||||
target_rate = info[src].play.sample_rate;
|
||||
#endif
|
||||
|
||||
output_size = (double)conv_size * target_rate / freq;
|
||||
output_size -= output_size % 4;
|
||||
output = malloc(output_size);
|
||||
|
||||
for(i = 0; i < output_size / sizeof(int16_t) / 2; i++){
|
||||
int ind = i * freq / target_rate * 2;
|
||||
output[i * 2 + 0] = conv[ind + 0] * gain;
|
||||
output[i * 2 + 1] = conv[ind + 1] * gain;
|
||||
}
|
||||
|
||||
write(audio[src], output, output_size);
|
||||
|
||||
free(conv);
|
||||
free(output);
|
||||
}
|
||||
|
||||
void givealbuffer(const void *buf){
|
||||
givealbuffer_common(buf, I_NORMAL, SOUNDBUFLEN << 1);
|
||||
}
|
||||
|
||||
void givealbuffer_music(const void *buf){
|
||||
givealbuffer_common(buf, I_MUSIC, MUSICBUFLEN << 1);
|
||||
}
|
||||
|
||||
void givealbuffer_wt(const void *buf){
|
||||
givealbuffer_common(buf, I_WT, WTBUFLEN << 1);
|
||||
}
|
||||
|
||||
void givealbuffer_cd(const void *buf){
|
||||
givealbuffer_common(buf, I_CD, CD_BUFLEN << 1);
|
||||
}
|
||||
void givealbuffer_midi(const void *buf, const uint32_t size){
|
||||
givealbuffer_common(buf, I_MIDI, (int) size);
|
||||
}
|
||||
|
||||
void al_set_midi(const int freq, UNUSED(const int buf_size)){
|
||||
freqs[I_MIDI] = freq;
|
||||
}
|
||||
140
src/sound/sndio.c
Normal file
140
src/sound/sndio.c
Normal file
@@ -0,0 +1,140 @@
|
||||
/*
|
||||
* 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.
|
||||
*
|
||||
* Interface to sndio
|
||||
*
|
||||
*
|
||||
* Authors: Nishi
|
||||
*
|
||||
* Copyright 2025 Nishi.
|
||||
*/
|
||||
#include <stdint.h>
|
||||
#include <unistd.h>
|
||||
#include <string.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <math.h>
|
||||
|
||||
#include <sndio.h>
|
||||
|
||||
#include <86box/86box.h>
|
||||
#include <86box/sound.h>
|
||||
#include <86box/plat_unused.h>
|
||||
|
||||
#define I_NORMAL 0
|
||||
#define I_MUSIC 1
|
||||
#define I_WT 2
|
||||
#define I_CD 3
|
||||
#define I_MIDI 4
|
||||
|
||||
static struct sio_hdl* audio[5] = {NULL, NULL, NULL, NULL, NULL};
|
||||
static struct sio_par info[5];
|
||||
static int freqs[5] = {SOUND_FREQ, MUSIC_FREQ, WT_FREQ, CD_FREQ, 0};
|
||||
|
||||
void closeal(void){
|
||||
int i;
|
||||
for(i = 0; i < sizeof(audio) / sizeof(audio[0]); i++){
|
||||
if(audio[i] != NULL){
|
||||
sio_close(audio[i]);
|
||||
}
|
||||
audio[i] = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
void inital(void){
|
||||
int i;
|
||||
for(i = 0; i < sizeof(audio) / sizeof(audio[0]); i++){
|
||||
audio[i] = sio_open(SIO_DEVANY, SIO_PLAY, 0);
|
||||
if(audio[i] != NULL){
|
||||
int rate;
|
||||
int max_frames;
|
||||
sio_getpar(audio[i], &info[i]);
|
||||
rate = info[i].rate;
|
||||
max_frames = info[i].bufsz;
|
||||
sio_initpar(&info[i]);
|
||||
info[i].sig = 1;
|
||||
info[i].bits = 16;
|
||||
info[i].pchan = 2;
|
||||
info[i].rate = rate;
|
||||
info[i].appbufsz = max_frames;
|
||||
sio_setpar(audio[i], &info[i]);
|
||||
sio_getpar(audio[i], &info[i]);
|
||||
if(!sio_start(audio[i])){
|
||||
sio_close(audio[i]);
|
||||
audio[i] = NULL;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void givealbuffer_common(const void *buf, const uint8_t src, const int size){
|
||||
const int freq = freqs[src];
|
||||
int16_t* output;
|
||||
int output_size;
|
||||
int16_t* conv;
|
||||
int conv_size;
|
||||
int i;
|
||||
double gain;
|
||||
int target_rate;
|
||||
if(audio[src] == NULL) return;
|
||||
|
||||
gain = sound_muted ? 0.0 : pow(10.0, (double) sound_gain / 20.0);
|
||||
|
||||
if(sound_is_float){
|
||||
float* input = (float*)buf;
|
||||
conv_size = sizeof(int16_t) * size;
|
||||
conv = malloc(conv_size);
|
||||
for(i = 0; i < conv_size / sizeof(int16_t); i++){
|
||||
conv[i] = 32767 * input[i];
|
||||
}
|
||||
}else{
|
||||
conv_size = size * sizeof(int16_t);
|
||||
conv = malloc(conv_size);
|
||||
memcpy(conv, buf, conv_size);
|
||||
}
|
||||
|
||||
target_rate = info[src].rate;
|
||||
|
||||
output_size = (double)conv_size * target_rate / freq;
|
||||
output_size -= output_size % 4;
|
||||
output = malloc(output_size);
|
||||
|
||||
for(i = 0; i < output_size / sizeof(int16_t) / 2; i++){
|
||||
int ind = i * freq / target_rate * 2;
|
||||
output[i * 2 + 0] = conv[ind + 0] * gain;
|
||||
output[i * 2 + 1] = conv[ind + 1] * gain;
|
||||
}
|
||||
|
||||
sio_write(audio[src], output, output_size);
|
||||
|
||||
free(conv);
|
||||
free(output);
|
||||
}
|
||||
|
||||
void givealbuffer(const void *buf){
|
||||
givealbuffer_common(buf, I_NORMAL, SOUNDBUFLEN << 1);
|
||||
}
|
||||
|
||||
void givealbuffer_music(const void *buf){
|
||||
givealbuffer_common(buf, I_MUSIC, MUSICBUFLEN << 1);
|
||||
}
|
||||
|
||||
void givealbuffer_wt(const void *buf){
|
||||
givealbuffer_common(buf, I_WT, WTBUFLEN << 1);
|
||||
}
|
||||
|
||||
void givealbuffer_cd(const void *buf){
|
||||
givealbuffer_common(buf, I_CD, CD_BUFLEN << 1);
|
||||
}
|
||||
void givealbuffer_midi(const void *buf, const uint32_t size){
|
||||
givealbuffer_common(buf, I_MIDI, (int) size);
|
||||
}
|
||||
|
||||
void al_set_midi(const int freq, UNUSED(const int buf_size)){
|
||||
freqs[I_MIDI] = freq;
|
||||
}
|
||||
@@ -47,9 +47,9 @@ void ega_doblit(int wx, int wy, ega_t *ega);
|
||||
|
||||
static video_timings_t timing_ega = { .type = VIDEO_ISA, .write_b = 8, .write_w = 16, .write_l = 32, .read_b = 8, .read_w = 16, .read_l = 32 };
|
||||
static uint8_t ega_rotate[8][256];
|
||||
static int active = 0;
|
||||
static uint32_t pallook16[256];
|
||||
static uint32_t pallook64[256];
|
||||
static int active = 0;
|
||||
uint32_t pallook16[256];
|
||||
uint32_t pallook64[256];
|
||||
static int ega_type = EGA_TYPE_IBM;
|
||||
static int old_overscan_color = 0;
|
||||
|
||||
|
||||
@@ -61,6 +61,7 @@
|
||||
|
||||
#define JEGA_PATH_BIOS "roms/video/jega/JEGABIOS.BIN"
|
||||
#define JEGA_PATH_FONTDBCS "roms/video/jega/JPNZN16X.FNT"
|
||||
#define IF386_PATH_VBIOS "roms/machines/if386sx/OKI_IF386SX_VBIOS.bin"
|
||||
#define SBCS19_FILESIZE (256 * 19 * 2) /* 8 x 19 x 256 chr x 2 pages */
|
||||
#define DBCS16_CHARS 0x2c10
|
||||
#define DBCS16_FILESIZE (DBCS16_CHARS * 16 * 2)
|
||||
@@ -137,7 +138,8 @@ typedef struct {
|
||||
uint16_t end;
|
||||
} fontx_tbl;
|
||||
|
||||
static uint32_t pallook64[256];
|
||||
extern uint32_t pallook16[256];
|
||||
extern uint32_t pallook64[256];
|
||||
static bool is_SJIS_1(uint8_t chr) { return (chr >= 0x81 && chr <= 0x9f) || (chr >= 0xe0 && chr <= 0xfc); }
|
||||
static bool is_SJIS_2(uint8_t chr) { return (chr >= 0x40 && chr <= 0x7e) || (chr >= 0x80 && chr <= 0xfc); }
|
||||
|
||||
@@ -615,8 +617,27 @@ LoadFontxFile(const char *fn, void *priv)
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void
|
||||
jega_commoninit(void *priv)
|
||||
{
|
||||
jega_t *jega = (jega_t *) priv;
|
||||
for (int c = 0; c < 256; c++) {
|
||||
pallook64[c] = makecol32(((c >> 2) & 1) * 0xaa, ((c >> 1) & 1) * 0xaa, (c & 1) * 0xaa);
|
||||
pallook64[c] += makecol32(((c >> 5) & 1) * 0x55, ((c >> 4) & 1) * 0x55, ((c >> 3) & 1) * 0x55);
|
||||
}
|
||||
video_inform(VIDEO_FLAG_TYPE_SPECIAL, &timing_ega);
|
||||
jega->pallook = pallook64;
|
||||
ega_init(&jega->ega, 9, 0);
|
||||
ega_set_type(&jega->ega, EGA_SUPEREGA);
|
||||
jega->ega.priv_parent = jega;
|
||||
mem_mapping_add(&jega->ega.mapping, 0xa0000, 0x20000, ega_read, NULL, NULL, ega_write, NULL, NULL, NULL, MEM_MAPPING_EXTERNAL, &jega->ega);
|
||||
/* I/O 3DD and 3DE are used by Oki if386 */
|
||||
io_sethandler(0x03b0, 0x002c, jega_in, NULL, NULL, jega_out, NULL, NULL, jega);
|
||||
jega->regs[RMOD1] = 0x48;
|
||||
}
|
||||
|
||||
static void *
|
||||
jega_init(const device_t *info)
|
||||
jega_standalone_init(const device_t *info)
|
||||
{
|
||||
jega_t *jega = calloc(1, sizeof(jega_t));
|
||||
|
||||
@@ -624,21 +645,7 @@ jega_init(const device_t *info)
|
||||
memset(&jega->jfont_dbcs_16, 0, DBCS16_FILESIZE);
|
||||
LoadFontxFile(JEGA_PATH_FONTDBCS, jega);
|
||||
|
||||
for (int c = 0; c < 256; c++) {
|
||||
pallook64[c] = makecol32(((c >> 2) & 1) * 0xaa, ((c >> 1) & 1) * 0xaa, (c & 1) * 0xaa);
|
||||
pallook64[c] += makecol32(((c >> 5) & 1) * 0x55, ((c >> 4) & 1) * 0x55, ((c >> 3) & 1) * 0x55);
|
||||
}
|
||||
|
||||
video_inform(VIDEO_FLAG_TYPE_SPECIAL, &timing_ega);
|
||||
jega->pallook = pallook64;
|
||||
ega_init(&jega->ega, 9, 0);
|
||||
ega_set_type(&jega->ega, EGA_SUPEREGA);
|
||||
jega->ega.priv_parent = jega;
|
||||
mem_mapping_add(&jega->ega.mapping, 0xa0000, 0x20000, ega_read, NULL, NULL, ega_write, NULL, NULL, NULL, MEM_MAPPING_EXTERNAL, &jega->ega);
|
||||
|
||||
io_sethandler(0x03b0, 0x0030, jega_in, NULL, NULL, jega_out, NULL, NULL, jega);
|
||||
|
||||
jega->regs[RMOD1] = 0x48;
|
||||
jega_commoninit(jega);
|
||||
|
||||
return jega;
|
||||
}
|
||||
@@ -665,10 +672,10 @@ jega_close(void *priv)
|
||||
fprintf(f, "Regs %02X: %4X\n", i, jega->regs[i]);
|
||||
for (int i = 0; i < 32; i++)
|
||||
fprintf(f, "Attr %02X: %4X\n", i, jega->attrregs[i]);
|
||||
for (int i = 0; i < 16; i++)
|
||||
fprintf(f, "JEGAPal %02X: %4X\n", i, jega->egapal[i]);
|
||||
for (int i = 0; i < 16; i++)
|
||||
fprintf(f, "EGAPal %02X: %4X\n", i, jega->ega.egapal[i]);
|
||||
for (int i = 0; i < 16; i++)
|
||||
fprintf(f, "JEGAPal %02X: %4X\n", i, jega->egapal[i]);
|
||||
for (int i = 0; i < 16; i++)
|
||||
fprintf(f, "EGAPal %02X: %4X\n", i, jega->ega.egapal[i]);
|
||||
for (int i = 0; i < 64; i++)
|
||||
fprintf(f, "RealPal %02X: %4X\n", i, jega->pallook[i]);
|
||||
fclose(f);
|
||||
@@ -683,7 +690,7 @@ jega_close(void *priv)
|
||||
fwrite(&ram[0x0], 0x500, 1, f);
|
||||
fclose(f);
|
||||
}
|
||||
// jega_log("jeclosed %04X:%04X DS %04X\n", cs >> 4, cpu_state.pc, DS);
|
||||
pclog("jeclosed %04X:%04X DS %04X\n", cs >> 4, cpu_state.pc, DS);
|
||||
#endif
|
||||
if (jega->ega.eeprom)
|
||||
free(jega->ega.eeprom);
|
||||
@@ -706,7 +713,7 @@ jega_speed_changed(void *priv)
|
||||
}
|
||||
|
||||
static int
|
||||
jega_available(void)
|
||||
jega_standalone_available(void)
|
||||
{
|
||||
return (rom_present(JEGA_PATH_BIOS) && rom_present(JEGA_PATH_FONTDBCS));
|
||||
}
|
||||
@@ -716,10 +723,124 @@ const device_t jega_device = {
|
||||
.internal_name = "jega",
|
||||
.flags = DEVICE_ISA,
|
||||
.local = 0,
|
||||
.init = jega_init,
|
||||
.init = jega_standalone_init,
|
||||
.close = jega_close,
|
||||
.reset = NULL,
|
||||
.available = jega_available,
|
||||
.available = jega_standalone_available,
|
||||
.speed_changed = jega_speed_changed,
|
||||
.force_redraw = NULL,
|
||||
.config = NULL
|
||||
};
|
||||
|
||||
static uint8_t p65idx = 0;
|
||||
// static uint8_t p3de_idx = 0;
|
||||
static uint8_t p65[6];
|
||||
// static uint8_t p3de[0x30];
|
||||
|
||||
|
||||
static uint8_t
|
||||
if386_p6x_read(uint16_t port, void *priv)
|
||||
{
|
||||
uint8_t ret = INVALIDACCESS8;
|
||||
if (port == 0x63) {
|
||||
ret = p65idx;
|
||||
} else if (port == 0x65) {
|
||||
ret = p65[p65idx];
|
||||
}
|
||||
// pclog("p%x_r: [%04x:%04x] [%02x]%02x\n", port, cs >> 4, cpu_state.pc , p65idx, ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
/*
|
||||
OKi if386AX/SX Power management and Miscellaneous
|
||||
I/O 63h: Index 0-5, I/O 65h: Data
|
||||
Index 2:
|
||||
Bit 3: Caps Lock enabled
|
||||
Bit 2: Num Lock enabled
|
||||
Bit 1: Scrl Lock enabled
|
||||
Bit 0: Kana Lock enabled
|
||||
Index 3
|
||||
Bit 2: External monitor output enabled
|
||||
Bit 1: Floppy drive 1 active
|
||||
Bit 0: Floppy drive 0 active
|
||||
Index 5
|
||||
Bit 8: ? (1=Disabled, 0=Enabled)
|
||||
Bit 7: Screen Off? (enabled by Ctrl + Alt + [1] and disabled by any key)
|
||||
Bit 4: Shutdown? (caused by POST rebooting and POWER OFF command in DOS 3.21)
|
||||
Bit 3: ?
|
||||
*/
|
||||
static void
|
||||
if386_p6x_write(uint16_t port, uint8_t val, void *priv)
|
||||
{
|
||||
jega_t *jega = (jega_t *) priv;
|
||||
// pclog("p%x_w: [%04x:%04x] val=%02x\n", port, cs >> 4, cpu_state.pc, val);
|
||||
if (port == 0x63 && val < 6)
|
||||
p65idx = val;
|
||||
if (port == 0x65) {
|
||||
// pclog("p65_w: [%04x:%04x] idx=%02x, val=%02x\n", cs >> 4, cpu_state.pc, p65idx, val);
|
||||
p65[p65idx] = val;
|
||||
if (p65idx == 0x03) {
|
||||
if (val & 0x04) { /* Color monitor */
|
||||
for (int c = 0; c < 256; c++) {
|
||||
pallook64[c] = makecol32(((c >> 2) & 1) * 0xaa, ((c >> 1) & 1) * 0xaa, (c & 1) * 0xaa);
|
||||
pallook64[c] += makecol32(((c >> 5) & 1) * 0x55, ((c >> 4) & 1) * 0x55, ((c >> 3) & 1) * 0x55);
|
||||
pallook16[c] = makecol32(((c >> 2) & 1) * 0xaa, ((c >> 1) & 1) * 0xaa, (c & 1) * 0xaa);
|
||||
pallook16[c] += makecol32(((c >> 4) & 1) * 0x55, ((c >> 4) & 1) * 0x55, ((c >> 4) & 1) * 0x55);
|
||||
if ((c & 0x17) == 6)
|
||||
pallook16[c] = makecol32(0xaa, 0x55, 0);
|
||||
}
|
||||
} else { /* Monochrome LCD */
|
||||
for (int c = 0; c < 256; c++) {
|
||||
int cval = 0;
|
||||
if (c & 0x0f)
|
||||
cval = ((c & 0x0e) * 0x10) + 0x1f;
|
||||
pallook64[c] = makecol32(cval, cval, cval);
|
||||
pallook16[c] = makecol32(cval, cval, cval);
|
||||
}
|
||||
}
|
||||
jega_recalctimings(jega);
|
||||
} else if (p65idx == 0x05) {
|
||||
if (val & 0x10) { /* Power off (instead this call hardware reset here) */
|
||||
resetx86();
|
||||
}
|
||||
}
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
static void *
|
||||
if386jega_init(const device_t *info)
|
||||
{
|
||||
jega_t *jega = calloc(1, sizeof(jega_t));
|
||||
|
||||
rom_init(&jega->bios_rom, IF386_PATH_VBIOS, 0xc0000, 0x8000, 0x7fff, 0, 0);
|
||||
memset(&jega->jfont_dbcs_16, 0, DBCS16_FILESIZE);
|
||||
LoadFontxFile(JEGA_PATH_FONTDBCS, jega);
|
||||
|
||||
jega_commoninit(jega);
|
||||
|
||||
io_sethandler(0x0063, 1, if386_p6x_read, NULL, NULL, if386_p6x_write, NULL, NULL, jega);
|
||||
io_sethandler(0x0065, 1, if386_p6x_read, NULL, NULL, if386_p6x_write, NULL, NULL, jega);
|
||||
// io_sethandler(0x03dd, 2, if386_p6x_read, NULL, NULL, if386_p6x_write, NULL, NULL, jega);
|
||||
|
||||
return jega;
|
||||
}
|
||||
|
||||
static int
|
||||
if386jega_available(void)
|
||||
{
|
||||
return (rom_present(IF386_PATH_VBIOS) && rom_present(JEGA_PATH_FONTDBCS));
|
||||
}
|
||||
|
||||
const device_t if386jega_device = {
|
||||
.name = "JEGA (if386AX)",
|
||||
.internal_name = "if386jega",
|
||||
.flags = DEVICE_ISA,
|
||||
.local = 0,
|
||||
.init = if386jega_init,
|
||||
.close = jega_close,
|
||||
.reset = NULL,
|
||||
.available = if386jega_available,
|
||||
.speed_changed = jega_speed_changed,
|
||||
.force_redraw = NULL,
|
||||
.config = NULL
|
||||
|
||||
Reference in New Issue
Block a user