Merge branch '86Box:master' into machine_23

This commit is contained in:
BurnedPinguin
2023-07-12 00:42:30 +02:00
committed by GitHub
14 changed files with 547 additions and 149 deletions

View File

@@ -24,8 +24,8 @@
# - For Windows (MSYS MinGW) builds:
# - Packaging requires 7-Zip on Program Files
# - Packaging the Ghostscript DLL requires 32-bit and/or 64-bit Ghostscript on Program Files
# - Packaging the FluidSynth DLL requires it to be at /home/86Box/dll32/libfluidsynth.dll
# and/or /home/86Box/dll64/libfluidsynth64.dll (for 32-bit and 64-bit builds respectively)
# - Packaging the XAudio2 DLL for FAudio requires it to be at /home/86Box/dll32/xaudio2*.dll
# and/or /home/86Box/dll64/xaudio2*.dll (for 32-bit and 64-bit builds respectively)
# - For Linux builds:
# - Only Debian and derivatives are supported
# - dpkg and apt-get are called through sudo to manage dependencies; make sure those
@@ -595,7 +595,7 @@ else
# ...and the ones we do want listed. Non-dev packages fill missing spots on the list.
libpkgs=""
longest_libpkg=0
for pkg in libc6-dev libstdc++6 libopenal-dev libfreetype6-dev libx11-dev libsdl2-dev libpng-dev librtmidi-dev qtdeclarative5-dev libwayland-dev libevdev-dev libxkbcommon-x11-dev libglib2.0-dev libslirp-dev libfaudio-dev libaudio-dev libjack-jackd2-dev libpipewire-0.3-dev libsamplerate0-dev libsndio-dev libvdeplug-dev
for pkg in libc6-dev libstdc++6 libopenal-dev libfreetype6-dev libx11-dev libsdl2-dev libpng-dev librtmidi-dev qtdeclarative5-dev libwayland-dev libevdev-dev libxkbcommon-x11-dev libglib2.0-dev libslirp-dev libfaudio-dev libaudio-dev libjack-jackd2-dev libpipewire-0.3-dev libsamplerate0-dev libsndio-dev libvdeplug-dev libfluidsynth-dev
do
libpkgs="$libpkgs $pkg:$arch_deb"
length=$(echo -n $pkg | sed 's/-dev$//' | sed "s/qtdeclarative/qt/" | wc -c)
@@ -810,8 +810,8 @@ then
"$sevenzip" e -y -o"archive_tmp" "$discord_zip" "lib/$arch_discord/discord_game_sdk.dll"
[ ! -e "archive_tmp/discord_game_sdk.dll" ] && echo [!] No Discord Game SDK for architecture [$arch_discord]
# Archive other DLLs from local directory.
cp -p "/home/$project/dll$arch/"* archive_tmp/
# Archive XAudio2 DLL if required.
grep -q "OPENAL:BOOL=ON" build/CMakeCache.txt || cp -p "/home/$project/dll$arch/xaudio2"* archive_tmp/
# Archive executable, while also stripping it if requested.
if [ $strip -ne 0 ]
@@ -1003,6 +1003,11 @@ else
ln -s "$relroot/usr/lib/libvulkan.so.1" "archive_tmp/usr/lib/libvulkan.so"
ln -s "$relroot/usr/lib/$libdir/libvulkan.so.1" "archive_tmp/usr/lib/$libdir/libvulkan.so"
# The FluidSynth packaged by Debian bullseye is ABI incompatible with
# the newer version we compile, despite sharing a major version. Since we
# don't run into the one breaking ABI change they made, just symlink it.
ln -s "$(readlink "archive_tmp/usr/lib/libfluidsynth.so.3")" "archive_tmp/usr/lib/libfluidsynth.so.2"
# Archive Discord Game SDK library.
7z e -y -o"archive_tmp/usr/lib" "$discord_zip" "lib/$arch_discord/discord_game_sdk.so"
[ ! -e "archive_tmp/usr/lib/discord_game_sdk.so" ] && echo [!] No Discord Game SDK for architecture [$arch_discord]

View File

@@ -41,6 +41,9 @@
#include <86box/machine.h>
#include <86box/chipset.h>
#include <86box/spd.h>
#ifndef USE_DRB_HACK
#include <86box/row.h>
#endif
#define MEM_STATE_SHADOW_R 0x01
#define MEM_STATE_SHADOW_W 0x02
@@ -158,6 +161,26 @@ i420ex_smram_handler_phase1(i420ex_t *dev)
(regs[0x70] & 0x70) == 0x40, !(regs[0x70] & 0x20));
}
#ifndef USE_DRB_HACK
static void
i420ex_drb_recalc(i420ex_t *dev)
{
int i;
uint32_t boundary;
for (i = 4; i >= 0; i--)
row_disable(i);
for (i = 0; i <= 4; i++) {
boundary = ((uint32_t) dev->regs[0x60 + i]) & 0xff;
row_set_boundary(i, boundary);
}
flushmmucache();
}
#endif
static void
i420ex_write(int func, int addr, uint8_t val, void *priv)
{
@@ -289,7 +312,12 @@ i420ex_write(int func, int addr, uint8_t val, void *priv)
case 0x62:
case 0x63:
case 0x64:
#ifdef USE_DRB_HACK
spd_write_drbs(dev->regs, 0x60, 0x64, 1);
#else
dev->regs[addr] = val;
i420ex_drb_recalc(dev);
#endif
break;
case 0x66:
case 0x67:
@@ -452,7 +480,7 @@ i420ex_reset(void *priv)
i420ex_write(0, 0x59 + i, 0x00, priv);
for (uint8_t i = 0; i <= 4; i++)
i420ex_write(0, 0x60 + i, 0x01, priv);
dev->regs[0x60 + i] = 0x01;
dev->regs[0x70] &= 0xef; /* Forcibly unlock the SMRAM register. */
dev->smram_locked = 0;
@@ -530,6 +558,11 @@ i420ex_init(const device_t *info)
device_add(&ide_pci_2ch_device);
#ifndef USE_DRB_HACK
row_device.local = 4 | (1 << 8) | (0x01 << 16) | (8 << 24);
device_add((const device_t *) &row_device);
#endif
i420ex_reset_hard(dev);
return dev;

View File

@@ -1537,7 +1537,12 @@ i4x0_reset(void *priv)
i4x0_write(0, 0x5a + i, 0x00, priv);
for (uint8_t i = 0; i <= dev->max_drb; i++)
i4x0_write(0, 0x60 + i, dev->drb_default, priv);
dev->regs[0x60 + i] = dev->drb_default;
if (dev->type >= INTEL_430NX) {
for (uint8_t i = 0; i < 4; i++)
dev->regs[0x68 + i] = 0x00;
}
if (dev->type >= INTEL_430FX) {
dev->regs[0x72] &= 0xef; /* Forcibly unlock the SMRAM register. */
@@ -1621,7 +1626,7 @@ i4x0_init(const device_t *info)
regs[0x59] = 0x0f;
regs[0x60] = regs[0x61] = regs[0x62] = regs[0x63] = 0x02;
dev->max_drb = 3;
dev->drb_unit = 4;
dev->drb_unit = 1;
dev->drb_default = 0x02;
break;
case INTEL_430LX:

View File

@@ -38,10 +38,17 @@
#include <86box/machine.h>
#include <86box/chipset.h>
#include <86box/spd.h>
#ifndef USE_DRB_HACK
#include <86box/row.h>
#endif
typedef struct sis_85c496_t {
uint8_t cur_reg;
uint8_t rmsmiblk_count;
#ifndef USE_DRB_HACK
uint8_t drb_default;
uint8_t drb_bits;
#endif
uint8_t regs[127];
uint8_t pci_conf[256];
smram_t *smram;
@@ -184,6 +191,26 @@ sis_85c496_ide_handler(sis_85c496_t *dev)
}
}
#ifndef USE_DRB_HACK
static void
sis_85c496_drb_recalc(sis_85c496_t *dev)
{
int i;
uint32_t boundary;
for (i = 7; i >= 0; i--)
row_disable(i);
for (i = 0; i <= 7; i++) {
boundary = ((uint32_t) dev->pci_conf[0x48 + i]);
row_set_boundary(i, boundary);
}
flushmmucache();
}
#endif
/* 00 - 3F = PCI Configuration, 40 - 7F = 85C496, 80 - FF = 85C497 */
static void
sis_85c49x_pci_write(UNUSED(int func), int addr, uint8_t val, void *priv)
@@ -259,10 +286,12 @@ sis_85c49x_pci_write(UNUSED(int func), int addr, uint8_t val, void *priv)
case 0x4d:
case 0x4e:
case 0x4f:
#if 0
dev->pci_conf[addr] = val;
#endif
#ifdef USE_DRB_HACK
spd_write_drbs(dev->pci_conf, 0x48, 0x4f, 1);
#else
dev->pci_conf[addr] = val;
sis_85c496_drb_recalc(dev);
#endif
break;
case 0x50:
case 0x51: /* Exclusive Area 0 Setup */
@@ -552,7 +581,7 @@ sis_85c496_reset(void *priv)
// sis_85c49x_pci_write(0, 0x5a, 0x06, dev);
for (uint8_t i = 0; i < 8; i++)
sis_85c49x_pci_write(0, 0x48 + i, 0x00, dev);
dev->pci_conf[0x48 + i] = 0x02;
sis_85c49x_pci_write(0, 0x80, 0x00, dev);
sis_85c49x_pci_write(0, 0x81, 0x00, dev);
@@ -643,6 +672,11 @@ static void
timer_add(&dev->rmsmiblk_timer, sis_85c496_rmsmiblk_count, dev, 0);
#ifndef USE_DRB_HACK
row_device.local = 7 | (1 << 8) | (0x02 << 16) | (7 << 24);
device_add((const device_t *) &row_device);
#endif
sis_85c496_reset(dev);
return dev;

46
src/include/86box/row.h Normal file
View File

@@ -0,0 +1,46 @@
/*
* 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.
*
* Definitions for the SMRAM interface.
*
*
*
* Authors: Miran Grca, <mgrca8@gmail.com>
*
* Copyright 2016-2020 Miran Grca.
*/
#ifndef EMU_ROW_H
# define EMU_ROW_H
typedef struct _row_
{
struct _smram_ *prev;
struct _smram_ *next;
uint8_t *buf;
mem_mapping_t mapping;
uint32_t host_base;
uint32_t host_size;
uint32_t ram_base;
uint32_t ram_size;
uint32_t ram_mask;
uint32_t boundary;
} row_t;
extern void row_disable(uint8_t row_id);
extern void row_set_boundary(uint8_t row_id, uint32_t boundary);
extern device_t row_device;
#endif /*EMU_ROW_H*/

View File

@@ -14,4 +14,4 @@
#
add_library(mem OBJECT catalyst_flash.c i2c_eeprom.c intel_flash.c mem.c rom.c
smram.c spd.c sst_flash.c)
row.c smram.c spd.c sst_flash.c)

343
src/mem/row.c Normal file
View File

@@ -0,0 +1,343 @@
/*
* 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.
*
* DRAM row handling.
*
* Authors: Miran Grca, <mgrca8@gmail.com>
*
* Copyright 2016-2020 Miran Grca.
*/
#include <inttypes.h>
#include <stdarg.h>
#include <stdio.h>
#include <stdint.h>
#include <string.h>
#include <stdlib.h>
#include <wchar.h>
#define HAVE_STDARG_H
#include <86box/86box.h>
#include "cpu.h"
#include "x86_ops.h"
#include "x86.h"
#include <86box/config.h>
#include <86box/device.h>
#include <86box/io.h>
#include <86box/mem.h>
#include <86box/spd.h>
#include <86box/row.h>
/* 0 1 2 3 4 5 6 7 */
static uint8_t rows_num, rows_default,
rows_bits;
static uint32_t row_unit;
static uint8_t drb_defaults[16];
static row_t *rows;
static uint8_t
row_read(uint32_t addr, void *priv)
{
row_t *dev = (row_t *) priv;
uint32_t new_addr = ((addr - dev->host_base) & dev->ram_mask) + dev->ram_base;
addreadlookup(mem_logical_addr, new_addr);
return dev->buf[new_addr];
}
static uint16_t
row_readw(uint32_t addr, void *priv)
{
row_t *dev = (row_t *) priv;
uint32_t new_addr = ((addr - dev->host_base) & dev->ram_mask) + dev->ram_base;
addreadlookup(mem_logical_addr, new_addr);
return *(uint16_t *) &(dev->buf[new_addr]);
}
static uint32_t
row_readl(uint32_t addr, void *priv)
{
row_t *dev = (row_t *) priv;
uint32_t new_addr = ((addr - dev->host_base) & dev->ram_mask) + dev->ram_base;
addreadlookup(mem_logical_addr, new_addr);
return *(uint32_t *) &(dev->buf[new_addr]);
}
static void
row_write(uint32_t addr, uint8_t val, void *priv)
{
row_t *dev = (row_t *) priv;
uint32_t new_addr = ((addr - dev->host_base) & dev->ram_mask) + dev->ram_base;
addwritelookup(mem_logical_addr, new_addr);
mem_write_ramb_page(new_addr, val, &pages[addr >> 12]);
}
static void
row_writew(uint32_t addr, uint16_t val, void *priv)
{
row_t *dev = (row_t *) priv;
uint32_t new_addr = ((addr - dev->host_base) & dev->ram_mask) + dev->ram_base;
addwritelookup(mem_logical_addr, new_addr);
mem_write_ramw_page(new_addr, val, &pages[addr >> 12]);
}
static void
row_writel(uint32_t addr, uint32_t val, void *priv)
{
row_t *dev = (row_t *) priv;
uint32_t new_addr = ((addr - dev->host_base) & dev->ram_mask) + dev->ram_base;
addwritelookup(mem_logical_addr, new_addr);
mem_write_raml_page(new_addr, val, &pages[addr >> 12]);
}
void
row_allocate(uint8_t row_id, uint8_t set)
{
uint32_t c, offset;
/* Do nothing if size is either zero or invalid. */
if ((rows[row_id].host_size == 0x00000000) || (rows[row_id].host_size == 0xffffffff))
return;
if (rows[row_id].ram_size == 0x00000000)
return;
for (c = (rows[row_id].host_base >> 12); c < ((rows[row_id].host_base + rows[row_id].host_size) >> 12); c++) {
offset = c - (rows[row_id].host_base >> 12);
pages[c].mem = set ? (rows[row_id].buf + rows[row_id].ram_base + ((offset << 12) & rows[row_id].ram_mask)) : page_ff;
pages[c].write_b = set ? mem_write_ramb_page : NULL;
pages[c].write_w = set ? mem_write_ramw_page : NULL;
pages[c].write_l = set ? mem_write_raml_page : NULL;
#ifdef USE_NEW_DYNAREC
pages[c].evict_prev = EVICT_NOT_IN_LIST;
pages[c].byte_dirty_mask = &byte_dirty_mask[offset * 64];
pages[c].byte_code_present_mask = &byte_code_present_mask[offset * 64];
#endif
}
if (rows[row_id].host_base >= 0x00100000) {
mem_set_mem_state_both(rows[row_id].host_base, rows[row_id].host_base + rows[row_id].host_size,
set ? (MEM_READ_INTERNAL | MEM_WRITE_INTERNAL) : (MEM_READ_EXTERNAL | MEM_WRITE_EXTERNAL));
} else {
if (0x000a0000 > rows[row_id].host_base) {
mem_set_mem_state_both(rows[row_id].host_base, 0x000a0000 - rows[row_id].host_base,
set ? (MEM_READ_INTERNAL | MEM_WRITE_INTERNAL) : (MEM_READ_EXTERNAL | MEM_WRITE_EXTERNAL));
}
if ((rows[row_id].host_base + rows[row_id].host_size) > 0x00100000) {
mem_set_mem_state_both(0x00100000, (rows[row_id].host_base + rows[row_id].host_size) - 0x00100000,
set ? (MEM_READ_INTERNAL | MEM_WRITE_INTERNAL) : (MEM_READ_EXTERNAL | MEM_WRITE_EXTERNAL));
}
}
if (set) {
mem_mapping_set_addr(&rows[row_id].mapping, rows[row_id].host_base, rows[row_id].host_size);
mem_mapping_set_exec(&rows[row_id].mapping, rows[row_id].buf + rows[row_id].ram_base);
mem_mapping_set_mask(&rows[row_id].mapping, rows[row_id].ram_mask);
if ((rows[row_id].host_base == rows[row_id].ram_base) && (rows[row_id].host_size == rows[row_id].ram_size)) {
#if (defined __amd64__ || defined _M_X64 || defined __aarch64__ || defined _M_ARM64)
mem_mapping_set_handler(&rows[row_id].mapping, mem_read_ram,mem_read_ramw,mem_read_raml,
mem_write_ram,mem_write_ramw,mem_write_raml);
#else
if (rows[row_id].buf == ram2) {
mem_mapping_set_handler(&rows[row_id].mapping, mem_read_ram_2gb,mem_read_ram_2gbw,mem_read_ram_2gbl,
mem_write_ram,mem_write_ramw,mem_write_raml);
} else {
mem_mapping_set_handler(&rows[row_id].mapping, mem_read_ram,mem_read_ramw,mem_read_raml,
mem_write_ram,mem_write_ramw,mem_write_raml);
}
#endif
} else {
mem_mapping_set_handler(&rows[row_id].mapping, row_read, row_readw, row_readl,
row_write, row_writew, row_writel);
}
} else
mem_mapping_disable(&rows[row_id].mapping);
}
void
row_disable(uint8_t row_id)
{
row_allocate(row_id, 0);
}
void
row_set_boundary(uint8_t row_id, uint32_t boundary)
{
if (row_id >= rows_num)
return;
boundary &= ((1 << rows_bits) - 1);
rows[row_id].host_size = boundary * row_unit;
if (row_id == 0)
rows[row_id].host_base = 0x00000000;
else {
rows[row_id].host_base = rows[row_id - 1].boundary * row_unit;
if (rows[row_id - 1].boundary > boundary)
rows[row_id].host_size = 0x00000000;
else
rows[row_id].host_size -= rows[row_id].host_base;
}
rows[row_id].boundary = boundary;
row_allocate(row_id, 1);
}
void
row_reset(void *priv)
{
int i;
uint32_t boundary, shift;
for (i = (rows_num - 1); i >= 0; i--)
row_disable(i);
for (i = 0; i < rows_num; i++) {
shift = (i & 1) << 2;
boundary = ((uint32_t) drb_defaults[i]) + (((((uint32_t) drb_defaults[(i >> 1) + 8]) >> shift) & 0xf) << 8);
row_set_boundary(i, boundary);
}
}
void
row_close(void *priv)
{
free(rows);
rows = NULL;
}
void *
row_init(const device_t *info)
{
uint32_t cur_drb = 0, cur_drbe = 0;
uint32_t last_drb = 0, last_drbe = 0;
uint8_t phys_drbs[16];
int i, max = info->local & 0xff;
int c;
uint32_t shift, drb;
uint32_t boundary, mask;
row_t *new_rows = NULL;
rows_bits = ((info->local >> 24) & 0xff);
mask = (1 << rows_bits) - 1;
row_unit = ((info->local >> 8) & 0xff);
memset(phys_drbs, 0x00, 16);
spd_write_drbs(phys_drbs, 0x00, max, row_unit);
row_unit <<= 20;
rows_default = (info->local >> 16) & 0xff;
memset(drb_defaults, 0x00, 16);
for (i = 0; i < 8; i++)
drb_defaults[i] = rows_default;
new_rows = calloc(max + 1, sizeof(row_t));
rows_num = max + 1;
rows = new_rows;
mem_mapping_disable(&ram_low_mapping);
mem_mapping_disable(&ram_mid_mapping);
mem_mapping_disable(&ram_high_mapping);
#if (!(defined __amd64__ || defined _M_X64 || defined __aarch64__ || defined _M_ARM64))
if (mem_size > 1048576)
mem_mapping_disable(&ram_2gb_mapping);
#endif
for (c = 0; c < pages_sz; c++) {
pages[c].mem = page_ff;
pages[c].write_b = NULL;
pages[c].write_w = NULL;
pages[c].write_l = NULL;
#ifdef USE_NEW_DYNAREC
pages[c].evict_prev = EVICT_NOT_IN_LIST;
pages[c].byte_dirty_mask = &byte_dirty_mask[c * 64];
pages[c].byte_code_present_mask = &byte_code_present_mask[c * 64];
#endif
}
/* Set all memory space above the default allocated area to external. */
boundary = ((uint32_t) rows_default) * row_unit;
mem_set_mem_state_both(boundary, (mem_size << 10) - boundary, MEM_READ_EXTERNAL | MEM_WRITE_EXTERNAL);
for (i = 0; i <= max; i++) {
cur_drb = phys_drbs[i];
cur_drbe = phys_drbs[(i >> 1) + 8];
shift = (i & 1) << 2;
drb = (cur_drb & mask) + (((cur_drbe >> shift) & 0x03) << 8);
rows[i].ram_size = drb * row_unit;
shift = ((i - 1) & 1) << 2;
drb = (last_drb & mask) + (((last_drbe >> shift) & 0x03) << 8);
rows[i].ram_base = drb * row_unit;
rows[i].ram_size -= rows[i].ram_base;
rows[i].buf = ram;
#if (!(defined __amd64__ || defined _M_X64 || defined __aarch64__ || defined _M_ARM64))
if (rows[i].ram_base >= (1 << 30)) {
rows[i].ram_base -= (1 << 30);
rows[i].buf = ram2;
}
#endif
rows[i].ram_mask = rows[i].ram_size - 1;
mem_mapping_add(&rows[i].mapping, rows[i].ram_base, rows[i].ram_size,
row_read, row_readw, row_readl,
row_write, row_writew, row_writel,
rows[i].buf + rows[i].ram_base, MEM_MAPPING_INTERNAL, &(rows[i]));
mem_mapping_disable(&rows[i].mapping);
shift = (i & 1) << 2;
boundary = ((uint32_t) drb_defaults[i]) + ((((uint32_t) drb_defaults[(i >> 1) + 8]) >> shift) << 8);
row_set_boundary(i, boundary);
last_drb = cur_drb;
last_drbe = cur_drbe;
}
flushmmucache();
return new_rows;
}
/* NOTE: NOT const, so that we can patch it at init. */
device_t row_device = {
.name = "DRAM Rows",
.internal_name = "dram_rows",
.flags = DEVICE_AT,
.local = 0x0000,
.init = row_init,
.close = row_close,
.reset = row_reset,
{ .available = NULL },
.speed_changed = NULL,
.force_redraw = NULL,
.config = NULL
};

View File

@@ -401,7 +401,7 @@ spd_write_drbs(uint8_t *regs, uint8_t reg_min, uint8_t reg_max, uint8_t drb_unit
}
}
/* Needed for 430LX. */
/* Needed for 430NX. */
void
spd_write_drbs_with_ext(uint8_t *regs, uint8_t reg_min, uint8_t reg_max, uint8_t drb_unit)
{
@@ -447,8 +447,9 @@ spd_write_drbs_with_ext(uint8_t *regs, uint8_t reg_min, uint8_t reg_max, uint8_t
row_val += size / drb_unit; /* this will intentionally overflow on 440GX with 2 GB */
regs[drb] = row_val & 0xff;
drb = reg_min + 8 + (row >> 1);
shift = (row & 0x01) << 3;
regs[drb] = (((row_val & 0xfff) >> 8) << shift);
shift = (row & 0x01) << 2;
/* Limit to 1 GB space, per the 430NX datasheet. */
regs[drb] = (regs[drb] & ~(0xf << shift)) | (((row_val >> 8) & 3) << shift);
spd_log("SPD: DRB[%d] = %d MB (%02Xh raw)\n", row, size, regs[drb]);
}
}

View File

@@ -31,6 +31,12 @@ FileField::FileField(QWidget *parent)
fileName_ = ui->label->text();
emit fileSelected(ui->label->text(), true);
});
connect(ui->label, &QLineEdit::textChanged, this, [this]() {
fileName_ = ui->label->text();
emit fileTextEntered(ui->label->text(), true);
});
this->setFixedWidth(this->sizeHint().width() + ui->pushButton->sizeHint().width());
}

View File

@@ -19,12 +19,14 @@ public:
void setFilter(const QString &filter) { filter_ = filter; }
QString selectedFilter() const { return selectedFilter_; }
void setselectedFilter(const QString &selectedFilter) { selectedFilter_ = selectedFilter; }
void setCreateFile(bool createFile) { createFile_ = createFile; }
bool createFile() { return createFile_; }
signals:
void fileSelected(const QString &fileName, bool precheck = false);
void fileTextEntered(const QString &fileName, bool precheck = false);
private slots:
void on_pushButton_clicked();

View File

@@ -84,6 +84,13 @@ HarddiskDialog::HarddiskDialog(bool existing, QWidget *parent)
ui->lineEditSize->setValidator(new QIntValidator());
ui->buttonBox->button(QDialogButtonBox::Ok)->setEnabled(false);
filters = QStringList({ tr("Raw image") % util::DlgFilter({ "img" }, true),
tr("HDI image") % util::DlgFilter({ "hdi" }, true),
tr("HDX image") % util::DlgFilter({ "hdx" }, true),
tr("Fixed-size VHD") % util::DlgFilter({ "vhd" }, true),
tr("Dynamic-size VHD") % util::DlgFilter({ "vhd" }, true),
tr("Differencing VHD") % util::DlgFilter({ "vhd" }, true) });
if (existing) {
ui->fileField->setFilter(tr("Hard disk images") % util::DlgFilter({ "hd?", "im?", "vhd" }) % tr("All files") % util::DlgFilter({ "*" }, true));
@@ -99,24 +106,26 @@ HarddiskDialog::HarddiskDialog(bool existing, QWidget *parent)
connect(ui->fileField, &FileField::fileSelected, this, &HarddiskDialog::onExistingFileSelected);
} else {
QStringList filters({ tr("Raw image") % util::DlgFilter({ "img" }, true),
tr("HDI image") % util::DlgFilter({ "hdi" }, true),
tr("HDX image") % util::DlgFilter({ "hdx" }, true),
tr("Fixed-size VHD") % util::DlgFilter({ "vhd" }, true),
tr("Dynamic-size VHD") % util::DlgFilter({ "vhd" }, true),
tr("Differencing VHD") % util::DlgFilter({ "vhd" }, true) });
ui->fileField->setFilter(filters.join(";;"));
setWindowTitle(tr("Add New Hard Disk"));
ui->fileField->setCreateFile(true);
connect(ui->fileField, &FileField::fileSelected, this, [this, filters] {
// Enable the OK button as long as the filename length is non-zero
connect(ui->fileField, &FileField::fileTextEntered, this, [this] {
ui->buttonBox->button(QDialogButtonBox::Ok)->setEnabled((this->fileName().length() > 0));
});
connect(ui->fileField, &FileField::fileSelected, this, [this] {
int filter = filters.indexOf(ui->fileField->selectedFilter());
if (filter > -1)
ui->comboBoxFormat->setCurrentIndex(filter);
ui->buttonBox->button(QDialogButtonBox::Ok)->setEnabled(true);
});
// Set the default format to Dynamic-size VHD. Do it last after everything is set up
// so the currentIndexChanged signal can do what is needed
ui->comboBoxFormat->setCurrentIndex(DEFAULT_DISK_FORMAT);
ui->fileField->setselectedFilter(filters.value(DEFAULT_DISK_FORMAT));
}
}
@@ -179,6 +188,7 @@ HarddiskDialog::on_comboBoxFormat_currentIndexChanged(int index)
ui->comboBoxBlockSize->show();
ui->labelBlockSize->show();
}
ui->fileField->setselectedFilter(filters.value(index));
}
/* If the disk geometry requested in the 86Box GUI is not compatible with the internal VHD geometry,

View File

@@ -52,6 +52,11 @@ private:
bool disallowSizeModifications = false;
QStringList filters;
// "Dynamic-size VHD" is number 4 in the `filters` list and the
// comboBoxFormat model
const uint8_t DEFAULT_DISK_FORMAT = 4;
bool checkAndAdjustCylinders();
bool checkAndAdjustHeads();
bool checkAndAdjustSectors();

View File

@@ -85,12 +85,13 @@ if(RTMIDI)
endif()
if(FLUIDSYNTH)
if(APPLE)
find_library(FLUIDSYNTH_LIB fluidsynth)
if (NOT FLUIDSYNTH_LIB)
message(WARNING "Could not find fluid synth. The library will not be bundled and any related features will not work.")
endif()
endif ()
find_package(PkgConfig REQUIRED)
pkg_check_modules(FLUIDSYNTH REQUIRED IMPORTED_TARGET fluidsynth)
target_link_libraries(86Box PkgConfig::FLUIDSYNTH)
if(STATIC_BUILD)
target_link_libraries(86Box -static ${FLUIDSYNTH_STATIC_LIBRARIES} -fopenmp)
endif()
target_compile_definitions(snd PRIVATE USE_FLUIDSYNTH)
target_sources(snd PRIVATE midi_fluidsynth.c)
endif()

View File

@@ -8,6 +8,8 @@
# ifdef __unix__
# include <unistd.h>
# endif
# define FLUIDSYNTH_NOT_A_DLL
# include <fluidsynth.h>
# include <86box/86box.h>
# include <86box/config.h>
@@ -28,79 +30,9 @@
# define RENDER_RATE 100
# define BUFFER_SEGMENTS 10
enum fluid_chorus_mod {
FLUID_CHORUS_MOD_SINE = 0,
FLUID_CHORUS_MOD_TRIANGLE = 1
};
enum fluid_interp {
FLUID_INTERP_NONE = 0,
FLUID_INTERP_LINEAR = 1,
FLUID_INTERP_DEFAULT = 4,
FLUID_INTERP_4THORDER = 4,
FLUID_INTERP_7THORDER = 7,
FLUID_INTERP_HIGHEST = 7
};
extern void givealbuffer_midi(void *buf, uint32_t size);
extern void al_set_midi(int freq, int buf_size);
static void *fluidsynth_handle; /* handle to FluidSynth DLL */
/* Pointers to the real functions. */
// clang-format off
static void *(*f_new_fluid_settings)(void);
static void (*f_delete_fluid_settings)(void *settings);
static int (*f_fluid_settings_setnum)(void *settings, const char *name, double val);
static int (*f_fluid_settings_getnum)(void *settings, const char *name, double *val);
static void *(*f_new_fluid_synth)(void *settings);
static int (*f_delete_fluid_synth)(void *synth);
static int (*f_fluid_synth_noteon)(void *synth, int chan, int key, int vel);
static int (*f_fluid_synth_noteoff)(void *synth, int chan, int key);
static int (*f_fluid_synth_cc)(void *synth, int chan, int ctrl, int val);
static int (*f_fluid_synth_channel_pressure)(void *synth, int chan, int val);
static int (*f_fluid_synth_sysex)(void *synth, const char *data, int len, char *response, int *response_len, int *handled, int dryrun);
static int (*f_fluid_synth_pitch_bend)(void *synth, int chan, int val);
static int (*f_fluid_synth_program_change)(void *synth, int chan, int program);
static int (*f_fluid_synth_sfload)(void *synth, const char *filename, int reset_presets);
static int (*f_fluid_synth_set_interp_method)(void *synth, int chan, int interp_method);
static void (*f_fluid_synth_set_reverb)(void *synth, double roomsize, double damping, double width, double level);
static void (*f_fluid_synth_set_reverb_on)(void *synth, int on);
static void (*f_fluid_synth_set_chorus)(void *synth, int nr, double level, double speed, double depth_ms, int type);
static void (*f_fluid_synth_set_chorus_on)(void *synth, int on);
static int (*f_fluid_synth_write_s16)(void *synth, int len, void *lout, int loff, int lincr, void *rout, int roff, int rincr);
static int (*f_fluid_synth_write_float)(void *synth, int len, void *lout, int loff, int lincr, void *rout, int roff, int rincr);
static char *(*f_fluid_version_str)(void);
// clang-format on
static dllimp_t fluidsynth_imports[] = {
// clang-format off
{ "new_fluid_settings", &f_new_fluid_settings },
{ "delete_fluid_settings", &f_delete_fluid_settings },
{ "fluid_settings_setnum", &f_fluid_settings_setnum },
{ "fluid_settings_getnum", &f_fluid_settings_getnum },
{ "new_fluid_synth", &f_new_fluid_synth },
{ "delete_fluid_synth", &f_delete_fluid_synth },
{ "fluid_synth_noteon", &f_fluid_synth_noteon },
{ "fluid_synth_noteoff", &f_fluid_synth_noteoff },
{ "fluid_synth_cc", &f_fluid_synth_cc },
{ "fluid_synth_channel_pressure", &f_fluid_synth_channel_pressure },
{ "fluid_synth_sysex", &f_fluid_synth_sysex },
{ "fluid_synth_pitch_bend", &f_fluid_synth_pitch_bend },
{ "fluid_synth_program_change", &f_fluid_synth_program_change },
{ "fluid_synth_sfload", &f_fluid_synth_sfload },
{ "fluid_synth_set_interp_method", &f_fluid_synth_set_interp_method },
{ "fluid_synth_set_reverb", &f_fluid_synth_set_reverb },
{ "fluid_synth_set_reverb_on", &f_fluid_synth_set_reverb_on },
{ "fluid_synth_set_chorus", &f_fluid_synth_set_chorus },
{ "fluid_synth_set_chorus_on", &f_fluid_synth_set_chorus_on },
{ "fluid_synth_write_s16", &f_fluid_synth_write_s16 },
{ "fluid_synth_write_float", &f_fluid_synth_write_float },
{ "fluid_version_str", &f_fluid_version_str },
{ NULL, NULL },
// clang-format on
};
typedef struct fluidsynth {
void *settings;
void *synth;
@@ -153,7 +85,7 @@ fluidsynth_thread(void *param)
float *buf = (float *) ((uint8_t *) data->buffer + buf_pos);
memset(buf, 0, buf_size);
if (data->synth)
f_fluid_synth_write_float(data->synth, buf_size / (2 * sizeof(float)), buf, 0, 2, buf, 1, 2);
fluid_synth_write_float(data->synth, buf_size / (2 * sizeof(float)), buf, 0, 2, buf, 1, 2);
buf_pos += buf_size;
if (buf_pos >= data->buf_size) {
givealbuffer_midi(data->buffer, data->buf_size / sizeof(float));
@@ -163,7 +95,7 @@ fluidsynth_thread(void *param)
int16_t *buf = (int16_t *) ((uint8_t *) data->buffer_int16 + buf_pos);
memset(buf, 0, buf_size);
if (data->synth)
f_fluid_synth_write_s16(data->synth, buf_size / (2 * sizeof(int16_t)), buf, 0, 2, buf, 1, 2);
fluid_synth_write_s16(data->synth, buf_size / (2 * sizeof(int16_t)), buf, 0, 2, buf, 1, 2);
buf_pos += buf_size;
if (buf_pos >= data->buf_size) {
givealbuffer_midi(data->buffer_int16, data->buf_size / sizeof(int16_t));
@@ -187,24 +119,24 @@ fluidsynth_msg(uint8_t *msg)
switch (cmd) {
case 0x80: /* Note Off */
f_fluid_synth_noteoff(data->synth, chan, param1);
fluid_synth_noteoff(data->synth, chan, param1);
break;
case 0x90: /* Note On */
f_fluid_synth_noteon(data->synth, chan, param1, param2);
fluid_synth_noteon(data->synth, chan, param1, param2);
break;
case 0xA0: /* Aftertouch */
break;
case 0xB0: /* Control Change */
f_fluid_synth_cc(data->synth, chan, param1, param2);
fluid_synth_cc(data->synth, chan, param1, param2);
break;
case 0xC0: /* Program Change */
f_fluid_synth_program_change(data->synth, chan, param1);
fluid_synth_program_change(data->synth, chan, param1);
break;
case 0xD0: /* Channel Pressure */
f_fluid_synth_channel_pressure(data->synth, chan, param1);
fluid_synth_channel_pressure(data->synth, chan, param1);
break;
case 0xE0: /* Pitch Bend */
f_fluid_synth_pitch_bend(data->synth, chan, (param2 << 7) | param1);
fluid_synth_pitch_bend(data->synth, chan, (param2 << 7) | param1);
break;
case 0xF0: /* SysEx */
break;
@@ -218,7 +150,7 @@ fluidsynth_sysex(uint8_t *data, unsigned int len)
{
fluidsynth_t *d = &fsdev;
f_fluid_synth_sysex(d->synth, (const char *) data, len, 0, 0, 0, 0);
fluid_synth_sysex(d->synth, (const char *) data, len, 0, 0, 0, 0);
}
void *
@@ -229,31 +161,12 @@ fluidsynth_init(const device_t *info)
memset(data, 0, sizeof(fluidsynth_t));
/* Try loading the DLL. */
# ifdef _WIN32
# if (!(defined __amd64__ || defined _M_X64 || defined __aarch64__ || defined _M_ARM64))
fluidsynth_handle = dynld_module("libfluidsynth.dll", fluidsynth_imports);
# else
fluidsynth_handle = dynld_module("libfluidsynth64.dll", fluidsynth_imports);
# endif
# elif defined __APPLE__
fluidsynth_handle = dynld_module("libfluidsynth.dylib", fluidsynth_imports);
# else
fluidsynth_handle = dynld_module("libfluidsynth.so.3", fluidsynth_imports);
if (fluidsynth_handle == NULL)
fluidsynth_handle = dynld_module("libfluidsynth.so.2", fluidsynth_imports);
# endif
if (fluidsynth_handle == NULL) {
ui_msgbox_header(MBX_ERROR, (wchar_t *) IDS_2080, (wchar_t *) IDS_2134);
return NULL;
}
data->settings = new_fluid_settings();
data->settings = f_new_fluid_settings();
fluid_settings_setnum(data->settings, "synth.sample-rate", 44100);
fluid_settings_setnum(data->settings, "synth.gain", device_get_config_int("output_gain") / 100.0f);
f_fluid_settings_setnum(data->settings, "synth.sample-rate", 44100);
f_fluid_settings_setnum(data->settings, "synth.gain", device_get_config_int("output_gain") / 100.0f);
data->synth = f_new_fluid_synth(data->settings);
data->synth = new_fluid_synth(data->settings);
const char *sound_font = (char *) device_get_config_string("sound_font");
# ifdef __unix__
@@ -261,10 +174,10 @@ fluidsynth_init(const device_t *info)
sound_font = (access("/usr/share/sounds/sf2/FluidR3_GM.sf2", F_OK) == 0 ? "/usr/share/sounds/sf2/FluidR3_GM.sf2" :
(access("/usr/share/soundfonts/default.sf2", F_OK) == 0 ? "/usr/share/soundfonts/default.sf2" : ""));
# endif
data->sound_font = f_fluid_synth_sfload(data->synth, sound_font, 1);
data->sound_font = fluid_synth_sfload(data->synth, sound_font, 1);
if (device_get_config_int("chorus")) {
f_fluid_synth_set_chorus_on(data->synth, 1);
fluid_synth_set_chorus_on(data->synth, 1);
int chorus_voices = device_get_config_int("chorus_voices");
double chorus_level = device_get_config_int("chorus_level") / 100.0;
@@ -277,21 +190,21 @@ fluidsynth_init(const device_t *info)
else
chorus_waveform = FLUID_CHORUS_MOD_TRIANGLE;
f_fluid_synth_set_chorus(data->synth, chorus_voices, chorus_level, chorus_speed, chorus_depth, chorus_waveform);
fluid_synth_set_chorus(data->synth, chorus_voices, chorus_level, chorus_speed, chorus_depth, chorus_waveform);
} else
f_fluid_synth_set_chorus_on(data->synth, 0);
fluid_synth_set_chorus_on(data->synth, 0);
if (device_get_config_int("reverb")) {
f_fluid_synth_set_reverb_on(data->synth, 1);
fluid_synth_set_reverb_on(data->synth, 1);
double reverb_room_size = device_get_config_int("reverb_room_size") / 100.0;
double reverb_damping = device_get_config_int("reverb_damping") / 100.0;
int reverb_width = device_get_config_int("reverb_width");
double reverb_level = device_get_config_int("reverb_level") / 100.0;
f_fluid_synth_set_reverb(data->synth, reverb_room_size, reverb_damping, reverb_width, reverb_level);
fluid_synth_set_reverb(data->synth, reverb_room_size, reverb_damping, reverb_width, reverb_level);
} else
f_fluid_synth_set_reverb_on(data->synth, 0);
fluid_synth_set_reverb_on(data->synth, 0);
int interpolation = device_get_config_int("interpolation");
int fs_interpolation = FLUID_INTERP_4THORDER;
@@ -305,10 +218,10 @@ fluidsynth_init(const device_t *info)
else if (interpolation == 3)
fs_interpolation = FLUID_INTERP_7THORDER;
f_fluid_synth_set_interp_method(data->synth, -1, fs_interpolation);
fluid_synth_set_interp_method(data->synth, -1, fs_interpolation);
double samplerate;
f_fluid_settings_getnum(data->settings, "synth.sample-rate", &samplerate);
fluid_settings_getnum(data->settings, "synth.sample-rate", &samplerate);
data->samplerate = (int) samplerate;
if (sound_is_float) {
data->buf_size = (data->samplerate / RENDER_RATE) * 2 * sizeof(float) * BUFFER_SEGMENTS;
@@ -357,12 +270,12 @@ fluidsynth_close(void *p)
thread_wait(data->thread_h);
if (data->synth) {
f_delete_fluid_synth(data->synth);
delete_fluid_synth(data->synth);
data->synth = NULL;
}
if (data->settings) {
f_delete_fluid_settings(data->settings);
delete_fluid_settings(data->settings);
data->settings = NULL;
}
@@ -375,12 +288,6 @@ fluidsynth_close(void *p)
free(data->buffer_int16);
data->buffer_int16 = NULL;
}
/* Unload the DLL if possible. */
if (fluidsynth_handle != NULL) {
dynld_close(fluidsynth_handle);
fluidsynth_handle = NULL;
}
}
static const device_config_t fluidsynth_config[] = {