Revert "Merge branch 'master' of https://github.com/86Box/86Box"

This reverts commit 7a4bddab3c, reversing
changes made to 416d4f673d.
This commit is contained in:
RichardG867
2020-06-07 15:52:45 -03:00
parent 7a4bddab3c
commit aa4028aaff
98 changed files with 1529 additions and 512 deletions

View File

@@ -787,6 +787,7 @@ acpi_reset(void *priv)
int i;
memset(&dev->regs, 0x00, sizeof(acpi_regs_t));
dev->regs.gpireg[0] = dev->regs.gpireg[1] = dev->regs.gpireg[2] = 0xff;
for (i = 0; i < 4; i++)
dev->regs.gporeg[i] = dev->gporeg_default[i];
}

View File

@@ -43,44 +43,30 @@ typedef struct acc2168_t
} acc2168_t;
/*
Based on reverse engineering using the AMI 386DX Clone BIOS:
Bit 0 of register 02 controls shadowing of C0000-C7FFF (1 = enabled, 0 = disabled);
Bit 1 of register 02 controls shadowing of C8000-CFFFF (1 = enabled, 0 = disabled);
Bit 2 of register 02 controls shadowing of D0000-DFFFF (1 = enabled, 0 = disabled);
Bit 3 of register 02 controls shadowing of E0000-EFFFF (1 = enabled, 0 = disabled);
Bit 4 of register 02 controls shadowing of F0000-FFFFF (1 = enabled, 0 = disabled);
Bit 5 is most likely: 1 = shadow enabled, 0 = shadow disabled;
Bit 6 of register 02 controls shadow RAM cacheability (1 = cacheable, 0 = non-cacheable).
*/
static void
acc2168_shadow_recalc(acc2168_t *dev)
{
if (dev->regs[0x02] & 8) {
switch (dev->regs[0x02] & 0x30) {
case 0x00:
mem_set_mem_state(0xf0000, 0x10000, MEM_READ_EXTANY | MEM_WRITE_INTERNAL);
break;
case 0x10:
mem_set_mem_state(0xf0000, 0x10000, MEM_READ_INTERNAL | MEM_WRITE_INTERNAL);
break;
case 0x20:
mem_set_mem_state(0xf0000, 0x10000, MEM_READ_EXTANY | MEM_WRITE_EXTANY);
break;
case 0x30:
mem_set_mem_state(0xf0000, 0x10000, MEM_READ_INTERNAL | MEM_WRITE_EXTANY);
break;
}
} else
mem_set_mem_state(0xf0000, 0x10000, MEM_READ_EXTANY | MEM_WRITE_EXTANY);
int state;
if (dev->regs[0x02] & 4) {
switch (dev->regs[0x02] & 0x30) {
case 0x00:
mem_set_mem_state(0xe0000, 0x10000, MEM_READ_EXTANY | MEM_WRITE_INTERNAL);
break;
case 0x10:
mem_set_mem_state(0xe0000, 0x10000, MEM_READ_INTERNAL | MEM_WRITE_INTERNAL);
break;
case 0x20:
mem_set_mem_state(0xe0000, 0x10000, MEM_READ_EXTANY | MEM_WRITE_EXTANY);
break;
case 0x30:
mem_set_mem_state(0xe0000, 0x10000, MEM_READ_INTERNAL | MEM_WRITE_EXTANY);
break;
}
} else
mem_set_mem_state(0xe0000, 0x10000, MEM_READ_EXTANY | MEM_WRITE_EXTANY);
if (dev->regs[0x02] & 0x20)
state = (dev->regs[0x02] & 0x20) ? (MEM_READ_INTERNAL | MEM_WRITE_INTERNAL) : (MEM_READ_EXTANY | MEM_WRITE_EXTANY);
mem_set_mem_state(0xc0000, 0x08000, (dev->regs[0x02] & 0x01) ? state : (MEM_READ_EXTANY | MEM_WRITE_EXTANY));
mem_set_mem_state(0xc8000, 0x08000, (dev->regs[0x02] & 0x02) ? state : (MEM_READ_EXTANY | MEM_WRITE_EXTANY));
mem_set_mem_state(0xd0000, 0x10000, (dev->regs[0x02] & 0x04) ? state : (MEM_READ_EXTANY | MEM_WRITE_EXTANY));
mem_set_mem_state(0xe0000, 0x10000, (dev->regs[0x02] & 0x08) ? state : (MEM_READ_EXTANY | MEM_WRITE_EXTANY));
mem_set_mem_state(0xf0000, 0x10000, (dev->regs[0x02] & 0x10) ? state : (MEM_READ_EXTANY | MEM_WRITE_EXTANY));
}

View File

@@ -43,6 +43,8 @@ enum
INTEL_430VX,
INTEL_430TX,
INTEL_440FX,
INTEL_440LX,
INTEL_440EX,
INTEL_440BX,
INTEL_440ZX
};
@@ -94,7 +96,7 @@ i4x0_smram_handler_phase0(i4x0_t *dev)
/* Disable any active mappings. */
if (dev->type >= INTEL_430FX) {
if (dev->type >= INTEL_440BX) {
if (dev->type >= INTEL_440LX) {
/* Disable high extended SMRAM. */
/* TODO: This area should point to A0000-FFFFF. */
for (i = 0x100a0000; i < 0x100fffff; i += MEM_GRANULARITY_SIZE) {
@@ -257,7 +259,7 @@ i4x0_write(int func, int addr, uint8_t val, void *priv)
regs[0x04] = (regs[0x04] & ~0x42) | (val & 0x42);
break;
case INTEL_430FX: case INTEL_430FX_PB640: case INTEL_430HX: case INTEL_430VX: case INTEL_430TX:
case INTEL_440FX:
case INTEL_440FX: case INTEL_440LX: case INTEL_440EX:
regs[0x04] = (regs[0x04] & ~0x02) | (val & 0x02);
break;
}
@@ -265,7 +267,7 @@ i4x0_write(int func, int addr, uint8_t val, void *priv)
case 0x05:
switch (dev->type) {
case INTEL_420TX: case INTEL_420ZX: case INTEL_430LX: case INTEL_430NX: case INTEL_430HX:
case INTEL_440FX:
case INTEL_440FX: case INTEL_440LX: case INTEL_440EX:
case INTEL_440BX: case INTEL_440ZX:
regs[0x05] = (regs[0x05] & ~0x01) | (val & 0x01);
break;
@@ -278,6 +280,7 @@ i4x0_write(int func, int addr, uint8_t val, void *priv)
regs[0x07] &= ~(val & 0x70);
break;
case INTEL_430FX: case INTEL_430FX_PB640: case INTEL_430VX: case INTEL_430TX:
case INTEL_440LX: case INTEL_440EX:
regs[0x07] &= ~(val & 0x30);
break;
case INTEL_440FX:
@@ -331,6 +334,14 @@ i4x0_write(int func, int addr, uint8_t val, void *priv)
break;
}
break;
case 0x34:
switch (dev->type) {
case INTEL_440LX: case INTEL_440EX:
regs[0x34] = (val & 0xa0);
}
break;
case 0x4f:
switch (dev->type) {
case INTEL_430HX:
@@ -365,6 +376,12 @@ i4x0_write(int func, int addr, uint8_t val, void *priv)
case INTEL_440FX:
regs[0x50] = (val & 0xf4);
break;
case INTEL_440LX:
regs[0x50] = (val & 0x03);
break;
case INTEL_440EX:
regs[0x50] = (val & 0x23);
break;
case INTEL_440BX:
regs[0x50] = (regs[0x50] & 0x14) | (val & 0xeb);
break;
@@ -382,6 +399,9 @@ i4x0_write(int func, int addr, uint8_t val, void *priv)
case INTEL_440FX:
regs[0x51] = (val & 0xc3);
break;
case INTEL_440LX: case INTEL_440EX:
regs[0x51] = (val & 0x80);
break;
case INTEL_440BX: case INTEL_440ZX:
regs[0x51] = (regs[0x50] & 0x70) | (val & 0x8f);
break;
@@ -400,6 +420,9 @@ i4x0_write(int func, int addr, uint8_t val, void *priv)
case INTEL_440FX:
regs[0x52] = val;
break;
case INTEL_440LX:
regs[0x52] = (val & 0xd0);
break;
case INTEL_440BX: case INTEL_440ZX:
regs[0x52] = val & 0x07;
break;
@@ -417,7 +440,10 @@ i4x0_write(int func, int addr, uint8_t val, void *priv)
case INTEL_430VX: case INTEL_430TX:
regs[0x53] = val & 0x3f;
break;
case INTEL_440BX:
case INTEL_440LX:
regs[0x53] = val & 0x0a;
break;
case INTEL_440EX: case INTEL_440BX:
/* Not applicable to 440ZX as that does not support ECC. */
regs[0x53] = val;
break;
@@ -438,6 +464,9 @@ i4x0_write(int func, int addr, uint8_t val, void *priv)
case INTEL_440FX:
regs[0x54] = val & 0x82;
break;
case INTEL_440LX:
regs[0x54] = val;
break;
}
break;
case 0x55:
@@ -445,7 +474,8 @@ i4x0_write(int func, int addr, uint8_t val, void *priv)
case INTEL_430VX: case INTEL_430TX:
regs[0x55] = val & 0x01;
break;
case INTEL_440FX:
case INTEL_440FX: case INTEL_440LX:
case INTEL_440EX:
regs[0x55] = val;
break;
}
@@ -461,7 +491,8 @@ i4x0_write(int func, int addr, uint8_t val, void *priv)
case INTEL_430TX:
regs[0x56] = val & 0x76;
break;
case INTEL_440FX:
case INTEL_440FX: case INTEL_440LX:
case INTEL_440EX:
regs[0x56] = val;
break;
}
@@ -472,7 +503,7 @@ i4x0_write(int func, int addr, uint8_t val, void *priv)
case INTEL_430LX: default:
regs[0x57] = val & 0x3f;
break;
case INTEL_430NX:
case INTEL_430NX: case INTEL_440EX:
regs[0x57] = val;
break;
case INTEL_430FX: case INTEL_430FX_PB640:
@@ -485,6 +516,9 @@ i4x0_write(int func, int addr, uint8_t val, void *priv)
case INTEL_440FX:
regs[0x57] = val & 0x77;
break;
case INTEL_440LX:
regs[0x57] = val & 0x11;
break;
case INTEL_440BX:
regs[0x57] = val & 0x3f;
break;
@@ -499,7 +533,7 @@ i4x0_write(int func, int addr, uint8_t val, void *priv)
case INTEL_430LX: default:
regs[0x58] = val & 0x01;
break;
case INTEL_430NX:
case INTEL_430NX: case INTEL_440LX:
case INTEL_440BX: case INTEL_440ZX:
regs[0x58] = val & 0x03;
break;
@@ -513,6 +547,9 @@ i4x0_write(int func, int addr, uint8_t val, void *priv)
case INTEL_430TX:
regs[0x57] = val & 0x7b;
break;
case INTEL_440EX:
regs[0x58] = val & 0xbf;
break;
}
break;
case 0x59: /* PAM0 */
@@ -576,7 +613,8 @@ i4x0_write(int func, int addr, uint8_t val, void *priv)
case INTEL_420TX: case INTEL_420ZX:
case INTEL_430LX: case INTEL_430NX:
case INTEL_430HX:
case INTEL_440FX:
case INTEL_440FX:
case INTEL_440LX: case INTEL_440EX:
case INTEL_440BX: case INTEL_440ZX:
default:
regs[addr] = val;
@@ -596,6 +634,7 @@ i4x0_write(int func, int addr, uint8_t val, void *priv)
case INTEL_430LX: case INTEL_430NX:
case INTEL_430HX:
case INTEL_440FX:
case INTEL_440LX: case INTEL_440EX:
case INTEL_440BX: case INTEL_440ZX:
regs[addr] = val;
break;
@@ -610,7 +649,8 @@ i4x0_write(int func, int addr, uint8_t val, void *priv)
case 0x66:
switch (dev->type) {
case INTEL_430NX: case INTEL_430HX:
case INTEL_440FX:
case INTEL_440FX: case INTEL_440LX:
case INTEL_440EX:
case INTEL_440BX: case INTEL_440ZX:
regs[addr] = val;
break;
@@ -619,7 +659,8 @@ i4x0_write(int func, int addr, uint8_t val, void *priv)
case 0x67:
switch (dev->type) {
case INTEL_430NX: case INTEL_430HX:
case INTEL_440FX:
case INTEL_440FX: case INTEL_440LX:
case INTEL_440EX:
case INTEL_440BX: case INTEL_440ZX:
regs[addr] = val;
break;
@@ -640,7 +681,8 @@ i4x0_write(int func, int addr, uint8_t val, void *priv)
case INTEL_430FX: case INTEL_430FX_PB640:
regs[0x68] = val & 0x1f;
break;
case INTEL_440FX:
case INTEL_440FX: case INTEL_440LX:
case INTEL_440EX:
regs[0x68] = val & 0xc0;
break;
case INTEL_440BX:
@@ -668,6 +710,8 @@ i4x0_write(int func, int addr, uint8_t val, void *priv)
case 0x6a: case 0x6b:
switch (dev->type) {
case INTEL_430NX:
case INTEL_440LX:
case INTEL_440EX:
case INTEL_440BX:
regs[addr] = val;
break;
@@ -681,6 +725,8 @@ i4x0_write(int func, int addr, uint8_t val, void *priv)
break;
case 0x6c: case 0x6d: case 0x6e:
switch (dev->type) {
case INTEL_440LX:
case INTEL_440EX:
case INTEL_440BX:
regs[addr] = val;
break;
@@ -692,6 +738,14 @@ i4x0_write(int func, int addr, uint8_t val, void *priv)
break;
}
break;
case 0x6f:
switch (dev->type){
case INTEL_440LX:
case INTEL_440EX:
regs[addr] = val;
break;
}
break;
case 0x70:
switch (dev->type) {
case INTEL_420TX: case INTEL_420ZX:
@@ -704,7 +758,8 @@ i4x0_write(int func, int addr, uint8_t val, void *priv)
case INTEL_430VX: case INTEL_430TX:
regs[addr] = val & 0xfc;
break;
case INTEL_440FX:
case INTEL_440FX: case INTEL_440LX:
case INTEL_440EX:
regs[addr] = val & 0xf8;
break;
}
@@ -715,10 +770,10 @@ i4x0_write(int func, int addr, uint8_t val, void *priv)
case INTEL_430LX:
regs[addr] = val & 0x4d;
break;
case INTEL_430TX:
case INTEL_430TX: case INTEL_440EX:
regs[addr] = val;
break;
case INTEL_440FX:
case INTEL_440FX: case INTEL_440LX:
regs[addr] = val & 0x1f;
break;
}
@@ -853,6 +908,12 @@ i4x0_write(int func, int addr, uint8_t val, void *priv)
case INTEL_440FX:
regs[0x80] = val & 0x1b;
break;
case INTEL_440LX:
regs[0x80] = val & 0x08;
break;
case INTEL_440EX:
regs[0x80] = val & 0x18;
break;
case INTEL_440BX: case INTEL_440ZX:
regs[0x7c] = val;
break;
@@ -861,7 +922,8 @@ i4x0_write(int func, int addr, uint8_t val, void *priv)
case 0x91:
switch (dev->type) {
case INTEL_430HX: case INTEL_440BX:
case INTEL_440FX:
case INTEL_440FX: case INTEL_440LX:
case INTEL_440EX:
/* Not applicable on 82443ZX. */
regs[0x91] &= ~(val & 0x11);
break;
@@ -869,6 +931,7 @@ i4x0_write(int func, int addr, uint8_t val, void *priv)
break;
case 0x92:
switch (dev->type) {
case INTEL_440LX: case INTEL_440EX:
case INTEL_440BX: case INTEL_440ZX:
regs[0x92] &= ~(val & 0x1f);
break;
@@ -877,6 +940,8 @@ i4x0_write(int func, int addr, uint8_t val, void *priv)
case 0x93:
switch (dev->type) {
case INTEL_440FX:
case INTEL_440LX:
case INTEL_440EX:
regs[0x93] = (val & 0x0f);
trc_write(0x0093, val & 0x06, NULL);
break;
@@ -898,6 +963,9 @@ i4x0_write(int func, int addr, uint8_t val, void *priv)
break;
case 0xb1:
switch (dev->type) {
case INTEL_440EX:
regs[0xb1] = (val & 0x22);
break;
case INTEL_440BX: case INTEL_440ZX:
regs[0xb1] = (val & 0xa0);
break;
@@ -918,7 +986,31 @@ i4x0_write(int func, int addr, uint8_t val, void *priv)
break;
}
break;
case 0xba: case 0xbb:
switch (dev->type) {
case INTEL_440BX: case INTEL_440ZX:
regs[addr] = val;
break;
}
break;
case 0xbc:
switch (dev->type) {
case INTEL_440EX:
regs[addr] = (val & 0xf8);
break;
}
break;
case 0xbd:
switch (dev->type) {
case INTEL_440EX:
regs[addr] = (val & 0xf8);
break;
}
break;
case 0xd0: case 0xd1: case 0xd2: case 0xd3: case 0xd4: case 0xd5: case 0xd6: case 0xd7:
switch (dev->type) {
case INTEL_440BX: case INTEL_440ZX:
@@ -1097,7 +1189,7 @@ i4x0_reset(void *priv)
else
i4x0_write(0, 0x72, 0x00, priv);
if ((dev->type == INTEL_440BX) || (dev->type == INTEL_440ZX)) {
if ((dev->type == INTEL_440LX) || (dev->type == INTEL_440BX) || (dev->type == INTEL_440ZX)) {
for (i = 0; i <= dev->max_func; i++)
memset(dev->regs_locked[i], 0x00, 256 * sizeof(uint8_t));
}
@@ -1268,6 +1360,50 @@ static void
regs[0x71] = 0x10;
regs[0x72] = 0x02;
break;
case INTEL_440LX:
dev->max_func = 1;
regs[0x02] = 0x80; regs[0x03] = 0x71; /* 82443LX */
regs[0x06] = 0x90;
regs[0x10] = 0x08;
regs[0x34] = 0xa0;
if (cpu_busspeed <= 66666667)
regs[0x51] |= 0x00;
else if ((cpu_busspeed > 66666667) && (cpu_busspeed <= 100000000))
regs[0x51] |= 0x20;
regs[0x53] = 0x83;
regs[0x57] = 0x28;
regs[0x60] = regs[0x61] = regs[0x62] = regs[0x63] = regs[0x64] = regs[0x65] = regs[0x66] = regs[0x67] = 0x01;
regs[0x6c] = regs[0x6d] = regs[0x6e] = regs[0x6f] = 0x55;
regs[0x72] = 0x02;
regs[0xa0] = 0x02;
regs[0xa2] = 0x10;
regs[0xa4] = 0x03;
regs[0xa5] = 0x02;
regs[0xa7] = 0x1f;
break;
case INTEL_440EX:
dev->max_func = 1;
regs[0x02] = 0x80; regs[0x03] = 0x71; /* 82443EX. Same Vendor ID as 440LX*/
regs[0x06] = 0x90;
regs[0x10] = 0x08;
regs[0x34] = 0xa0;
if (cpu_busspeed <= 66666667)
regs[0x51] |= 0x00;
else if ((cpu_busspeed > 66666667) && (cpu_busspeed <= 100000000))
regs[0x51] |= 0x20;
regs[0x53] = 0x83;
regs[0x57] = 0x28;
regs[0x60] = regs[0x61] = regs[0x62] = regs[0x63] = regs[0x64] = regs[0x65] = regs[0x66] = regs[0x67] = 0x01;
regs[0x6c] = regs[0x6d] = regs[0x6e] = regs[0x6f] = 0x55;
regs[0x72] = 0x02;
regs[0xa0] = 0x02;
regs[0xa2] = 0x10;
regs[0xa4] = 0x03;
regs[0xa5] = 0x02;
regs[0xa7] = 0x1f;
break;
case INTEL_440BX: case INTEL_440ZX:
regs[0x7a] = (info->local >> 8) & 0xff;
dev->max_func = (regs[0x7a] & 0x02) ? 0 : 1;
@@ -1313,6 +1449,20 @@ static void
i4x0_write(regs[0x5f], 0x5f, 0x00, dev);
i4x0_write(regs[0x72], 0x72, 0x00, dev);
if (((dev->type == INTEL_440LX) || (dev->type == INTEL_440EX)) && (dev->max_func == 1)) {
regs = (uint8_t *) dev->regs[1];
regs[0x00] = 0x86; regs[0x01] = 0x80; /* Intel */
regs[0x02] = 0x81; regs[0x03] = 0x71; /* 82443LX */
regs[0x06] = 0xa0; regs[0x07] = 0x02;
regs[0x0a] = 0x04; regs[0x0b] = 0x06;
regs[0x0e] = 0x01;
regs[0x1c] = 0xf0;
regs[0x1e] = 0xa0; regs[0x1f] = 0x02;
regs[0x20] = 0xf0; regs[0x21] = 0xff;
regs[0x24] = 0xf0; regs[0x25] = 0xff;
}
if (((dev->type == INTEL_440BX) || (dev->type == INTEL_440ZX)) && (dev->max_func == 1)) {
regs = (uint8_t *) dev->regs[1];
@@ -1484,6 +1634,34 @@ const device_t i440fx_device =
NULL
};
const device_t i440lx_device =
{
"Intel 82443LX",
DEVICE_PCI,
INTEL_440LX,
i4x0_init,
i4x0_close,
i4x0_reset,
NULL,
NULL,
NULL,
NULL
};
const device_t i440ex_device =
{
"Intel 82443EX",
DEVICE_PCI,
INTEL_440EX,
i4x0_init,
i4x0_close,
i4x0_reset,
NULL,
NULL,
NULL,
NULL
};
const device_t i440bx_device =
{

125
src/chipset/opti5x7.c Normal file
View File

@@ -0,0 +1,125 @@
/*Based off the OPTI 82C546/82C547 datasheet.
The earlier 596/597 appears to be register compatible with the 546/547 from testing.*/
#include <stdarg.h>
#include <stdint.h>
#include <stdio.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>
#include <86box/io.h>
#include <86box/device.h>
#include <86box/keyboard.h>
#include <86box/mem.h>
#include <86box/fdd.h>
#include <86box/fdc.h>
#include <86box/port_92.h>
#include <86box/chipset.h>
typedef struct
{
uint8_t cur_reg,
regs[64];
port_92_t *port_92;
} opti5x7_t;
static void
opti5x7_recalcmapping(opti5x7_t *dev)
{
uint32_t shflags = 0;
shadowbios = 0;
shadowbios_write = 0;
shadowbios |= !!(dev->regs[0x06] & 0x05);
shadowbios_write |= !!(dev->regs[0x06] & 0x0a);
shflags = (dev->regs[0x06] & 0x01) ? MEM_READ_INTERNAL : MEM_READ_EXTANY;
shflags |= (dev->regs[0x06] & 0x02) ? MEM_WRITE_INTERNAL : MEM_WRITE_EXTANY;
mem_set_mem_state(0xe0000, 0x10000, shflags);
shflags = (dev->regs[0x06] & 0x04) ? MEM_READ_INTERNAL : MEM_READ_EXTANY;
shflags |= (dev->regs[0x06] & 0x08) ? MEM_WRITE_INTERNAL : MEM_WRITE_EXTANY;
mem_set_mem_state(0xf0000, 0x10000, shflags);
flushmmucache();
}
static void
opti5x7_write(uint16_t addr, uint8_t val, void *priv)
{
opti5x7_t *dev = (opti5x7_t *) priv;
// pclog("Write %02x to OPTi 5x7 address %02x\n", val, addr);
switch (addr) {
case 0x22:
dev->cur_reg = val;
break;
case 0x24:
dev->regs[dev->cur_reg] = val;
if (dev->cur_reg == 0x02) {
cpu_cache_ext_enabled = val & 0x10;
}
if (dev->cur_reg == 0x06) {
opti5x7_recalcmapping(dev);
}
break;
}
}
static uint8_t
opti5x7_read(uint16_t addr, void *priv)
{
uint8_t ret = 0xff;
opti5x7_t *dev = (opti5x7_t *) priv;
switch (addr) {
case 0x24:
// pclog("Read from OPTI 5x7 register %02x\n", dev->cur_reg);
ret = dev->regs[dev->cur_reg];
break;
}
return ret;
}
static void
opti5x7_close(void *priv)
{
opti5x7_t *dev = (opti5x7_t *) priv;
free(dev);
}
static void *
opti5x7_init(const device_t *info)
{
opti5x7_t *dev = (opti5x7_t *) malloc(sizeof(opti5x7_t));
memset(dev, 0, sizeof(opti5x7_t));
io_sethandler(0x0022, 0x0001, opti5x7_read, NULL, NULL, opti5x7_write, NULL, NULL, dev);
io_sethandler(0x0024, 0x0001, opti5x7_read, NULL, NULL, opti5x7_write, NULL, NULL, dev);
dev->port_92 = device_add(&port_92_device);
// pclog("OPTi 5x7 init\n");
opti5x7_recalcmapping(dev);
return dev;
}
const device_t opti5x7_device = {
"OPTi 82C5x6/82C5x7",
0,
0,
opti5x7_init, opti5x7_close, NULL,
NULL, NULL, NULL,
NULL
};

150
src/chipset/rabbit.c Normal file
View File

@@ -0,0 +1,150 @@
#include <stdarg.h>
#include <stdint.h>
#include <stdio.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>
#include <86box/io.h>
#include <86box/device.h>
#include <86box/keyboard.h>
#include <86box/mem.h>
#include <86box/fdd.h>
#include <86box/fdc.h>
#include <86box/chipset.h>
typedef struct
{
uint8_t cur_reg, tries,
regs[258];
} rabbit_t;
static void
rabbit_recalcmapping(rabbit_t *dev)
{
uint32_t shread, shwrite;
uint32_t shflags = 0;
shread = !!(dev->regs[0x101] & 0x40);
shwrite = !!(dev->regs[0x100] & 0x02);
shflags = shread ? MEM_READ_INTERNAL : MEM_READ_EXTANY;
shflags |= shwrite ? MEM_WRITE_INTERNAL : MEM_WRITE_EXTANY;
shadowbios = !!shread;
shadowbios_write = !!shwrite;
#ifdef USE_SHADOW_C0000
mem_set_mem_state(0x000c0000, 0x00040000, MEM_READ_EXTANY | MEM_WRITE_EXTANY);
#else
mem_set_mem_state(0x000e0000, 0x00020000, MEM_READ_EXTANY | MEM_WRITE_EXTANY);
#endif
switch (dev->regs[0x100] & 0x09) {
case 0x01:
/* The one BIOS we use seems to use something else to control C0000-DFFFF shadow,
no idea what. */
#ifdef USE_SHADOW_C0000
/* 64K at 0C0000-0CFFFF */
mem_set_mem_state(0x000c0000, 0x00010000, shflags);
/* FALLTHROUGH */
#endif
case 0x00:
/* 64K at 0F0000-0FFFFF */
mem_set_mem_state(0x000f0000, 0x00010000, shflags);
break;
case 0x09:
#ifdef USE_SHADOW_C0000
/* 128K at 0C0000-0DFFFF */
mem_set_mem_state(0x000c0000, 0x00020000, shflags);
/* FALLTHROUGH */
#endif
case 0x08:
/* 128K at 0E0000-0FFFFF */
mem_set_mem_state(0x000e0000, 0x00020000, shflags);
break;
}
flushmmucache();
}
static void
rabbit_write(uint16_t addr, uint8_t val, void *priv)
{
rabbit_t *dev = (rabbit_t *) priv;
switch (addr) {
case 0x22:
dev->cur_reg = val;
dev->tries = 0;
break;
case 0x23:
if (dev->cur_reg == 0x83) {
if (dev->tries < 0x02) {
dev->regs[dev->tries++ | 0x100] = val;
if (dev->tries == 0x02)
rabbit_recalcmapping(dev);
}
} else
dev->regs[dev->cur_reg] = val;
break;
}
}
static uint8_t
rabbit_read(uint16_t addr, void *priv)
{
uint8_t ret = 0xff;
rabbit_t *dev = (rabbit_t *) priv;
switch (addr) {
case 0x23:
if (dev->cur_reg == 0x83) {
if (dev->tries < 0x02)
ret = dev->regs[dev->tries++ | 0x100];
} else
ret = dev->regs[dev->cur_reg];
break;
}
return ret;
}
static void
rabbit_close(void *priv)
{
rabbit_t *dev = (rabbit_t *) priv;
free(dev);
}
static void *
rabbit_init(const device_t *info)
{
rabbit_t *dev = (rabbit_t *) malloc(sizeof(rabbit_t));
memset(dev, 0, sizeof(rabbit_t));
io_sethandler(0x0022, 0x0002, rabbit_read, NULL, NULL, rabbit_write, NULL, NULL, dev);
return dev;
}
const device_t rabbit_device = {
"SiS Rabbit",
0,
0,
rabbit_init, rabbit_close, NULL,
NULL, NULL, NULL,
NULL
};

View File

@@ -141,7 +141,7 @@ CPU *cpu_s;
int cpu_effective;
int cpu_multi;
double cpu_dmulti;
int cpu_16bitbus;
int cpu_16bitbus, cpu_64bitbus;
int cpu_busspeed;
int cpu_cyrix_alignment;
int CPUID;
@@ -309,7 +309,7 @@ cpu_set(void)
isdx4 = (cpu_s->cpu_type >= CPU_iDX4) && (cpu_s->cpu_type < CPU_WINCHIP);
is_am486 = (cpu_s->cpu_type == CPU_Am486SX) || (cpu_s->cpu_type == CPU_Am486SX2) || (cpu_s->cpu_type == CPU_Am486DX) ||
(cpu_s->cpu_type == CPU_Am486DX2) || (cpu_s->cpu_type == CPU_Am486DX4) || (cpu_s->cpu_type == CPU_Am5x86);
is_pentium = (cpu_s->cpu_type == CPU_PENTIUM) || (cpu_s->cpu_type == CPU_PENTIUMMMX);
is_pentium = (cpu_s->cpu_type == CPU_P24T) || (cpu_s->cpu_type == CPU_PENTIUM) || (cpu_s->cpu_type == CPU_PENTIUMMMX);
/* Not Pentiums, but they share the same SMM save state table layout. */
is_pentium |= (cpu_s->cpu_type == CPU_i486DX2) || (cpu_s->cpu_type == CPU_iDX4);
/* The WinChip datasheet claims these are Pentium-compatible. */
@@ -335,7 +335,8 @@ cpu_set(void)
#endif
cpu_16bitbus = (cpu_s->cpu_type == CPU_286 || cpu_s->cpu_type == CPU_386SX || cpu_s->cpu_type == CPU_486SLC || cpu_s->cpu_type == CPU_IBM386SLC || cpu_s->cpu_type == CPU_IBM486SLC );
cpu_64bitbus = (cpu_s->cpu_type >= CPU_WINCHIP);
if (cpu_s->multi)
cpu_busspeed = cpu_s->rspeed / cpu_s->multi;
else
@@ -995,6 +996,7 @@ cpu_set(void)
#endif
break;
case CPU_P24T:
case CPU_PENTIUM:
#ifdef USE_DYNAREC
x86_setopcodes(ops_386, ops_pentium_0f, dynarec_ops_386, dynarec_ops_pentium_0f);
@@ -1787,7 +1789,8 @@ cpu_CPUID(void)
break;
}
break;
case CPU_P24T:
case CPU_PENTIUM:
if (!EAX)
{
@@ -2697,6 +2700,7 @@ void cpu_RDMSR()
}
break;
case CPU_P24T:
case CPU_PENTIUM:
case CPU_PENTIUMMMX:
EAX = EDX = 0;
@@ -3175,7 +3179,8 @@ void cpu_WRMSR()
break;
}
break;
case CPU_P24T:
case CPU_PENTIUM:
case CPU_PENTIUMMMX:
switch (ECX)

View File

@@ -52,6 +52,7 @@ enum {
CPU_Cx486DX4,
CPU_Am5x86,
CPU_Cx5x86,
CPU_P24T,
CPU_WINCHIP, /* 586 class CPUs */
CPU_WINCHIP2,
CPU_PENTIUM,
@@ -370,7 +371,7 @@ COMPILE_TIME_ASSERT(sizeof(cpu_state) <= 128)
/* Global variables. */
extern int cpu_iscyrix;
extern int cpu_16bitbus;
extern int cpu_16bitbus, cpu_64bitbus;
extern int cpu_busspeed, cpu_pci_speed;
extern int cpu_multi;
extern double cpu_dmulti;
@@ -379,8 +380,8 @@ extern int cpu_cyrix_alignment; /*Cyrix 5x86/6x86 only has data misalignment
extern int is8086, is286, is386, is486, is486sx, is486dx, is486sx2, is486dx2, isdx4;
extern int is_am486, is_pentium, is_k5, is_k6, is_p6;
extern int hascache;
extern int isibm486;
extern int hascache;
extern int isibm486;
extern int is_rapidcad;
extern int hasfpu;
#define CPU_FEATURE_RDTSC (1 << 0)

View File

@@ -288,8 +288,8 @@ CPU cpus_i486[] = {
{"iDX4/100", CPU_iDX4, 100000000, 3.0, 0x483, 0x483, 0x0000, CPU_SUPPORTS_DYNAREC, 18,18, 9, 9, 12}, /*Is on some real Intel DX2s, limit here is pretty arbitary*/
{"iDX4 OverDrive 75", CPU_iDX4, 75000000, 3.0, 0x1480, 0x1480, 0x0000, CPU_SUPPORTS_DYNAREC, 12,12, 9, 9, 9},
{"iDX4 OverDrive 100", CPU_iDX4, 100000000, 3.0, 0x1480, 0x1480, 0x0000, CPU_SUPPORTS_DYNAREC, 18,18, 9, 9, 12},
{"Pentium OverDrive 63", CPU_PENTIUM, 62500000, 2.5, 0x1531, 0x1531, 0x0000, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 10,10,7,7, 15/2},
{"Pentium OverDrive 83", CPU_PENTIUM, 83333333, 2.5, 0x1532, 0x1532, 0x0000, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 15,15,8,8, 10},
{"Pentium OverDrive 63", CPU_P24T, 62500000, 2.5, 0x1531, 0x1531, 0x0000, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 10,10,7,7, 15/2},
{"Pentium OverDrive 83", CPU_P24T, 83333333, 2.5, 0x1532, 0x1532, 0x0000, CPU_SUPPORTS_DYNAREC | CPU_REQUIRES_DYNAREC, 15,15,8,8, 10},
{"", -1, 0, 0, 0, 0, 0x0000, 0, 0, 0, 0, 0, 0}
};

View File

@@ -42,11 +42,14 @@ extern const device_t i430hx_device;
extern const device_t i430vx_device;
extern const device_t i430tx_device;
extern const device_t i440fx_device;
extern const device_t i440lx_device;
extern const device_t i440ex_device;
extern const device_t i440bx_device;
extern const device_t i440zx_device;
/* OPTi */
extern const device_t opti495_device;
extern const device_t opti5x7_device;
/* C&T */
extern const device_t neat_device;
@@ -56,6 +59,7 @@ extern const device_t scat_sx_device;
extern const device_t cs8230_device;
/* SiS */
extern const device_t rabbit_device;
extern const device_t sis_85c471_device;
extern const device_t sis_85c496_device;
#if defined(DEV_BRANCH) && defined(USE_SIS_85C50X)

View File

@@ -214,6 +214,7 @@ extern const device_t *at_commodore_sl386sx_get_device(void);
/* m_at_386dx_486.c */
extern int machine_at_acc386_init(const machine_t *);
extern int machine_at_asus386_init(const machine_t *);
extern int machine_at_ecs386_init(const machine_t *);
extern int machine_at_micronics386_init(const machine_t *);
@@ -253,6 +254,8 @@ extern const device_t *at_cpqiii_get_device(void);
#endif
/* m_at_socket4_5.c */
extern int machine_at_excalibur_init(const machine_t *);
extern int machine_at_batman_init(const machine_t *);
extern int machine_at_ambradp60_init(const machine_t *);
#if defined(DEV_BRANCH) && defined(USE_VPP60)
@@ -310,9 +313,6 @@ extern int machine_at_p5mms98_init(const machine_t *);
extern int machine_at_ficva502_init(const machine_t *);
extern int machine_at_ficpa2012_init(const machine_t *);
#if defined(DEV_BRANCH) && defined(NO_SIO)
extern int machine_at_advanceii_init(const machine_t *);
#endif
#ifdef EMU_DEVICE_H
extern const device_t *at_pb640_get_device(void);
@@ -336,6 +336,8 @@ extern int machine_at_p65up5_cp6nd_init(const machine_t *);
extern int machine_at_p65up5_cpknd_init(const machine_t *);
extern int machine_at_kn97_init(const machine_t *);
extern int machine_at_p6i440e2_init(const machine_t *);
extern int machine_at_p2bls_init(const machine_t *);
extern int machine_at_p3bf_init(const machine_t *);
extern int machine_at_bf6_init(const machine_t *);
@@ -357,9 +359,8 @@ extern int machine_at_s2dge_init(const machine_t *);
#endif
/* m_at_socket370.c */
#if defined(DEV_BRANCH) && defined(NO_SIO)
extern int machine_at_s370slm_init(const machine_t *);
#endif
extern int machine_at_cubx_init(const machine_t *);
extern int machine_at_atc7020bxii_init(const machine_t *);
extern int machine_at_63a_init(const machine_t *);

View File

@@ -63,6 +63,25 @@ machine_at_acc386_init(const machine_t *model)
return ret;
}
int
machine_at_asus386_init(const machine_t *model)
{
int ret;
ret = bios_load_linear(L"roms/machines/asus386/ASUS_ISA-386C_BIOS.bin",
0x000f0000, 65536, 0);
if (bios_only || !ret)
return ret;
machine_at_common_init(model);
device_add(&rabbit_device);
device_add(&keyboard_at_ami_device);
device_add(&fdc_at_device);
return ret;
}
int
machine_at_ecs386_init(const machine_t *model)
{

View File

@@ -108,6 +108,59 @@ machine_at_kn97_init(const machine_t *model)
return ret;
}
int
machine_at_p6i440e2_init(const machine_t *model)
{
int ret;
ret = bios_load_linear(L"roms/machines/p6i440e2/E2_v14sl.bin",
0x000e0000, 131072, 0);
if (bios_only || !ret)
return ret;
machine_at_common_init_ex(model, 2);
pci_init(PCI_CONFIG_TYPE_1);
pci_register_slot(0x00, PCI_CARD_NORTHBRIDGE, 0, 0, 0, 0);
pci_register_slot(0x07, PCI_CARD_SOUTHBRIDGE, 0, 0, 0, 0);
pci_register_slot(0x09, PCI_CARD_NORMAL, 1, 2, 3, 4);
pci_register_slot(0x0A, PCI_CARD_NORMAL, 2, 3, 4, 1);
pci_register_slot(0x01, PCI_CARD_NORMAL, 1, 2, 3, 4);
device_add(&i440ex_device);
device_add(&piix4_device);
device_add(&keyboard_ps2_pci_device);
device_add(&w83977tf_device);
device_add(&sst_flash_29ee010_device);
spd_register(SPD_TYPE_SDRAM, 0x03, 256);
hwm_values_t machine_hwm = {
{ /* fan speeds */
3000, /* Chassis */
3000, /* CPU */
3000 /* Power */
}, { /* temperatures */
30, /* MB */
0, /* unused */
27 /* CPU */
}, { /* voltages */
2050, /* VCORE (2.05V by default) */
0, /* unused */
3300, /* +3.3V */
RESISTOR_DIVIDER(5000, 11, 16), /* +5V (divider values bruteforced) */
RESISTOR_DIVIDER(12000, 28, 10), /* +12V (28K/10K divider suggested in the W83781D datasheet) */
RESISTOR_DIVIDER(12000, 853, 347), /* -12V (divider values bruteforced) */
RESISTOR_DIVIDER(5000, 1, 2) /* -5V (divider values bruteforced) */
}
};
if (model->cpu[cpu_manufacturer].cpus[cpu_effective].cpu_type == CPU_PENTIUM2)
machine_hwm.voltages[0] = 2800; /* set higher VCORE (2.8V) for Klamath */
hwm_set_values(machine_hwm);
device_add(&w83781d_device);
return ret;
}
int
machine_at_p2bls_init(const machine_t *model)
{

View File

@@ -41,7 +41,6 @@
#include "cpu.h"
#include <86box/machine.h>
#if defined(DEV_BRANCH) && defined(NO_SIO)
int
machine_at_s370slm_init(const machine_t *model)
{
@@ -65,7 +64,7 @@ machine_at_s370slm_init(const machine_t *model)
pci_register_slot(0x0E, PCI_CARD_NORMAL, 1, 2, 3, 4);
pci_register_slot(0x01, PCI_CARD_NORMAL, 1, 2, 3, 4);
pci_register_slot(0x0D, PCI_CARD_NORMAL, 1, 2, 3, 4);
device_add(&i440bx_device); /*i440LX*/
device_add(&i440lx_device);
device_add(&piix4e_device);
device_add(&w83977tf_device);
device_add(&keyboard_ps2_ami_pci_device);
@@ -96,7 +95,6 @@ machine_at_s370slm_init(const machine_t *model)
return ret;
}
#endif
int
machine_at_cubx_init(const machine_t *model)

View File

@@ -41,6 +41,26 @@
#include <86box/sio.h>
#include <86box/video.h>
#include <86box/machine.h>
int
machine_at_excalibur_init(const machine_t *model)
{
int ret;
ret = bios_load_linear_inverted(L"roms/machines/excalibur/S75P.ROM",
0x000e0000, 131072, 0);
if (bios_only || !ret)
return ret;
machine_at_common_init(model);
device_add(&ide_vlb_device);
device_add(&opti5x7_device);
device_add(&fdc37c663_device);
device_add(&keyboard_at_ami_device);
return ret;
}
static void

View File

@@ -968,33 +968,3 @@ machine_at_ficpa2012_init(const machine_t *model)
return ret;
}
#if defined(DEV_BRANCH) && defined(NO_SIO)
int
machine_at_advanceii_init(const machine_t *model)
{
int ret;
ret = bios_load_linear(L"roms/machines/advanceii/VP3_V27.BIN",
0x000e0000, 131072, 0);
if (bios_only || !ret)
return ret;
machine_at_common_init_ex(model, 2);
pci_init(PCI_CONFIG_TYPE_1);
pci_register_slot(0x00, PCI_CARD_NORTHBRIDGE, 0, 0, 0, 0);
pci_register_slot(0x08, PCI_CARD_NORMAL, 1, 2, 3, 4);
pci_register_slot(0x09, PCI_CARD_NORMAL, 2, 3, 4, 1);
pci_register_slot(0x0A, PCI_CARD_NORMAL, 3, 4, 1, 2);
pci_register_slot(0x07, PCI_CARD_SOUTHBRIDGE, 1, 2, 3, 4);
device_add(&via_vp3_device);
device_add(&via_vt82c586b_device);
device_add(&keyboard_ps2_pci_device);
device_add(&um8669f_device); //IT8661F
device_add(&sst_flash_39sf010_device);
return ret;
}
#endif

View File

@@ -108,9 +108,9 @@ const machine_t machines[] = {
/* 286 AT machines */
{ "[286 ISA] AMI 286 clone", "ami286", {{"", cpus_286}, {"", NULL}, {"", NULL}, {"", NULL}, {"", NULL}}, MACHINE_ISA | MACHINE_AT, 512, 8192, 128, 127, machine_at_neat_ami_init, NULL },
{ "[286 ISA] Award 286 clone", "award286", {{"", cpus_286}, {"", NULL}, {"", NULL}, {"", NULL}, {"", NULL}}, MACHINE_ISA | MACHINE_AT, 512,16384, 128, 127, machine_at_award286_init, NULL },
{ "[286 ISA] Phoenix 286 clone", "px286", {{"", cpus_286}, {"", NULL}, {"", NULL}, {"", NULL}, {"", NULL}}, MACHINE_ISA | MACHINE_AT, 512,16384, 128, 127, machine_at_px286_init, NULL },
{ "[286 ISA] Phoenix 286 clone", "px286", {{"", cpus_286}, {"", NULL}, {"", NULL}, {"", NULL}, {"", NULL}}, MACHINE_ISA | MACHINE_AT, 512,16384, 128, 127, machine_at_px286_init, NULL },
{ "[286 ISA] Quadtel 286 clone", "quadt286", {{"", cpus_286}, {"", NULL}, {"", NULL}, {"", NULL}, {"", NULL}}, MACHINE_ISA | MACHINE_AT, 512,16384, 128, 127, machine_at_quadt286_init, NULL },
{ "[286 ISA] MR 286 clone", "mr286", {{"", cpus_286}, {"", NULL}, {"", NULL}, {"", NULL}, {"", NULL}}, MACHINE_ISA | MACHINE_AT, 512,16384, 128, 127, machine_at_mr286_init, NULL },
{ "[286 ISA] MR 286 clone", "mr286", {{"", cpus_286}, {"", NULL}, {"", NULL}, {"", NULL}, {"", NULL}}, MACHINE_ISA | MACHINE_AT, 512, 16384, 128, 127, machine_at_mr286_init, NULL },
{ "[286 ISA] Commodore PC 30 III", "cmdpc30", {{"", cpus_286}, {"", NULL}, {"", NULL}, {"", NULL}, {"", NULL}}, MACHINE_ISA | MACHINE_AT, 640,16384, 128, 127, machine_at_cmdpc_init, NULL },
{ "[286 ISA] Compaq Portable II", "portableii", {{"", cpus_286}, {"", NULL}, {"", NULL}, {"", NULL}, {"", NULL}}, MACHINE_ISA | MACHINE_AT, 640,16384, 128, 127, machine_at_portableii_init, NULL },
{ "[286 ISA] Compaq Portable III", "portableiii", {{"", cpus_286}, {"", NULL}, {"", NULL}, {"", NULL}, {"", NULL}}, MACHINE_ISA | MACHINE_AT | MACHINE_VIDEO, 640,16384, 128, 127, machine_at_portableiii_init, at_cpqiii_get_device },
@@ -146,7 +146,7 @@ const machine_t machines[] = {
{ "[386SX ISA] AMI Unknown 386SX", "ami386", {{"Intel", cpus_i386SX}, {"AMD", cpus_Am386SX}, {"Cyrix", cpus_486SLC}, {"", NULL}, {"", NULL}}, MACHINE_ISA | MACHINE_AT | MACHINE_HDC, 512,16384, 128, 127, machine_at_headland_init, NULL },
#endif
{ "[386SX ISA] Amstrad MegaPC", "megapc", {{"Intel", cpus_i386SX}, {"AMD", cpus_Am386SX}, {"Cyrix", cpus_486SLC}, {"", NULL}, {"", NULL}}, MACHINE_ISA | MACHINE_AT | MACHINE_PS2 | MACHINE_VIDEO | MACHINE_HDC, 1, 32, 1, 127, machine_at_wd76c10_init, NULL },
{ "[386SX ISA] Commodore SL386SX", "cbm_sl386sx25", {{"Intel", cpus_i386SX}, {"AMD", cpus_Am386SX}, {"Cyrix", cpus_486SLC}, {"", NULL}, {"", NULL}}, MACHINE_ISA | MACHINE_AT | MACHINE_PS2 | MACHINE_VIDEO | MACHINE_HDC, 1024,8192, 512, 127,machine_at_commodore_sl386sx_init, at_commodore_sl386sx_get_device },
{ "[386SX ISA] Commodore SL386SX", "cbm_sl386sx25", {{"Intel", cpus_i386SX}, {"AMD", cpus_Am386SX}, {"Cyrix", cpus_486SLC}, {"", NULL}, {"", NULL}}, MACHINE_ISA | MACHINE_AT | MACHINE_PS2 | MACHINE_VIDEO | MACHINE_HDC, 1024, 8192, 512, 127, machine_at_commodore_sl386sx_init, at_commodore_sl386sx_get_device },
{ "[386SX ISA] DTK 386SX clone", "dtk386", {{"Intel", cpus_i386SX}, {"AMD", cpus_Am386SX}, {"Cyrix", cpus_486SLC}, {"", NULL}, {"", NULL}}, MACHINE_ISA | MACHINE_AT | MACHINE_HDC, 512, 8192, 128, 127, machine_at_neat_init, NULL },
{ "[386SX ISA] IBM PS/1 model 2121", "ibmps1_2121", {{"Intel", cpus_i386SX}, {"AMD", cpus_Am386SX}, {"Cyrix", cpus_486SLC}, {"", NULL}, {"", NULL}}, MACHINE_ISA | MACHINE_AT | MACHINE_PS2 | MACHINE_HDC | MACHINE_VIDEO | MACHINE_VIDEO_FIXED, 2, 6, 1, 63, machine_ps1_m2121_init, NULL },
{ "[386SX ISA] IBM PS/1 m.2121+ISA", "ibmps1_2121_isa", {{"Intel", cpus_i386SX}, {"AMD", cpus_Am386SX}, {"Cyrix", cpus_486SLC}, {"", NULL}, {"", NULL}}, MACHINE_ISA | MACHINE_AT | MACHINE_PS2 | MACHINE_HDC | MACHINE_VIDEO, 2, 6, 1, 63, machine_ps1_m2121_init, NULL },
@@ -159,8 +159,9 @@ const machine_t machines[] = {
/* 386DX machines */
{ "[386DX ISA] Compaq Portable III (386)", "portableiii386", {{"Intel", cpus_i386DX}, {"AMD", cpus_Am386DX}, {"Cyrix", cpus_486DLC}, {"", NULL}, {"", NULL}}, MACHINE_ISA | MACHINE_AT | MACHINE_HDC | MACHINE_VIDEO, 1, 14, 1, 127, machine_at_portableiii386_init, at_cpqiii_get_device },
{ "[386DX ISA] AMI 386DX clone", "acc386", {{"Intel", cpus_i386DX}, {"AMD", cpus_Am386DX}, {"Cyrix", cpus_486DLC}, {"", NULL}, {"", NULL}}, MACHINE_ISA | MACHINE_AT | MACHINE_HDC, 512,16384, 128, 127, machine_at_acc386_init, NULL },
{ "[386DX ISA] ECS 386/32", "ecs386", {{"Intel", cpus_i386DX}, {"AMD", cpus_Am386DX}, {"Cyrix", cpus_486DLC}, {"", NULL}, {"", NULL}}, MACHINE_ISA | MACHINE_AT, 1, 32, 1, 127, machine_at_ecs386_init, NULL },
{ "[386DX ISA] AMI 386DX clone", "acc386", {{"Intel", cpus_i386DX}, {"AMD", cpus_Am386DX}, {"Cyrix", cpus_486DLC}, {"", NULL}, {"", NULL}}, MACHINE_ISA | MACHINE_AT | MACHINE_HDC, 512, 16384, 128, 127, machine_at_acc386_init, NULL },
{ "[386DX ISA] ASUS 386DX ISA", "asus386", {{"Intel", cpus_i386DX}, {"AMD", cpus_Am386DX}, {"Cyrix", cpus_486DLC}, {"", NULL}, {"", NULL}}, MACHINE_ISA | MACHINE_AT | MACHINE_HDC, 512, 16384, 128, 127, machine_at_asus386_init, NULL },
{ "[386DX ISA] ECS 386/32", "ecs386", {{"Intel", cpus_i386DX}, {"AMD", cpus_Am386DX}, {"Cyrix", cpus_486DLC}, {"", NULL}, {"", NULL}}, MACHINE_ISA | MACHINE_AT, 1, 32, 1, 127, machine_at_ecs386_init, NULL },
{ "[386DX ISA] Micronics 386 clone", "micronics386", {{"Intel", cpus_i386DX}, {"AMD", cpus_Am386DX}, {"Cyrix", cpus_486DLC}, {"", NULL}, {"", NULL}}, MACHINE_ISA | MACHINE_AT | MACHINE_HDC, 512, 8192, 128, 127, machine_at_micronics386_init, NULL },
/* 386DX machines which utilize the VLB bus */
@@ -206,6 +207,9 @@ const machine_t machines[] = {
{ "[486 PCI] Zida Tomato 4DP", "4dps", {{"Intel", cpus_i486}, {"AMD", cpus_Am486}, {"Cyrix", cpus_Cx486}, {"", NULL}, {"", NULL}}, MACHINE_PCI | MACHINE_ISA | MACHINE_AT | MACHINE_HDC, 1, 255, 1, 127, machine_at_4dps_init, NULL },
/* Socket 4 machines */
/* OPTi 596/597 */
{ "[Socket 4 OPTi] AMI Excalibur VLB", "excalibur", {{"Intel", cpus_Pentium5V}, {"", NULL}, {"", NULL}, {"", NULL}, {"", NULL}}, MACHINE_ISA | MACHINE_VLB | MACHINE_AT | MACHINE_HDC, 1, 64, 1, 127, machine_at_excalibur_init, NULL },
/* 430LX */
{ "[Socket 4 LX] IBM Ambra DP60 PCI", "ambradp60", {{"Intel", cpus_Pentium5V}, {"", NULL}, {"", NULL}, {"", NULL}, {"", NULL}}, MACHINE_PCI | MACHINE_ISA | MACHINE_AT | MACHINE_PS2 | MACHINE_HDC, 2, 128, 2, 127, machine_at_ambradp60_init, NULL },
#if defined(DEV_BRANCH) && defined(USE_VPP60)
@@ -230,8 +234,8 @@ const machine_t machines[] = {
/* Socket 7 machines */
/* 430FX */
{ "[Socket 7-3V FX] ASUS P/I-P54TP4XE", "p54tp4xe", MACHINE_CPUS_PENTIUM_S73V, MACHINE_PCI | MACHINE_ISA | MACHINE_AT | MACHINE_PS2 | MACHINE_HDC, 8, 128, 8, 127, machine_at_p54tp4xe_init, NULL },
{ "[Socket 7-3V FX] QDI Chariot", "chariot", MACHINE_CPUS_PENTIUM_S73VCH, MACHINE_PCI | MACHINE_ISA | MACHINE_AT | MACHINE_HDC, 8, 128, 8, 127, machine_at_chariot_init, NULL },
{ "[Socket 7-3V FX] MR 430FX clone", "mr586", MACHINE_CPUS_PENTIUM_S73V, MACHINE_PCI | MACHINE_ISA | MACHINE_AT | MACHINE_HDC | MACHINE_PS2, 8, 128, 8, 127, machine_at_mr586_init, NULL },
{ "[Socket 7-3V FX] QDI Chariot", "chariot", MACHINE_CPUS_PENTIUM_S73VCH, MACHINE_PCI | MACHINE_ISA | MACHINE_AT | MACHINE_HDC, 8, 128, 8, 127, machine_at_chariot_init, NULL },
{ "[Socket 7-3V FX] MR 430FX clone", "mr586", MACHINE_CPUS_PENTIUM_S73V, MACHINE_PCI | MACHINE_ISA | MACHINE_AT | MACHINE_HDC | MACHINE_PS2, 8, 128, 8, 127, machine_at_mr586_init, NULL },
{ "[Socket 7-3V FX] Intel Advanced/ATX", "thor", MACHINE_CPUS_PENTIUM_S73V, MACHINE_PCI | MACHINE_ISA | MACHINE_AT | MACHINE_PS2 | MACHINE_HDC, 8, 128, 8, 127, machine_at_thor_init, NULL },
{ "[Socket 7-3V FX] Intel Advanced/EV", "endeavor", MACHINE_CPUS_PENTIUM_S73V, MACHINE_PCI | MACHINE_ISA | MACHINE_AT | MACHINE_PS2 | MACHINE_HDC | MACHINE_VIDEO, 8, 128, 8, 127, machine_at_endeavor_init, at_endeavor_get_device },
{ "[Socket 7-3V FX] MR Intel Advanced/ATX", "mrthor", MACHINE_CPUS_PENTIUM_S73V, MACHINE_PCI | MACHINE_ISA | MACHINE_AT | MACHINE_PS2 | MACHINE_HDC, 8, 128, 8, 127, machine_at_mrthor_init, NULL },
@@ -254,7 +258,7 @@ const machine_t machines[] = {
{ "[Socket 7 VX] Shuttle HOT-557", "430vx", MACHINE_CPUS_PENTIUM_S7, MACHINE_PCI | MACHINE_ISA | MACHINE_AT | MACHINE_PS2 | MACHINE_HDC, 8, 128, 8, 127, machine_at_i430vx_init, NULL },
{ "[Socket 7 VX] Epox P55-VA", "p55va", MACHINE_CPUS_PENTIUM_S7, MACHINE_PCI | MACHINE_ISA | MACHINE_AT | MACHINE_PS2 | MACHINE_HDC, 8, 128, 8, 127, machine_at_p55va_init, NULL },
{ "[Socket 7 VX] HP Brio 80xx", "brio80xx", MACHINE_CPUS_PENTIUM_S7, MACHINE_PCI | MACHINE_ISA | MACHINE_AT | MACHINE_PS2 | MACHINE_HDC, 8, 128, 8, 127, machine_at_brio80xx_init, NULL },
{ "[Socket 7 VX] Biostar 8500TVX-A", "8500tvxa", {{"Intel", cpus_Pentium}, {"", NULL}, {"", NULL}, {"", NULL}, {"", NULL}}, MACHINE_PCI | MACHINE_ISA | MACHINE_AT | MACHINE_PS2 | MACHINE_HDC, 8, 128, 8, 127, machine_at_8500tvxa_init, NULL },
{ "[Socket 7 VX] Biostar 8500TVX-A", "8500tvxa", {{ "Intel", cpus_Pentium}, {"", NULL}, {"", NULL}, {"", NULL}, {"", NULL}}, MACHINE_PCI | MACHINE_ISA | MACHINE_AT | MACHINE_PS2 | MACHINE_HDC, 8, 128, 8, 127, machine_at_8500tvxa_init, NULL },
{ "[Socket 7 VX] Packard Bell PB680", "pb680", MACHINE_CPUS_PENTIUM_S7, MACHINE_PCI | MACHINE_ISA | MACHINE_AT | MACHINE_PS2 | MACHINE_HDC, 8, 128, 8, 127, machine_at_pb680_init, NULL },
/* 430TX */
@@ -270,9 +274,6 @@ const machine_t machines[] = {
/* Apollo VP3 */
{ "[Socket 7 VP3] FIC PA-2012", "ficpa2012", MACHINE_CPUS_PENTIUM_S7, MACHINE_PCI | MACHINE_ISA | MACHINE_AT | MACHINE_PS2 | MACHINE_HDC, 8, 192, 8, 127, machine_at_ficpa2012_init, NULL },
#if defined(DEV_BRANCH) && defined(NO_SIO)
{ "[Socket 7 VP3] QDI Advance II", "advanceii", MACHINE_CPUS_PENTIUM_S7, MACHINE_PCI | MACHINE_ISA | MACHINE_AT | MACHINE_PS2 | MACHINE_HDC, 8, 128, 8, 127, machine_at_advanceii_init, NULL },
#endif
/* Super Socket 7 machines */
/* Apollo MVP3 */
@@ -281,26 +282,26 @@ const machine_t machines[] = {
/* Socket 8 machines */
/* 440FX */
{ "[Socket 8 FX] Gigabyte GA-686NX", "686nx", {{"Intel", cpus_PentiumPro}, {"", NULL}, {"", NULL}, {"", NULL}, {"", NULL}}, MACHINE_PCI | MACHINE_ISA | MACHINE_AT | MACHINE_PS2 | MACHINE_HDC, 8, 512, 8, 127, machine_at_686nx_init, NULL },
{ "[Socket 8 FX] PC Partner MB600N", "mb600n", {{"Intel", cpus_PentiumPro}, {"", NULL}, {"", NULL}, {"", NULL}, {"", NULL}}, MACHINE_PCI | MACHINE_ISA | MACHINE_AT | MACHINE_PS2 | MACHINE_HDC, 8, 512, 8, 127, machine_at_mb600n_init, NULL },
{ "[Socket 8 FX] Biostar MB-8500ttc", "8500ttc", {{"Intel", cpus_PentiumPro}, {"", NULL}, {"", NULL}, {"", NULL}, {"", NULL}}, MACHINE_PCI | MACHINE_ISA | MACHINE_AT | MACHINE_PS2 | MACHINE_HDC, 8, 1024, 8, 127, machine_at_8500ttc_init, NULL },
{ "[Socket 8 FX] Micronics M6Mi", "m6mi", {{"Intel", cpus_PentiumPro}, {"", NULL}, {"", NULL}, {"", NULL}, {"", NULL}}, MACHINE_PCI | MACHINE_ISA | MACHINE_AT | MACHINE_PS2 | MACHINE_HDC, 8, 768, 8, 127, machine_at_m6mi_init, NULL },
{ "[Socket 8 FX] ASUS P/I-P65UP5 (C-P6ND)", "p65up5_cp6nd", {{"Intel", cpus_PentiumPro}, {"", NULL}, {"", NULL}, {"", NULL}, {"", NULL}}, MACHINE_PCI | MACHINE_ISA | MACHINE_AT | MACHINE_PS2 | MACHINE_HDC, 8, 1024, 8, 127, machine_at_p65up5_cp6nd_init, NULL },
{ "[Socket 8 FX] Gigabyte GA-686NX", "686nx", {{"Intel", cpus_PentiumPro}, {"", NULL}, {"", NULL}, {"", NULL}, {"", NULL}}, MACHINE_PCI | MACHINE_ISA | MACHINE_AT | MACHINE_PS2 | MACHINE_HDC, 8, 256, 8, 127, machine_at_686nx_init, NULL },
{ "[Socket 8 FX] PC Partner MB600N", "mb600n", {{"Intel", cpus_PentiumPro}, {"", NULL}, {"", NULL}, {"", NULL}, {"", NULL}}, MACHINE_PCI | MACHINE_ISA | MACHINE_AT | MACHINE_PS2 | MACHINE_HDC, 8, 256, 8, 127, machine_at_mb600n_init, NULL },
{ "[Socket 8 FX] Biostar MB-8500ttc", "8500ttc", {{"Intel", cpus_PentiumPro}, {"", NULL}, {"", NULL}, {"", NULL}, {"", NULL}}, MACHINE_PCI | MACHINE_ISA | MACHINE_AT | MACHINE_PS2 | MACHINE_HDC, 8, 512, 8, 127, machine_at_8500ttc_init, NULL },
{ "[Socket 8 FX] Micronics M6MI", "m6mi", {{"Intel", cpus_PentiumPro}, {"", NULL}, {"", NULL}, {"", NULL}, {"", NULL}}, MACHINE_PCI | MACHINE_ISA | MACHINE_AT | MACHINE_PS2 | MACHINE_HDC, 8, 384, 8, 127, machine_at_m6mi_init, NULL },
{ "[Socket 8 FX] ASUS P/I-P65UP5 (C-P6ND)", "p65up5_cp6nd", {{"Intel", cpus_PentiumPro}, {"", NULL}, {"", NULL}, {"", NULL}, {"", NULL}}, MACHINE_PCI | MACHINE_ISA | MACHINE_AT | MACHINE_PS2 | MACHINE_HDC, 8, 512, 8, 127, machine_at_p65up5_cp6nd_init, NULL },
/* Slot 1 machines */
/* 440FX */
{ "[Slot 1 FX] ASUS P/I-P65UP5 (C-PKND)", "p65up5_cpknd", {{"Intel", cpus_PentiumII66}, {"", NULL}, {"", NULL}, {"", NULL}, {"", NULL}}, MACHINE_PCI | MACHINE_ISA | MACHINE_AT | MACHINE_PS2 | MACHINE_HDC, 8, 1024, 8, 127, machine_at_p65up5_cpknd_init, NULL },
{ "[Slot 1 FX] ASUS KN97", "kn97", {{"Intel", cpus_PentiumII66}, {"", NULL}, {"", NULL}, {"", NULL}, {"", NULL}}, MACHINE_PCI | MACHINE_ISA | MACHINE_AT | MACHINE_PS2 | MACHINE_HDC, 8, 768, 8, 127, machine_at_kn97_init, NULL },
{ "[Slot 1 FX] ASUS P/I-P65UP5 (C-PKND)", "p65up5_cpknd", {{"Intel", cpus_PentiumII66}, {"", NULL}, {"", NULL}, {"", NULL}, {"", NULL}}, MACHINE_PCI | MACHINE_ISA | MACHINE_AT | MACHINE_PS2 | MACHINE_HDC, 8, 512, 8, 127, machine_at_p65up5_cpknd_init, NULL },
{ "[Slot 1 FX] ASUS KN97", "kn97", {{"Intel", cpus_PentiumII66}, {"", NULL}, {"", NULL}, {"", NULL}, {"", NULL}}, MACHINE_PCI | MACHINE_ISA | MACHINE_AT | MACHINE_PS2 | MACHINE_HDC, 8, 384, 8, 127, machine_at_kn97_init, NULL },
/* 440EX */
{ "[Slot 1 EX] QDI EXCELLENT II", "p6i440e2", {{"Intel", cpus_PentiumII66}, {"", NULL}, {"", NULL}, {"", NULL}, {"", NULL}}, MACHINE_PCI | MACHINE_ISA | MACHINE_AT | MACHINE_PS2 | MACHINE_HDC, 8, 512, 8, 255, machine_at_p6i440e2_init, NULL },
{ "[Slot 1 EX] QDI EXCELLENT II", "p6i440e2", {{"Intel", cpus_PentiumII66}, {"", NULL}, {"", NULL}, {"", NULL}, {"", NULL}}, MACHINE_PCI | MACHINE_ISA | MACHINE_AT | MACHINE_PS2 | MACHINE_HDC, 8, 512, 8, 255, machine_at_p6i440e2_init, NULL },
/* 440BX */
{ "[Slot 1 BX] ASUS P2B-LS", "p2bls", {{"Intel", cpus_PentiumII}, {"Intel/PGA370", cpus_Celeron},{"VIA", cpus_Cyrix3},{"", NULL},{"", NULL}}, MACHINE_PCI | MACHINE_ISA | MACHINE_AT | MACHINE_PS2 | MACHINE_HDC, 8, 1024, 8, 255, machine_at_p2bls_init, NULL },
{ "[Slot 1 BX] ASUS P3B-F", "p3bf", {{"Intel", cpus_PentiumII}, {"Intel/PGA370", cpus_Celeron},{"VIA", cpus_Cyrix3},{"", NULL},{"", NULL}}, MACHINE_PCI | MACHINE_ISA | MACHINE_AT | MACHINE_PS2 | MACHINE_HDC, 8, 1024, 8, 255, machine_at_p3bf_init, NULL },
{ "[Slot 1 BX] ABit BF6", "bf6", {{"Intel", cpus_PentiumII}, {"Intel/PGA370", cpus_Celeron},{"VIA", cpus_Cyrix3},{"", NULL},{"", NULL}}, MACHINE_PCI | MACHINE_ISA | MACHINE_AT | MACHINE_PS2 | MACHINE_HDC, 8, 768, 8, 255, machine_at_bf6_init, NULL },
{ "[Slot 1 BX] A-Trend ATC6310BXII", "atc6310bxii", {{"Intel", cpus_PentiumII}, {"Intel/PGA370", cpus_Celeron},{"VIA", cpus_Cyrix3},{"", NULL},{"", NULL}}, MACHINE_PCI | MACHINE_ISA | MACHINE_AT | MACHINE_PS2 | MACHINE_HDC, 8, 768, 8, 255, machine_at_atc6310bxii_init, NULL },
{ "[Slot 1 BX] A-Trend ATC6310BXII", "atc6310bxii", {{"Intel", cpus_PentiumII}, {"Intel/PGA370", cpus_Celeron},{"VIA", cpus_Cyrix3},{"", NULL},{"", NULL}}, MACHINE_PCI | MACHINE_ISA | MACHINE_AT | MACHINE_PS2 | MACHINE_HDC, 8, 1024, 8, 255, machine_at_atc6310bxii_init, NULL },
#if defined(DEV_BRANCH) && defined(NO_SIO)
{ "[Slot 1 BX] Tyan Tsunami ATX", "tsunamiatx", {{"Intel", cpus_PentiumII}, {"Intel/PGA370", cpus_Celeron},{"VIA", cpus_Cyrix3},{"", NULL},{"", NULL}}, MACHINE_PCI | MACHINE_ISA | MACHINE_AT | MACHINE_PS2 | MACHINE_HDC | MACHINE_SOUND, 8, 1024, 8, 255, machine_at_tsunamiatx_init, at_tsunamiatx_get_device },
#endif

View File

@@ -1029,8 +1029,10 @@ pit_set_clock(int clock)
TIMER_USEC = (uint64_t)((cpuclock / 1000000.0) * (double)(1ull << 32));
isa_timing = (cpuclock / (double)8000000.0);
bus_timing = (cpuclock / (double)cpu_busspeed);
if (cpu_64bitbus)
bus_timing = (cpuclock / ((double)cpu_busspeed) / 2);
else
bus_timing = (cpuclock / (double)cpu_busspeed);
pci_timing = (cpuclock / (double)cpu_pci_speed);
/* PCICLK in us for use with timer_on_auto(). */

View File

@@ -1,5 +1,5 @@
/* Copyright (C) 2003, 2004, 2005, 2006, 2008, 2009 Dean Beeler, Jerome Fisher
* Copyright (C) 2011-2017 Dean Beeler, Jerome Fisher, Sergey V. Mikayev
* Copyright (C) 2011-2020 Dean Beeler, Jerome Fisher, Sergey V. Mikayev
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by

View File

@@ -1,5 +1,5 @@
/* Copyright (C) 2003, 2004, 2005, 2006, 2008, 2009 Dean Beeler, Jerome Fisher
* Copyright (C) 2011-2017 Dean Beeler, Jerome Fisher, Sergey V. Mikayev
* Copyright (C) 2011-2020 Dean Beeler, Jerome Fisher, Sergey V. Mikayev
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by

View File

@@ -1,5 +1,5 @@
/* Copyright (C) 2003, 2004, 2005, 2006, 2008, 2009 Dean Beeler, Jerome Fisher
* Copyright (C) 2011-2017 Dean Beeler, Jerome Fisher, Sergey V. Mikayev
* Copyright (C) 2011-2020 Dean Beeler, Jerome Fisher, Sergey V. Mikayev
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by

View File

@@ -1,5 +1,5 @@
/* Copyright (C) 2003, 2004, 2005, 2006, 2008, 2009 Dean Beeler, Jerome Fisher
* Copyright (C) 2011-2017 Dean Beeler, Jerome Fisher, Sergey V. Mikayev
* Copyright (C) 2011-2020 Dean Beeler, Jerome Fisher, Sergey V. Mikayev
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by

View File

@@ -1,5 +1,5 @@
/* Copyright (C) 2003, 2004, 2005, 2006, 2008, 2009 Dean Beeler, Jerome Fisher
* Copyright (C) 2011-2017 Dean Beeler, Jerome Fisher, Sergey V. Mikayev
* Copyright (C) 2011-2020 Dean Beeler, Jerome Fisher, Sergey V. Mikayev
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by

View File

@@ -1,5 +1,5 @@
/* Copyright (C) 2003, 2004, 2005, 2006, 2008, 2009 Dean Beeler, Jerome Fisher
* Copyright (C) 2011-2017 Dean Beeler, Jerome Fisher, Sergey V. Mikayev
* Copyright (C) 2011-2020 Dean Beeler, Jerome Fisher, Sergey V. Mikayev
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by

View File

@@ -1,5 +1,5 @@
/* Copyright (C) 2003, 2004, 2005, 2006, 2008, 2009 Dean Beeler, Jerome Fisher
* Copyright (C) 2011-2017 Dean Beeler, Jerome Fisher, Sergey V. Mikayev
* Copyright (C) 2011-2020 Dean Beeler, Jerome Fisher, Sergey V. Mikayev
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by

View File

@@ -1,5 +1,5 @@
/* Copyright (C) 2003, 2004, 2005, 2006, 2008, 2009 Dean Beeler, Jerome Fisher
* Copyright (C) 2011-2017 Dean Beeler, Jerome Fisher, Sergey V. Mikayev
* Copyright (C) 2011-2020 Dean Beeler, Jerome Fisher, Sergey V. Mikayev
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
@@ -15,12 +15,26 @@
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#ifdef MT32EMU_SHARED
#include <locale>
#endif
#include "internals.h"
#include "FileStream.h"
namespace MT32Emu {
static inline void configureSystemLocale() {
#ifdef MT32EMU_SHARED
static bool configured = false;
if (configured) return;
configured = true;
std::locale::global(std::locale(""));
#endif
}
using std::ios_base;
FileStream::FileStream() : ifsp(*new std::ifstream), data(NULL), size(0)
@@ -70,6 +84,7 @@ const Bit8u *FileStream::getData() {
}
bool FileStream::open(const char *filename) {
configureSystemLocale();
ifsp.clear();
ifsp.open(filename, ios_base::in | ios_base::binary);
return !ifsp.fail();

View File

@@ -1,5 +1,5 @@
/* Copyright (C) 2003, 2004, 2005, 2006, 2008, 2009 Dean Beeler, Jerome Fisher
* Copyright (C) 2011-2017 Dean Beeler, Jerome Fisher, Sergey V. Mikayev
* Copyright (C) 2011-2020 Dean Beeler, Jerome Fisher, Sergey V. Mikayev
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by

View File

@@ -1,5 +1,5 @@
/* Copyright (C) 2003, 2004, 2005, 2006, 2008, 2009 Dean Beeler, Jerome Fisher
* Copyright (C) 2011-2017 Dean Beeler, Jerome Fisher, Sergey V. Mikayev
* Copyright (C) 2011-2020 Dean Beeler, Jerome Fisher, Sergey V. Mikayev
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by

View File

@@ -1,5 +1,5 @@
/* Copyright (C) 2003, 2004, 2005, 2006, 2008, 2009 Dean Beeler, Jerome Fisher
* Copyright (C) 2011-2017 Dean Beeler, Jerome Fisher, Sergey V. Mikayev
* Copyright (C) 2011-2020 Dean Beeler, Jerome Fisher, Sergey V. Mikayev
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by

View File

@@ -1,5 +1,5 @@
/* Copyright (C) 2003, 2004, 2005, 2006, 2008, 2009 Dean Beeler, Jerome Fisher
* Copyright (C) 2011-2017 Dean Beeler, Jerome Fisher, Sergey V. Mikayev
* Copyright (C) 2011-2020 Dean Beeler, Jerome Fisher, Sergey V. Mikayev
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by

View File

@@ -1,5 +1,5 @@
/* Copyright (C) 2003, 2004, 2005, 2006, 2008, 2009 Dean Beeler, Jerome Fisher
* Copyright (C) 2011-2017 Dean Beeler, Jerome Fisher, Sergey V. Mikayev
* Copyright (C) 2011-2020 Dean Beeler, Jerome Fisher, Sergey V. Mikayev
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by

View File

@@ -1,5 +1,5 @@
/* Copyright (C) 2003, 2004, 2005, 2006, 2008, 2009 Dean Beeler, Jerome Fisher
* Copyright (C) 2011-2017 Dean Beeler, Jerome Fisher, Sergey V. Mikayev
* Copyright (C) 2011-2020 Dean Beeler, Jerome Fisher, Sergey V. Mikayev
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by

View File

@@ -1,5 +1,5 @@
/* Copyright (C) 2003, 2004, 2005, 2006, 2008, 2009 Dean Beeler, Jerome Fisher
* Copyright (C) 2011-2017 Dean Beeler, Jerome Fisher, Sergey V. Mikayev
* Copyright (C) 2011-2020 Dean Beeler, Jerome Fisher, Sergey V. Mikayev
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by

View File

@@ -1,5 +1,5 @@
/* Copyright (C) 2003, 2004, 2005, 2006, 2008, 2009 Dean Beeler, Jerome Fisher
* Copyright (C) 2011-2017 Dean Beeler, Jerome Fisher, Sergey V. Mikayev
* Copyright (C) 2011-2020 Dean Beeler, Jerome Fisher, Sergey V. Mikayev
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by

View File

@@ -1,5 +1,5 @@
/* Copyright (C) 2003, 2004, 2005, 2006, 2008, 2009 Dean Beeler, Jerome Fisher
* Copyright (C) 2011-2017 Dean Beeler, Jerome Fisher, Sergey V. Mikayev
* Copyright (C) 2011-2020 Dean Beeler, Jerome Fisher, Sergey V. Mikayev
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
@@ -23,20 +23,6 @@
namespace MT32Emu {
/**
* Used to safely store timestamped MIDI events in a local queue.
*/
struct MidiEvent {
Bit32u shortMessageData;
const Bit8u *sysexData;
Bit32u sysexLength;
Bit32u timestamp;
~MidiEvent();
void setShortMessage(Bit32u shortMessageData, Bit32u timestamp);
void setSysex(const Bit8u *sysexData, Bit32u sysexLength, Bit32u timestamp);
};
/**
* Simple queue implementation using a ring buffer to store incoming MIDI event before the synth actually processes it.
* It is intended to:
@@ -48,22 +34,38 @@ struct MidiEvent {
* and one performs only writing. More complicated usage requires external synchronisation.
*/
class MidiEventQueue {
private:
MidiEvent * const ringBuffer;
const Bit32u ringBufferMask;
volatile Bit32u startPosition;
volatile Bit32u endPosition;
public:
MidiEventQueue(Bit32u ringBufferSize = DEFAULT_MIDI_EVENT_QUEUE_SIZE); // Must be a power of 2
class SysexDataStorage;
struct MidiEvent {
const Bit8u *sysexData;
union {
Bit32u sysexLength;
Bit32u shortMessageData;
};
Bit32u timestamp;
};
explicit MidiEventQueue(
// Must be a power of 2
Bit32u ringBufferSize,
Bit32u storageBufferSize
);
~MidiEventQueue();
void reset();
bool pushShortMessage(Bit32u shortMessageData, Bit32u timestamp);
bool pushSysex(const Bit8u *sysexData, Bit32u sysexLength, Bit32u timestamp);
const MidiEvent *peekMidiEvent();
const volatile MidiEvent *peekMidiEvent();
void dropMidiEvent();
bool isFull() const;
bool inline isEmpty() const;
inline bool isEmpty() const;
private:
SysexDataStorage &sysexDataStorage;
MidiEvent * const ringBuffer;
const Bit32u ringBufferMask;
volatile Bit32u startPosition;
volatile Bit32u endPosition;
};
} // namespace MT32Emu

View File

@@ -1,5 +1,5 @@
/* Copyright (C) 2003, 2004, 2005, 2006, 2008, 2009 Dean Beeler, Jerome Fisher
* Copyright (C) 2011-2017 Dean Beeler, Jerome Fisher, Sergey V. Mikayev
* Copyright (C) 2011-2020 Dean Beeler, Jerome Fisher, Sergey V. Mikayev
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by

View File

@@ -1,5 +1,5 @@
/* Copyright (C) 2003, 2004, 2005, 2006, 2008, 2009 Dean Beeler, Jerome Fisher
* Copyright (C) 2011-2017 Dean Beeler, Jerome Fisher, Sergey V. Mikayev
* Copyright (C) 2011-2020 Dean Beeler, Jerome Fisher, Sergey V. Mikayev
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by

View File

@@ -1,5 +1,5 @@
/* Copyright (C) 2003, 2004, 2005, 2006, 2008, 2009 Dean Beeler, Jerome Fisher
* Copyright (C) 2011-2017 Dean Beeler, Jerome Fisher, Sergey V. Mikayev
* Copyright (C) 2011-2020 Dean Beeler, Jerome Fisher, Sergey V. Mikayev
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by

View File

@@ -1,5 +1,5 @@
/* Copyright (C) 2003, 2004, 2005, 2006, 2008, 2009 Dean Beeler, Jerome Fisher
* Copyright (C) 2011-2017 Dean Beeler, Jerome Fisher, Sergey V. Mikayev
* Copyright (C) 2011-2020 Dean Beeler, Jerome Fisher, Sergey V. Mikayev
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by

View File

@@ -1,5 +1,5 @@
/* Copyright (C) 2003, 2004, 2005, 2006, 2008, 2009 Dean Beeler, Jerome Fisher
* Copyright (C) 2011-2017 Dean Beeler, Jerome Fisher, Sergey V. Mikayev
* Copyright (C) 2011-2020 Dean Beeler, Jerome Fisher, Sergey V. Mikayev
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
@@ -21,6 +21,7 @@
#include "Partial.h"
#include "Part.h"
#include "PartialManager.h"
#include "Poly.h"
#include "Synth.h"
#include "Tables.h"
@@ -36,22 +37,22 @@ static const Bit8u PAN_NUMERATOR_SLAVE[] = {0, 1, 2, 3, 4, 5, 6, 7, 7, 7, 7, 7,
// We assume the pan is applied using the same 13-bit multiplier circuit that is also used for ring modulation
// because of the observed sample overflow, so the panSetting values are likely mapped in a similar way via a LUT.
// FIXME: Sample analysis suggests that the use of panSetting is linear, but there are some quirks that still need to be resolved.
static Bit32s getPANFactor(Bit32s panSetting) {
static const Bit32s PAN_FACTORS_COUNT = 15;
static Bit32s getPanFactor(Bit32s panSetting) {
static const Bit32u PAN_FACTORS_COUNT = 15;
static Bit32s PAN_FACTORS[PAN_FACTORS_COUNT];
static bool firstRun = true;
if (firstRun) {
firstRun = false;
for (Bit32u i = 1; i < (Bit32u)PAN_FACTORS_COUNT; i++) {
for (Bit32u i = 1; i < PAN_FACTORS_COUNT; i++) {
PAN_FACTORS[i] = Bit32s(0.5 + i * 8192.0 / double(PAN_FACTORS_COUNT - 1));
}
}
return PAN_FACTORS[panSetting];
}
Partial::Partial(Synth *useSynth, int useDebugPartialNum) :
synth(useSynth), debugPartialNum(useDebugPartialNum), sampleNum(0),
Partial::Partial(Synth *useSynth, int usePartialIndex) :
synth(useSynth), partialIndex(usePartialIndex), sampleNum(0),
floatMode(useSynth->getSelectedRendererType() == RendererType_FLOAT) {
// Initialisation of tva, tvp and tvf uses 'this' pointer
// and thus should not be in the initializer list to avoid a compiler warning
@@ -82,7 +83,7 @@ Partial::~Partial() {
// Only used for debugging purposes
int Partial::debugGetPartialNum() const {
return debugPartialNum;
return partialIndex;
}
// Only used for debugging purposes
@@ -112,11 +113,12 @@ void Partial::deactivate() {
return;
}
ownerPart = -1;
synth->partialManager->partialDeactivated(partialIndex);
if (poly != NULL) {
poly->partialDeactivated(this);
}
#if MT32EMU_MONITOR_PARTIALS > 2
synth->printDebug("[+%lu] [Partial %d] Deactivated", sampleNum, debugPartialNum);
synth->printDebug("[+%lu] [Partial %d] Deactivated", sampleNum, partialIndex);
synth->printPartialUsage(sampleNum);
#endif
if (isRingModulatingSlave()) {
@@ -135,7 +137,7 @@ void Partial::deactivate() {
void Partial::startPartial(const Part *part, Poly *usePoly, const PatchCache *usePatchCache, const MemParams::RhythmTemp *rhythmTemp, Partial *pairPartial) {
if (usePoly == NULL || usePatchCache == NULL) {
synth->printDebug("[Partial %d] *** Error: Starting partial for owner %d, usePoly=%s, usePatchCache=%s", debugPartialNum, ownerPart, usePoly == NULL ? "*** NULL ***" : "OK", usePatchCache == NULL ? "*** NULL ***" : "OK");
synth->printDebug("[Partial %d] *** Error: Starting partial for owner %d, usePoly=%s, usePatchCache=%s", partialIndex, ownerPart, usePoly == NULL ? "*** NULL ***" : "OK", usePatchCache == NULL ? "*** NULL ***" : "OK");
return;
}
patchCache = usePatchCache;
@@ -153,20 +155,18 @@ void Partial::startPartial(const Part *part, Poly *usePoly, const PatchCache *us
// Do a normal mix independent of any pair partial.
mixType = 0;
pairPartial = NULL;
} else {
} else if (!synth->isNicePanningEnabled()) {
// Mok wanted an option for smoother panning, and we love Mok.
#ifndef INACCURATE_SMOOTH_PAN
// CONFIRMED by Mok: exactly bytes like this (right shifted?) are sent to the LA32.
// CONFIRMED by Mok: exactly bytes like this (right shifted) are sent to the LA32.
panSetting &= 0x0E;
#endif
}
leftPanValue = synth->reversedStereoEnabled ? 14 - panSetting : panSetting;
rightPanValue = 14 - leftPanValue;
if (!floatMode) {
leftPanValue = getPANFactor(leftPanValue);
rightPanValue = getPANFactor(rightPanValue);
leftPanValue = getPanFactor(leftPanValue);
rightPanValue = getPanFactor(rightPanValue);
}
// SEMI-CONFIRMED: From sample analysis:
@@ -174,7 +174,7 @@ void Partial::startPartial(const Part *part, Poly *usePoly, const PatchCache *us
// Either partial pairs are added or subtracted, it depends on how the partial pairs are allocated.
// It seems that partials are grouped into quarters and if the partial pairs are allocated in different quarters the subtraction happens.
// Though, this matters little for the majority of timbres, it becomes crucial for timbres which contain several partials that sound very close.
// In this case that timbre can sound totally different depending of the way it is mixed up.
// In this case that timbre can sound totally different depending on the way it is mixed up.
// Most easily this effect can be displayed with the help of a special timbre consisting of several identical square wave partials (3 or 4).
// Say, it is 3-partial timbre. Just play any two notes simultaneously and the polys very probably are mixed differently.
// Moreover, the partial allocator retains the last partial assignment it did and all the subsequent notes will sound the same as the last released one.
@@ -182,8 +182,7 @@ void Partial::startPartial(const Part *part, Poly *usePoly, const PatchCache *us
// whole-quarter assignment or after some partials got aborted, even 4-partial timbres can be found sounding differently.
// This behaviour is also confirmed with two more special timbres: one with identical sawtooth partials, and one with PCM wave 02.
// For my personal taste, this behaviour rather enriches the sounding and should be emulated.
// Also, the current partial allocator model probably needs to be refined.
if (debugPartialNum & 8) {
if (!synth->isNicePartialMixingEnabled() && (partialIndex & 4)) {
leftPanValue = -leftPanValue;
rightPanValue = -rightPanValue;
}
@@ -307,7 +306,7 @@ bool Partial::canProduceOutput() {
return false;
}
if (poly == NULL) {
synth->printDebug("[Partial %d] *** ERROR: poly is NULL at Partial::produceOutput()!", debugPartialNum);
synth->printDebug("[Partial %d] *** ERROR: poly is NULL at Partial::produceOutput()!", partialIndex);
return false;
}
return true;

View File

@@ -1,5 +1,5 @@
/* Copyright (C) 2003, 2004, 2005, 2006, 2008, 2009 Dean Beeler, Jerome Fisher
* Copyright (C) 2011-2017 Dean Beeler, Jerome Fisher, Sergey V. Mikayev
* Copyright (C) 2011-2020 Dean Beeler, Jerome Fisher, Sergey V. Mikayev
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
@@ -40,13 +40,14 @@ struct ControlROMPCMStruct;
class Partial {
private:
Synth *synth;
const int debugPartialNum; // Only used for debugging
const int partialIndex; // Index of this Partial in the global partial table
// Number of the sample currently being rendered by produceOutput(), or 0 if no run is in progress
// This is only kept available for debugging purposes.
Bit32u sampleNum;
// Actually, this is a 4-bit register but we abuse this to emulate inverted mixing.
// Also we double the value to enable INACCURATE_SMOOTH_PAN, with respect to MoK.
// Actually, LA-32 receives only 3 bits as a pan setting, but we abuse these to emulate
// the inverted partial mixing as well. Also we double the values (making them correspond
// to the panpot range) to enable NicePanning mode, with respect to MoK.
Bit32s leftPanValue, rightPanValue;
int ownerPart; // -1 if unassigned

View File

@@ -1,5 +1,5 @@
/* Copyright (C) 2003, 2004, 2005, 2006, 2008, 2009 Dean Beeler, Jerome Fisher
* Copyright (C) 2011-2017 Dean Beeler, Jerome Fisher, Sergey V. Mikayev
* Copyright (C) 2011-2020 Dean Beeler, Jerome Fisher, Sergey V. Mikayev
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
@@ -31,11 +31,14 @@ namespace MT32Emu {
PartialManager::PartialManager(Synth *useSynth, Part **useParts) {
synth = useSynth;
parts = useParts;
partialTable = new Partial *[synth->getPartialCount()];
inactivePartialCount = synth->getPartialCount();
partialTable = new Partial *[inactivePartialCount];
inactivePartials = new int[inactivePartialCount];
freePolys = new Poly *[synth->getPartialCount()];
firstFreePolyIndex = 0;
for (unsigned int i = 0; i < synth->getPartialCount(); i++) {
partialTable[i] = new Partial(synth, i);
inactivePartials[i] = inactivePartialCount - i - 1;
freePolys[i] = new Poly();
}
}
@@ -46,6 +49,7 @@ PartialManager::~PartialManager(void) {
if (freePolys[i] != NULL) delete freePolys[i];
}
delete[] partialTable;
delete[] inactivePartials;
delete[] freePolys;
}
@@ -83,29 +87,21 @@ unsigned int PartialManager::setReserve(Bit8u *rset) {
}
Partial *PartialManager::allocPartial(int partNum) {
Partial *outPartial = NULL;
// Get the first inactive partial
for (unsigned int partialNum = 0; partialNum < synth->getPartialCount(); partialNum++) {
if (!partialTable[partialNum]->isActive()) {
outPartial = partialTable[partialNum];
break;
}
if (inactivePartialCount > 0) {
Partial *partial = partialTable[inactivePartials[--inactivePartialCount]];
partial->activate(partNum);
return partial;
}
if (outPartial != NULL) {
outPartial->activate(partNum);
synth->printDebug("PartialManager Error: No inactive partials to allocate for part %d, current partial state:\n", partNum);
for (Bit32u i = 0; i < synth->getPartialCount(); i++) {
const Partial *partial = partialTable[i];
synth->printDebug("[Partial %d]: activation=%d, owner part=%d\n", i, partial->isActive(), partial->getOwnerPart());
}
return outPartial;
return NULL;
}
unsigned int PartialManager::getFreePartialCount(void) {
int count = 0;
for (unsigned int i = 0; i < synth->getPartialCount(); i++) {
if (!partialTable[i]->isActive()) {
count++;
}
}
return count;
unsigned int PartialManager::getFreePartialCount() {
return inactivePartialCount;
}
// This function is solely used to gather data for debug output at the moment.
@@ -279,7 +275,7 @@ Poly *PartialManager::assignPolyToPart(Part *part) {
void PartialManager::polyFreed(Poly *poly) {
if (0 == firstFreePolyIndex) {
synth->printDebug("Cannot return freed poly, currently active polys:\n");
synth->printDebug("PartialManager Error: Cannot return freed poly, currently active polys:\n");
for (Bit32u partNum = 0; partNum < 9; partNum++) {
const Poly *activePoly = synth->getPart(partNum)->getFirstActivePoly();
Bit32u polyCount = 0;
@@ -289,10 +285,23 @@ void PartialManager::polyFreed(Poly *poly) {
}
synth->printDebug("Part: %i, active poly count: %i\n", partNum, polyCount);
}
} else {
firstFreePolyIndex--;
freePolys[firstFreePolyIndex] = poly;
}
poly->setPart(NULL);
firstFreePolyIndex--;
freePolys[firstFreePolyIndex] = poly;
}
void PartialManager::partialDeactivated(int partialIndex) {
if (inactivePartialCount < synth->getPartialCount()) {
inactivePartials[inactivePartialCount++] = partialIndex;
return;
}
synth->printDebug("PartialManager Error: Cannot return deactivated partial %d, current partial state:\n", partialIndex);
for (Bit32u i = 0; i < synth->getPartialCount(); i++) {
const Partial *partial = partialTable[i];
synth->printDebug("[Partial %d]: activation=%d, owner part=%d\n", i, partial->isActive(), partial->getOwnerPart());
}
}
} // namespace MT32Emu

View File

@@ -1,5 +1,5 @@
/* Copyright (C) 2003, 2004, 2005, 2006, 2008, 2009 Dean Beeler, Jerome Fisher
* Copyright (C) 2011-2017 Dean Beeler, Jerome Fisher, Sergey V. Mikayev
* Copyright (C) 2011-2020 Dean Beeler, Jerome Fisher, Sergey V. Mikayev
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
@@ -37,6 +37,8 @@ private:
Partial **partialTable;
Bit8u numReservedPartialsForPart[9];
Bit32u firstFreePolyIndex;
int *inactivePartials; // Holds indices of inactive Partials in the Partial table
Bit32u inactivePartialCount;
bool abortFirstReleasingPolyWhereReserveExceeded(int minPart);
bool abortFirstPolyPreferHeldWhereReserveExceeded(int minPart);
@@ -45,7 +47,7 @@ public:
PartialManager(Synth *synth, Part **parts);
~PartialManager();
Partial *allocPartial(int partNum);
unsigned int getFreePartialCount(void);
unsigned int getFreePartialCount();
void getPerPartPartialUsage(unsigned int perPartPartialUsage[9]);
bool freePartials(unsigned int needed, int partNum);
unsigned int setReserve(Bit8u *rset);
@@ -57,6 +59,7 @@ public:
const Partial *getPartial(unsigned int partialNum) const;
Poly *assignPolyToPart(Part *part);
void polyFreed(Poly *poly);
void partialDeactivated(int partialIndex);
}; // class PartialManager
} // namespace MT32Emu

View File

@@ -1,5 +1,5 @@
/* Copyright (C) 2003, 2004, 2005, 2006, 2008, 2009 Dean Beeler, Jerome Fisher
* Copyright (C) 2011-2017 Dean Beeler, Jerome Fisher, Sergey V. Mikayev
* Copyright (C) 2011-2020 Dean Beeler, Jerome Fisher, Sergey V. Mikayev
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by

View File

@@ -1,5 +1,5 @@
/* Copyright (C) 2003, 2004, 2005, 2006, 2008, 2009 Dean Beeler, Jerome Fisher
* Copyright (C) 2011-2017 Dean Beeler, Jerome Fisher, Sergey V. Mikayev
* Copyright (C) 2011-2020 Dean Beeler, Jerome Fisher, Sergey V. Mikayev
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by

View File

@@ -1,5 +1,5 @@
/* Copyright (C) 2003, 2004, 2005, 2006, 2008, 2009 Dean Beeler, Jerome Fisher
* Copyright (C) 2011-2017 Dean Beeler, Jerome Fisher, Sergey V. Mikayev
* Copyright (C) 2011-2020 Dean Beeler, Jerome Fisher, Sergey V. Mikayev
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by

View File

@@ -1,5 +1,5 @@
/* Copyright (C) 2003, 2004, 2005, 2006, 2008, 2009 Dean Beeler, Jerome Fisher
* Copyright (C) 2011-2017 Dean Beeler, Jerome Fisher, Sergey V. Mikayev
* Copyright (C) 2011-2020 Dean Beeler, Jerome Fisher, Sergey V. Mikayev
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by

View File

@@ -1,4 +1,4 @@
/* Copyright (C) 2015-2017 Sergey V. Mikayev
/* Copyright (C) 2015-2020 Sergey V. Mikayev
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
@@ -14,13 +14,15 @@
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include <cstddef>
#include "SampleRateConverter.h"
#if MT32EMU_WITH_LIBSOXR_RESAMPLER
#include "srchelper/SoxrAdapter.h"
#elif MT32EMU_WITH_LIBSAMPLERATE_RESAMPLER
#include "srchelper/SamplerateAdapter.h"
#else
#elif MT32EMU_WITH_INTERNAL_RESAMPLER
#include "srchelper/InternalResampler.h"
#endif
@@ -33,8 +35,11 @@ static inline void *createDelegate(Synth &synth, double targetSampleRate, Sample
return new SoxrAdapter(synth, targetSampleRate, quality);
#elif MT32EMU_WITH_LIBSAMPLERATE_RESAMPLER
return new SamplerateAdapter(synth, targetSampleRate, quality);
#else
#elif MT32EMU_WITH_INTERNAL_RESAMPLER
return new InternalResampler(synth, targetSampleRate, quality);
#else
(void)synth, (void)targetSampleRate, (void)quality;
return NULL;
#endif
}
@@ -47,6 +52,15 @@ AnalogOutputMode SampleRateConverter::getBestAnalogOutputMode(double targetSampl
return AnalogOutputMode_COARSE;
}
double SampleRateConverter::getSupportedOutputSampleRate(double desiredSampleRate) {
#if MT32EMU_WITH_LIBSOXR_RESAMPLER || MT32EMU_WITH_LIBSAMPLERATE_RESAMPLER || MT32EMU_WITH_INTERNAL_RESAMPLER
return desiredSampleRate > 0 ? desiredSampleRate : 0;
#else
(void)desiredSampleRate;
return 0;
#endif
}
SampleRateConverter::SampleRateConverter(Synth &useSynth, double targetSampleRate, SamplerateConversionQuality useQuality) :
synthInternalToTargetSampleRateRatio(SAMPLE_RATE / targetSampleRate),
useSynthDelegate(useSynth.getStereoOutputSampleRate() == targetSampleRate),
@@ -59,7 +73,7 @@ SampleRateConverter::~SampleRateConverter() {
delete static_cast<SoxrAdapter *>(srcDelegate);
#elif MT32EMU_WITH_LIBSAMPLERATE_RESAMPLER
delete static_cast<SamplerateAdapter *>(srcDelegate);
#else
#elif MT32EMU_WITH_INTERNAL_RESAMPLER
delete static_cast<InternalResampler *>(srcDelegate);
#endif
}
@@ -75,8 +89,10 @@ void SampleRateConverter::getOutputSamples(float *buffer, unsigned int length) {
static_cast<SoxrAdapter *>(srcDelegate)->getOutputSamples(buffer, length);
#elif MT32EMU_WITH_LIBSAMPLERATE_RESAMPLER
static_cast<SamplerateAdapter *>(srcDelegate)->getOutputSamples(buffer, length);
#else
#elif MT32EMU_WITH_INTERNAL_RESAMPLER
static_cast<InternalResampler *>(srcDelegate)->getOutputSamples(buffer, length);
#else
Synth::muteSampleBuffer(buffer, length);
#endif
}

View File

@@ -1,4 +1,4 @@
/* Copyright (C) 2015-2017 Sergey V. Mikayev
/* Copyright (C) 2015-2020 Sergey V. Mikayev
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
@@ -37,6 +37,10 @@ public:
// at the sample rate specified by the targetSampleRate argument.
static AnalogOutputMode getBestAnalogOutputMode(double targetSampleRate);
// Returns the sample rate supported by the sample rate conversion implementation currently in effect
// that is closest to the one specified by the desiredSampleRate argument.
static double getSupportedOutputSampleRate(double desiredSampleRate);
// Creates a SampleRateConverter instance that converts output signal from the synth to the given sample rate
// with the specified conversion quality.
SampleRateConverter(Synth &synth, double targetSampleRate, SamplerateConversionQuality quality);

View File

@@ -16,7 +16,7 @@
#include <stdint.h>
#include <stdio.h>
#include <86box/plat.h>
#include "../../../plat.h"
#include "SampleRateConverter.h"
#include "Synth.h"

View File

@@ -1,5 +1,5 @@
/* Copyright (C) 2003, 2004, 2005, 2006, 2008, 2009 Dean Beeler, Jerome Fisher
* Copyright (C) 2011-2017 Dean Beeler, Jerome Fisher, Sergey V. Mikayev
* Copyright (C) 2011-2020 Dean Beeler, Jerome Fisher, Sergey V. Mikayev
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by

View File

@@ -1,5 +1,5 @@
/* Copyright (C) 2003, 2004, 2005, 2006, 2008, 2009 Dean Beeler, Jerome Fisher
* Copyright (C) 2011-2017 Dean Beeler, Jerome Fisher, Sergey V. Mikayev
* Copyright (C) 2011-2020 Dean Beeler, Jerome Fisher, Sergey V. Mikayev
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
@@ -195,6 +195,20 @@ public:
RendererType selectedRendererType;
Bit32s masterTunePitchDelta;
bool niceAmpRamp;
bool nicePanning;
bool nicePartialMixing;
// Here we keep the reverse mapping of assigned parts per MIDI channel.
// NOTE: value above 8 means that the channel is not assigned
Bit8u chantable[16][9];
// This stores the index of Part in chantable that failed to play and required partial abortion.
Bit32u abortingPartIx;
bool preallocatedReverbMemory;
Bit32u midiEventQueueSize;
Bit32u midiEventQueueSysexStorageBufferSize;
};
Bit32u Synth::getLibraryVersionInt() {
@@ -238,7 +252,8 @@ Synth::Synth(ReportHandler *useReportHandler) :
isDefaultReportHandler = false;
}
for (int i = 0; i < 4; i++) {
extensions.preallocatedReverbMemory = false;
for (int i = REVERB_MODE_ROOM; i <= REVERB_MODE_TAP_DELAY; i++) {
reverbModels[i] = NULL;
}
reverbModel = NULL;
@@ -250,6 +265,8 @@ Synth::Synth(ReportHandler *useReportHandler) :
setReverbOutputGain(1.0f);
setReversedStereoEnabled(false);
setNiceAmpRampEnabled(true);
setNicePanningEnabled(false);
setNicePartialMixingEnabled(false);
selectRendererType(RendererType_BIT16S);
patchTempMemoryRegion = NULL;
@@ -267,6 +284,8 @@ Synth::Synth(ReportHandler *useReportHandler) :
pcmROMData = NULL;
soundGroupNames = NULL;
midiQueue = NULL;
extensions.midiEventQueueSize = DEFAULT_MIDI_EVENT_QUEUE_SIZE;
extensions.midiEventQueueSysexStorageBufferSize = 0;
lastReceivedMIDIEventTimestamp = 0;
memset(parts, 0, sizeof(parts));
renderedSampleCount = 0;
@@ -313,15 +332,26 @@ void Synth::newTimbreSet(Bit8u partNum, Bit8u timbreGroup, Bit8u timbreNumber, c
reportHandler->onProgramChanged(partNum, soundGroupName, patchName);
}
void Synth::printDebug(const char *fmt, ...) {
va_list ap;
va_start(ap, fmt);
#if MT32EMU_DEBUG_SAMPLESTAMPS > 0
reportHandler->printDebug("[%u]", (va_list)&renderedSampleCount);
#endif
reportHandler->printDebug(fmt, ap);
#define MT32EMU_PRINT_DEBUG \
va_list ap; \
va_start(ap, fmt); \
reportHandler->printDebug(fmt, ap); \
va_end(ap);
#if MT32EMU_DEBUG_SAMPLESTAMPS > 0
static inline void printSamplestamp(ReportHandler *reportHandler, const char *fmt, ...) {
MT32EMU_PRINT_DEBUG
}
#endif
void Synth::printDebug(const char *fmt, ...) {
#if MT32EMU_DEBUG_SAMPLESTAMPS > 0
printSamplestamp(reportHandler, "[%u]", renderedSampleCount);
#endif
MT32EMU_PRINT_DEBUG
}
#undef MT32EMU_PRINT_DEBUG
void Synth::setReverbEnabled(bool newReverbEnabled) {
if (!opened) return;
@@ -332,9 +362,9 @@ void Synth::setReverbEnabled(bool newReverbEnabled) {
refreshSystemReverbParameters();
reverbOverridden = oldReverbOverridden;
} else {
#if MT32EMU_REDUCE_REVERB_MEMORY
reverbModel->close();
#endif
if (!extensions.preallocatedReverbMemory) {
reverbModel->close();
}
reverbModel = NULL;
}
}
@@ -355,7 +385,7 @@ void Synth::setReverbCompatibilityMode(bool mt32CompatibleMode) {
if (!opened || (isMT32ReverbCompatibilityMode() == mt32CompatibleMode)) return;
bool oldReverbEnabled = isReverbEnabled();
setReverbEnabled(false);
for (int i = 0; i < 4; i++) {
for (int i = REVERB_MODE_ROOM; i <= REVERB_MODE_TAP_DELAY; i++) {
delete reverbModels[i];
}
initReverbModels(mt32CompatibleMode);
@@ -371,6 +401,19 @@ bool Synth::isDefaultReverbMT32Compatible() const {
return opened && controlROMFeatures->defaultReverbMT32Compatible;
}
void Synth::preallocateReverbMemory(bool enabled) {
if (extensions.preallocatedReverbMemory == enabled) return;
extensions.preallocatedReverbMemory = enabled;
if (!opened) return;
for (int i = REVERB_MODE_ROOM; i <= REVERB_MODE_TAP_DELAY; i++) {
if (enabled) {
reverbModels[i]->open();
} else if (reverbModel != reverbModels[i]) {
reverbModels[i]->close();
}
}
}
void Synth::setDACInputMode(DACInputMode mode) {
dacInputMode = mode;
}
@@ -423,6 +466,22 @@ bool Synth::isNiceAmpRampEnabled() const {
return extensions.niceAmpRamp;
}
void Synth::setNicePanningEnabled(bool enabled) {
extensions.nicePanning = enabled;
}
bool Synth::isNicePanningEnabled() const {
return extensions.nicePanning;
}
void Synth::setNicePartialMixingEnabled(bool enabled) {
extensions.nicePartialMixing = enabled;
}
bool Synth::isNicePartialMixingEnabled() const {
return extensions.nicePartialMixing;
}
bool Synth::loadControlROM(const ROMImage &controlROMImage) {
File *file = controlROMImage.getFile();
const ROMInfo *controlROMInfo = controlROMImage.getROMInfo();
@@ -565,15 +624,13 @@ bool Synth::initTimbres(Bit16u mapAddress, Bit16u offset, Bit16u count, Bit16u s
}
void Synth::initReverbModels(bool mt32CompatibleMode) {
reverbModels[REVERB_MODE_ROOM] = BReverbModel::createBReverbModel(REVERB_MODE_ROOM, mt32CompatibleMode, getSelectedRendererType());
reverbModels[REVERB_MODE_HALL] = BReverbModel::createBReverbModel(REVERB_MODE_HALL, mt32CompatibleMode, getSelectedRendererType());
reverbModels[REVERB_MODE_PLATE] = BReverbModel::createBReverbModel(REVERB_MODE_PLATE, mt32CompatibleMode, getSelectedRendererType());
reverbModels[REVERB_MODE_TAP_DELAY] = BReverbModel::createBReverbModel(REVERB_MODE_TAP_DELAY, mt32CompatibleMode, getSelectedRendererType());
#if !MT32EMU_REDUCE_REVERB_MEMORY
for (int i = REVERB_MODE_ROOM; i <= REVERB_MODE_TAP_DELAY; i++) {
reverbModels[i]->open();
for (int mode = REVERB_MODE_ROOM; mode <= REVERB_MODE_TAP_DELAY; mode++) {
reverbModels[mode] = BReverbModel::createBReverbModel(ReverbMode(mode), mt32CompatibleMode, getSelectedRendererType());
if (extensions.preallocatedReverbMemory) {
reverbModels[mode]->open();
}
}
#endif
}
void Synth::initSoundGroups(char newSoundGroupNames[][9]) {
@@ -594,6 +651,7 @@ bool Synth::open(const ROMImage &controlROMImage, const ROMImage &pcmROMImage, B
}
partialCount = usePartialCount;
abortingPoly = NULL;
extensions.abortingPartIx = 0;
// This is to help detect bugs
memset(&mt32ram, '?', sizeof(mt32ram));
@@ -751,7 +809,7 @@ bool Synth::open(const ROMImage &controlROMImage, const ROMImage &pcmROMImage, B
// For resetting mt32 mid-execution
mt32default = mt32ram;
midiQueue = new MidiEventQueue();
midiQueue = new MidiEventQueue(extensions.midiEventQueueSize, extensions.midiEventQueueSysexStorageBufferSize);
analog = Analog::createAnalog(analogOutputMode, controlROMFeatures->oldMT32AnalogLPF, getSelectedRendererType());
#if MT32EMU_MONITOR_INIT
@@ -820,7 +878,7 @@ void Synth::dispose() {
deleteMemoryRegions();
for (int i = 0; i < 4; i++) {
for (int i = REVERB_MODE_ROOM; i <= REVERB_MODE_TAP_DELAY; i++) {
delete reverbModels[i];
reverbModels[i] = NULL;
}
@@ -840,26 +898,24 @@ bool Synth::isOpen() const {
}
void Synth::flushMIDIQueue() {
if (midiQueue != NULL) {
for (;;) {
const MidiEvent *midiEvent = midiQueue->peekMidiEvent();
if (midiEvent == NULL) break;
if (midiEvent->sysexData == NULL) {
playMsgNow(midiEvent->shortMessageData);
} else {
playSysexNow(midiEvent->sysexData, midiEvent->sysexLength);
}
midiQueue->dropMidiEvent();
if (midiQueue == NULL) return;
for (;;) {
const volatile MidiEventQueue::MidiEvent *midiEvent = midiQueue->peekMidiEvent();
if (midiEvent == NULL) break;
if (midiEvent->sysexData == NULL) {
playMsgNow(midiEvent->shortMessageData);
} else {
playSysexNow(midiEvent->sysexData, midiEvent->sysexLength);
}
lastReceivedMIDIEventTimestamp = renderedSampleCount;
midiQueue->dropMidiEvent();
}
lastReceivedMIDIEventTimestamp = renderedSampleCount;
}
Bit32u Synth::setMIDIEventQueueSize(Bit32u useSize) {
static const Bit32u MAX_QUEUE_SIZE = (1 << 24); // This results in about 256 Mb - much greater than any reasonable value
if (midiQueue == NULL) return 0;
flushMIDIQueue();
if (extensions.midiEventQueueSize == useSize) return useSize;
// Find a power of 2 that is >= useSize
Bit32u binarySize = 1;
@@ -869,11 +925,26 @@ Bit32u Synth::setMIDIEventQueueSize(Bit32u useSize) {
} else {
binarySize = MAX_QUEUE_SIZE;
}
delete midiQueue;
midiQueue = new MidiEventQueue(binarySize);
extensions.midiEventQueueSize = binarySize;
if (midiQueue != NULL) {
flushMIDIQueue();
delete midiQueue;
midiQueue = new MidiEventQueue(binarySize, extensions.midiEventQueueSysexStorageBufferSize);
}
return binarySize;
}
void Synth::configureMIDIEventQueueSysexStorage(Bit32u storageBufferSize) {
if (extensions.midiEventQueueSysexStorageBufferSize == storageBufferSize) return;
extensions.midiEventQueueSysexStorageBufferSize = storageBufferSize;
if (midiQueue != NULL) {
flushMIDIQueue();
delete midiQueue;
midiQueue = new MidiEventQueue(extensions.midiEventQueueSize, storageBufferSize);
}
}
Bit32u Synth::getShortMessageLength(Bit32u msg) {
if ((msg & 0xF0) == 0xF0) {
switch (msg & 0xFF) {
@@ -955,14 +1026,24 @@ void Synth::playMsgNow(Bit32u msg) {
//printDebug("Playing chan %d, code 0x%01x note: 0x%02x", chan, code, note);
Bit8u part = chantable[chan];
if (part > 8) {
Bit8u *chanParts = extensions.chantable[chan];
if (*chanParts > 8) {
#if MT32EMU_MONITOR_MIDI > 0
printDebug("Play msg on unreg chan %d (%d): code=0x%01x, vel=%d", chan, part, code, velocity);
printDebug("Play msg on unreg chan %d (%d): code=0x%01x, vel=%d", chan, *chanParts, code, velocity);
#endif
return;
}
playMsgOnPart(part, code, note, velocity);
for (Bit32u i = extensions.abortingPartIx; i <= 8; i++) {
const Bit32u partNum = chanParts[i];
if (partNum > 8) break;
playMsgOnPart(partNum, code, note, velocity);
if (isAbortingPoly()) {
extensions.abortingPartIx = i;
break;
} else if (extensions.abortingPartIx) {
extensions.abortingPartIx = 0;
}
}
}
void Synth::playMsgOnPart(Bit8u part, Bit8u code, Bit8u note, Bit8u velocity) {
@@ -1153,7 +1234,7 @@ void Synth::playSysexWithoutHeader(Bit8u device, Bit8u command, const Bit8u *sys
break;
}
*/
// Deliberate fall-through
// Fall-through
case SYSEX_CMD_DT1:
writeSysex(device, sysex, len);
break;
@@ -1163,7 +1244,7 @@ void Synth::playSysexWithoutHeader(Bit8u device, Bit8u command, const Bit8u *sys
// FIXME: We should send SYSEX_CMD_RJC in this case
break;
}
// Deliberate fall-through
// Fall-through
case SYSEX_CMD_RQ1:
readSysex(device, sysex, len);
break;
@@ -1193,45 +1274,59 @@ void Synth::writeSysex(Bit8u device, const Bit8u *sysex, Bit32u len) {
printDebug("WRITE-CHANNEL: Channel %d temp area 0x%06x", device, MT32EMU_SYSEXMEMADDR(addr));
#endif
if (/*addr >= MT32EMU_MEMADDR(0x000000) && */addr < MT32EMU_MEMADDR(0x010000)) {
int offset;
if (chantable[device] > 8) {
addr += MT32EMU_MEMADDR(0x030000);
Bit8u *chanParts = extensions.chantable[device];
if (*chanParts > 8) {
#if MT32EMU_MONITOR_SYSEX > 0
printDebug(" (Channel not mapped to a part... 0 offset)");
#endif
offset = 0;
} else if (chantable[device] == 8) {
#if MT32EMU_MONITOR_SYSEX > 0
printDebug(" (Channel mapped to rhythm... 0 offset)");
#endif
offset = 0;
} else {
offset = chantable[device] * sizeof(MemParams::PatchTemp);
for (Bit32u partIx = 0; partIx <= 8; partIx++) {
if (chanParts[partIx] > 8) break;
int offset;
if (chanParts[partIx] == 8) {
#if MT32EMU_MONITOR_SYSEX > 0
printDebug(" (Setting extra offset to %d)", offset);
printDebug(" (Channel mapped to rhythm... 0 offset)");
#endif
offset = 0;
} else {
offset = chanParts[partIx] * sizeof(MemParams::PatchTemp);
#if MT32EMU_MONITOR_SYSEX > 0
printDebug(" (Setting extra offset to %d)", offset);
#endif
}
writeSysexGlobal(addr + offset, sysex, len);
}
return;
}
addr += MT32EMU_MEMADDR(0x030000) + offset;
} else if (/*addr >= MT32EMU_MEMADDR(0x010000) && */ addr < MT32EMU_MEMADDR(0x020000)) {
addr += MT32EMU_MEMADDR(0x030110) - MT32EMU_MEMADDR(0x010000);
} else if (/*addr >= MT32EMU_MEMADDR(0x020000) && */ addr < MT32EMU_MEMADDR(0x030000)) {
int offset;
if (chantable[device] > 8) {
addr += MT32EMU_MEMADDR(0x040000) - MT32EMU_MEMADDR(0x020000);
Bit8u *chanParts = extensions.chantable[device];
if (*chanParts > 8) {
#if MT32EMU_MONITOR_SYSEX > 0
printDebug(" (Channel not mapped to a part... 0 offset)");
#endif
offset = 0;
} else if (chantable[device] == 8) {
#if MT32EMU_MONITOR_SYSEX > 0
printDebug(" (Channel mapped to rhythm... 0 offset)");
#endif
offset = 0;
} else {
offset = chantable[device] * sizeof(TimbreParam);
for (Bit32u partIx = 0; partIx <= 8; partIx++) {
if (chanParts[partIx] > 8) break;
int offset;
if (chanParts[partIx] == 8) {
#if MT32EMU_MONITOR_SYSEX > 0
printDebug(" (Setting extra offset to %d)", offset);
printDebug(" (Channel mapped to rhythm... 0 offset)");
#endif
offset = 0;
} else {
offset = chanParts[partIx] * sizeof(TimbreParam);
#if MT32EMU_MONITOR_SYSEX > 0
printDebug(" (Setting extra offset to %d)", offset);
#endif
}
writeSysexGlobal(addr + offset, sysex, len);
}
return;
}
addr += MT32EMU_MEMADDR(0x040000) - MT32EMU_MEMADDR(0x020000) + offset;
} else {
#if MT32EMU_MONITOR_SYSEX > 0
printDebug(" Invalid channel");
@@ -1239,8 +1334,11 @@ void Synth::writeSysex(Bit8u device, const Bit8u *sysex, Bit32u len) {
return;
}
}
writeSysexGlobal(addr, sysex, len);
}
// Process device-global sysex (possibly converted from channel-specific sysex above)
// Process device-global sysex (possibly converted from channel-specific sysex above)
void Synth::writeSysexGlobal(Bit32u addr, const Bit8u *sysex, Bit32u len) {
for (;;) {
// Find the appropriate memory region
const MemoryRegion *region = findMemoryRegion(addr);
@@ -1429,7 +1527,7 @@ void Synth::writeMemoryRegion(const MemoryRegion *region, Bit32u addr, Bit32u le
char instrumentName[11];
memcpy(instrumentName, mt32ram.timbres[patchAbsTimbreNum].timbre.common.name, 10);
instrumentName[10] = 0;
Bit8u *n = (Bit8u *)patch;
Bit8u *n = reinterpret_cast<Bit8u *>(patch);
printDebug("WRITE-PATCH (%d-%d@%d..%d): %d; timbre=%d (%s) %02X%02X%02X%02X%02X%02X%02X%02X", first, last, off, off + len, i, patchAbsTimbreNum, instrumentName, n[0], n[1], n[2], n[3], n[4], n[5], n[6], n[7]);
}
#endif
@@ -1614,18 +1712,18 @@ void Synth::refreshSystemReverbParameters() {
reverbModel = reverbModels[mt32ram.system.reverbMode];
}
if (reverbModel != oldReverbModel) {
#if MT32EMU_REDUCE_REVERB_MEMORY
if (oldReverbModel != NULL) {
oldReverbModel->close();
if (extensions.preallocatedReverbMemory) {
if (isReverbEnabled()) {
reverbModel->mute();
}
} else {
if (oldReverbModel != NULL) {
oldReverbModel->close();
}
if (isReverbEnabled()) {
reverbModel->open();
}
}
if (isReverbEnabled()) {
reverbModel->open();
}
#else
if (isReverbEnabled()) {
reverbModel->mute();
}
#endif
}
if (isReverbEnabled()) {
reverbModel->setParameters(mt32ram.system.reverbTime, mt32ram.system.reverbLevel);
@@ -1641,9 +1739,10 @@ void Synth::refreshSystemReserveSettings() {
}
void Synth::refreshSystemChanAssign(Bit8u firstPart, Bit8u lastPart) {
memset(chantable, 0xFF, sizeof(chantable));
memset(extensions.chantable, 0xFF, sizeof(extensions.chantable));
// CONFIRMED: In the case of assigning a channel to multiple parts, the lower part wins.
// CONFIRMED: In the case of assigning a MIDI channel to multiple parts,
// the messages received on that MIDI channel are handled by all the parts.
for (Bit32u i = 0; i <= 8; i++) {
if (parts[i] != NULL && i >= firstPart && i <= lastPart) {
// CONFIRMED: Decay is started for all polys, and all controllers are reset, for every part whose assignment was touched by the sysex write.
@@ -1651,8 +1750,13 @@ void Synth::refreshSystemChanAssign(Bit8u firstPart, Bit8u lastPart) {
parts[i]->resetAllControllers();
}
Bit8u chan = mt32ram.system.chanAssign[i];
if (chan < 16 && chantable[chan] > 8) {
chantable[chan] = Bit8u(i);
if (chan > 15) continue;
Bit8u *chanParts = extensions.chantable[chan];
for (Bit32u j = 0; j <= 8; j++) {
if (chanParts[j] > 8) {
chanParts[j] = Bit8u(i);
break;
}
}
}
@@ -1712,40 +1816,120 @@ Bit32s Synth::getMasterTunePitchDelta() const {
return extensions.masterTunePitchDelta;
}
MidiEvent::~MidiEvent() {
if (sysexData != NULL) {
/** Defines an interface of a class that maintains storage of variable-sized data of SysEx messages. */
class MidiEventQueue::SysexDataStorage {
public:
static MidiEventQueue::SysexDataStorage *create(Bit32u storageBufferSize);
virtual ~SysexDataStorage() {}
virtual Bit8u *allocate(Bit32u sysexLength) = 0;
virtual void reclaimUnused(const Bit8u *sysexData, Bit32u sysexLength) = 0;
virtual void dispose(const Bit8u *sysexData, Bit32u sysexLength) = 0;
};
/** Storage space for SysEx data is allocated dynamically on demand and is disposed lazily. */
class DynamicSysexDataStorage : public MidiEventQueue::SysexDataStorage {
public:
Bit8u *allocate(Bit32u sysexLength) {
return new Bit8u[sysexLength];
}
void reclaimUnused(const Bit8u *, Bit32u) {}
void dispose(const Bit8u *sysexData, Bit32u) {
delete[] sysexData;
}
};
/**
* SysEx data is stored in a preallocated buffer, that makes this kind of storage safe
* for use in a realtime thread. Additionally, the space retained by a SysEx event,
* that has been processed and thus is no longer necessary, is disposed instantly.
*/
class BufferedSysexDataStorage : public MidiEventQueue::SysexDataStorage {
public:
explicit BufferedSysexDataStorage(Bit32u useStorageBufferSize) :
storageBuffer(new Bit8u[useStorageBufferSize]),
storageBufferSize(useStorageBufferSize),
startPosition(),
endPosition()
{}
~BufferedSysexDataStorage() {
delete[] storageBuffer;
}
Bit8u *allocate(Bit32u sysexLength) {
Bit32u myStartPosition = startPosition;
Bit32u myEndPosition = endPosition;
// When the free space isn't contiguous, the data is allocated either right after the end position
// or at the buffer beginning, wherever it fits.
if (myStartPosition > myEndPosition) {
if (myStartPosition - myEndPosition <= sysexLength) return NULL;
} else if (storageBufferSize - myEndPosition < sysexLength) {
// There's not enough free space at the end to place the data block.
if (myStartPosition == myEndPosition) {
// The buffer is empty -> reset positions to the buffer beginning.
if (storageBufferSize <= sysexLength) return NULL;
if (myStartPosition != 0) {
myStartPosition = 0;
// It's OK to write startPosition here non-atomically. We don't expect any
// concurrent reads, as there must be no SysEx messages in the queue.
startPosition = myStartPosition;
}
} else if (myStartPosition <= sysexLength) return NULL;
myEndPosition = 0;
}
endPosition = myEndPosition + sysexLength;
return storageBuffer + myEndPosition;
}
void reclaimUnused(const Bit8u *sysexData, Bit32u sysexLength) {
if (sysexData == NULL) return;
Bit32u allocatedPosition = startPosition;
if (storageBuffer + allocatedPosition == sysexData) {
startPosition = allocatedPosition + sysexLength;
} else if (storageBuffer == sysexData) {
// Buffer wrapped around.
startPosition = sysexLength;
}
}
void dispose(const Bit8u *, Bit32u) {}
private:
Bit8u * const storageBuffer;
const Bit32u storageBufferSize;
volatile Bit32u startPosition;
volatile Bit32u endPosition;
};
MidiEventQueue::SysexDataStorage *MidiEventQueue::SysexDataStorage::create(Bit32u storageBufferSize) {
if (storageBufferSize > 0) {
return new BufferedSysexDataStorage(storageBufferSize);
} else {
return new DynamicSysexDataStorage;
}
}
void MidiEvent::setShortMessage(Bit32u useShortMessageData, Bit32u useTimestamp) {
if (sysexData != NULL) {
delete[] sysexData;
MidiEventQueue::MidiEventQueue(Bit32u useRingBufferSize, Bit32u storageBufferSize) :
sysexDataStorage(*SysexDataStorage::create(storageBufferSize)),
ringBuffer(new MidiEvent[useRingBufferSize]), ringBufferMask(useRingBufferSize - 1)
{
for (Bit32u i = 0; i <= ringBufferMask; i++) {
ringBuffer[i].sysexData = NULL;
}
shortMessageData = useShortMessageData;
timestamp = useTimestamp;
sysexData = NULL;
sysexLength = 0;
}
void MidiEvent::setSysex(const Bit8u *useSysexData, Bit32u useSysexLength, Bit32u useTimestamp) {
if (sysexData != NULL) {
delete[] sysexData;
}
shortMessageData = 0;
timestamp = useTimestamp;
sysexLength = useSysexLength;
Bit8u *dstSysexData = new Bit8u[sysexLength];
sysexData = dstSysexData;
memcpy(dstSysexData, useSysexData, sysexLength);
}
MidiEventQueue::MidiEventQueue(Bit32u useRingBufferSize) : ringBuffer(new MidiEvent[useRingBufferSize]), ringBufferMask(useRingBufferSize - 1) {
memset(ringBuffer, 0, useRingBufferSize * sizeof(MidiEvent));
reset();
}
MidiEventQueue::~MidiEventQueue() {
for (Bit32u i = 0; i <= ringBufferMask; i++) {
volatile MidiEvent &currentEvent = ringBuffer[i];
sysexDataStorage.dispose(currentEvent.sysexData, currentEvent.sysexLength);
}
delete &sysexDataStorage;
delete[] ringBuffer;
}
@@ -1756,35 +1940,42 @@ void MidiEventQueue::reset() {
bool MidiEventQueue::pushShortMessage(Bit32u shortMessageData, Bit32u timestamp) {
Bit32u newEndPosition = (endPosition + 1) & ringBufferMask;
// Is ring buffer full?
// If ring buffer is full, bail out.
if (startPosition == newEndPosition) return false;
ringBuffer[endPosition].setShortMessage(shortMessageData, timestamp);
volatile MidiEvent &newEvent = ringBuffer[endPosition];
sysexDataStorage.dispose(newEvent.sysexData, newEvent.sysexLength);
newEvent.sysexData = NULL;
newEvent.shortMessageData = shortMessageData;
newEvent.timestamp = timestamp;
endPosition = newEndPosition;
return true;
}
bool MidiEventQueue::pushSysex(const Bit8u *sysexData, Bit32u sysexLength, Bit32u timestamp) {
Bit32u newEndPosition = (endPosition + 1) & ringBufferMask;
// Is ring buffer full?
// If ring buffer is full, bail out.
if (startPosition == newEndPosition) return false;
ringBuffer[endPosition].setSysex(sysexData, sysexLength, timestamp);
volatile MidiEvent &newEvent = ringBuffer[endPosition];
sysexDataStorage.dispose(newEvent.sysexData, newEvent.sysexLength);
Bit8u *dstSysexData = sysexDataStorage.allocate(sysexLength);
if (dstSysexData == NULL) return false;
memcpy(dstSysexData, sysexData, sysexLength);
newEvent.sysexData = dstSysexData;
newEvent.sysexLength = sysexLength;
newEvent.timestamp = timestamp;
endPosition = newEndPosition;
return true;
}
const MidiEvent *MidiEventQueue::peekMidiEvent() {
const volatile MidiEventQueue::MidiEvent *MidiEventQueue::peekMidiEvent() {
return isEmpty() ? NULL : &ringBuffer[startPosition];
}
void MidiEventQueue::dropMidiEvent() {
// Is ring buffer empty?
if (startPosition != endPosition) {
startPosition = (startPosition + 1) & ringBufferMask;
}
}
bool MidiEventQueue::isFull() const {
return startPosition == ((endPosition + 1) & ringBufferMask);
if (isEmpty()) return;
volatile MidiEvent &unusedEvent = ringBuffer[startPosition];
sysexDataStorage.reclaimUnused(unusedEvent.sysexData, unusedEvent.sysexLength);
startPosition = (startPosition + 1) & ringBufferMask;
}
bool MidiEventQueue::isEmpty() const {
@@ -1923,7 +2114,7 @@ void RendererImpl<Sample>::doRenderStreams(const DACOutputStreams<Sample> &strea
// We need to ensure zero-duration notes will play so add minimum 1-sample delay.
Bit32u thisLen = 1;
if (!isAbortingPoly()) {
const MidiEvent *nextEvent = getMidiQueue().peekMidiEvent();
const volatile MidiEventQueue::MidiEvent *nextEvent = getMidiQueue().peekMidiEvent();
Bit32s samplesToNextEvent = (nextEvent != NULL) ? Bit32s(nextEvent->timestamp - getRenderedSampleCount()) : MAX_SAMPLES_PER_RUN;
if (samplesToNextEvent > 0) {
thisLen = len > MAX_SAMPLES_PER_RUN ? MAX_SAMPLES_PER_RUN : len;

View File

@@ -1,5 +1,5 @@
/* Copyright (C) 2003, 2004, 2005, 2006, 2008, 2009 Dean Beeler, Jerome Fisher
* Copyright (C) 2011-2017 Dean Beeler, Jerome Fisher, Sergey V. Mikayev
* Copyright (C) 2011-2020 Dean Beeler, Jerome Fisher, Sergey V. Mikayev
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
@@ -115,6 +115,7 @@ public:
class Synth {
friend class DefaultMidiStreamParser;
friend class MemoryRegion;
friend class Part;
friend class Partial;
friend class PartialManager;
@@ -153,7 +154,7 @@ private:
const char (*soundGroupNames)[9]; // Array
Bit32u partialCount;
Bit8u chantable[16]; // NOTE: value above 8 means that the channel is not assigned
Bit8u nukeme[16]; // FIXME: Nuke it. For binary compatibility only.
MidiEventQueue *midiQueue;
volatile Bit32u lastReceivedMIDIEventTimestamp;
@@ -198,6 +199,7 @@ private:
Bit32u addMIDIInterfaceDelay(Bit32u len, Bit32u timestamp);
bool isAbortingPoly() const { return abortingPoly != NULL; }
void writeSysexGlobal(Bit32u addr, const Bit8u *sysex, Bit32u len);
void readSysex(Bit8u channel, const Bit8u *sysex, Bit32u len) const;
void initMemoryRegions();
void deleteMemoryRegions();
@@ -310,7 +312,18 @@ public:
// Sets size of the internal MIDI event queue. The queue size is set to the minimum power of 2 that is greater or equal to the size specified.
// The queue is flushed before reallocation.
// Returns the actual queue size being used.
MT32EMU_EXPORT Bit32u setMIDIEventQueueSize(Bit32u);
MT32EMU_EXPORT Bit32u setMIDIEventQueueSize(Bit32u requestedSize);
// Configures the SysEx storage of the internal MIDI event queue.
// Supplying 0 in the storageBufferSize argument makes the SysEx data stored
// in multiple dynamically allocated buffers per MIDI event. These buffers are only disposed
// when a new MIDI event replaces the SysEx event in the queue, thus never on the rendering thread.
// This is the default behaviour.
// In contrast, when a positive value is specified, SysEx data will be stored in a single preallocated buffer,
// which makes this kind of storage safe for use in a realtime thread. Additionally, the space retained
// by a SysEx event, that has been processed and thus is no longer necessary, is disposed instantly.
// Note, the queue is flushed and recreated in the process so that its size remains intact.
MT32EMU_EXPORT void configureMIDIEventQueueSysexStorage(Bit32u storageBufferSize);
// Returns current value of the global counter of samples rendered since the synth was created (at the native sample rate 32000 Hz).
// This method helps to compute accurate timestamp of a MIDI message to use with the methods below.
@@ -378,6 +391,10 @@ public:
MT32EMU_EXPORT bool isMT32ReverbCompatibilityMode() const;
// Returns whether default reverb compatibility mode is the old MT-32 compatibility mode.
MT32EMU_EXPORT bool isDefaultReverbMT32Compatible() const;
// If enabled, reverb buffers for all modes are keept around allocated all the time to avoid memory
// allocating/freeing in the rendering thread, which may be required for realtime operation.
// Otherwise, reverb buffers that are not in use are deleted to save memory (the default behaviour).
MT32EMU_EXPORT void preallocateReverbMemory(bool enabled);
// Sets new DAC input mode. See DACInputMode for details.
MT32EMU_EXPORT void setDACInputMode(DACInputMode mode);
// Returns current DAC input mode. See DACInputMode for details.
@@ -421,6 +438,29 @@ public:
// Returns whether NiceAmpRamp mode is enabled.
MT32EMU_EXPORT bool isNiceAmpRampEnabled() const;
// Allows to toggle the NicePanning mode.
// Despite the Roland's manual specifies allowed panpot values in range 0-14,
// the LA-32 only receives 3-bit pan setting in fact. In particular, this
// makes it impossible to set the "middle" panning for a single partial.
// In the NicePanning mode, we enlarge the pan setting accuracy to 4 bits
// making it smoother thus sacrificing the emulation accuracy.
// This mode is disabled by default.
MT32EMU_EXPORT void setNicePanningEnabled(bool enabled);
// Returns whether NicePanning mode is enabled.
MT32EMU_EXPORT bool isNicePanningEnabled() const;
// Allows to toggle the NicePartialMixing mode.
// LA-32 is known to mix partials either in-phase (so that they are added)
// or in counter-phase (so that they are subtracted instead).
// In some cases, this quirk isn't highly desired because a pair of closely
// sounding partials may occasionally cancel out.
// In the NicePartialMixing mode, the mixing is always performed in-phase,
// thus making the behaviour more predictable.
// This mode is disabled by default.
MT32EMU_EXPORT void setNicePartialMixingEnabled(bool enabled);
// Returns whether NicePartialMixing mode is enabled.
MT32EMU_EXPORT bool isNicePartialMixingEnabled() const;
// Selects new type of the wave generator and renderer to be used during subsequent calls to open().
// By default, RendererType_BIT16S is selected.
// See RendererType for details.

View File

@@ -1,5 +1,5 @@
/* Copyright (C) 2003, 2004, 2005, 2006, 2008, 2009 Dean Beeler, Jerome Fisher
* Copyright (C) 2011-2017 Dean Beeler, Jerome Fisher, Sergey V. Mikayev
* Copyright (C) 2011-2020 Dean Beeler, Jerome Fisher, Sergey V. Mikayev
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by

View File

@@ -1,5 +1,5 @@
/* Copyright (C) 2003, 2004, 2005, 2006, 2008, 2009 Dean Beeler, Jerome Fisher
* Copyright (C) 2011-2017 Dean Beeler, Jerome Fisher, Sergey V. Mikayev
* Copyright (C) 2011-2020 Dean Beeler, Jerome Fisher, Sergey V. Mikayev
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by

View File

@@ -1,5 +1,5 @@
/* Copyright (C) 2003, 2004, 2005, 2006, 2008, 2009 Dean Beeler, Jerome Fisher
* Copyright (C) 2011-2017 Dean Beeler, Jerome Fisher, Sergey V. Mikayev
* Copyright (C) 2011-2020 Dean Beeler, Jerome Fisher, Sergey V. Mikayev
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by

View File

@@ -1,5 +1,5 @@
/* Copyright (C) 2003, 2004, 2005, 2006, 2008, 2009 Dean Beeler, Jerome Fisher
* Copyright (C) 2011-2017 Dean Beeler, Jerome Fisher, Sergey V. Mikayev
* Copyright (C) 2011-2020 Dean Beeler, Jerome Fisher, Sergey V. Mikayev
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by

View File

@@ -1,5 +1,5 @@
/* Copyright (C) 2003, 2004, 2005, 2006, 2008, 2009 Dean Beeler, Jerome Fisher
* Copyright (C) 2011-2017 Dean Beeler, Jerome Fisher, Sergey V. Mikayev
* Copyright (C) 2011-2020 Dean Beeler, Jerome Fisher, Sergey V. Mikayev
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
@@ -104,12 +104,12 @@ static Bit32u calcBasePitch(const Partial *partial, const TimbreParam::PartialPa
// MT-32 GEN0 does 16-bit calculations here, allowing an integer overflow.
// This quirk is observable playing the patch defined for timbre "HIT BOTTOM" in Larry 3.
// Note, the upper bound isn't checked either.
if (controlROMFeatures->quirkBasePitchOverflow) {
basePitch = basePitch & 0xffff;
} else if (basePitch < 0) {
basePitch = 0;
}
if (basePitch > 59392) {
} else if (basePitch > 59392) {
basePitch = 59392;
}
return Bit32u(basePitch);
@@ -151,6 +151,7 @@ void TVP::reset(const Part *usePart, const TimbreParam::PartialParam *usePartial
// FIXME: We're using a per-TVP timer instead of a system-wide one for convenience.
timeElapsed = 0;
processTimerIncrement = 0;
basePitch = calcBasePitch(partial, partialParam, patchTemp, key, partial->getSynth()->controlROMFeatures);
currentPitchOffset = calcTargetPitchOffsetWithoutLFO(partialParam, 0, velocity);
@@ -194,6 +195,7 @@ void TVP::updatePitch() {
} else if (newPitch < 0) {
newPitch = 0;
}
// This check is present in every unit.
if (newPitch > 59392) {
newPitch = 59392;
}

View File

@@ -1,5 +1,5 @@
/* Copyright (C) 2003, 2004, 2005, 2006, 2008, 2009 Dean Beeler, Jerome Fisher
* Copyright (C) 2011-2017 Dean Beeler, Jerome Fisher, Sergey V. Mikayev
* Copyright (C) 2011-2020 Dean Beeler, Jerome Fisher, Sergey V. Mikayev
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by

View File

@@ -1,5 +1,5 @@
/* Copyright (C) 2003, 2004, 2005, 2006, 2008, 2009 Dean Beeler, Jerome Fisher
* Copyright (C) 2011-2017 Dean Beeler, Jerome Fisher, Sergey V. Mikayev
* Copyright (C) 2011-2020 Dean Beeler, Jerome Fisher, Sergey V. Mikayev
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by

View File

@@ -1,5 +1,5 @@
/* Copyright (C) 2003, 2004, 2005, 2006, 2008, 2009 Dean Beeler, Jerome Fisher
* Copyright (C) 2011-2017 Dean Beeler, Jerome Fisher, Sergey V. Mikayev
* Copyright (C) 2011-2020 Dean Beeler, Jerome Fisher, Sergey V. Mikayev
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by

View File

@@ -1,5 +1,5 @@
/* Copyright (C) 2003, 2004, 2005, 2006, 2008, 2009 Dean Beeler, Jerome Fisher
* Copyright (C) 2011-2017 Dean Beeler, Jerome Fisher, Sergey V. Mikayev
* Copyright (C) 2011-2020 Dean Beeler, Jerome Fisher, Sergey V. Mikayev
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by

View File

@@ -1,5 +1,5 @@
/* Copyright (C) 2003, 2004, 2005, 2006, 2008, 2009 Dean Beeler, Jerome Fisher
* Copyright (C) 2011-2017 Dean Beeler, Jerome Fisher, Sergey V. Mikayev
* Copyright (C) 2011-2020 Dean Beeler, Jerome Fisher, Sergey V. Mikayev
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
@@ -41,7 +41,7 @@ static mt32emu_service_version getSynthVersionID(mt32emu_service_i) {
return MT32EMU_SERVICE_VERSION_CURRENT;
}
static const mt32emu_service_i_v2 SERVICE_VTABLE = {
static const mt32emu_service_i_v3 SERVICE_VTABLE = {
getSynthVersionID,
mt32emu_get_supported_report_handler_version,
mt32emu_get_supported_midi_receiver_version,
@@ -112,7 +112,13 @@ static const mt32emu_service_i_v2 SERVICE_VTABLE = {
mt32emu_convert_synth_to_output_timestamp,
mt32emu_get_internal_rendered_sample_count,
mt32emu_set_nice_amp_ramp_enabled,
mt32emu_is_nice_amp_ramp_enabled
mt32emu_is_nice_amp_ramp_enabled,
mt32emu_set_nice_panning_enabled,
mt32emu_is_nice_panning_enabled,
mt32emu_set_nice_partial_mixing_enabled,
mt32emu_is_nice_partial_mixing_enabled,
mt32emu_preallocate_reverb_memory,
mt32emu_configure_midi_event_queue_sysex_storage
};
} // namespace MT32Emu
@@ -323,7 +329,7 @@ extern "C" {
mt32emu_service_i mt32emu_get_service_i() {
mt32emu_service_i i;
i.v2 = &SERVICE_VTABLE;
i.v3 = &SERVICE_VTABLE;
return i;
}
@@ -450,9 +456,7 @@ void mt32emu_set_analog_output_mode(mt32emu_context context, const mt32emu_analo
}
void mt32emu_set_stereo_output_samplerate(mt32emu_context context, const double samplerate) {
if (0.0 <= samplerate) {
context->srcState->outputSampleRate = samplerate;
}
context->srcState->outputSampleRate = SampleRateConverter::getSupportedOutputSampleRate(samplerate);
}
void mt32emu_set_samplerate_conversion_quality(mt32emu_context context, const mt32emu_samplerate_conversion_quality quality) {
@@ -519,6 +523,10 @@ mt32emu_bit32u mt32emu_set_midi_event_queue_size(mt32emu_const_context context,
return context->synth->setMIDIEventQueueSize(queue_size);
}
void mt32emu_configure_midi_event_queue_sysex_storage(mt32emu_const_context context, const mt32emu_bit32u storage_buffer_size) {
return context->synth->configureMIDIEventQueueSysexStorage(storage_buffer_size);
}
void mt32emu_set_midi_receiver(mt32emu_context context, mt32emu_midi_receiver_i midi_receiver, void *instance_data) {
delete context->midiParser;
context->midiParser = (midi_receiver.v0 != NULL) ? new DelegatingMidiStreamParser(context, midi_receiver, instance_data) : new DefaultMidiStreamParser(*context->synth);
@@ -612,6 +620,10 @@ mt32emu_boolean mt32emu_is_default_reverb_mt32_compatible(mt32emu_const_context
return context->synth->isDefaultReverbMT32Compatible() ? MT32EMU_BOOL_TRUE : MT32EMU_BOOL_FALSE;
}
void mt32emu_preallocate_reverb_memory(mt32emu_const_context context, const mt32emu_boolean enabled) {
return context->synth->preallocateReverbMemory(enabled != MT32EMU_BOOL_FALSE);
}
void mt32emu_set_dac_input_mode(mt32emu_const_context context, const mt32emu_dac_input_mode mode) {
context->synth->setDACInputMode(static_cast<DACInputMode>(mode));
}
@@ -660,6 +672,22 @@ mt32emu_boolean mt32emu_is_nice_amp_ramp_enabled(mt32emu_const_context context)
return context->synth->isNiceAmpRampEnabled() ? MT32EMU_BOOL_TRUE : MT32EMU_BOOL_FALSE;
}
MT32EMU_EXPORT void mt32emu_set_nice_panning_enabled(mt32emu_const_context context, const mt32emu_boolean enabled) {
context->synth->setNicePanningEnabled(enabled != MT32EMU_BOOL_FALSE);
}
MT32EMU_EXPORT mt32emu_boolean mt32emu_is_nice_panning_enabled(mt32emu_const_context context) {
return context->synth->isNicePanningEnabled() ? MT32EMU_BOOL_TRUE : MT32EMU_BOOL_FALSE;
}
MT32EMU_EXPORT void mt32emu_set_nice_partial_mixing_enabled(mt32emu_const_context context, const mt32emu_boolean enabled) {
context->synth->setNicePartialMixingEnabled(enabled != MT32EMU_BOOL_FALSE);
}
MT32EMU_EXPORT mt32emu_boolean mt32emu_is_nice_partial_mixing_enabled(mt32emu_const_context context) {
return context->synth->isNicePartialMixingEnabled() ? MT32EMU_BOOL_TRUE : MT32EMU_BOOL_FALSE;
}
void mt32emu_render_bit16s(mt32emu_const_context context, mt32emu_bit16s *stream, mt32emu_bit32u len) {
if (context->srcState->src != NULL) {
context->srcState->src->getOutputSamples(stream, len);

View File

@@ -1,5 +1,5 @@
/* Copyright (C) 2003, 2004, 2005, 2006, 2008, 2009 Dean Beeler, Jerome Fisher
* Copyright (C) 2011-2017 Dean Beeler, Jerome Fisher, Sergey V. Mikayev
* Copyright (C) 2011-2020 Dean Beeler, Jerome Fisher, Sergey V. Mikayev
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
@@ -35,7 +35,7 @@ extern "C" {
/* === Interface handling === */
/** Returns mt32emu_service_i interface. */
MT32EMU_EXPORT mt32emu_service_i mt32emu_get_service_i();
MT32EMU_EXPORT mt32emu_service_i mt32emu_get_service_i(void);
#if MT32EMU_EXPORTS_TYPE == 2
#undef MT32EMU_EXPORT
@@ -46,13 +46,13 @@ MT32EMU_EXPORT mt32emu_service_i mt32emu_get_service_i();
* Returns the version ID of mt32emu_report_handler_i interface the library has been compiled with.
* This allows a client to fall-back gracefully instead of silently not receiving expected event reports.
*/
MT32EMU_EXPORT mt32emu_report_handler_version mt32emu_get_supported_report_handler_version();
MT32EMU_EXPORT mt32emu_report_handler_version mt32emu_get_supported_report_handler_version(void);
/**
* Returns the version ID of mt32emu_midi_receiver_version_i interface the library has been compiled with.
* This allows a client to fall-back gracefully instead of silently not receiving expected MIDI messages.
*/
MT32EMU_EXPORT mt32emu_midi_receiver_version mt32emu_get_supported_midi_receiver_version();
MT32EMU_EXPORT mt32emu_midi_receiver_version mt32emu_get_supported_midi_receiver_version(void);
/**
* Returns library version as an integer in format: 0x00MMmmpp, where:
@@ -60,12 +60,12 @@ MT32EMU_EXPORT mt32emu_midi_receiver_version mt32emu_get_supported_midi_receiver
* mm - minor version number
* pp - patch number
*/
MT32EMU_EXPORT mt32emu_bit32u mt32emu_get_library_version_int();
MT32EMU_EXPORT mt32emu_bit32u mt32emu_get_library_version_int(void);
/**
* Returns library version as a C-string in format: "MAJOR.MINOR.PATCH".
*/
MT32EMU_EXPORT const char *mt32emu_get_library_version_string();
MT32EMU_EXPORT const char *mt32emu_get_library_version_string(void);
/**
* Returns output sample rate used in emulation of stereo analog circuitry of hardware units for particular analog_output_mode.
@@ -201,6 +201,19 @@ MT32EMU_EXPORT void mt32emu_flush_midi_queue(mt32emu_const_context context);
*/
MT32EMU_EXPORT mt32emu_bit32u mt32emu_set_midi_event_queue_size(mt32emu_const_context context, const mt32emu_bit32u queue_size);
/**
* Configures the SysEx storage of the internal MIDI event queue.
* Supplying 0 in the storage_buffer_size argument makes the SysEx data stored
* in multiple dynamically allocated buffers per MIDI event. These buffers are only disposed
* when a new MIDI event replaces the SysEx event in the queue, thus never on the rendering thread.
* This is the default behaviour.
* In contrast, when a positive value is specified, SysEx data will be stored in a single preallocated buffer,
* which makes this kind of storage safe for use in a realtime thread. Additionally, the space retained
* by a SysEx event, that has been processed and thus is no longer necessary, is disposed instantly.
* Note, the queue is flushed and recreated in the process so that its size remains intact.
*/
void mt32emu_configure_midi_event_queue_sysex_storage(mt32emu_const_context context, const mt32emu_bit32u storage_buffer_size);
/**
* Installs custom MIDI receiver object intended for receiving MIDI messages generated by MIDI stream parser.
* MIDI stream parser is involved when functions mt32emu_parse_stream() and mt32emu_play_short_message() or the likes are called.
@@ -316,6 +329,13 @@ MT32EMU_EXPORT mt32emu_boolean mt32emu_is_mt32_reverb_compatibility_mode(mt32emu
/** Returns whether default reverb compatibility mode is the old MT-32 compatibility mode. */
MT32EMU_EXPORT mt32emu_boolean mt32emu_is_default_reverb_mt32_compatible(mt32emu_const_context context);
/**
* If enabled, reverb buffers for all modes are keept around allocated all the time to avoid memory
* allocating/freeing in the rendering thread, which may be required for realtime operation.
* Otherwise, reverb buffers that are not in use are deleted to save memory (the default behaviour).
*/
MT32EMU_EXPORT void mt32emu_preallocate_reverb_memory(mt32emu_const_context context, const mt32emu_boolean enabled);
/** Sets new DAC input mode. See mt32emu_dac_input_mode for details. */
MT32EMU_EXPORT void mt32emu_set_dac_input_mode(mt32emu_const_context context, const mt32emu_dac_input_mode mode);
/** Returns current DAC input mode. See mt32emu_dac_input_mode for details. */
@@ -366,6 +386,33 @@ MT32EMU_EXPORT void mt32emu_set_nice_amp_ramp_enabled(mt32emu_const_context cont
/** Returns whether NiceAmpRamp mode is enabled. */
MT32EMU_EXPORT mt32emu_boolean mt32emu_is_nice_amp_ramp_enabled(mt32emu_const_context context);
/**
* Allows to toggle the NicePanning mode.
* Despite the Roland's manual specifies allowed panpot values in range 0-14,
* the LA-32 only receives 3-bit pan setting in fact. In particular, this
* makes it impossible to set the "middle" panning for a single partial.
* In the NicePanning mode, we enlarge the pan setting accuracy to 4 bits
* making it smoother thus sacrificing the emulation accuracy.
* This mode is disabled by default.
*/
MT32EMU_EXPORT void mt32emu_set_nice_panning_enabled(mt32emu_const_context context, const mt32emu_boolean enabled);
/** Returns whether NicePanning mode is enabled. */
MT32EMU_EXPORT mt32emu_boolean mt32emu_is_nice_panning_enabled(mt32emu_const_context context);
/**
* Allows to toggle the NicePartialMixing mode.
* LA-32 is known to mix partials either in-phase (so that they are added)
* or in counter-phase (so that they are subtracted instead).
* In some cases, this quirk isn't highly desired because a pair of closely
* sounding partials may occasionally cancel out.
* In the NicePartialMixing mode, the mixing is always performed in-phase,
* thus making the behaviour more predictable.
* This mode is disabled by default.
*/
MT32EMU_EXPORT void mt32emu_set_nice_partial_mixing_enabled(mt32emu_const_context context, const mt32emu_boolean enabled);
/** Returns whether NicePartialMixing mode is enabled. */
MT32EMU_EXPORT mt32emu_boolean mt32emu_is_nice_partial_mixing_enabled(mt32emu_const_context context);
/**
* Renders samples to the specified output stream as if they were sampled at the analog stereo output at the desired sample rate.
* If the output sample rate is not specified explicitly, the default output sample rate is used which depends on the current

View File

@@ -1,5 +1,5 @@
/* Copyright (C) 2003, 2004, 2005, 2006, 2008, 2009 Dean Beeler, Jerome Fisher
* Copyright (C) 2011-2017 Dean Beeler, Jerome Fisher, Sergey V. Mikayev
* Copyright (C) 2011-2020 Dean Beeler, Jerome Fisher, Sergey V. Mikayev
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
@@ -121,7 +121,8 @@ typedef enum {
MT32EMU_SERVICE_VERSION_0 = 0,
MT32EMU_SERVICE_VERSION_1 = 1,
MT32EMU_SERVICE_VERSION_2 = 2,
MT32EMU_SERVICE_VERSION_CURRENT = MT32EMU_SERVICE_VERSION_2
MT32EMU_SERVICE_VERSION_3 = 3,
MT32EMU_SERVICE_VERSION_CURRENT = MT32EMU_SERVICE_VERSION_3
} mt32emu_service_version;
/* === Report Handler Interface === */
@@ -216,11 +217,11 @@ typedef union mt32emu_service_i mt32emu_service_i;
#define MT32EMU_SERVICE_I_V0 \
/** Returns the actual interface version ID */ \
mt32emu_service_version (*getVersionID)(mt32emu_service_i i); \
mt32emu_report_handler_version (*getSupportedReportHandlerVersionID)(); \
mt32emu_midi_receiver_version (*getSupportedMIDIReceiverVersionID)(); \
mt32emu_report_handler_version (*getSupportedReportHandlerVersionID)(void); \
mt32emu_midi_receiver_version (*getSupportedMIDIReceiverVersionID)(void); \
\
mt32emu_bit32u (*getLibraryVersionInt)(); \
const char *(*getLibraryVersionString)(); \
mt32emu_bit32u (*getLibraryVersionInt)(void); \
const char *(*getLibraryVersionString)(void); \
\
mt32emu_bit32u (*getStereoOutputSamplerate)(const mt32emu_analog_output_mode analog_output_mode); \
\
@@ -303,6 +304,14 @@ typedef union mt32emu_service_i mt32emu_service_i;
void (*setNiceAmpRampEnabled)(mt32emu_const_context context, const mt32emu_boolean enabled); \
mt32emu_boolean (*isNiceAmpRampEnabled)(mt32emu_const_context context);
#define MT32EMU_SERVICE_I_V3 \
void (*setNicePanningEnabled)(mt32emu_const_context context, const mt32emu_boolean enabled); \
mt32emu_boolean (*isNicePanningEnabled)(mt32emu_const_context context); \
void (*setNicePartialMixingEnabled)(mt32emu_const_context context, const mt32emu_boolean enabled); \
mt32emu_boolean (*isNicePartialMixingEnabled)(mt32emu_const_context context); \
void (*preallocateReverbMemory)(mt32emu_const_context context, const mt32emu_boolean enabled); \
void (*configureMIDIEventQueueSysexStorage)(mt32emu_const_context context, const mt32emu_bit32u storage_buffer_size);
typedef struct {
MT32EMU_SERVICE_I_V0
} mt32emu_service_i_v0;
@@ -318,6 +327,13 @@ typedef struct {
MT32EMU_SERVICE_I_V2
} mt32emu_service_i_v2;
typedef struct {
MT32EMU_SERVICE_I_V0
MT32EMU_SERVICE_I_V1
MT32EMU_SERVICE_I_V2
MT32EMU_SERVICE_I_V3
} mt32emu_service_i_v3;
/**
* Extensible interface for all the library services.
* Union intended to view an interface of any subsequent version as any parent interface not requiring a cast.
@@ -327,10 +343,12 @@ union mt32emu_service_i {
const mt32emu_service_i_v0 *v0;
const mt32emu_service_i_v1 *v1;
const mt32emu_service_i_v2 *v2;
const mt32emu_service_i_v3 *v3;
};
#undef MT32EMU_SERVICE_I_V0
#undef MT32EMU_SERVICE_I_V1
#undef MT32EMU_SERVICE_I_V2
#undef MT32EMU_SERVICE_I_V3
#endif /* #ifndef MT32EMU_C_TYPES_H */

View File

@@ -1,5 +1,5 @@
/* Copyright (C) 2003, 2004, 2005, 2006, 2008, 2009 Dean Beeler, Jerome Fisher
* Copyright (C) 2011-2017 Dean Beeler, Jerome Fisher, Sergey V. Mikayev
* Copyright (C) 2011-2020 Dean Beeler, Jerome Fisher, Sergey V. Mikayev
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
@@ -60,6 +60,7 @@ mt32emu_service_i mt32emu_get_service_i();
#define mt32emu_convert_synth_to_output_timestamp iV1()->convertSynthToOutputTimestamp
#define mt32emu_flush_midi_queue i.v0->flushMIDIQueue
#define mt32emu_set_midi_event_queue_size i.v0->setMIDIEventQueueSize
#define mt32emu_configure_midi_event_queue_sysex_storage iV3()->configureMIDIEventQueueSysexStorage
#define mt32emu_set_midi_receiver i.v0->setMIDIReceiver
#define mt32emu_get_internal_rendered_sample_count iV2()->getInternalRenderedSampleCount
#define mt32emu_parse_stream i.v0->parseStream
@@ -81,6 +82,7 @@ mt32emu_service_i mt32emu_get_service_i();
#define mt32emu_set_reverb_compatibility_mode i.v0->setReverbCompatibilityMode
#define mt32emu_is_mt32_reverb_compatibility_mode i.v0->isMT32ReverbCompatibilityMode
#define mt32emu_is_default_reverb_mt32_compatible i.v0->isDefaultReverbMT32Compatible
#define mt32emu_preallocate_reverb_memory iV3()->preallocateReverbMemory
#define mt32emu_set_dac_input_mode i.v0->setDACInputMode
#define mt32emu_get_dac_input_mode i.v0->getDACInputMode
#define mt32emu_set_midi_delay_mode i.v0->setMIDIDelayMode
@@ -93,6 +95,10 @@ mt32emu_service_i mt32emu_get_service_i();
#define mt32emu_is_reversed_stereo_enabled i.v0->isReversedStereoEnabled
#define mt32emu_set_nice_amp_ramp_enabled iV2()->setNiceAmpRampEnabled
#define mt32emu_is_nice_amp_ramp_enabled iV2()->isNiceAmpRampEnabled
#define mt32emu_set_nice_panning_enabled iV3()->setNicePanningEnabled
#define mt32emu_is_nice_panning_enabled iV3()->isNicePanningEnabled
#define mt32emu_set_nice_partial_mixing_enabled iV3()->setNicePartialMixingEnabled
#define mt32emu_is_nice_partial_mixing_enabled iV3()->isNicePartialMixingEnabled
#define mt32emu_render_bit16s i.v0->renderBit16s
#define mt32emu_render_float i.v0->renderFloat
#define mt32emu_render_bit16s_streams i.v0->renderBit16sStreams
@@ -213,6 +219,7 @@ public:
Bit32u convertSynthToOutputTimestamp(Bit32u synth_timestamp) { return mt32emu_convert_synth_to_output_timestamp(c, synth_timestamp); }
void flushMIDIQueue() { mt32emu_flush_midi_queue(c); }
Bit32u setMIDIEventQueueSize(const Bit32u queue_size) { return mt32emu_set_midi_event_queue_size(c, queue_size); }
void configureMIDIEventQueueSysexStorage(const Bit32u storage_buffer_size) { mt32emu_configure_midi_event_queue_sysex_storage(c, storage_buffer_size); }
void setMIDIReceiver(mt32emu_midi_receiver_i midi_receiver, void *instance_data) { mt32emu_set_midi_receiver(c, midi_receiver, instance_data); }
void setMIDIReceiver(IMidiReceiver &midi_receiver) { setMIDIReceiver(CppInterfaceImpl::getMidiReceiverThunk(), &midi_receiver); }
@@ -238,6 +245,7 @@ public:
void setReverbCompatibilityMode(const bool mt32_compatible_mode) { mt32emu_set_reverb_compatibility_mode(c, mt32_compatible_mode ? MT32EMU_BOOL_TRUE : MT32EMU_BOOL_FALSE); }
bool isMT32ReverbCompatibilityMode() { return mt32emu_is_mt32_reverb_compatibility_mode(c) != MT32EMU_BOOL_FALSE; }
bool isDefaultReverbMT32Compatible() { return mt32emu_is_default_reverb_mt32_compatible(c) != MT32EMU_BOOL_FALSE; }
void preallocateReverbMemory(const bool enabled) { mt32emu_preallocate_reverb_memory(c, enabled ? MT32EMU_BOOL_TRUE : MT32EMU_BOOL_FALSE); }
void setDACInputMode(const DACInputMode mode) { mt32emu_set_dac_input_mode(c, static_cast<mt32emu_dac_input_mode>(mode)); }
DACInputMode getDACInputMode() { return static_cast<DACInputMode>(mt32emu_get_dac_input_mode(c)); }
@@ -256,6 +264,12 @@ public:
void setNiceAmpRampEnabled(const bool enabled) { mt32emu_set_nice_amp_ramp_enabled(c, enabled ? MT32EMU_BOOL_TRUE : MT32EMU_BOOL_FALSE); }
bool isNiceAmpRampEnabled() { return mt32emu_is_nice_amp_ramp_enabled(c) != MT32EMU_BOOL_FALSE; }
void setNicePanningEnabled(const bool enabled) { mt32emu_set_nice_panning_enabled(c, enabled ? MT32EMU_BOOL_TRUE : MT32EMU_BOOL_FALSE); }
bool isNicePanningEnabled() { return mt32emu_is_nice_panning_enabled(c) != MT32EMU_BOOL_FALSE; }
void setNicePartialMixingEnabled(const bool enabled) { mt32emu_set_nice_partial_mixing_enabled(c, enabled ? MT32EMU_BOOL_TRUE : MT32EMU_BOOL_FALSE); }
bool isNicePartialMixingEnabled() { return mt32emu_is_nice_partial_mixing_enabled(c) != MT32EMU_BOOL_FALSE; }
void renderBit16s(Bit16s *stream, Bit32u len) { mt32emu_render_bit16s(c, stream, len); }
void renderFloat(float *stream, Bit32u len) { mt32emu_render_float(c, stream, len); }
void renderBit16sStreams(const mt32emu_dac_output_bit16s_streams *streams, Bit32u len) { mt32emu_render_bit16s_streams(c, streams, len); }
@@ -279,6 +293,7 @@ private:
#if MT32EMU_API_TYPE == 2
const mt32emu_service_i_v1 *iV1() { return (getVersionID() < MT32EMU_SERVICE_VERSION_1) ? NULL : i.v1; }
const mt32emu_service_i_v2 *iV2() { return (getVersionID() < MT32EMU_SERVICE_VERSION_2) ? NULL : i.v2; }
const mt32emu_service_i_v3 *iV3() { return (getVersionID() < MT32EMU_SERVICE_VERSION_3) ? NULL : i.v3; }
#endif
};
@@ -428,6 +443,7 @@ static mt32emu_midi_receiver_i getMidiReceiverThunk() {
#undef mt32emu_convert_synth_to_output_timestamp
#undef mt32emu_flush_midi_queue
#undef mt32emu_set_midi_event_queue_size
#undef mt32emu_configure_midi_event_queue_sysex_storage
#undef mt32emu_set_midi_receiver
#undef mt32emu_get_internal_rendered_sample_count
#undef mt32emu_parse_stream
@@ -449,6 +465,7 @@ static mt32emu_midi_receiver_i getMidiReceiverThunk() {
#undef mt32emu_set_reverb_compatibility_mode
#undef mt32emu_is_mt32_reverb_compatibility_mode
#undef mt32emu_is_default_reverb_mt32_compatible
#undef mt32emu_preallocate_reverb_memory
#undef mt32emu_set_dac_input_mode
#undef mt32emu_get_dac_input_mode
#undef mt32emu_set_midi_delay_mode
@@ -461,6 +478,10 @@ static mt32emu_midi_receiver_i getMidiReceiverThunk() {
#undef mt32emu_is_reversed_stereo_enabled
#undef mt32emu_set_nice_amp_ramp_enabled
#undef mt32emu_is_nice_amp_ramp_enabled
#undef mt32emu_set_nice_panning_enabled
#undef mt32emu_is_nice_panning_enabled
#undef mt32emu_set_nice_partial_mixing_enabled
#undef mt32emu_is_nice_partial_mixing_enabled
#undef mt32emu_render_bit16s
#undef mt32emu_render_float
#undef mt32emu_render_bit16s_streams

View File

@@ -18,9 +18,9 @@
#ifndef MT32EMU_CONFIG_H
#define MT32EMU_CONFIG_H
#define MT32EMU_VERSION "2.2.0"
#define MT32EMU_VERSION "2.4.0"
#define MT32EMU_VERSION_MAJOR 2
#define MT32EMU_VERSION_MINOR 2
#define MT32EMU_VERSION_MINOR 4
#define MT32EMU_VERSION_PATCH 0
/* Library Exports Configuration
@@ -37,4 +37,9 @@
#define MT32EMU_API_TYPE 0
#define MT32EMU_WITH_LIBSOXR_RESAMPLER 0
#define MT32EMU_WITH_LIBSAMPLERATE_RESAMPLER 0
#define MT32EMU_WITH_INTERNAL_RESAMPLER 1
#endif

View File

@@ -0,0 +1,38 @@
/* Copyright (C) 2003, 2004, 2005, 2006, 2008, 2009 Dean Beeler, Jerome Fisher
* Copyright (C) 2011-2020 Dean Beeler, Jerome Fisher, Sergey V. Mikayev
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation, either version 2.1 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef MT32EMU_CONFIG_H
#define MT32EMU_CONFIG_H
#define MT32EMU_VERSION "@libmt32emu_VERSION@"
#define MT32EMU_VERSION_MAJOR @libmt32emu_VERSION_MAJOR@
#define MT32EMU_VERSION_MINOR @libmt32emu_VERSION_MINOR@
#define MT32EMU_VERSION_PATCH @libmt32emu_VERSION_PATCH@
/* Library Exports Configuration
*
* This reflects the API types actually provided by the library build.
* 0: The full-featured C++ API is only available in this build. The client application may ONLY use MT32EMU_API_TYPE 0.
* 1: The C-compatible API is only available. The library is built as a shared object, only C functions are exported,
* and thus the client application may NOT use MT32EMU_API_TYPE 0.
* 2: The C-compatible API is only available. The library is built as a shared object, only the factory function
* is exported, and thus the client application may ONLY use MT32EMU_API_TYPE 2.
* 3: All the available API types are provided by the library build.
*/
#define MT32EMU_EXPORTS_TYPE @libmt32emu_EXPORTS_TYPE@
#endif

View File

@@ -1,5 +1,5 @@
/* Copyright (C) 2003, 2004, 2005, 2006, 2008, 2009 Dean Beeler, Jerome Fisher
* Copyright (C) 2011-2017 Dean Beeler, Jerome Fisher, Sergey V. Mikayev
* Copyright (C) 2011-2020 Dean Beeler, Jerome Fisher, Sergey V. Mikayev
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by

View File

@@ -1,5 +1,5 @@
/* Copyright (C) 2003, 2004, 2005, 2006, 2008, 2009 Dean Beeler, Jerome Fisher
* Copyright (C) 2011-2017 Dean Beeler, Jerome Fisher, Sergey V. Mikayev
* Copyright (C) 2011-2020 Dean Beeler, Jerome Fisher, Sergey V. Mikayev
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
@@ -81,12 +81,6 @@
// Configuration
// If non-zero, deletes reverb buffers that are not in use to save memory.
// If zero, keeps reverb buffers for all modes around all the time to avoid allocating/freeing in the critical path.
#ifndef MT32EMU_REDUCE_REVERB_MEMORY
#define MT32EMU_REDUCE_REVERB_MEMORY 1
#endif
// 0: Maximum speed at the cost of a bit lower emulation accuracy.
// 1: Maximum achievable emulation accuracy.
#ifndef MT32EMU_BOSS_REVERB_PRECISE_MODE

View File

@@ -1,5 +1,5 @@
/* Copyright (C) 2003, 2004, 2005, 2006, 2008, 2009 Dean Beeler, Jerome Fisher
* Copyright (C) 2011-2017 Dean Beeler, Jerome Fisher, Sergey V. Mikayev
* Copyright (C) 2011-2020 Dean Beeler, Jerome Fisher, Sergey V. Mikayev
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by

View File

@@ -1,5 +1,5 @@
/* Copyright (C) 2003, 2004, 2005, 2006, 2008, 2009 Dean Beeler, Jerome Fisher
* Copyright (C) 2011-2017 Dean Beeler, Jerome Fisher, Sergey V. Mikayev
* Copyright (C) 2011-2020 Dean Beeler, Jerome Fisher, Sergey V. Mikayev
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by

View File

@@ -1,4 +1,4 @@
/* Copyright (C) 2015-2017 Sergey V. Mikayev
/* Copyright (C) 2015-2020 Sergey V. Mikayev
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
@@ -16,8 +16,8 @@
#include "InternalResampler.h"
#include <SincResampler.h>
#include <ResamplerModel.h>
#include "srctools/include/SincResampler.h"
#include "srctools/include/ResamplerModel.h"
#include "../Synth.h"

View File

@@ -1,4 +1,4 @@
/* Copyright (C) 2015-2017 Sergey V. Mikayev
/* Copyright (C) 2015-2020 Sergey V. Mikayev
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
@@ -19,7 +19,7 @@
#include "../Enumerations.h"
#include "FloatSampleProvider.h"
#include "srctools/include/FloatSampleProvider.h"
namespace MT32Emu {

View File

@@ -1,4 +1,4 @@
/* Copyright (C) 2015-2017 Sergey V. Mikayev
/* Copyright (C) 2015-2020 Sergey V. Mikayev
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by

View File

@@ -1,4 +1,4 @@
/* Copyright (C) 2015-2017 Sergey V. Mikayev
/* Copyright (C) 2015-2020 Sergey V. Mikayev
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by

View File

@@ -1,4 +1,4 @@
/* Copyright (C) 2015-2017 Sergey V. Mikayev
/* Copyright (C) 2015-2020 Sergey V. Mikayev
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by

View File

@@ -1,4 +1,4 @@
/* Copyright (C) 2015-2017 Sergey V. Mikayev
/* Copyright (C) 2015-2020 Sergey V. Mikayev
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by

View File

@@ -1,4 +1,4 @@
/* Copyright (C) 2015-2017 Sergey V. Mikayev
/* Copyright (C) 2015-2020 Sergey V. Mikayev
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by

View File

@@ -1,4 +1,4 @@
/* Copyright (C) 2015-2017 Sergey V. Mikayev
/* Copyright (C) 2015-2020 Sergey V. Mikayev
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by

View File

@@ -1,4 +1,4 @@
/* Copyright (C) 2015-2017 Sergey V. Mikayev
/* Copyright (C) 2015-2020 Sergey V. Mikayev
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by

View File

@@ -1,4 +1,4 @@
/* Copyright (C) 2015-2017 Sergey V. Mikayev
/* Copyright (C) 2015-2020 Sergey V. Mikayev
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by

View File

@@ -1,4 +1,4 @@
/* Copyright (C) 2015-2017 Sergey V. Mikayev
/* Copyright (C) 2015-2020 Sergey V. Mikayev
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by

View File

@@ -1,4 +1,4 @@
/* Copyright (C) 2015-2017 Sergey V. Mikayev
/* Copyright (C) 2015-2020 Sergey V. Mikayev
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by

View File

@@ -1,4 +1,4 @@
/* Copyright (C) 2015-2017 Sergey V. Mikayev
/* Copyright (C) 2015-2020 Sergey V. Mikayev
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by

View File

@@ -1,4 +1,4 @@
/* Copyright (C) 2015-2017 Sergey V. Mikayev
/* Copyright (C) 2015-2020 Sergey V. Mikayev
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
@@ -17,7 +17,7 @@
#include <cmath>
#include <cstring>
#include "FIRResampler.h"
#include "../include/FIRResampler.h"
using namespace SRCTools;

View File

@@ -1,4 +1,4 @@
/* Copyright (C) 2015-2017 Sergey V. Mikayev
/* Copyright (C) 2015-2020 Sergey V. Mikayev
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
@@ -16,7 +16,7 @@
#include <cstddef>
#include "IIR2xResampler.h"
#include "../include/IIR2xResampler.h"
namespace SRCTools {

View File

@@ -1,4 +1,4 @@
/* Copyright (C) 2015-2017 Sergey V. Mikayev
/* Copyright (C) 2015-2020 Sergey V. Mikayev
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
@@ -14,7 +14,7 @@
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include "LinearResampler.h"
#include "../include/LinearResampler.h"
using namespace SRCTools;

View File

@@ -1,4 +1,4 @@
/* Copyright (C) 2015-2017 Sergey V. Mikayev
/* Copyright (C) 2015-2020 Sergey V. Mikayev
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
@@ -17,12 +17,12 @@
#include <cmath>
#include <cstddef>
#include "ResamplerModel.h"
#include "../include/ResamplerModel.h"
#include "ResamplerStage.h"
#include "SincResampler.h"
#include "IIR2xResampler.h"
#include "LinearResampler.h"
#include "../include/ResamplerStage.h"
#include "../include/SincResampler.h"
#include "../include/IIR2xResampler.h"
#include "../include/LinearResampler.h"
namespace SRCTools {

View File

@@ -1,4 +1,4 @@
/* Copyright (C) 2015-2017 Sergey V. Mikayev
/* Copyright (C) 2015-2020 Sergey V. Mikayev
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
@@ -20,7 +20,7 @@
#include <iostream>
#endif
#include "SincResampler.h"
#include "../include/SincResampler.h"
#ifndef M_PI
static const double M_PI = 3.1415926535897932;

View File

@@ -1,6 +1,5 @@
/*PCem v0.8 by Tom Walker
AD1848 CODEC emulation (Windows Sound System compatible)*/
/*
AD1848 / CS4248 / CS4231 CODEC emulation (Windows Sound System compatible)*/
#include <stdio.h>
#include <stdint.h>
@@ -14,6 +13,7 @@
#include <86box/sound.h>
#include <86box/snd_ad1848.h>
#define CS4231 0x80
static int ad1848_vols_6bits[64];
static uint32_t ad1848_vols_5bits_aux_gain[32];
@@ -40,7 +40,11 @@ uint8_t ad1848_read(uint16_t addr, void *p)
break;
case 1:
temp = ad1848->regs[ad1848->index];
break;
if (ad1848->index == 0x0b) {
temp ^= 0x20;
ad1848->regs[ad1848->index] = temp;
}
break;
case 2:
temp = ad1848->status;
break;
@@ -97,6 +101,10 @@ void ad1848_write(uint16_t addr, uint8_t val, void *p)
}
break;
case 11:
break;
case 12:
if (ad1848->type != AD1848_TYPE_DEFAULT)
ad1848->regs[12] = ((ad1848->regs[12] & 0x0f) + (val & 0xf0)) | 0x80;
@@ -105,6 +113,14 @@ void ad1848_write(uint16_t addr, uint8_t val, void *p)
case 14:
ad1848->count = ad1848->regs[15] | (val << 8);
break;
case 24:
if (! (val & 0x70))
ad1848->status &= 0xfe;
break;
case 25:
break;
}
ad1848->regs[ad1848->index] = val;
@@ -197,7 +213,7 @@ static void ad1848_poll(void *p)
if (!(ad1848->status & 0x01))
{
ad1848->status |= 0x01;
if (ad1848->regs[0xa] & 2)
if (ad1848->regs[10] & 2)
picint(1 << ad1848->irq);
}
}
@@ -221,9 +237,9 @@ void ad1848_init(ad1848_t *ad1848, int type)
ad1848->mce = 0x40;
ad1848->regs[0] = ad1848->regs[1] = 0;
ad1848->regs[2] = ad1848->regs[3] = 0x80; /* AZT2316A Line-in */
ad1848->regs[2] = ad1848->regs[3] = 0x80; /* Line-in */
ad1848->regs[4] = ad1848->regs[5] = 0x80;
ad1848->regs[6] = ad1848->regs[7] = 0x80; /* AZT2316A Master? */
ad1848->regs[6] = ad1848->regs[7] = 0x80; /* Left/right Output */
ad1848->regs[8] = 0;
ad1848->regs[9] = 0x08;
ad1848->regs[10] = ad1848->regs[11] = 0;
@@ -236,8 +252,13 @@ void ad1848_init(ad1848_t *ad1848, int type)
if (type == AD1848_TYPE_CS4231)
{
ad1848->regs[0x12] = ad1848->regs[0x13] = 0x80; // AZT2316A CD
ad1848->regs[0x1A] = 0x80; // AZT2316A Mic
ad1848->regs[16] = ad1848->regs[17] = 0;
ad1848->regs[18] = ad1848->regs[19] = 0x88;
ad1848->regs[22] = 0x80;
ad1848->regs[24] = 0;
ad1848->regs[25] = CS4231;
ad1848->regs[26] = 0x80;
ad1848->regs[29] = 0x80;
}
ad1848->out_l = 0;

View File

@@ -14,6 +14,8 @@
#include <86box/device.h>
#include <86box/sound.h>
#include <86box/midi.h>
#include <86Box/snd_ad1848.h>
#include <math.h>
enum
{
@@ -108,6 +110,12 @@ typedef struct gus_t
uint16_t gp1_addr, gp2_addr;
uint8_t usrr;
uint8_t max_ctrl;
#if defined(DEV_BRANCH) && defined(USE_GUSMAX)
ad1848_t ad1848;
#endif
} gus_t;
static int gus_gf1_irqs[8] = {-1, 2, 5, 3, 7, 11, 12, 15};
@@ -182,6 +190,9 @@ void writegus(uint16_t addr, uint8_t val, void *p)
int c, d;
int old;
uint16_t port;
#if defined(DEV_BRANCH) && defined(USE_GUSMAX)
uint16_t csioport;
#endif
if ((addr == 0x388) || (addr == 0x389))
port = addr;
@@ -526,10 +537,16 @@ gus->curx[gus->voice]=(gus->curx[gus->voice]&0xFFF8000)|((val&0x7F)<<8);
}
else
gus->irq_midi = gus_midi_irqs[(val >> 3) & 7];
#if defined(DEV_BRANCH) && defined(USE_GUSMAX)
ad1848_setirq(&gus->ad1848, gus->irq);
#endif
gus->sb_nmi = val & 0x80;
} else {
gus->dma = gus_dmas[val & 7];
#if defined(DEV_BRANCH) && defined(USE_GUSMAX)
ad1848_setdma(&gus->ad1848, gus->dma);
#endif
}
break;
case 1:
@@ -584,6 +601,25 @@ gus->curx[gus->voice]=(gus->curx[gus->voice]&0xFFF8000)|((val&0x7F)<<8);
case 0x20f:
gus->reg_ctrl = val;
break;
case 0x306: case 0x706:
if (gus->dma >= 4)
val |= 0x30;
gus->max_ctrl = (val >> 6) & 1;
#if defined(DEV_BRANCH) && defined(USE_GUSMAX)
if (val & 0x40) {
if ((val & 0xF) != ((addr >> 4) & 0xF)) {
csioport = 0x30c | ((addr >> 4) & 0xf);
io_removehandler(csioport, 4,
ad1848_read,NULL,NULL,
ad1848_write,NULL,NULL,&gus->ad1848);
csioport = 0x30c | ((val & 0xf) << 4);
io_sethandler(csioport, 4,
ad1848_read,NULL,NULL,
ad1848_write,NULL,NULL, &gus->ad1848);
}
}
#endif
break;
}
}
@@ -632,7 +668,11 @@ uint8_t readgus(uint16_t addr, void *p)
return val;
case 0x20F:
return 0;
if (gus->max_ctrl)
val = 0x02;
else
val = 0x00;
break;
case 0x302:
return gus->voice;
@@ -719,8 +759,14 @@ uint8_t readgus(uint16_t addr, void *p)
break;
}
break;
case 0x306: case 0x706: /*Revision level*/
return 0xff; /*Pre 3.7 - no mixer*/
case 0x306: case 0x706:
if (gus->max_ctrl)
val = 0x0a; /* GUS MAX */
else
val = 0xff; /*Pre 3.7 - no mixer*/
break;
break;
case 0x307: /*DRAM access*/
val=gus->ram[gus->addr];
gus->addr&=0xFFFFF;
@@ -1031,13 +1077,25 @@ static void gus_get_buffer(int32_t *buffer, int len, void *p)
gus_t *gus = (gus_t *)p;
int c;
#if defined(DEV_BRANCH) && defined(USE_GUSMAX)
if (gus->max_ctrl)
ad1848_update(&gus->ad1848);
#endif
gus_update(gus);
for (c = 0; c < len * 2; c++)
{
#if defined(DEV_BRANCH) && defined(USE_GUSMAX)
if (gus->max_ctrl)
buffer[c] += (int32_t)(gus->ad1848.buffer[c] / 2);
#endif
buffer[c] += (int32_t)gus->buffer[c & 1][c >> 1];
}
#if defined(DEV_BRANCH) && defined(USE_GUSMAX)
if (gus->max_ctrl)
gus->ad1848.pos = 0;
#endif
gus->pos = 0;
}
@@ -1119,6 +1177,15 @@ void *gus_init(const device_t *info)
io_sethandler(0x0100+gus->base, 0x0010, readgus, NULL, NULL, writegus, NULL, NULL, gus);
io_sethandler(0x0506+gus->base, 0x0001, readgus, NULL, NULL, writegus, NULL, NULL, gus);
io_sethandler(0x0388, 0x0002, readgus, NULL, NULL, writegus, NULL, NULL, gus);
#if defined(DEV_BRANCH) && defined(USE_GUSMAX)
ad1848_init(&gus->ad1848, AD1848_TYPE_CS4231);
ad1848_setirq(&gus->ad1848, 5);
ad1848_setdma(&gus->ad1848, 3);
io_sethandler(0x10C+gus->base, 4,
ad1848_read,NULL,NULL, ad1848_write,NULL,NULL, &gus->ad1848);
#endif
timer_add(&gus->samp_timer, gus_poll_wave, gus, 1);
timer_add(&gus->timer_1, gus_poll_timer_1, gus, 1);
timer_add(&gus->timer_2, gus_poll_timer_2, gus, 1);
@@ -1147,6 +1214,11 @@ void gus_speed_changed(void *p)
gus->samp_latch = (uint64_t)(TIMER_USEC * (1000000.0 / 44100.0));
else
gus->samp_latch = (uint64_t)(TIMER_USEC * (1000000.0 / gusfreqs[gus->voices - 14]));
#if defined(DEV_BRANCH) && defined(USE_GUSMAX)
if (gus->max_ctrl)
ad1848_speed_changed(&gus->ad1848);
#endif
}
static const device_config_t gus_config[] = {
@@ -1156,7 +1228,7 @@ static const device_config_t gus_config[] = {
{
"Classic", GUS_CLASSIC
},
#if 0
#if defined(DEV_BRANCH) && defined(USE_GUSMAX)
{
"MAX", GUS_MAX
},

View File

@@ -277,56 +277,6 @@ et4000_out(uint16_t addr, uint8_t val, void *priv)
svga_recalctimings(svga);
}
}
/*
* Note - Silly hack to determine video memory
* size automatically by ET4000 BIOS.
*/
if ((svga->crtcreg == 0x37) && (dev->type != 1)) {
switch (val & 0x0b) {
case 0x00:
case 0x01:
if (svga->vram_max == 64 * 1024)
mem_mapping_enable(&svga->mapping);
else
mem_mapping_disable(&svga->mapping);
break;
case 0x02:
if (svga->vram_max == 128 * 1024)
mem_mapping_enable(&svga->mapping);
else
mem_mapping_disable(&svga->mapping);
break;
case 0x03:
case 0x08:
case 0x09:
if (svga->vram_max == 256 * 1024)
mem_mapping_enable(&svga->mapping);
else
mem_mapping_disable(&svga->mapping);
break;
case 0x0a:
if (svga->vram_max == 512 * 1024)
mem_mapping_enable(&svga->mapping);
else
mem_mapping_disable(&svga->mapping);
break;
case 0x0b:
if (svga->vram_max == 1024 * 1024)
mem_mapping_enable(&svga->mapping);
else
mem_mapping_disable(&svga->mapping);
break;
default:
mem_mapping_enable(&svga->mapping);
break;
}
}
break;
}

View File

@@ -1210,7 +1210,7 @@ uint8_t et4000w32p_pci_read(int func, int addr, void *p)
case 0x09: return 0; /*Programming interface*/
case 0x0a: return 0x00; /*Supports VGA interface, XGA compatible*/
case 0x0b: return is_pentium ? 0x03 : 0x00; /* This has to be done in order to make this card work with the two 486 PCI machines. */
case 0x0b: return cpu_64bitbus ? 0x03 : 0x00; /* This has to be done in order to make this card work with the two 486 PCI machines. */
case 0x10: return 0x00; /*Linear frame buffer address*/
case 0x11: return 0x00;

View File

@@ -25,6 +25,7 @@
#include <86box/pci.h>
#include <86box/rom.h>
#include <86box/device.h>
#include <86box/dma.h>
#include <86box/plat.h>
#include <86box/video.h>
#include <86box/vid_svga.h>
@@ -2233,14 +2234,14 @@ run_dma(mystique_t *mystique)
switch (mystique->dma.primaddress & DMA_MODE_MASK) {
case DMA_MODE_REG:
if (mystique->dma.pri_state == 0) {
mystique->dma.pri_header = *(uint32_t *)&ram[mystique->dma.primaddress & DMA_ADDR_MASK];
dma_bm_read(mystique->dma.primaddress & DMA_ADDR_MASK, (uint8_t *) &mystique->dma.pri_header, 4, 4);
mystique->dma.primaddress += 4;
}
if ((mystique->dma.pri_header & 0xff) != 0x15) {
uint32_t val = *(uint32_t *)&ram[mystique->dma.primaddress & DMA_ADDR_MASK];
uint32_t reg_addr;
uint32_t val, reg_addr;
dma_bm_read(mystique->dma.primaddress & DMA_ADDR_MASK, (uint8_t *) &val, 4, 4);
mystique->dma.primaddress += 4;
reg_addr = (mystique->dma.pri_header & 0x7f) << 2;
@@ -2276,13 +2277,13 @@ run_dma(mystique_t *mystique)
switch (mystique->dma.secaddress & DMA_MODE_MASK) {
case DMA_MODE_REG:
if (mystique->dma.sec_state == 0) {
mystique->dma.sec_header = *(uint32_t *)&ram[mystique->dma.secaddress & DMA_ADDR_MASK];
dma_bm_read(mystique->dma.secaddress & DMA_ADDR_MASK, (uint8_t *) &mystique->dma.sec_header, 4, 4);
mystique->dma.secaddress += 4;
}
uint32_t val = *(uint32_t *)&ram[mystique->dma.secaddress & DMA_ADDR_MASK];
uint32_t reg_addr;
uint32_t val, reg_addr;
dma_bm_read(mystique->dma.secaddress & DMA_ADDR_MASK, (uint8_t *) &val, 4, 4);
mystique->dma.secaddress += 4;
reg_addr = (mystique->dma.sec_header & 0x7f) << 2;
@@ -2310,7 +2311,9 @@ run_dma(mystique_t *mystique)
break;
case DMA_MODE_BLIT: {
uint32_t val = *(uint32_t *)&ram[mystique->dma.secaddress & DMA_ADDR_MASK];
uint32_t val;
dma_bm_read(mystique->dma.secaddress & DMA_ADDR_MASK, (uint8_t *) &val, 4, 4);
mystique->dma.secaddress += 4;
if (mystique->busy)

View File

@@ -611,7 +611,6 @@ svga_poll(void *p)
svga_t *svga = (svga_t *)p;
uint32_t x, blink_delay;
int wx, wy;
int skip = (svga->crtc[8] >> 5) & 0x03;
int ret, old_ma;
if (!svga->linepos) {
@@ -812,9 +811,9 @@ svga_poll(void *p)
svga->ma = svga->maback = svga->ma_latch + ((svga->crtc[5] & 0x60) >> 5);
svga->ca = ((svga->crtc[0xe] << 8) | svga->crtc[0xf]) + ((svga->crtc[0xb] & 0x60) >> 5) + svga->ca_adj;
svga->ma = (svga->ma << 2) + (skip << 2);
svga->maback = (svga->maback << 2) + (skip << 2);
svga->ca = (svga->ca << 2) + (skip << 2);
svga->ma = (svga->ma << 2);
svga->maback = (svga->maback << 2);
svga->ca = (svga->ca << 2);
if (svga->vsync_callback)
svga->vsync_callback(svga);

View File

@@ -8,7 +8,7 @@
#
# Makefile for Win32 (MinGW32) environment.
#
# Version: @(#)Makefile.mingw 1.0.143 2020/01/25
# Version: @(#)Makefile.mingw 1.0.144 2020/06/06
#
# Authors: Miran Grca, <mgrca8@gmail.com>
# Fred N. van Kempen, <decwiz@yahoo.com>
@@ -86,6 +86,9 @@ ifeq ($(DEV_BUILD), y)
ifndef NO_SIO
NO_SIO := y
endif
ifndef GUSMAX
GUSMAX := y
endif
else
ifndef DEBUG
DEBUG := n
@@ -141,6 +144,9 @@ else
ifndef NO_SIO
NO_SIO := n
endif
ifndef GUSMAX
GUSMAX := n
endif
endif
# Defaults for several build options (possibly defined in a chained file.)
@@ -244,7 +250,7 @@ VPATH := $(EXPATH) . cpu cpu_common \
printer \
sound \
sound/munt sound/munt/c_interface sound/munt/sha1 \
sound/munt/srchelper \
sound/munt/srchelper sound/munt/srchelper/srctools/src \
sound/resid-fp \
scsi video network network/slirp win
ifeq ($(X64), y)
@@ -378,8 +384,10 @@ MUNTOBJ := midi_mt32.o \
Analog.o BReverbModel.o File.o FileStream.o LA32Ramp.o \
LA32FloatWaveGenerator.o LA32WaveGenerator.o \
MidiStreamParser.o Part.o Partial.o PartialManager.o \
Poly.o ROMInfo.o SampleRateConverter_dummy.o Synth.o \
Tables.o TVA.o TVF.o TVP.o sha1.o c_interface.o
Poly.o ROMInfo.o SampleRateConverter.o \
FIRResampler.o IIR2xResampler.o LinearResampler.o ResamplerModel.o \
SincResampler.o InternalResampler.o \
Synth.o Tables.o TVA.o TVF.o TVP.o sha1.o c_interface.o
endif
ifeq ($(VNC), y)
@@ -471,6 +479,10 @@ ifeq ($(NO_SIO), y)
OPTS += -DNO_SIO
endif
ifeq ($(GUSMAX), y)
OPTS += -DUSE_GUSMAX
endif
endif
@@ -515,8 +527,8 @@ CPUOBJ := cpu.o cpu_table.o \
$(DYNARECOBJ)
CHIPSETOBJ := acc2168.o acer_m3a.o cs8230.o ali1429.o headland.o \
intel_4x0.o neat.o opti495.o scamp.o scat.o \
sis_85c471.o sis_85c496.o \
intel_4x0.o neat.o opti495.o opti5x7.o scamp.o scat.o \
rabbit.o sis_85c471.o sis_85c496.o \
via_apollo.o via_vpx.o wd76c10.o
MCHOBJ := machine.o machine_table.o \

View File

@@ -8,7 +8,7 @@
#
# Makefile for Win32 (MinGW32) environment.
#
# Version: @(#)Makefile.mingw 1.0.142 2020/01/25
# Version: @(#)Makefile.mingw 1.0.143 2020/06/06
#
# Authors: Miran Grca, <mgrca8@gmail.com>
# Fred N. van Kempen, <decwiz@yahoo.com>
@@ -86,6 +86,9 @@ ifeq ($(DEV_BUILD), y)
ifndef NO_SIO
NO_SIO := y
endif
ifndef GUSMAX
GUSMAX := y
endif
else
ifndef DEBUG
DEBUG := n
@@ -144,6 +147,9 @@ else
ifndef NO_SIO
NO_SIO := n
endif
ifndef GUSMAX
GUSMAX := n
endif
endif
# Defaults for several build options (possibly defined in a chained file.)
@@ -241,7 +247,7 @@ VPATH := $(EXPATH) . cpu_new cpu_common \
printer \
sound \
sound/munt sound/munt/c_interface sound/munt/sha1 \
sound/munt/srchelper \
sound/munt/srchelper sound/munt/srchelper/srctools/src \
sound/resid-fp \
scsi video network network/slirp win
ifeq ($(X64), y)
@@ -387,8 +393,10 @@ MUNTOBJ := midi_mt32.o \
Analog.o BReverbModel.o File.o FileStream.o LA32Ramp.o \
LA32FloatWaveGenerator.o LA32WaveGenerator.o \
MidiStreamParser.o Part.o Partial.o PartialManager.o \
Poly.o ROMInfo.o SampleRateConverter_dummy.o Synth.o \
Tables.o TVA.o TVF.o TVP.o sha1.o c_interface.o
Poly.o ROMInfo.o SampleRateConverter.o \
FIRResampler.o IIR2xResampler.o LinearResampler.o ResamplerModel.o \
SincResampler.o InternalResampler.o \
Synth.o Tables.o TVA.o TVF.o TVP.o sha1.o c_interface.o
endif
ifeq ($(VNC), y)
@@ -480,6 +488,10 @@ ifeq ($(NO_SIO), y)
OPTS += -DNO_SIO
endif
ifeq ($(GUSMAX), y)
OPTS += -DUSE_GUSMAX
endif
endif
@@ -519,8 +531,8 @@ CPUOBJ := cpu.o cpu_table.o \
$(DYNARECOBJ)
CHIPSETOBJ := acc2168.o acer_m3a.o cs8230.o ali1429.o headland.o \
intel_4x0.o neat.o opti495.o scamp.o scat.o \
sis_85c471.o sis_85c496.o \
intel_4x0.o neat.o opti495.o opti5x7.o scamp.o scat.o \
rabbit.o sis_85c471.o sis_85c496.o \
via_apollo.o via_vpx.o wd76c10.o
MCHOBJ := machine.o machine_table.o \

View File

@@ -1307,4 +1307,5 @@ plat_set_input(HWND h)
input_orig_proc = GetWindowLongPtr(h, GWLP_WNDPROC);
input_orig_hwnd = h;
SetWindowLongPtr(h, GWLP_WNDPROC, (LONG_PTR)&input_proc);
ImmAssociateContext(h, NULL);
}