CMI8x38 megacommit

This commit is contained in:
RichardG867
2022-03-06 01:29:29 -03:00
154 changed files with 22874 additions and 22952 deletions

18
.clang-format Normal file
View File

@@ -0,0 +1,18 @@
BasedOnStyle: WebKit
AlignAfterOpenBracket: Align
AlignArrayOfStructures: Left
AlignConsecutiveMacros: AcrossEmptyLines
AlignConsecutiveAssignments: Consecutive
AlignConsecutiveBitFields: AcrossEmptyLines
AlignConsecutiveDeclarations: Consecutive
AlignEscapedNewlines: Left
AlignTrailingComments: true
AlwaysBreakAfterReturnType: TopLevelDefinitions
BreakBeforeTernaryOperators: true
IndentCaseLabels: true
IndentCaseBlocks: true
IndentGotoLabels: false
IndentPPDirectives: AfterHash
IndentExternBlock: NoIndent
PointerAlignment: Right
SpaceAfterCStyleCast: true

View File

@@ -1,21 +1,21 @@
[*]
charset = utf-8
end_of_line = lf
indent_style = tab
indent_size = 8
tab_width = 8
indent_style = space
indent_size = 4
tab_width = 4
# Disabled for now since not all editors support setting a tab_width value different from indent_size
# Relevant VSCode extension issue: https://github.com/editorconfig/editorconfig-vscode/issues/190
# [*.rc]
# indent_style = space
# indent_size = 4
# tab_width = 8
# tab_width = 4
# [Makefile.*]
# indent_style = space
# indent_size = 4
# tab_width = 8
# tab_width = 4
[*.manifest]
indent_style = space

View File

@@ -143,7 +143,7 @@ cmake_dependent_option(MGA "Matrox Mystique graphics adapters"
cmake_dependent_option(NO_SIO "Machines without emulated Super I/O chips" ON "DEV_BRANCH" OFF)
cmake_dependent_option(OLIVETTI "Olivetti M290" ON "DEV_BRANCH" OFF)
cmake_dependent_option(OPEN_AT "OpenAT" ON "DEV_BRANCH" OFF)
cmake_dependent_option(PAS16 "Pro Audio Spectrum 16" OFF "DEV_BRANCH" OFF)
cmake_dependent_option(PAS16 "Pro Audio Spectrum 16" ON "DEV_BRANCH" OFF)
cmake_dependent_option(SIO_DETECT "Super I/O Detection Helper" ON "DEV_BRANCH" OFF)
cmake_dependent_option(TANDY_ISA "Tandy PSG ISA clone boards" ON "DEV_BRANCH" OFF)
cmake_dependent_option(VGAWONDER "ATI VGA Wonder (ATI-18800)" ON "DEV_BRANCH" OFF)

View File

@@ -710,7 +710,11 @@ usage:
if (rom_path[0] != '\0')
pclog("# ROM path: %s\n", rom_path);
else
pclog("# ROM path: %sroms\\\n", exe_path);
#ifndef _WIN32
pclog("# ROM path: %sroms/\n", exe_path);
#else
pclog("# ROM path: %sroms\\\n", exe_path);
#endif
pclog("# Configuration file: %s\n#\n\n", cfg_path);
/*
* We are about to read the configuration file, which MAY

View File

@@ -1402,6 +1402,7 @@ load_hard_disks(void)
} else {
plat_append_filename(hdd[c].fn, usr_path, p);
}
plat_path_normalize(hdd[c].fn);
/* If disk is empty or invalid, mark it for deletion. */
if (! hdd_is_valid(c)) {
@@ -2810,11 +2811,13 @@ save_hard_disks(void)
}
sprintf(temp, "hdd_%02i_fn", c+1);
if (hdd_is_valid(c) && (strlen(hdd[c].fn) != 0))
if (hdd_is_valid(c) && (strlen(hdd[c].fn) != 0)) {
plat_path_normalize(hdd[c].fn);
if (!strnicmp(hdd[c].fn, usr_path, strlen(usr_path)))
config_set_string(cat, temp, &hdd[c].fn[strlen(usr_path)]);
else
config_set_string(cat, temp, hdd[c].fn);
}
else
config_delete_var(cat, temp);
}

View File

@@ -351,7 +351,7 @@ static void
bug_close(UNUSED(void *priv))
{
io_removehandler(BUGGER_ADDR, BUGGER_ADDRLEN,
bug_read, NULL, NULL, bug_write, NULL, NULL, NULL);
bug_read, NULL, NULL, bug_write, NULL, NULL, NULL);
}

View File

@@ -676,22 +676,20 @@ isamem_close(void *priv)
free(dev);
}
static const device_config_t ibmxt_config[] =
{
{
"size", "Memory Size", CONFIG_SPINNER, "", 128, "",
{ 0, 512, 16 },
{ { 0 } }
},
{
"start", "Start Address", CONFIG_SPINNER, "", 256, "",
{ 0, 576, 64 },
{ { 0 } }
},
{
"", "", -1
}
static const device_config_t ibmxt_config[] = {
// clang-format off
{
"size", "Memory Size", CONFIG_SPINNER, "", 128, "",
{ 0, 512, 16 },
{ { 0 } }
},
{
"start", "Start Address", CONFIG_SPINNER, "", 256, "",
{ 0, 576, 64 },
{ { 0 } }
},
{ "", "", -1 }
// clang-format on
};
static const device_t ibmxt_device = {
@@ -704,22 +702,20 @@ static const device_t ibmxt_device = {
ibmxt_config
};
static const device_config_t genericxt_config[] =
{
{
"size", "Memory Size", CONFIG_SPINNER, "", 16, "",
{ 0, 640, 16 },
{ { 0 } }
},
{
"start", "Start Address", CONFIG_SPINNER, "", 0, "",
{ 0, 624, 16 },
{ { 0 } }
},
{
"", "", -1
}
static const device_config_t genericxt_config[] = {
// clang-format off
{
"size", "Memory Size", CONFIG_SPINNER, "", 16, "",
{ 0, 640, 16 },
{ { 0 } }
},
{
"start", "Start Address", CONFIG_SPINNER, "", 0, "",
{ 0, 624, 16 },
{ { 0 } }
},
{ "", "", -1 }
// clang-format on
};
static const device_t genericxt_device = {
@@ -733,21 +729,20 @@ static const device_t genericxt_device = {
};
static const device_config_t ibmat_config[] =
{
{
"size", "Memory Size", CONFIG_SPINNER, "", 512, "",
{ 0, 12288, 512 },
{ { 0 } }
},
{
"start", "Start Address", CONFIG_SPINNER, "", 512, "",
{ 0, 15872, 512 },
{ { 0 } }
},
{
"", "", -1
}
static const device_config_t ibmat_config[] = {
// clang-format off
{
"size", "Memory Size", CONFIG_SPINNER, "", 512, "",
{ 0, 12288, 512 },
{ { 0 } }
},
{
"start", "Start Address", CONFIG_SPINNER, "", 512, "",
{ 0, 15872, 512 },
{ { 0 } }
},
{ "", "", -1 }
// clang-format on
};
static const device_t ibmat_device = {
@@ -761,21 +756,20 @@ static const device_t ibmat_device = {
};
static const device_config_t genericat_config[] =
{
{
"size", "Memory Size", CONFIG_SPINNER, "", 512, "",
{ 0, 16384, 512 },
{ { 0 } }
},
{
"start", "Start Address", CONFIG_SPINNER, "", 512, "",
{ 0, 15872, 128 },
{ { 0 } }
},
{
"", "", -1
}
static const device_config_t genericat_config[] = {
// clang-format off
{
"size", "Memory Size", CONFIG_SPINNER, "", 512, "",
{ 0, 16384, 512 },
{ { 0 } }
},
{
"start", "Start Address", CONFIG_SPINNER, "", 512, "",
{ 0, 15872, 128 },
{ { 0 } }
},
{ "", "", -1 }
// clang-format on
};
static const device_t genericat_device = {
@@ -789,21 +783,20 @@ static const device_t genericat_device = {
};
static const device_config_t p5pak_config[] =
{
{
"size", "Memory Size", CONFIG_SPINNER, "", 128, "",
{ 0, 384, 64 },
{ { 0 } }
},
{
"start", "Start Address", CONFIG_SPINNER, "", 512, "",
{ 64, 576, 64 },
{ { 0 } }
},
{
"", "", -1
}
static const device_config_t p5pak_config[] = {
// clang-format off
{
"size", "Memory Size", CONFIG_SPINNER, "", 128, "",
{ 0, 384, 64 },
{ { 0 } }
},
{
"start", "Start Address", CONFIG_SPINNER, "", 512, "",
{ 64, 576, 64 },
{ { 0 } }
},
{ "", "", -1 }
// clang-format on
};
static const device_t p5pak_device = {
@@ -817,21 +810,20 @@ static const device_t p5pak_device = {
};
static const device_config_t a6pak_config[] =
{
{
"size", "Memory Size", CONFIG_SPINNER, "", 64, "",
{ 0, 576, 64 },
{ { 0 } }
},
{
"start", "Start Address", CONFIG_SPINNER, "", 256, "",
{ 64, 512, 64 },
{ { 0 } }
},
{
"", "", -1
}
static const device_config_t a6pak_config[] = {
// clang-format off
{
"size", "Memory Size", CONFIG_SPINNER, "", 64, "",
{ 0, 576, 64 },
{ { 0 } }
},
{
"start", "Start Address", CONFIG_SPINNER, "", 256, "",
{ 64, 512, 64 },
{ { 0 } }
},
{ "", "", -1 }
// clang-format on
};
static const device_t a6pak_device = {
@@ -845,40 +837,26 @@ static const device_t a6pak_device = {
};
static const device_config_t ems5150_config[] =
{
{
"size", "Memory Size", CONFIG_SPINNER, "", 256,
"",
{ 0, 2048, 64 },
{ { 0 } }
},
{
"base", "Address", CONFIG_HEX16, "", 0, "", { 0 },
{
{
"Disabled", 0
},
{
"Board 1", 0x0208
},
{
"Board 2", 0x020a
},
{
"Board 3", 0x020c
},
{
"Board 4", 0x020e
},
{
""
}
},
},
{
"", "", -1
}
static const device_config_t ems5150_config[] = {
// clang-format off
{
"size", "Memory Size", CONFIG_SPINNER, "", 256, "",
{ 0, 2048, 64 },
{ { 0 } }
},
{
"base", "Address", CONFIG_HEX16, "", 0, "", { 0 },
{
{ "Disabled", 0x0000 },
{ "Board 1", 0x0208 },
{ "Board 2", 0x020a },
{ "Board 3", 0x020c },
{ "Board 4", 0x020e },
{ "" }
},
},
{ "", "", -1 }
// clang-format on
};
static const device_t ems5150_device = {
@@ -891,98 +869,62 @@ static const device_t ems5150_device = {
ems5150_config
};
static const device_config_t ev159_config[] =
{
{
"size", "Memory Size", CONFIG_SPINNER, "", 512, "",
{ 0, 3072, 512 },
{ { 0 } }
},
{
"start", "Start Address", CONFIG_SPINNER, "", 0, "",
{ 0, 16128, 128 },
{ { 0 } }
},
{
"length", "Contiguous Size", CONFIG_SPINNER, "", 0, "",
{ 0, 16384, 128 },
{ { 0 } }
},
{
"width", "I/O Width", CONFIG_SELECTION, "", 0, "", { 0 },
{
{
"8-bit", 0
},
{
"16-bit", 1
},
{
""
}
},
},
{
"speed", "Transfer Speed", CONFIG_SELECTION, "", 0, "", { 0 },
{
{
"Standard (150ns)", 0
},
{
"High-Speed (120ns)", 1
},
{
""
}
}
},
{
"ems", "EMS mode", CONFIG_SELECTION, "", 0, "", { 0 },
{
{
"Disabled", 0
},
{
"Enabled", 1
},
{
""
}
},
},
{
"base", "Address", CONFIG_HEX16, "", 0x0258, "", { 0 },
{
{
"208H", 0x0208
},
{
"218H", 0x0218
},
{
"258H", 0x0258
},
{
"268H", 0x0268
},
{
"2A8H", 0x02A8
},
{
"2B8H", 0x02B8
},
{
"2E8H", 0x02E8
},
{
""
}
},
},
{
"", "", -1
}
static const device_config_t ev159_config[] = {
// clang-format off
{
"size", "Memory Size", CONFIG_SPINNER, "", 512, "",
{ 0, 3072, 512 },
{ { 0 } }
},
{
"start", "Start Address", CONFIG_SPINNER, "", 0, "",
{ 0, 16128, 128 },
{ { 0 } }
},
{
"length", "Contiguous Size", CONFIG_SPINNER, "", 0, "",
{ 0, 16384, 128 },
{ { 0 } }
},
{
"width", "I/O Width", CONFIG_SELECTION, "", 0, "", { 0 },
{
{ "8-bit", 0 },
{ "16-bit", 1 },
{ "" }
},
},
{
"speed", "Transfer Speed", CONFIG_SELECTION, "", 0, "", { 0 },
{
{ "Standard (150ns)", 0 },
{ "High-Speed (120ns)", 1 },
{ "" }
}
},
{
"ems", "EMS mode", CONFIG_SELECTION, "", 0, "", { 0 },
{
{ "Disabled", 0 },
{ "Enabled", 1 },
{ "" }
},
},
{
"base", "Address", CONFIG_HEX16, "", 0x0258, "", { 0 },
{
{ "208H", 0x0208 },
{ "218H", 0x0218 },
{ "258H", 0x0258 },
{ "268H", 0x0268 },
{ "2A8H", 0x02A8 },
{ "2B8H", 0x02B8 },
{ "2E8H", 0x02E8 },
{ "" }
},
},
{ "", "", -1 }
// clang-format on
};
static const device_t ev159_device = {
@@ -995,84 +937,52 @@ static const device_t ev159_device = {
ev159_config
};
#if defined(DEV_BRANCH) && defined(USE_ISAMEM_BRAT)
static const device_config_t brat_config[] =
{
{
"base", "Address", CONFIG_HEX16, "", 0x0258, "", { 0 },
{
{
"208H", 0x0208
},
{
"218H", 0x0218
},
{
"258H", 0x0258
},
{
"268H", 0x0268
},
{
""
}
},
},
{
"frame", "Frame Address", CONFIG_HEX20, "", 0, "", { 0 },
{
{
"Disabled", 0x00000
},
{
"D000H", 0xD0000
},
{
"E000H", 0xE0000
},
{
""
}
},
},
{
"width", "I/O Width", CONFIG_SELECTION, "", 8, "", { 0 },
{
{
"8-bit", 8
},
{
"16-bit", 16
},
{
""
}
},
},
{
"speed", "Transfer Speed", CONFIG_SELECTION, "", 0, "", { 0 },
{
{
"Standard", 0
},
{
"High-Speed", 1
},
{
""
}
}
},
{
"size", "Memory Size", CONFIG_SPINNER, "", 128,
"",
{ 0, 8192, 512 },
{ { 0 } }
},
{
"", "", -1
}
static const device_config_t brat_config[] = {
// clang-format off
{
"base", "Address", CONFIG_HEX16, "", 0x0258, "", { 0 },
{
{ "208H", 0x0208 },
{ "218H", 0x0218 },
{ "258H", 0x0258 },
{ "268H", 0x0268 },
{ "" }
},
},
{
"frame", "Frame Address", CONFIG_HEX20, "", 0, "", { 0 },
{
{ "Disabled", 0x00000 },
{ "D000H", 0xD0000 },
{ "E000H", 0xE0000 },
{ "" }
},
},
{
"width", "I/O Width", CONFIG_SELECTION, "", 8, "", { 0 },
{
{ "8-bit", 8 },
{ "16-bit", 16 },
{ "" }
},
},
{
"speed", "Transfer Speed", CONFIG_SELECTION, "", 0, "", { 0 },
{
{ "Standard", 0 },
{ "High-Speed", 1 },
{ "" }
}
},
{
"size", "Memory Size", CONFIG_SPINNER, "", 128,
"",
{ 0, 8192, 512 },
{ { 0 } }
},
{ "", "", -1 }
// clang-format on
};
static const device_t brat_device = {
@@ -1086,96 +996,55 @@ static const device_t brat_device = {
};
#endif
#if defined(DEV_BRANCH) && defined(USE_ISAMEM_RAMPAGE)
static const device_config_t rampage_config[] =
{
{
"base", "Address", CONFIG_HEX16, "", 0x0258, "", { 0 },
{
{
"208H", 0x0208
},
{
"218H", 0x0218
},
{
"258H", 0x0258
},
{
"268H", 0x0268
},
{
"2A8H", 0x02A8
},
{
"2B8H", 0x02B8
},
{
"2E8H", 0x02E8
},
{
""
}
},
},
{
"frame", "Frame Address", CONFIG_HEX20, "", 0, "", { 0 },
{
{
"Disabled", 0x00000
},
{
"C000H", 0xC0000
},
{
"D000H", 0xD0000
},
{
"E000H", 0xE0000
},
{
""
}
},
},
{
"width", "I/O Width", CONFIG_SELECTION, "", 8, "", { 0 },
{
{
"8-bit", 8
},
{
"16-bit", 16
},
{
""
}
},
},
{
"speed", "Transfer Speed", CONFIG_SELECTION, "", 0, "", { 0 },
{
{
"Standard", 0
},
{
"High-Speed", 1
},
{
""
}
}
},
{
"size", "Memory Size", CONFIG_SPINNER, "", 128,
"",
{ 0, 8192, 128 },
{ { 0 } }
},
{
"", "", -1
}
static const device_config_t rampage_config[] = {
// clang-format off
{
"base", "Address", CONFIG_HEX16, "", 0x0258, "", { 0 },
{
{ "208H", 0x0208 },
{ "218H", 0x0218 },
{ "258H", 0x0258 },
{ "268H", 0x0268 },
{ "2A8H", 0x02A8 },
{ "2B8H", 0x02B8 },
{ "2E8H", 0x02E8 },
{ "" }
},
},
{
"frame", "Frame Address", CONFIG_HEX20, "", 0, "", { 0 },
{
{ "Disabled", 0x00000 },
{ "C000H", 0xC0000 },
{ "D000H", 0xD0000 },
{ "E000H", 0xE0000 },
{ "" }
},
},
{
"width", "I/O Width", CONFIG_SELECTION, "", 8, "", { 0 },
{
{ "8-bit", 8 },
{ "16-bit", 16 },
{ "" }
},
},
{
"speed", "Transfer Speed", CONFIG_SELECTION, "", 0, "", { 0 },
{
{ "Standard", 0 },
{ "High-Speed", 1 },
{ "" }
}
},
{
"size", "Memory Size", CONFIG_SPINNER, "", 128, "",
{ 0, 8192, 128 },
{ { 0 } }
},
{ "", "", -1 }
// clang-format on
};
static const device_t rampage_device = {
@@ -1191,94 +1060,54 @@ static const device_t rampage_device = {
#if defined(DEV_BRANCH) && defined(USE_ISAMEM_IAB)
static const device_config_t iab_config[] =
{
{
"base", "Address", CONFIG_HEX16, "", 0x0258, "", { 0 },
{
{
"208H", 0x0208
},
{
"218H", 0x0218
},
{
"258H", 0x0258
},
{
"268H", 0x0268
},
{
"2A8H", 0x02A8
},
{
"2B8H", 0x02B8
},
{
"2E8H", 0x02E8
},
{
""
}
},
},
{
"frame", "Frame Address", CONFIG_HEX20, "", 0, "", { 0 },
{
{
"Disabled", 0x00000
},
{
"C000H", 0xC0000
},
{
"D000H", 0xD0000
},
{
"E000H", 0xE0000
},
{
""
}
},
},
{
"width", "I/O Width", CONFIG_SELECTION, "", 8, "", { 0 },
{
{
"8-bit", 8
},
{
"16-bit", 16
},
{
""
}
},
},
{
"speed", "Transfer Speed", CONFIG_SELECTION, "", 0, "", { 0 },
{
{
"Standard", 0
},
{
"High-Speed", 1
},
{
""
}
}
},
{
"size", "Memory Size", CONFIG_SPINNER, "", 128,
"",
{ 0, 8192, 128 },
{ { 0 } }
},
{
"", "", -1
}
static const device_config_t iab_config[] = {
// clang-format off
{
"base", "Address", CONFIG_HEX16, "", 0x0258, "", { 0 },
{
{ "208H", 0x0208 },
{ "218H", 0x0218 },
{ "258H", 0x0258 },
{ "268H", 0x0268 },
{ "2A8H", 0x02A8 },
{ "2B8H", 0x02B8 },
{ "2E8H", 0x02E8 },
{ "" }
},
},
{
"frame", "Frame Address", CONFIG_HEX20, "", 0, "", { 0 },
{
{ "Disabled", 0x00000 },
{ "C000H", 0xC0000 },
{ "D000H", 0xD0000 },
{ "E000H", 0xE0000 },
{ "" }
},
},
{
"width", "I/O Width", CONFIG_SELECTION, "", 8, "", { 0 },
{
{ "8-bit", 8 },
{ "16-bit", 16 },
{ "" }
},
},
{
"speed", "Transfer Speed", CONFIG_SELECTION, "", 0, "", { 0 },
{
{ "Standard", 0 },
{ "High-Speed", 1 },
{ "" }
}
},
{
"size", "Memory Size", CONFIG_SPINNER, "", 128, "",
{ 0, 8192, 128 },
{ { 0 } }
},
{ "", "", -1 }
// clang-format on
};
static const device_t iab_device = {
@@ -1292,7 +1121,6 @@ static const device_t iab_device = {
};
#endif
static const device_t isa_none_device = {
"None",
"none",
@@ -1302,32 +1130,32 @@ static const device_t isa_none_device = {
NULL
};
static const struct {
const device_t *dev;
} boards[] = {
{ &isa_none_device },
{ &ibmxt_device },
{ &genericxt_device },
{ &ibmat_device },
{ &genericat_device },
{ &p5pak_device },
{ &a6pak_device },
{ &ems5150_device },
{ &ev159_device },
// clang-format off
{ &isa_none_device },
{ &ibmxt_device },
{ &genericxt_device },
{ &ibmat_device },
{ &genericat_device },
{ &p5pak_device },
{ &a6pak_device },
{ &ems5150_device },
{ &ev159_device },
#if defined(DEV_BRANCH) && defined(USE_ISAMEM_BRAT)
{ &brat_device },
{ &brat_device },
#endif
#if defined(DEV_BRANCH) && defined(USE_ISAMEM_RAMPAGE)
{ &rampage_device },
{ &rampage_device },
#endif
#if defined(DEV_BRANCH) && defined(USE_ISAMEM_IAB)
{ &iab_device },
{ &iab_device },
#endif
{ NULL }
{ NULL }
// clang-format on
};
void
isamem_reset(void)
{
@@ -1345,7 +1173,6 @@ isamem_reset(void)
}
}
const char *
isamem_get_name(int board)
{
@@ -1354,15 +1181,12 @@ isamem_get_name(int board)
return(boards[board].dev->name);
}
const char *
isamem_get_internal_name(int board)
{
return device_get_internal_name(boards[board].dev);
}
int
isamem_get_from_internal_name(const char *s)
{
@@ -1378,7 +1202,6 @@ isamem_get_from_internal_name(const char *s)
return(0);
}
const device_t *
isamem_get_device(int board)
{

View File

@@ -53,7 +53,7 @@ static const uint8_t pnp_init_key[32] = { 0x6A, 0xB5, 0xDA, 0xED, 0xF6, 0xFB, 0x
0xE8, 0x74, 0x3A, 0x9D, 0xCE, 0xE7, 0x73, 0x39 };
static const device_t isapnp_device;
#define ENABLE_ISAPNP_LOG 1
#ifdef ENABLE_ISAPNP_LOG
int isapnp_do_log = ENABLE_ISAPNP_LOG;

View File

@@ -594,43 +594,27 @@ isartc_close(void *priv)
static const device_config_t ev170_config[] = {
{
"base", "Address", CONFIG_HEX16, "", 0x02C0, "", { 0 },
{
{
"240H", 0x0240
},
{
"2C0H", 0x02c0
},
{
""
}
},
},
{
"irq", "IRQ", CONFIG_SELECTION, "", -1, "", { 0 },
{
{
"Disabled", -1
},
{
"IRQ2", 2
},
{
"IRQ5", 5
},
{
"IRQ7", 7
},
{
""
}
},
},
{
"", "", -1
}
// clang-format off
{
"base", "Address", CONFIG_HEX16, "", 0x02C0, "", { 0 },
{
{ "240H", 0x0240 },
{ "2C0H", 0x02c0 },
{ "" }
},
},
{
"irq", "IRQ", CONFIG_SELECTION, "", -1, "", { 0 },
{
{ "Disabled", -1 },
{ "IRQ2", 2 },
{ "IRQ5", 5 },
{ "IRQ7", 7 },
{ "" }
},
},
{ "", "", -1 }
// clang-format on
};
static const device_t ev170_device = {
@@ -645,23 +629,17 @@ static const device_t ev170_device = {
static const device_config_t pii147_config[] = {
{
"base", "Address", CONFIG_HEX16, "", 0x0240, "", { 0 },
{
{
"Clock 1", 0x0240
},
{
"Clock 2", 0x0340
},
{
""
}
},
},
{
"", "", -1
}
// clang-format off
{
"base", "Address", CONFIG_HEX16, "", 0x0240, "", { 0 },
{
{ "Clock 1", 0x0240 },
{ "Clock 2", 0x0340 },
{ "" }
},
},
{ "", "", -1 }
// clang-format on
};
static const device_t pii147_device = {
@@ -676,29 +654,19 @@ static const device_t pii147_device = {
static const device_config_t p5pak_config[] = {
{
"irq", "IRQ", CONFIG_SELECTION, "", -1, "", { 0 },
{
{
"Disabled", -1
},
{
"IRQ2", 2
},
{
"IRQ3", 3
},
{
"IRQ5", 5
},
{
""
}
},
},
{
"", "", -1
}
// clang-format off
{
"irq", "IRQ", CONFIG_SELECTION, "", -1, "", { 0 },
{
{ "Disabled", -1 },
{ "IRQ2", 2 },
{ "IRQ3", 3 },
{ "IRQ5", 5 },
{ "" }
},
},
{ "", "", -1 }
// clang-format on
};
static const device_t p5pak_device = {
@@ -713,29 +681,19 @@ static const device_t p5pak_device = {
static const device_config_t a6pak_config[] = {
{
"irq", "IRQ", CONFIG_SELECTION, "", -1, "", { 0 },
{
{
"Disabled", -1
},
{
"IRQ2", 2
},
{
"IRQ3", 3
},
{
"IRQ5", 5
},
{
""
}
},
},
{
"", "", -1
}
// clang-format off
{
"irq", "IRQ", CONFIG_SELECTION, "", -1, "", { 0 },
{
{ "Disabled", -1 },
{ "IRQ2", 2 },
{ "IRQ3", 3 },
{ "IRQ5", 5 },
{ "" }
},
},
{ "", "", -1 }
// clang-format on
};
static const device_t a6pak_device = {
@@ -748,7 +706,6 @@ static const device_t a6pak_device = {
a6pak_config
};
static const device_t isartc_none_device = {
"None",
"none",
@@ -758,19 +715,19 @@ static const device_t isartc_none_device = {
NULL
};
static const struct {
const device_t *dev;
} boards[] = {
{ &isartc_none_device },
{ &ev170_device },
{ &pii147_device },
{ &p5pak_device },
{ &a6pak_device },
{ NULL },
// clang-format off
{ &isartc_none_device },
{ &ev170_device },
{ &pii147_device },
{ &p5pak_device },
{ &a6pak_device },
{ NULL },
// clang-format on
};
void
isartc_reset(void)
{
@@ -780,7 +737,6 @@ isartc_reset(void)
device_add(boards[isartc_type].dev);
}
char *
isartc_get_internal_name(int board)
{

View File

@@ -61,18 +61,20 @@ static const device_t mouse_internal_device = {
static mouse_t mouse_devices[] = {
{ &mouse_none_device },
{ &mouse_internal_device },
{ &mouse_logibus_device },
{ &mouse_msinport_device },
// clang-format off
{ &mouse_none_device },
{ &mouse_internal_device },
{ &mouse_logibus_device },
{ &mouse_msinport_device },
#if 0
{ &mouse_genibus_device },
{ &mouse_genibus_device },
#endif
{ &mouse_mssystems_device },
{ &mouse_msserial_device },
{ &mouse_ltserial_device },
{ &mouse_ps2_device },
{ NULL }
{ &mouse_mssystems_device },
{ &mouse_msserial_device },
{ &mouse_ltserial_device },
{ &mouse_ps2_device },
{ NULL }
// clang-format on
};

View File

@@ -693,144 +693,77 @@ bm_init(const device_t *info)
return dev;
}
static const device_config_t lt_config[] = {
// clang-format off
{
"base", "Address", CONFIG_HEX16, "", 0x23c, "", { 0 },
{
{
"0x230", 0x230
},
{
"0x234", 0x234
},
{
"0x238", 0x238
},
{
"0x23C", 0x23c
},
{
""
}
}
"base", "Address", CONFIG_HEX16, "", 0x23c, "", { 0 }, {
{ "0x230", 0x230 },
{ "0x234", 0x234 },
{ "0x238", 0x238 },
{ "0x23C", 0x23c },
{ "" }
}
},
{
"irq", "IRQ", CONFIG_SELECTION, "", 5, "", { 0 }, {
{
"IRQ 2", 2
},
{
"IRQ 3", 3
},
{
"IRQ 4", 4
},
{
"IRQ 5", 5
},
{
""
}
}
"irq", "IRQ", CONFIG_SELECTION, "", 5, "", { 0 }, {
{ "IRQ 2", 2 },
{ "IRQ 3", 3 },
{ "IRQ 4", 4 },
{ "IRQ 5", 5 },
{ "" }
}
},
{
"hz", "Hz", CONFIG_SELECTION, "", 45, "", { 0 }, {
{
"Non-timed (original)", 0
},
{
"30 Hz (JMP2 = 1)", 30
},
{
"45 Hz (JMP2 not populated)", 45
},
{
"60 Hz (JMP 2 = 2)", 60
},
{
""
}
}
"hz", "Hz", CONFIG_SELECTION, "", 45, "", { 0 }, {
{ "Non-timed (original)", 0 },
{ "30 Hz (JMP2 = 1)", 30 },
{ "45 Hz (JMP2 not populated)", 45 },
{ "60 Hz (JMP 2 = 2)", 60 },
{ "" }
}
},
{
"buttons", "Buttons", CONFIG_SELECTION, "", 2, "", { 0 }, {
{
"Two", 2
},
{
"Three", 3
},
{
""
}
}
"buttons", "Buttons", CONFIG_SELECTION, "", 2, "", { 0 }, {
{ "Two", 2 },
{ "Three", 3 },
{ "" }
}
},
{
"", "", -1
}
{ "", "", -1 }
// clang-format on
};
static const device_config_t ms_config[] = {
// clang-format off
{
"base", "Address", CONFIG_HEX16, "", 0x23c, "", { 0 },
{
{
"0x230", 0x230
},
{
"0x234", 0x234
},
{
"0x238", 0x238
},
{
"0x23C", 0x23c
},
{
""
}
}
"base", "Address", CONFIG_HEX16, "", 0x23c, "", { 0 }, {
{ "0x230", 0x230 },
{ "0x234", 0x234 },
{ "0x238", 0x238 },
{ "0x23C", 0x23c },
{ "" }
}
},
{
"irq", "IRQ", CONFIG_SELECTION, "", 5, "", { 0 }, {
{
"IRQ 2", 2
},
{
"IRQ 3", 3
},
{
"IRQ 4", 4
},
{
"IRQ 5", 5
},
{
""
}
}
"irq", "IRQ", CONFIG_SELECTION, "", 5, "", { 0 }, {
{ "IRQ 2", 2 },
{ "IRQ 3", 3 },
{ "IRQ 4", 4 },
{ "IRQ 5", 5 },
{ "" }
}
},
{
"buttons", "Buttons", CONFIG_SELECTION, "", 2, "", { 0 }, {
{
"Two", 2
},
{
"Three", 3
},
{
""
}
}
"buttons", "Buttons", CONFIG_SELECTION, "", 2, "", { 0 }, {
{ "Two", 2 },
{ "Three", 3 },
{ "" }
}
},
{
"", "", -1
}
{ "", "", -1 }
// clang-format on
};
const device_t mouse_logibus_device = {
"Logitech/Microsoft Bus Mouse",
"logibus",

View File

@@ -331,28 +331,21 @@ ps2_close(void *priv)
static const device_config_t ps2_config[] = {
// clang-format off
{
"buttons", "Buttons", CONFIG_SELECTION, "", 2, "", { 0 }, {
{
"Two", 2
},
{
"Three", 3
},
{
"Wheel", 4
},
{
""
}
}
"buttons", "Buttons", CONFIG_SELECTION, "", 2, "", { 0 }, {
{ "Two", 2 },
{ "Three", 3 },
{ "Wheel", 4 },
{ "" }
}
},
{
"", "", -1
"", "", -1
}
// clang-format on
};
const device_t mouse_ps2_device = {
"Standard PS/2 Mouse",
"ps2",

View File

@@ -830,74 +830,51 @@ sermouse_init(const device_t *info)
static const device_config_t mssermouse_config[] = {
// clang-format off
{
"port", "Serial Port", CONFIG_SELECTION, "", 0, "", { 0 }, {
{
"COM1", 0
},
{
"COM2", 1
},
{
""
}
}
"port", "Serial Port", CONFIG_SELECTION, "", 0, "", { 0 }, {
{ "COM1", 0 },
{ "COM2", 1 },
{ "COM3", 2 },
{ "COM4", 3 },
{ "" }
}
},
{
"buttons", "Buttons", CONFIG_SELECTION, "", 2, "", { 0 }, {
{
"Two", 2
},
{
"Three", 3
},
{
"Wheel", 4
},
{
""
}
}
"buttons", "Buttons", CONFIG_SELECTION, "", 2, "", { 0 }, {
{ "Two", 2 },
{ "Three", 3 },
{ "Wheel", 4 },
{ "" }
}
},
{
"", "", -1
}
{ "", "", -1 }
// clang-format on
};
static const device_config_t ltsermouse_config[] = {
// clang-format off
{
"port", "Serial Port", CONFIG_SELECTION, "", 0, "", { 0 }, {
{
"COM1", 0
},
{
"COM2", 1
},
{
""
}
}
"port", "Serial Port", CONFIG_SELECTION, "", 0, "", { 0 }, {
{ "COM1", 0 },
{ "COM2", 1 },
{ "COM3", 2 },
{ "COM4", 3 },
{ "" }
}
},
{
"buttons", "Buttons", CONFIG_SELECTION, "", 2, "", { 0 }, {
{
"Two", 2
},
{
"Three", 3
},
{
""
}
}
"buttons", "Buttons", CONFIG_SELECTION, "", 2, "", { 0 }, {
{ "Two", 2 },
{ "Three", 3 },
{ "" }
}
},
{
"", "", -1
}
{ "", "", -1 }
// clang-format on
};
const device_t mouse_mssystems_device = {
"Mouse Systems Serial Mouse",
"mssystems",

View File

@@ -92,35 +92,36 @@ static const device_t hdc_internal_device = {
static const struct {
// clang-format off
const device_t *device;
} controllers[] = {
{ &hdc_none_device },
{ &hdc_internal_device },
{ &st506_xt_xebec_device },
{ &st506_xt_dtc5150x_device },
{ &st506_xt_st11_m_device },
{ &st506_xt_wd1002a_wx1_device },
{ &st506_at_wd1003_device },
{ &st506_xt_st11_r_device },
{ &st506_xt_wd1002a_27x_device },
{ &esdi_at_wd1007vse1_device },
{ &ide_isa_device },
{ &ide_isa_2ch_device },
{ &xtide_at_device },
{ &xtide_at_386_device },
{ &xtide_at_ps2_device },
{ &xta_wdxt150_device },
{ &xtide_acculogic_device },
{ &xtide_device },
{ &esdi_ps2_device },
{ &ide_pci_device },
{ &ide_pci_2ch_device },
{ &ide_vlb_device },
{ &ide_vlb_2ch_device },
{ &hdc_none_device },
{ &hdc_internal_device },
{ &st506_xt_xebec_device },
{ &st506_xt_dtc5150x_device },
{ &st506_xt_st11_m_device },
{ &st506_xt_wd1002a_wx1_device },
{ &st506_at_wd1003_device },
{ &st506_xt_st11_r_device },
{ &st506_xt_wd1002a_27x_device },
{ &esdi_at_wd1007vse1_device },
{ &ide_isa_device },
{ &ide_isa_2ch_device },
{ &xtide_at_device },
{ &xtide_at_386_device },
{ &xtide_at_ps2_device },
{ &xta_wdxt150_device },
{ &xtide_acculogic_device },
{ &xtide_device },
{ &esdi_ps2_device },
{ &ide_pci_device },
{ &ide_pci_2ch_device },
{ &ide_vlb_device },
{ &ide_vlb_2ch_device },
{ NULL }
// clang-format on
};
/* Initialize the 'hdc_current' value based on configured HDC name. */
void
hdc_init(void)

View File

@@ -3117,95 +3117,47 @@ const device_t ide_pci_2ch_device = {
{ NULL }, NULL, NULL, NULL
};
static const device_config_t ide_ter_config[] =
{
// clang-format off
static const device_config_t ide_ter_config[] = {
{
"irq", "IRQ", CONFIG_SELECTION, "", 10, "", { 0 },
{
"irq", "IRQ", CONFIG_SELECTION, "", 10, "", { 0 },
{
{
"Plug and Play", -1
},
{
"IRQ 2", 2
},
{
"IRQ 3", 3
},
{
"IRQ 4", 4
},
{
"IRQ 5", 5
},
{
"IRQ 7", 7
},
{
"IRQ 9", 9
},
{
"IRQ 10", 10
},
{
"IRQ 11", 11
},
{
"IRQ 12", 12
},
{
""
}
}
},
{
"", "", -1
{ "Plug and Play", -1 },
{ "IRQ 2", 2 },
{ "IRQ 3", 3 },
{ "IRQ 4", 4 },
{ "IRQ 5", 5 },
{ "IRQ 7", 7 },
{ "IRQ 9", 9 },
{ "IRQ 10", 10 },
{ "IRQ 11", 11 },
{ "IRQ 12", 12 },
{ "" }
}
},
{ "", "", -1 }
};
static const device_config_t ide_qua_config[] =
{
static const device_config_t ide_qua_config[] = {
{
"irq", "IRQ", CONFIG_SELECTION, "", 11, "", { 0 },
{
"irq", "IRQ", CONFIG_SELECTION, "", 11, "", { 0 },
{
{
"Plug and Play", -1
},
{
"IRQ 2", 2
},
{
"IRQ 3", 3
},
{
"IRQ 4", 4
},
{
"IRQ 5", 5
},
{
"IRQ 7", 7
},
{
"IRQ 9", 9
},
{
"IRQ 10", 10
},
{
"IRQ 11", 11
},
{
"IRQ 12", 12
},
{
""
}
}
},
{
"", "", -1
{ "Plug and Play", -1 },
{ "IRQ 2", 2 },
{ "IRQ 3", 3 },
{ "IRQ 4", 4 },
{ "IRQ 5", 5 },
{ "IRQ 7", 7 },
{ "IRQ 9", 9 },
{ "IRQ 10", 10 },
{ "IRQ 11", 11 },
{ "IRQ 12", 12 },
{ "" }
}
},
{ "", "", -1 }
};
// clang-format on
const device_t ide_ter_device = {
"Tertiary IDE Controller",

View File

@@ -1614,223 +1614,127 @@ wd1002a_27x_available(void)
return(rom_present(WD1002A_27X_BIOS_FILE));
}
// clang-format off
static const device_config_t dtc_config[] = {
{
"bios_addr", "BIOS address", CONFIG_HEX20, "", 0xc8000, "", { 0 },
{
{
"Disabled", 0x00000
},
{
"C800H", 0xc8000
},
{
"CA00H", 0xca000
},
{
"D800H", 0xd8000
},
{
"F400H", 0xf4000
},
{
""
}
}
"bios_addr", "BIOS address", CONFIG_HEX20, "", 0xc8000, "", { 0 },
{
{ "Disabled", 0x00000 },
{ "C800H", 0xc8000 },
{ "CA00H", 0xca000 },
{ "D800H", 0xd8000 },
{ "F400H", 0xf4000 },
{ "" }
}
},
{
"", "", -1
}
{ "", "", -1 }
};
static const device_config_t st11_config[] = {
{
"base", "Address", CONFIG_HEX16, "", 0x0320, "", { 0 },
{
{
"320H", 0x0320
},
{
"324H", 0x0324
},
{
"328H", 0x0328
},
{
"32CH", 0x032c
},
{
""
}
}
"base", "Address", CONFIG_HEX16, "", 0x0320, "", { 0 },
{
{ "320H", 0x0320 },
{ "324H", 0x0324 },
{ "328H", 0x0328 },
{ "32CH", 0x032c },
{ "" }
}
},
{
"irq", "IRQ", CONFIG_SELECTION, "", 5, "", { 0 },
{
{
"IRQ 2", 2
},
{
"IRQ 5", 5
},
{
""
}
}
"irq", "IRQ", CONFIG_SELECTION, "", 5, "", { 0 },
{
{ "IRQ 2", 2 },
{ "IRQ 5", 5 },
{ "" }
}
},
{
"bios_addr", "BIOS address", CONFIG_HEX20, "", 0xc8000, "", { 0 },
{
{
"Disabled", 0x00000
},
{
"C800H", 0xc8000
},
{
"D000H", 0xd0000
},
{
"D800H", 0xd8000
},
{
"E000H", 0xe0000
},
{
""
}
}
"bios_addr", "BIOS address", CONFIG_HEX20, "", 0xc8000, "", { 0 },
{
{ "Disabled", 0x00000 },
{ "C800H", 0xc8000 },
{ "D000H", 0xd0000 },
{ "D800H", 0xd8000 },
{ "E000H", 0xe0000 },
{ "" }
}
},
{
"revision", "Board Revision", CONFIG_SELECTION, "", 19, "", { 0 },
{
{
"Rev. 05 (v1.7)", 5
},
{
"Rev. 19 (v2.0)", 19
},
{
""
}
}
"revision", "Board Revision", CONFIG_SELECTION, "", 19, "", { 0 },
{
{ "Rev. 05 (v1.7)", 5 },
{ "Rev. 19 (v2.0)", 19 },
{ "" }
}
},
{
"", "", -1
}
{ "", "", -1 }
};
static const device_config_t wd_config[] = {
{
"bios_addr", "BIOS address", CONFIG_HEX20, "", 0xc8000, "", { 0 },
{
{
"Disabled", 0x00000
},
{
"C800H", 0xc8000
},
{
""
}
}
"bios_addr", "BIOS address", CONFIG_HEX20, "", 0xc8000, "", { 0 },
{
{ "Disabled", 0x00000 },
{ "C800H", 0xc8000 },
{ "" }
}
},
{
"base", "Address", CONFIG_HEX16, "", 0x0320, "", { 0 },
{
{
"320H", 0x0320
},
{
"324H", 0x0324
},
{
""
}
}
"base", "Address", CONFIG_HEX16, "", 0x0320, "", { 0 },
{
{ "320H", 0x0320 },
{ "324H", 0x0324 },
{ "" }
}
},
{
"irq", "IRQ", CONFIG_SELECTION, "", 5, "", { 0 },
{
{
"IRQ 2", 2
},
{
"IRQ 5", 5
},
{
""
}
}
"irq", "IRQ", CONFIG_SELECTION, "", 5, "", { 0 },
{
{ "IRQ 2", 2 },
{ "IRQ 5", 5 },
{ "" }
}
},
{
"", "", -1
}
{ "", "", -1 }
};
static const device_config_t wd_rll_config[] = {
{
"bios_addr", "BIOS address", CONFIG_HEX20, "", 0xc8000, "", { 0 },
{
{
"Disabled", 0x00000
},
{
"C800H", 0xc8000
},
{
""
}
}
"bios_addr", "BIOS address", CONFIG_HEX20, "", 0xc8000, "", { 0 },
{
{ "Disabled", 0x00000 },
{ "C800H", 0xc8000 },
{ "" }
}
},
{
"base", "Address", CONFIG_HEX16, "", 0x0320, "", { 0 },
{
{
"320H", 0x0320
},
{
"324H", 0x0324
},
{
""
}
}
"base", "Address", CONFIG_HEX16, "", 0x0320, "", { 0 },
{
{ "320H", 0x0320 },
{ "324H", 0x0324 },
{ "" }
}
},
{
"irq", "IRQ", CONFIG_SELECTION, "", 5, "", { 0 },
{
{
"IRQ 2", 2
},
{
"IRQ 5", 5
},
{
""
}
}
"irq", "IRQ", CONFIG_SELECTION, "", 5, "", { 0 },
{
{ "IRQ 2", 2 },
{ "IRQ 5", 5 },
{ "" }
}
},
{
"translate", "Translate 26 -> 17", CONFIG_SELECTION, "", 0, "", { 0 },
{
{
"Off", 0
},
{
"On", 1
},
{
""
}
}
"translate", "Translate 26 -> 17", CONFIG_SELECTION, "", 0, "", { 0 },
{
{ "Off", 0 },
{ "On", 1 },
{ "" }
}
},
{
"", "", -1
}
{ "", "", -1 }
};
// clang-format on
const device_t st506_xt_xebec_device = {
"IBM PC Fixed Disk Adapter (MFM)",

View File

@@ -1104,54 +1104,35 @@ xta_close(void *priv)
static const device_config_t wdxt150_config[] = {
// clang-format off
{
"base", "Address", CONFIG_HEX16, "", 0x0320, "", { 0 }, /*W2*/
{
"base", "Address", CONFIG_HEX16, "", 0x0320, "", { 0 }, /*W2*/
{
{
"320H", 0x0320
},
{
"324H", 0x0324
},
{
""
}
},
{ "320H", 0x0320 },
{ "324H", 0x0324 },
{ "" }
},
},
{
"irq", "IRQ", CONFIG_SELECTION, "", 5, "", { 0 }, /*W3*/
{
"irq", "IRQ", CONFIG_SELECTION, "", 5, "", { 0 }, /*W3*/
{
{
"IRQ 5", 5
},
{
"IRQ 4", 4
},
{
""
}
},
{ "IRQ 5", 5 },
{ "IRQ 4", 4 },
{ "" }
},
},
{
"bios_addr", "BIOS Address", CONFIG_HEX20, "", 0xc8000, "", { 0 }, /*W1*/
{
"bios_addr", "BIOS Address", CONFIG_HEX20, "", 0xc8000, "", { 0 }, /*W1*/
{
{
"C800H", 0xc8000
},
{
"CA00H", 0xca000
},
{
""
}
},
{ "C800H", 0xc8000 },
{ "CA00H", 0xca000 },
{ "" }
},
{
"", "", -1
}
},
{ "", "", -1 }
// clang-format off
};
const device_t xta_wdxt150_device = {
"WDXT-150 XTA Fixed Disk Controller",
"xta_wdxt150",
@@ -1162,7 +1143,6 @@ const device_t xta_wdxt150_device = {
wdxt150_config
};
const device_t xta_hd20_device = {
"EuroPC HD20 Fixed Disk Controller",
"xta_hd20",

View File

@@ -252,6 +252,10 @@ hdd_image_load(int id)
int vhd_error = 0;
memset(empty_sector, 0, sizeof(empty_sector));
if (fn) {
plat_path_normalize(fn);
}
hdd_images[id].base = 0;

View File

@@ -2381,9 +2381,6 @@ fdc_3f1_enable(fdc_t *fdc, int enable)
fdc->enable_3f1 = enable;
}
const device_t fdc_xt_device = {
"PC/XT Floppy Drive Controller",
"fdc_xt",

View File

@@ -112,23 +112,17 @@ static int b215_available(void)
}
static const device_config_t b215_config[] = {
// clang-format off
{
"bios_addr", "BIOS Address:", CONFIG_HEX20, "", 0xca000, "", { 0 },
{
{
"CA00H", 0xca000
},
{
"CC00H", 0xcc000
},
{
""
}
}
"bios_addr", "BIOS Address:", CONFIG_HEX20, "", 0xca000, "", { 0 },
{
{ "CA00H", 0xca000 },
{ "CC00H", 0xcc000 },
{ "" }
}
},
{
"", "", -1
}
{ "", "", -1 }
// clang-format on
};
const device_t fdc_b215_device = {

View File

@@ -122,29 +122,19 @@ static int pii_158_available(void)
}
static const device_config_t pii_config[] = {
// clang-format off
{
"bios_addr", "BIOS Address:", CONFIG_HEX20, "", 0xce000, "", { 0 },
{
{
"Disabled", 0
},
{
"CA00H", 0xca000
},
{
"CC00H", 0xcc000
},
{
"CE00H", 0xce000
},
{
""
}
}
"bios_addr", "BIOS Address:", CONFIG_HEX20, "", 0xce000, "", { 0 },
{
{ "Disabled", 0 },
{ "CA00H", 0xca000 },
{ "CC00H", 0xcc000 },
{ "CE00H", 0xce000 },
{ "" }
}
},
{
"", "", -1
}
{ "", "", -1 }
// clang-format on
};
const device_t fdc_pii151b_device = {

View File

@@ -438,7 +438,6 @@ gameport_close(void *priv)
free(dev);
}
const device_t gameport_device = {
"Game port",
"gameport",

View File

@@ -613,6 +613,9 @@ extern int machine_at_s370sba_init(const machine_t *);
extern int machine_at_apas3_init(const machine_t *);
extern int machine_at_gt694va_init(const machine_t *);
extern int machine_at_cuv4xls_init(const machine_t *);
#ifdef EMU_DEVICE_H
extern const device_t *at_cuv4xls_get_device(void);
#endif
extern int machine_at_6via90ap_init(const machine_t *);
extern int machine_at_s1857_init(const machine_t *);
extern int machine_at_p6bap_init(const machine_t *);

View File

@@ -1,6 +1,5 @@
#ifndef EMU_SOUND_MIDI_H
# define EMU_SOUND_MIDI_H
#define EMU_SOUND_MIDI_H
#define SYSEX_SIZE 8192
@@ -14,34 +13,31 @@ extern void (*input_msg)(void *p, uint8_t *msg, uint32_t len);
extern int (*input_sysex)(void *p, uint8_t *buf, uint32_t len, int abort);
extern void *midi_in_p;
extern int midi_device_available(int card);
extern int midi_in_device_available(int card);
extern int midi_device_available(int card);
extern int midi_in_device_available(int card);
#ifdef EMU_DEVICE_H
const device_t *midi_device_getdevice(int card);
const device_t *midi_in_device_getdevice(int card);
#endif
extern int midi_device_has_config(int card);
extern int midi_in_device_has_config(int card);
extern char * midi_device_get_internal_name(int card);
extern char * midi_in_device_get_internal_name(int card);
extern int midi_device_get_from_internal_name(char *s);
extern int midi_in_device_get_from_internal_name(char *s);
extern void midi_device_init();
extern void midi_in_device_init();
extern int midi_device_has_config(int card);
extern int midi_in_device_has_config(int card);
extern char *midi_device_get_internal_name(int card);
extern char *midi_in_device_get_internal_name(int card);
extern int midi_device_get_from_internal_name(char *s);
extern int midi_in_device_get_from_internal_name(char *s);
extern void midi_device_init();
extern void midi_in_device_init();
typedef struct midi_device_t
{
typedef struct midi_device_t {
void (*play_sysex)(uint8_t *sysex, unsigned int len);
void (*play_msg)(uint8_t *msg);
void (*poll)();
int (*write)(uint8_t val);
} midi_device_t;
typedef struct midi_in_handler_t
{
typedef struct midi_in_handler_t {
uint8_t *buf;
int cnt;
int cnt;
uint32_t len;
void (*msg)(void *p, uint8_t *msg, uint32_t len);
@@ -50,60 +46,59 @@ typedef struct midi_in_handler_t
struct midi_in_handler_t *prev, *next;
} midi_in_handler_t;
typedef struct midi_t
{
typedef struct midi_t {
uint8_t midi_rt_buf[8], midi_cmd_buf[8],
midi_status, midi_sysex_data[SYSEX_SIZE];
midi_status, midi_sysex_data[SYSEX_SIZE];
int midi_cmd_pos, midi_cmd_len, midi_cmd_r,
midi_realtime, thruchan, midi_clockout;
midi_realtime, thruchan, midi_clockout;
unsigned int midi_sysex_start, midi_sysex_delay,
midi_pos;
midi_device_t *m_out_device, *m_in_device;
midi_pos;
midi_device_t *m_out_device, *m_in_device;
} midi_t;
extern midi_t *midi, *midi_in;
extern void midi_init(midi_device_t* device);
extern void midi_in_init(midi_device_t* device, midi_t **mididev);
extern void midi_close();
extern void midi_in_close(void);
extern void midi_raw_out_rt_byte(uint8_t val);
extern void midi_raw_out_thru_rt_byte(uint8_t val);
extern void midi_raw_out_byte(uint8_t val);
extern void midi_clear_buffer(void);
extern void midi_poll();
extern void midi_init(midi_device_t *device);
extern void midi_in_init(midi_device_t *device, midi_t **mididev);
extern void midi_close();
extern void midi_in_close(void);
extern void midi_raw_out_rt_byte(uint8_t val);
extern void midi_raw_out_thru_rt_byte(uint8_t val);
extern void midi_raw_out_byte(uint8_t val);
extern void midi_clear_buffer(void);
extern void midi_poll();
extern void midi_in_handler(int set, void (*msg)(void *p, uint8_t *msg, uint32_t len), int (*sysex)(void *p, uint8_t *buffer, uint32_t len, int abort), void *p);
extern void midi_in_handlers_clear(void);
extern void midi_in_msg(uint8_t *msg, uint32_t len);
extern void midi_in_sysex(uint8_t *buffer, uint32_t len);
extern void midi_in_handler(int set, void (*msg)(void *p, uint8_t *msg, uint32_t len), int (*sysex)(void *p, uint8_t *buffer, uint32_t len, int abort), void *p);
extern void midi_in_handlers_clear(void);
extern void midi_in_msg(uint8_t *msg, uint32_t len);
extern void midi_in_sysex(uint8_t *buffer, uint32_t len);
#if 0
#ifdef _WIN32
#define SYSTEM_MIDI_NAME "Windows MIDI"
#define SYSTEM_MIDI_INTERNAL_NAME "windows_midi"
# ifdef _WIN32
# define SYSTEM_MIDI_NAME "Windows MIDI"
# define SYSTEM_MIDI_INTERNAL_NAME "windows_midi"
# else
# define SYSTEM_MIDI_NAME "System MIDI"
# define SYSTEM_MIDI_INTERNAL_NAME "system_midi"
# endif
#else
#define SYSTEM_MIDI_NAME "System MIDI"
#define SYSTEM_MIDI_INTERNAL_NAME "system_midi"
#endif
#else
#define SYSTEM_MIDI_NAME "System MIDI"
#define SYSTEM_MIDI_INTERNAL_NAME "system_midi"
# define SYSTEM_MIDI_NAME "System MIDI"
# define SYSTEM_MIDI_INTERNAL_NAME "system_midi"
#endif
#define MIDI_INPUT_NAME "MIDI Input Device"
#define MIDI_INPUT_NAME "MIDI Input Device"
#define MIDI_INPUT_INTERNAL_NAME "midi_in"
#ifdef EMU_DEVICE_H
extern const device_t rtmidi_device;
extern const device_t rtmidi_input_device;
#ifdef USE_FLUIDSYNTH
# ifdef USE_FLUIDSYNTH
extern const device_t fluidsynth_device;
#endif
#ifdef USE_MUNT
# endif
# ifdef USE_MUNT
extern const device_t mt32_device;
extern const device_t cm32l_device;
#endif
# endif
#endif
#endif /*EMU_SOUND_MIDI_H*/
#endif /*EMU_SOUND_MIDI_H*/

View File

@@ -1,15 +1,14 @@
#ifndef EMU_SOUND_RTMIDI_H
# define EMU_SOUND_RTMIDI_H
#define EMU_SOUND_RTMIDI_H
#ifdef __cplusplus
extern "C"
{
extern "C" {
#endif
extern int rtmidi_get_num_devs(void);
extern void rtmidi_get_dev_name(int num, char *s);
extern int rtmidi_in_get_num_devs(void);
extern void rtmidi_in_get_dev_name(int num, char *s);
extern int rtmidi_get_num_devs(void);
extern void rtmidi_get_dev_name(int num, char *s);
extern int rtmidi_in_get_num_devs(void);
extern void rtmidi_in_get_dev_name(int num, char *s);
#ifdef __cplusplus
}

View File

@@ -111,6 +111,7 @@ extern char *plat_get_extension(char *s);
extern void plat_append_filename(char *dest, const char *s1, const char *s2);
extern void plat_put_backslash(char *s);
extern void plat_path_slash(char *path);
extern void plat_path_normalize(char *path);
extern int plat_path_abs(char *path);
extern int plat_dir_check(char *path);
extern int plat_dir_create(char *path);

View File

@@ -28,6 +28,7 @@ extern const device_t scsi_lcs6821n_device;
extern const device_t scsi_rt1000b_device;
extern const device_t scsi_t128_device;
extern const device_t scsi_t130b_device;
extern const device_t scsi_ls2000_device;
#if defined(DEV_BRANCH) && defined(USE_SUMO)
extern const device_t scsi_scsiat_device;
#endif

View File

@@ -15,82 +15,81 @@
* Copyright 2021 RichardG.
*/
#ifndef SOUND_AC97_H
# define SOUND_AC97_H
#define SOUND_AC97_H
#define AC97_VENDOR_ID(f, s, t, dev) ((((f) & 0xff) << 24) | (((s) & 0xff) << 16) | (((t) & 0xff) << 8) | ((dev) & 0xff))
#define AC97_VENDOR_ID(f, s, t, dev) ((((f) &0xff) << 24) | (((s) &0xff) << 16) | (((t) &0xff) << 8) | ((dev) &0xff))
/* Misc support bits (misc_flags). Most of these are not part of any
registers, but control enabling/disabling of registers and bits. */
#define AC97_MASTER_6B (1 << 0) /* register 02 bits [13,5] (ML5/MR5) */
#define AC97_AUXOUT (1 << 1) /* register 04 */
#define AC97_AUXOUT_6B (1 << 2) /* register 04 bits [13,5] (ML5/MR5) */
#define AC97_MONOOUT (1 << 3) /* register 06 */
#define AC97_MONOOUT_6B (1 << 4) /* register 06 bit 5 (MM5) */
#define AC97_PCBEEP (1 << 5) /* register 0A */
#define AC97_PCBEEP_GEN (1 << 6) /* register 0A bits [12:5] (F[7:0]) */
#define AC97_PHONE (1 << 9) /* register 0C */
#define AC97_VIDEO (1 << 10) /* register 14 */
#define AC97_AUXIN (1 << 11) /* register 16 */
#define AC97_POP (1 << 15) /* register 20 bit 15 (POP) - definition shared with General Purpose bits */
#define AC97_MS (1 << 8) /* register 20 bit 8 (MS) - definition shared with General Purpose bits */
#define AC97_LPBK (1 << 7) /* register 20 bit 7 (LPBK) - definition shared with General Purpose bits */
#define AC97_DSA (1 << 12) /* register 28 bits [5:4] (DSA[1:0]) */
#define AC97_LFE_6B (1 << 13) /* register 36 bit 13 (LFE5) */
#define AC97_CENTER_6B (1 << 14) /* register 36 bit 5 (CNT5) */
#define AC97_SURR_6B (1 << 16) /* register 38 bits [13,5] (LSR5/RSR5) */
#define AC97_MASTER_6B (1 << 0) /* register 02 bits [13,5] (ML5/MR5) */
#define AC97_AUXOUT (1 << 1) /* register 04 */
#define AC97_AUXOUT_6B (1 << 2) /* register 04 bits [13,5] (ML5/MR5) */
#define AC97_MONOOUT (1 << 3) /* register 06 */
#define AC97_MONOOUT_6B (1 << 4) /* register 06 bit 5 (MM5) */
#define AC97_PCBEEP (1 << 5) /* register 0A */
#define AC97_PCBEEP_GEN (1 << 6) /* register 0A bits [12:5] (F[7:0]) */
#define AC97_PHONE (1 << 9) /* register 0C */
#define AC97_VIDEO (1 << 10) /* register 14 */
#define AC97_AUXIN (1 << 11) /* register 16 */
#define AC97_POP (1 << 15) /* register 20 bit 15 (POP) - definition shared with General Purpose bits */
#define AC97_MS (1 << 8) /* register 20 bit 8 (MS) - definition shared with General Purpose bits */
#define AC97_LPBK (1 << 7) /* register 20 bit 7 (LPBK) - definition shared with General Purpose bits */
#define AC97_DSA (1 << 12) /* register 28 bits [5:4] (DSA[1:0]) */
#define AC97_LFE_6B (1 << 13) /* register 36 bit 13 (LFE5) */
#define AC97_CENTER_6B (1 << 14) /* register 36 bit 5 (CNT5) */
#define AC97_SURR_6B (1 << 16) /* register 38 bits [13,5] (LSR5/RSR5) */
/* Reset bits (reset_flags), register 00. */
#define AC97_MICPCM (1 << 0)
#define AC97_MODEMLINE (1 << 1)
#define AC97_TONECTL (1 << 2)
#define AC97_SIMSTEREO (1 << 3)
#define AC97_HPOUT (1 << 4)
#define AC97_LOUDNESS (1 << 5)
#define AC97_DAC_18B (1 << 6)
#define AC97_DAC_20B (1 << 7)
#define AC97_ADC_18B (1 << 8)
#define AC97_ADC_20B (1 << 9)
#define AC97_3D_SHIFT 10
#define AC97_MICPCM (1 << 0)
#define AC97_MODEMLINE (1 << 1)
#define AC97_TONECTL (1 << 2)
#define AC97_SIMSTEREO (1 << 3)
#define AC97_HPOUT (1 << 4)
#define AC97_LOUDNESS (1 << 5)
#define AC97_DAC_18B (1 << 6)
#define AC97_DAC_20B (1 << 7)
#define AC97_ADC_18B (1 << 8)
#define AC97_ADC_20B (1 << 9)
#define AC97_3D_SHIFT 10
/* Extended Audio ID bits (extid_flags), register 28. */
#define AC97_VRA (1 << 0)
#define AC97_DRA (1 << 1)
#define AC97_SPDIF (1 << 2)
#define AC97_VRM (1 << 3)
#define AC97_CDAC (1 << 6)
#define AC97_SDAC (1 << 7)
#define AC97_LDAC (1 << 8)
#define AC97_AMAP (1 << 9)
#define AC97_REV_2_1 (0 << 10)
#define AC97_REV_2_2 (1 << 10)
#define AC97_REV_2_3 (2 << 10)
#define AC97_REV_MASK (3 << 10)
#define AC97_VRA (1 << 0)
#define AC97_DRA (1 << 1)
#define AC97_SPDIF (1 << 2)
#define AC97_VRM (1 << 3)
#define AC97_CDAC (1 << 6)
#define AC97_SDAC (1 << 7)
#define AC97_LDAC (1 << 8)
#define AC97_AMAP (1 << 9)
#define AC97_REV_2_1 (0 << 10)
#define AC97_REV_2_2 (1 << 10)
#define AC97_REV_2_3 (2 << 10)
#define AC97_REV_MASK (3 << 10)
/* Volume bits. */
#define AC97_MUTE (1 << 15)
#define AC97_MUTE_L (1 << 15)
#define AC97_MUTE_R (1 << 7)
#define AC97_MUTE (1 << 15)
#define AC97_MUTE_L (1 << 15)
#define AC97_MUTE_R (1 << 7)
/* General Purpose bits, register 20. */
/* POP already defined */
#define AC97_ST (1 << 14)
#define AC97_3D (1 << 13)
#define AC97_LD (1 << 12)
#define AC97_DRSS_MASK (3 << 10)
#define AC97_MIX (1 << 9)
#define AC97_ST (1 << 14)
#define AC97_3D (1 << 13)
#define AC97_LD (1 << 12)
#define AC97_DRSS_MASK (3 << 10)
#define AC97_MIX (1 << 9)
/* MS already defined */
/* LPBK already defined */
/* Extended Audio Status/Control bits, register 2A. */
#define AC97_SPSA_SHIFT 4
#define AC97_SPSA_MASK 3
#define AC97_MADC (1 << 9)
#define AC97_SPCV (1 << 10)
#define AC97_PRI (1 << 11)
#define AC97_PRJ (1 << 12)
#define AC97_PRK (1 << 13)
#define AC97_PRL (1 << 14)
#define AC97_SPSA_SHIFT 4
#define AC97_SPSA_MASK 3
#define AC97_MADC (1 << 9)
#define AC97_SPCV (1 << 10)
#define AC97_PRI (1 << 11)
#define AC97_PRJ (1 << 12)
#define AC97_PRK (1 << 13)
#define AC97_PRL (1 << 14)
/* New codecs should be added to the end of this enum to avoid breaking configs. */
enum {
@@ -104,52 +103,49 @@ enum {
AC97_CODEC_AK4540
};
typedef struct {
const uint16_t index, value, write_mask;
} ac97_vendor_reg_t;
typedef struct {
uint32_t vendor_id, min_rate, max_rate, misc_flags;
uint16_t reset_flags, extid_flags,
powerdown_mask, regs[64];
uint8_t codec_id, vendor_reg_page_max;
uint32_t vendor_id, min_rate, max_rate, misc_flags;
uint16_t reset_flags, extid_flags,
powerdown_mask, regs[64];
uint8_t codec_id, vendor_reg_page_max;
const ac97_vendor_reg_t *vendor_regs;
uint16_t *vendor_reg_pages;
uint16_t *vendor_reg_pages;
} ac97_codec_t;
extern uint16_t ac97_codec_readw(ac97_codec_t *dev, uint8_t reg);
extern void ac97_codec_writew(ac97_codec_t *dev, uint8_t reg, uint16_t val);
extern void ac97_codec_reset(void *priv);
extern void ac97_codec_getattn(void *priv, uint8_t reg, int *l, int *r);
extern uint32_t ac97_codec_getrate(void *priv, uint8_t reg);
extern uint16_t ac97_codec_readw(ac97_codec_t *dev, uint8_t reg);
extern void ac97_codec_writew(ac97_codec_t *dev, uint8_t reg, uint16_t val);
extern void ac97_codec_reset(void *priv);
extern void ac97_codec_getattn(void *priv, uint8_t reg, int *l, int *r);
extern uint32_t ac97_codec_getrate(void *priv, uint8_t reg);
extern const device_t *ac97_codec_get(int model);
extern void ac97_via_set_slot(void *priv, int slot, int irq_pin);
extern uint8_t ac97_via_read_status(void *priv, uint8_t modem);
extern void ac97_via_write_control(void *priv, uint8_t modem, uint8_t val);
extern void ac97_via_remap_audio_sgd(void *priv, uint16_t new_io_base, uint8_t enable);
extern void ac97_via_remap_modem_sgd(void *priv, uint16_t new_io_base, uint8_t enable);
extern void ac97_via_remap_audio_codec(void *priv, uint16_t new_io_base, uint8_t enable);
extern void ac97_via_remap_modem_codec(void *priv, uint16_t new_io_base, uint8_t enable);
extern void ac97_via_set_slot(void *priv, int slot, int irq_pin);
extern uint8_t ac97_via_read_status(void *priv, uint8_t modem);
extern void ac97_via_write_control(void *priv, uint8_t modem, uint8_t val);
extern void ac97_via_remap_audio_sgd(void *priv, uint16_t new_io_base, uint8_t enable);
extern void ac97_via_remap_modem_sgd(void *priv, uint16_t new_io_base, uint8_t enable);
extern void ac97_via_remap_audio_codec(void *priv, uint16_t new_io_base, uint8_t enable);
extern void ac97_via_remap_modem_codec(void *priv, uint16_t new_io_base, uint8_t enable);
extern ac97_codec_t **ac97_codec, **ac97_modem_codec;
extern int ac97_codec_count, ac97_modem_codec_count,
ac97_codec_id, ac97_modem_codec_id;
extern ac97_codec_t **ac97_codec, **ac97_modem_codec;
extern int ac97_codec_count, ac97_modem_codec_count,
ac97_codec_id, ac97_modem_codec_id;
#ifdef EMU_DEVICE_H
extern const device_t ad1881_device;
extern const device_t ak4540_device;
extern const device_t alc100_device;
extern const device_t cs4297_device;
extern const device_t cs4297a_device;
extern const device_t stac9708_device;
extern const device_t stac9721_device;
extern const device_t wm9701a_device;
extern const device_t ad1881_device;
extern const device_t ak4540_device;
extern const device_t alc100_device;
extern const device_t cs4297_device;
extern const device_t cs4297a_device;
extern const device_t stac9708_device;
extern const device_t stac9721_device;
extern const device_t wm9701a_device;
extern const device_t ac97_via_device;
extern const device_t ac97_via_device;
#endif
#endif /*SOUND_AC97_H*/

View File

@@ -20,7 +20,7 @@
*/
#ifndef SOUND_AD1848_H
# define SOUND_AD1848_H
#define SOUND_AD1848_H
enum {
AD1848_TYPE_DEFAULT = 0,
@@ -30,44 +30,42 @@ enum {
AD1848_TYPE_CS4236
};
typedef struct {
uint8_t type, index, xindex, regs[32], xregs[32], status; /* 16 original registers + 16 CS4231A extensions + 32 CS4236 extensions */
uint8_t type, index, xindex, regs[32], xregs[32], status; /* 16 original registers + 16 CS4231A extensions + 32 CS4236 extensions */
int count;
uint8_t trd, mce, wten: 1;
int count;
uint8_t trd, mce, wten : 1;
int16_t out_l, out_r;
double cd_vol_l, cd_vol_r;
int fm_vol_l, fm_vol_r;
uint8_t fmt_mask, wave_vol_mask;
int16_t out_l, out_r;
double cd_vol_l, cd_vol_r;
int fm_vol_l, fm_vol_r;
uint8_t fmt_mask, wave_vol_mask;
uint8_t enable: 1, irq: 4, dma: 3;
int freq;
uint8_t enable : 1, irq : 4, dma : 3;
int freq;
pc_timer_t timer_count;
uint64_t timer_latch;
pc_timer_t timer_count;
uint64_t timer_latch;
int16_t buffer[SOUNDBUFLEN * 2];
int pos;
int16_t buffer[SOUNDBUFLEN * 2];
int pos;
void *cram_priv,
(*cram_write)(uint16_t addr, uint8_t val, void *priv);
uint8_t (*cram_read)(uint16_t addr, void *priv);
void *cram_priv,
(*cram_write)(uint16_t addr, uint8_t val, void *priv);
uint8_t (*cram_read)(uint16_t addr, void *priv);
} ad1848_t;
extern void ad1848_setirq(ad1848_t *ad1848, int irq);
extern void ad1848_setdma(ad1848_t *ad1848, int dma);
extern void ad1848_updatevolmask(ad1848_t *ad1848);
extern void ad1848_setirq(ad1848_t *ad1848, int irq);
extern void ad1848_setdma(ad1848_t *ad1848, int dma);
extern void ad1848_updatevolmask(ad1848_t *ad1848);
extern uint8_t ad1848_read(uint16_t addr, void *priv);
extern void ad1848_write(uint16_t addr, uint8_t val, void *priv);
extern uint8_t ad1848_read(uint16_t addr, void *priv);
extern void ad1848_write(uint16_t addr, uint8_t val, void *priv);
extern void ad1848_update(ad1848_t *ad1848);
extern void ad1848_speed_changed(ad1848_t *ad1848);
extern void ad1848_filter_cd_audio(int channel, double *buffer, void *priv);
extern void ad1848_update(ad1848_t *ad1848);
extern void ad1848_speed_changed(ad1848_t *ad1848);
extern void ad1848_filter_cd_audio(int channel, double *buffer, void *priv);
extern void ad1848_init(ad1848_t *ad1848, uint8_t type);
extern void ad1848_init(ad1848_t *ad1848, uint8_t type);
#endif /*SOUND_AD1848_H*/

View File

@@ -1,5 +1,5 @@
#ifndef SOUND_AZT2316A_H
# define SOUND_AZT2316A_H
#define SOUND_AZT2316A_H
extern void azt2316a_enable_wss(uint8_t enable, void *p);

View File

@@ -1,35 +1,33 @@
#ifndef SOUND_CMS_H
# define SOUND_CMS_H
#define SOUND_CMS_H
#include <stdint.h>
#include <86box/sound.h>
#include <stdint.h>
#define MASTER_CLOCK 7159090
typedef struct cms_t
{
int addrs[2];
uint8_t regs[2][32];
uint16_t latch[2][6];
int freq[2][6];
float count[2][6];
int vol[2][6][2];
int stat[2][6];
uint16_t noise[2][2];
uint16_t noisefreq[2][2];
int noisecount[2][2];
int noisetype[2][2];
typedef struct cms_t {
int addrs[2];
uint8_t regs[2][32];
uint16_t latch[2][6];
int freq[2][6];
float count[2][6];
int vol[2][6][2];
int stat[2][6];
uint16_t noise[2][2];
uint16_t noisefreq[2][2];
int noisecount[2][2];
int noisetype[2][2];
uint8_t latched_data;
uint8_t latched_data;
int16_t buffer[SOUNDBUFLEN * 2];
int16_t buffer[SOUNDBUFLEN * 2];
int pos;
int pos;
} cms_t;
extern void cms_update(cms_t *cms);
extern void cms_write(uint16_t addr, uint8_t val, void *p);
extern void cms_update(cms_t *cms);
extern void cms_write(uint16_t addr, uint8_t val, void *p);
extern uint8_t cms_read(uint16_t addr, void *p);
#endif /*SOUND_CMS_H*/
#endif /*SOUND_CMS_H*/

View File

@@ -1,37 +1,37 @@
#ifndef SOUND_EMU8K_H
# define SOUND_EMU8K_H
#define SOUND_EMU8K_H
/* All these defines are in samples, not in bytes. */
#define EMU8K_MEM_ADDRESS_MASK 0xFFFFFF
#define EMU8K_RAM_MEM_START 0x200000
#define EMU8K_FM_MEM_ADDRESS 0xFFFFE0
#define EMU8K_MEM_ADDRESS_MASK 0xFFFFFF
#define EMU8K_RAM_MEM_START 0x200000
#define EMU8K_FM_MEM_ADDRESS 0xFFFFE0
#define EMU8K_RAM_POINTERS_MASK 0x3F
#define EMU8K_LFOCHORUS_SIZE 0x4000
#define EMU8K_LFOCHORUS_SIZE 0x4000
/*
* Everything in this file assumes little endian
*/
/* used for the increment of oscillator position*/
typedef struct emu8k_mem_internal_t {
union {
uint64_t addr;
struct {
uint16_t fract_lw_address;
uint16_t fract_address;
uint32_t int_address;
};
union {
uint64_t addr;
struct {
uint16_t fract_lw_address;
uint16_t fract_address;
uint32_t int_address;
};
};
} emu8k_mem_internal_t;
/* used for access to ram pointers from oscillator position. */
typedef struct emu8k_mem_pointers_t {
union {
uint32_t addr;
struct {
uint16_t lw_address;
uint8_t hb_address;
uint8_t unused_address;
};
union {
uint32_t addr;
struct {
uint16_t lw_address;
uint8_t hb_address;
uint8_t unused_address;
};
};
} emu8k_mem_pointers_t;
/*
@@ -84,33 +84,30 @@ typedef struct emu8k_mem_pointers_t {
* This allows to operate db values by simply adding them.
*/
typedef struct emu8k_envelope_t {
int state;
int32_t delay_samples, hold_samples, attack_samples;
int32_t value_amp_hz, value_db_oct;
int32_t sustain_value_db_oct;
int32_t attack_amount_amp_hz, ramp_amount_db_oct;
int state;
int32_t delay_samples, hold_samples, attack_samples;
int32_t value_amp_hz, value_db_oct;
int32_t sustain_value_db_oct;
int32_t attack_amount_amp_hz, ramp_amount_db_oct;
} emu8k_envelope_t;
typedef struct emu8k_chorus_eng_t {
int32_t write;
int32_t feedback;
int32_t delay_samples_central;
double lfodepth_multip;
double delay_offset_samples_right;
emu8k_mem_internal_t lfo_inc;
emu8k_mem_internal_t lfo_pos;
int32_t write;
int32_t feedback;
int32_t delay_samples_central;
double lfodepth_multip;
double delay_offset_samples_right;
emu8k_mem_internal_t lfo_inc;
emu8k_mem_internal_t lfo_pos;
int32_t chorus_left_buffer[EMU8K_LFOCHORUS_SIZE];
int32_t chorus_right_buffer[EMU8K_LFOCHORUS_SIZE];
int32_t chorus_left_buffer[EMU8K_LFOCHORUS_SIZE];
int32_t chorus_right_buffer[EMU8K_LFOCHORUS_SIZE];
} emu8k_chorus_eng_t;
/* 32 * 242. 32 comes from the "right" room resso case.*/
#define MAX_REFL_SIZE 7744
/* Reverb parameters description, extracted from AST sources.
Mix level
Decay
@@ -133,267 +130,258 @@ typedef struct emu8k_chorus_eng_t {
Ref 6 feedback L&R
*/
typedef struct emu8k_reverb_combfilter_t {
int read_pos;
int32_t reflection[MAX_REFL_SIZE];
float output_gain;
float feedback;
float damp1;
float damp2;
int bufsize;
int32_t filterstore;
int read_pos;
int32_t reflection[MAX_REFL_SIZE];
float output_gain;
float feedback;
float damp1;
float damp2;
int bufsize;
int32_t filterstore;
} emu8k_reverb_combfilter_t;
typedef struct emu8k_reverb_eng_t {
int16_t out_mix;
int16_t link_return_amp; /* tail part output gain ? */
int8_t link_return_type;
int16_t out_mix;
int16_t link_return_amp; /* tail part output gain ? */
int8_t link_return_type;
uint8_t refl_in_amp;
uint8_t refl_in_amp;
emu8k_reverb_combfilter_t reflections[6];
emu8k_reverb_combfilter_t allpass[8];
emu8k_reverb_combfilter_t tailL;
emu8k_reverb_combfilter_t tailR;
emu8k_reverb_combfilter_t reflections[6];
emu8k_reverb_combfilter_t allpass[8];
emu8k_reverb_combfilter_t tailL;
emu8k_reverb_combfilter_t tailR;
emu8k_reverb_combfilter_t damper;
emu8k_reverb_combfilter_t damper;
} emu8k_reverb_eng_t;
typedef struct emu8k_slide_t {
int32_t last;
int32_t last;
} emu8k_slide_t;
typedef struct emu8k_voice_t
{
union {
uint32_t cpf;
struct {
uint16_t cpf_curr_frac_addr; /* fractional part of the playing cursor. */
uint16_t cpf_curr_pitch; /* 0x4000 = no shift. Linear increment */
};
typedef struct emu8k_voice_t {
union {
uint32_t cpf;
struct {
uint16_t cpf_curr_frac_addr; /* fractional part of the playing cursor. */
uint16_t cpf_curr_pitch; /* 0x4000 = no shift. Linear increment */
};
union {
uint32_t ptrx;
struct {
uint8_t ptrx_pan_aux;
uint8_t ptrx_revb_send;
uint16_t ptrx_pit_target; /* target pitch to which slide at curr_pitch speed. */
};
};
union {
uint32_t ptrx;
struct {
uint8_t ptrx_pan_aux;
uint8_t ptrx_revb_send;
uint16_t ptrx_pit_target; /* target pitch to which slide at curr_pitch speed. */
};
union {
uint32_t cvcf;
struct {
uint16_t cvcf_curr_filt_ctoff;
uint16_t cvcf_curr_volume;
};
};
union {
uint32_t cvcf;
struct {
uint16_t cvcf_curr_filt_ctoff;
uint16_t cvcf_curr_volume;
};
emu8k_slide_t volumeslide;
union {
uint32_t vtft;
struct {
uint16_t vtft_filter_target;
uint16_t vtft_vol_target; /* written to by the envelope engine. */
};
};
emu8k_slide_t volumeslide;
union {
uint32_t vtft;
struct {
uint16_t vtft_filter_target;
uint16_t vtft_vol_target; /* written to by the envelope engine. */
};
/* These registers are used at least by the Windows drivers, and seem to be resetting
* something, similarly to targets and current, but... of what?
* what is curious is that if they are already zero, they are not written to, so it really
* looks like they are information about the status of the channel. (lfo position maybe?) */
uint32_t unknown_data0_4;
uint32_t unknown_data0_5;
union {
uint32_t psst;
struct {
uint16_t psst_lw_address;
uint8_t psst_hw_address;
uint8_t psst_pan;
};
#define PSST_LOOP_START_MASK 0x00FFFFFF /* In samples, i.e. uint16_t array[BOARD_RAM/2]; */
};
/* These registers are used at least by the Windows drivers, and seem to be resetting
* something, similarly to targets and current, but... of what?
* what is curious is that if they are already zero, they are not written to, so it really
* looks like they are information about the status of the channel. (lfo position maybe?) */
uint32_t unknown_data0_4;
uint32_t unknown_data0_5;
union {
uint32_t psst;
struct {
uint16_t psst_lw_address;
uint8_t psst_hw_address;
uint8_t psst_pan;
};
union {
uint32_t csl;
struct {
uint16_t csl_lw_address;
uint8_t csl_hw_address;
uint8_t csl_chor_send;
};
#define CSL_LOOP_END_MASK 0x00FFFFFF /* In samples, i.e. uint16_t array[BOARD_RAM/2]; */
#define PSST_LOOP_START_MASK 0x00FFFFFF /* In samples, i.e. uint16_t array[BOARD_RAM/2]; */
};
union {
uint32_t csl;
struct {
uint16_t csl_lw_address;
uint8_t csl_hw_address;
uint8_t csl_chor_send;
};
union {
uint32_t ccca;
struct {
uint16_t ccca_lw_addr;
uint8_t ccca_hb_addr;
uint8_t ccca_qcontrol;
};
#define CSL_LOOP_END_MASK 0x00FFFFFF /* In samples, i.e. uint16_t array[BOARD_RAM/2]; */
};
union {
uint32_t ccca;
struct {
uint16_t ccca_lw_addr;
uint8_t ccca_hb_addr;
uint8_t ccca_qcontrol;
};
#define CCCA_FILTQ_GET(ccca) (ccca>>28)
#define CCCA_FILTQ_SET(ccca,q) ccca = (ccca&0x0FFFFFFF) | (q<<28)
/* Bit 27 should always be zero */
#define CCCA_DMA_ACTIVE(ccca) (ccca&0x04000000)
#define CCCA_DMA_WRITE_MODE(ccca) (ccca&0x02000000)
#define CCCA_DMA_WRITE_RIGHT(ccca) (ccca&0x01000000)
};
#define CCCA_FILTQ_GET(ccca) (ccca >> 28)
#define CCCA_FILTQ_SET(ccca, q) ccca = (ccca & 0x0FFFFFFF) | (q << 28)
/* Bit 27 should always be zero */
#define CCCA_DMA_ACTIVE(ccca) (ccca & 0x04000000)
#define CCCA_DMA_WRITE_MODE(ccca) (ccca & 0x02000000)
#define CCCA_DMA_WRITE_RIGHT(ccca) (ccca & 0x01000000)
uint16_t envvol;
#define ENVVOL_NODELAY(envol) (envvol&0x8000)
/* Verified with a soundfont bank. 7FFF is the minimum delay time, and 0 is the max delay time */
#define ENVVOL_TO_EMU_SAMPLES(envvol) (envvol&0x8000) ? 0 : ((0x8000-(envvol&0x7FFF)) <<5)
uint16_t envvol;
#define ENVVOL_NODELAY(envol) (envvol & 0x8000)
/* Verified with a soundfont bank. 7FFF is the minimum delay time, and 0 is the max delay time */
#define ENVVOL_TO_EMU_SAMPLES(envvol) (envvol & 0x8000) ? 0 : ((0x8000 - (envvol & 0x7FFF)) << 5)
uint16_t dcysusv;
#define DCYSUSV_IS_RELEASE(dcysusv) (dcysusv&0x8000)
#define DCYSUSV_GENERATOR_ENGINE_ON(dcysusv) !(dcysusv&0x0080)
#define DCYSUSV_SUSVALUE_GET(dcysusv) ((dcysusv>>8)&0x7F)
/* Inverting the range compared to documentation because the envelope runs from 0dBFS = 0 to -96dBFS = (1 <<21) */
#define DCYSUSV_SUS_TO_ENV_RANGE(susvalue) (((0x7F-susvalue) << 21)/0x7F)
#define DCYSUSV_DECAYRELEASE_GET(dcysusv) (dcysusv&0x7F)
uint16_t dcysusv;
#define DCYSUSV_IS_RELEASE(dcysusv) (dcysusv & 0x8000)
#define DCYSUSV_GENERATOR_ENGINE_ON(dcysusv) !(dcysusv & 0x0080)
#define DCYSUSV_SUSVALUE_GET(dcysusv) ((dcysusv >> 8) & 0x7F)
/* Inverting the range compared to documentation because the envelope runs from 0dBFS = 0 to -96dBFS = (1 <<21) */
#define DCYSUSV_SUS_TO_ENV_RANGE(susvalue) (((0x7F - susvalue) << 21) / 0x7F)
#define DCYSUSV_DECAYRELEASE_GET(dcysusv) (dcysusv & 0x7F)
uint16_t envval;
#define ENVVAL_NODELAY(enval) (envval&0x8000)
/* Verified with a soundfont bank. 7FFF is the minimum delay time, and 0 is the max delay time */
#define ENVVAL_TO_EMU_SAMPLES(envval)(envval&0x8000) ? 0 : ((0x8000-(envval&0x7FFF)) <<5)
uint16_t envval;
#define ENVVAL_NODELAY(enval) (envval & 0x8000)
/* Verified with a soundfont bank. 7FFF is the minimum delay time, and 0 is the max delay time */
#define ENVVAL_TO_EMU_SAMPLES(envval) (envval & 0x8000) ? 0 : ((0x8000 - (envval & 0x7FFF)) << 5)
uint16_t dcysus;
#define DCYSUS_IS_RELEASE(dcysus) (dcysus&0x8000)
#define DCYSUS_SUSVALUE_GET(dcysus) ((dcysus>>8)&0x7F)
#define DCYSUS_SUS_TO_ENV_RANGE(susvalue) ((susvalue << 21)/0x7F)
#define DCYSUS_DECAYRELEASE_GET(dcysus) (dcysus&0x7F)
uint16_t dcysus;
#define DCYSUS_IS_RELEASE(dcysus) (dcysus & 0x8000)
#define DCYSUS_SUSVALUE_GET(dcysus) ((dcysus >> 8) & 0x7F)
#define DCYSUS_SUS_TO_ENV_RANGE(susvalue) ((susvalue << 21) / 0x7F)
#define DCYSUS_DECAYRELEASE_GET(dcysus) (dcysus & 0x7F)
uint16_t atkhldv;
#define ATKHLDV_TRIGGER(atkhldv) !(atkhldv&0x8000)
#define ATKHLDV_HOLD(atkhldv) ((atkhldv>>8)&0x7F)
#define ATKHLDV_HOLD_TO_EMU_SAMPLES(atkhldv) (4096*(0x7F-((atkhldv>>8)&0x7F)))
#define ATKHLDV_ATTACK(atkhldv) (atkhldv&0x7F)
uint16_t atkhldv;
#define ATKHLDV_TRIGGER(atkhldv) !(atkhldv & 0x8000)
#define ATKHLDV_HOLD(atkhldv) ((atkhldv >> 8) & 0x7F)
#define ATKHLDV_HOLD_TO_EMU_SAMPLES(atkhldv) (4096 * (0x7F - ((atkhldv >> 8) & 0x7F)))
#define ATKHLDV_ATTACK(atkhldv) (atkhldv & 0x7F)
uint16_t lfo1val, lfo2val;
#define LFOxVAL_NODELAY(lfoxval) (lfoxval&0x8000)
#define LFOxVAL_TO_EMU_SAMPLES(lfoxval) (lfoxval&0x8000) ? 0 : ((0x8000-(lfoxval&0x7FFF)) <<5)
uint16_t lfo1val, lfo2val;
#define LFOxVAL_NODELAY(lfoxval) (lfoxval & 0x8000)
#define LFOxVAL_TO_EMU_SAMPLES(lfoxval) (lfoxval & 0x8000) ? 0 : ((0x8000 - (lfoxval & 0x7FFF)) << 5)
uint16_t atkhld;
#define ATKHLD_TRIGGER(atkhld) !(atkhld&0x8000)
#define ATKHLD_HOLD(atkhld) ((atkhld>>8)&0x7F)
#define ATKHLD_HOLD_TO_EMU_SAMPLES(atkhld) (4096*(0x7F-((atkhld>>8)&0x7F)))
#define ATKHLD_ATTACK(atkhld) (atkhld&0x7F)
uint16_t atkhld;
#define ATKHLD_TRIGGER(atkhld) !(atkhld & 0x8000)
#define ATKHLD_HOLD(atkhld) ((atkhld >> 8) & 0x7F)
#define ATKHLD_HOLD_TO_EMU_SAMPLES(atkhld) (4096 * (0x7F - ((atkhld >> 8) & 0x7F)))
#define ATKHLD_ATTACK(atkhld) (atkhld & 0x7F)
uint16_t ip;
#define INTIAL_PITCH_CENTER 0xE000
#define INTIAL_PITCH_OCTAVE 0x1000
uint16_t ip;
#define INTIAL_PITCH_CENTER 0xE000
#define INTIAL_PITCH_OCTAVE 0x1000
union {
uint16_t ifatn;
struct{
uint8_t ifatn_attenuation;
uint8_t ifatn_init_filter;
};
union {
uint16_t ifatn;
struct {
uint8_t ifatn_attenuation;
uint8_t ifatn_init_filter;
};
union {
uint16_t pefe;
struct {
int8_t pefe_modenv_filter_height;
int8_t pefe_modenv_pitch_height;
};
};
union {
uint16_t pefe;
struct {
int8_t pefe_modenv_filter_height;
int8_t pefe_modenv_pitch_height;
};
union {
uint16_t fmmod;
struct {
int8_t fmmod_lfo1_filt_mod;
int8_t fmmod_lfo1_vibrato;
};
};
union {
uint16_t fmmod;
struct {
int8_t fmmod_lfo1_filt_mod;
int8_t fmmod_lfo1_vibrato;
};
union {
uint16_t tremfrq;
struct {
uint8_t tremfrq_lfo1_freq;
int8_t tremfrq_lfo1_tremolo;
};
};
union {
uint16_t tremfrq;
struct {
uint8_t tremfrq_lfo1_freq;
int8_t tremfrq_lfo1_tremolo;
};
union {
uint16_t fm2frq2;
struct {
uint8_t fm2frq2_lfo2_freq;
int8_t fm2frq2_lfo2_vibrato;
};
};
union {
uint16_t fm2frq2;
struct {
uint8_t fm2frq2_lfo2_freq;
int8_t fm2frq2_lfo2_vibrato;
};
};
int env_engine_on;
int env_engine_on;
emu8k_mem_internal_t addr, loop_start, loop_end;
emu8k_mem_internal_t addr, loop_start, loop_end;
int32_t initial_att;
int32_t initial_filter;
int32_t initial_att;
int32_t initial_filter;
emu8k_envelope_t vol_envelope;
emu8k_envelope_t mod_envelope;
emu8k_envelope_t vol_envelope;
emu8k_envelope_t mod_envelope;
int64_t lfo1_speed, lfo2_speed;
emu8k_mem_internal_t lfo1_count, lfo2_count;
int32_t lfo1_delay_samples, lfo2_delay_samples;
int vol_l, vol_r;
int64_t lfo1_speed, lfo2_speed;
emu8k_mem_internal_t lfo1_count, lfo2_count;
int32_t lfo1_delay_samples, lfo2_delay_samples;
int vol_l, vol_r;
int16_t fixed_modenv_filter_height;
int16_t fixed_modenv_pitch_height;
int16_t fixed_lfo1_filt_mod;
int16_t fixed_lfo1_vibrato;
int16_t fixed_lfo1_tremolo;
int16_t fixed_lfo2_vibrato;
int16_t fixed_modenv_filter_height;
int16_t fixed_modenv_pitch_height;
int16_t fixed_lfo1_filt_mod;
int16_t fixed_lfo1_vibrato;
int16_t fixed_lfo1_tremolo;
int16_t fixed_lfo2_vibrato;
/* filter internal data. */
int filterq_idx;
int32_t filt_att;
int64_t filt_buffer[5];
/* filter internal data. */
int filterq_idx;
int32_t filt_att;
int64_t filt_buffer[5];
} emu8k_voice_t;
typedef struct emu8k_t
{
emu8k_voice_t voice[32];
typedef struct emu8k_t {
emu8k_voice_t voice[32];
uint16_t hwcf1, hwcf2, hwcf3;
uint32_t hwcf4, hwcf5, hwcf6, hwcf7;
uint16_t hwcf1, hwcf2, hwcf3;
uint32_t hwcf4, hwcf5, hwcf6, hwcf7;
uint16_t init1[32], init2[32], init3[32], init4[32];
uint16_t init1[32], init2[32], init3[32], init4[32];
uint32_t smalr, smarr, smalw, smarw;
uint16_t smld_buffer, smrd_buffer;
uint32_t smalr, smarr, smalw, smarw;
uint16_t smld_buffer, smrd_buffer;
uint16_t wc;
uint16_t wc;
uint16_t id;
uint16_t id;
/* The empty block is used to act as an unallocated memory returning zero. */
int16_t *ram, *rom, *empty;
/* The empty block is used to act as an unallocated memory returning zero. */
int16_t *ram, *rom, *empty;
/* RAM pointers are a way to avoid checking ram boundaries on read */
int16_t *ram_pointers[0x100];
uint32_t ram_end_addr;
/* RAM pointers are a way to avoid checking ram boundaries on read */
int16_t *ram_pointers[0x100];
uint32_t ram_end_addr;
int cur_reg, cur_voice;
int cur_reg, cur_voice;
int16_t out_l, out_r;
int16_t out_l, out_r;
emu8k_chorus_eng_t chorus_engine;
int32_t chorus_in_buffer[SOUNDBUFLEN];
emu8k_reverb_eng_t reverb_engine;
int32_t reverb_in_buffer[SOUNDBUFLEN];
emu8k_chorus_eng_t chorus_engine;
int32_t chorus_in_buffer[SOUNDBUFLEN];
emu8k_reverb_eng_t reverb_engine;
int32_t reverb_in_buffer[SOUNDBUFLEN];
int pos;
int32_t buffer[SOUNDBUFLEN * 2];
int pos;
int32_t buffer[SOUNDBUFLEN * 2];
uint16_t addr;
uint16_t addr;
} emu8k_t;
void emu8k_change_addr(emu8k_t *emu8k, uint16_t emu_addr);
void emu8k_init(emu8k_t *emu8k, uint16_t emu_addr, int onboard_ram);
void emu8k_close(emu8k_t *emu8k);
void emu8k_update(emu8k_t *emu8k);
/*
Section E - Introduction to the EMU8000 Chip
@@ -656,12 +644,12 @@ Short Delay Short Delay + Feedback
// Chorus Params
typedef struct {
WORD FbkLevel; // Feedback Level (0xE600-0xE6FF)
WORD Delay; // Delay (0-0x0DA3) [1/44100 sec]
WORD LfoDepth; // LFO Depth (0xBC00-0xBCFF)
DWORD DelayR; // Right Delay (0-0xFFFFFFFF) [1/256/44100 sec]
DWORD LfoFreq; // LFO Frequency (0-0xFFFFFFFF)
} CHORUS_TYPE;
WORD FbkLevel; // Feedback Level (0xE600-0xE6FF)
WORD Delay; // Delay (0-0x0DA3) [1/44100 sec]
WORD LfoDepth; // LFO Depth (0xBC00-0xBCFF)
DWORD DelayR; // Right Delay (0-0xFFFFFFFF) [1/256/44100 sec]
DWORD LfoFreq; // LFO Frequency (0-0xFFFFFFFF)
} CHORUS_TYPE;
Registers to write the Reverb Parameters to (they are all 16-bit):

View File

@@ -21,30 +21,28 @@
*/
#ifndef SOUND_MPU401_H
# define SOUND_MPU401_H
#define SOUND_MPU401_H
#define MPU401_VERSION 0x15
#define MPU401_REVISION 0x01
#define MPU401_QUEUE 64
#define MPU401_INPUT_QUEUE 1024
#define MPU401_TIMECONSTANT (60000000/1000.0f)
#define MPU401_RESETBUSY 27.0f
#define MPU401_VERSION 0x15
#define MPU401_REVISION 0x01
#define MPU401_QUEUE 64
#define MPU401_INPUT_QUEUE 1024
#define MPU401_TIMECONSTANT (60000000 / 1000.0f)
#define MPU401_RESETBUSY 27.0f
/*helpers*/
#define M_GETKEY key[key/32]&(1<<(key%32))
#define M_SETKEY key[key/32]|=(1<<(key%32))
#define M_DELKEY key[key/32]&=~(1<<(key%32))
#define M_GETKEY key[key / 32] & (1 << (key % 32))
#define M_SETKEY key[key / 32] |= (1 << (key % 32))
#define M_DELKEY key[key / 32] &= ~(1 << (key % 32))
typedef enum MpuMode
{
typedef enum MpuMode {
M_UART,
M_INTELLIGENT
} MpuMode;
#define M_MCA 0x10
typedef enum MpuDataType
{
typedef enum MpuDataType {
T_OVERFLOW,
T_MARK,
T_MIDI_SYS,
@@ -52,118 +50,114 @@ typedef enum MpuDataType
T_COMMAND
} MpuDataType;
typedef enum RecState
{
M_RECOFF,
M_RECSTB,
M_RECON
typedef enum RecState {
M_RECOFF,
M_RECSTB,
M_RECON
} RecState;
/* Messages sent to MPU-401 from host */
#define MSG_EOX 0xf7
#define MSG_OVERFLOW 0xf8
#define MSG_MARK 0xfc
#define MSG_EOX 0xf7
#define MSG_OVERFLOW 0xf8
#define MSG_MARK 0xfc
/* Messages sent to host from MPU-401 */
#define MSG_MPU_OVERFLOW 0xf8
#define MSG_MPU_COMMAND_REQ 0xf9
#define MSG_MPU_END 0xfc
#define MSG_MPU_CLOCK 0xfd
#define MSG_MPU_ACK 0xfe
#define MSG_MPU_OVERFLOW 0xf8
#define MSG_MPU_COMMAND_REQ 0xf9
#define MSG_MPU_END 0xfc
#define MSG_MPU_CLOCK 0xfd
#define MSG_MPU_ACK 0xfe
typedef struct mpu_t
{
typedef struct mpu_t {
uint16_t addr;
int uart_mode, intelligent,
irq, midi_thru,
queue_pos, queue_used;
int uart_mode, intelligent,
irq, midi_thru,
queue_pos, queue_used;
uint8_t rx_data, is_mca,
status,
queue[MPU401_QUEUE], pos_regs[8];
MpuMode mode;
uint8_t rec_queue[MPU401_INPUT_QUEUE];
int rec_queue_pos, rec_queue_used;
uint32_t ch_toref[16];
struct track
{
int counter;
uint8_t value[3], sys_val,
vlength,length;
MpuDataType type;
status,
queue[MPU401_QUEUE], pos_regs[8];
MpuMode mode;
uint8_t rec_queue[MPU401_INPUT_QUEUE];
int rec_queue_pos, rec_queue_used;
uint32_t ch_toref[16];
struct track {
int counter;
uint8_t value[3], sys_val,
vlength, length;
MpuDataType type;
} playbuf[8], condbuf;
struct {
int conductor, cond_req,
cond_set, block_ack,
playing, reset,
wsd, wsm, wsd_start,
run_irq, irq_pending,
track_req,
send_now, eoi_scheduled,
data_onoff, clock_to_host,
sync_in, sysex_in_finished,
rec_copy;
RecState rec;
uint8_t tmask, cmask,
amask,
last_rtcmd;
uint16_t midi_mask, req_mask;
uint32_t command_byte, cmd_pending,
track, old_track;
int conductor, cond_req,
cond_set, block_ack,
playing, reset,
wsd, wsm, wsd_start,
run_irq, irq_pending,
track_req,
send_now, eoi_scheduled,
data_onoff, clock_to_host,
sync_in, sysex_in_finished,
rec_copy;
RecState rec;
uint8_t tmask, cmask,
amask,
last_rtcmd;
uint16_t midi_mask, req_mask;
uint32_t command_byte, cmd_pending,
track, old_track;
} state;
struct {
uint8_t timebase, old_timebase,
tempo, old_tempo,
tempo_rel, old_tempo_rel,
tempo_grad, cth_rate[4],
cth_mode, midimetro,
metromeas;
uint32_t cth_counter, cth_old,
rec_counter;
int32_t measure_counter, meas_old,
freq;
int ticks_in, active;
float freq_mod;
uint8_t timebase, old_timebase,
tempo, old_tempo,
tempo_rel, old_tempo_rel,
tempo_grad, cth_rate[4],
cth_mode, midimetro,
metromeas;
uint32_t cth_counter, cth_old,
rec_counter;
int32_t measure_counter, meas_old,
freq;
int ticks_in, active;
float freq_mod;
} clock;
struct {
int all_thru, midi_thru,
sysex_thru, commonmsgs_thru,
modemsgs_in, commonmsgs_in,
bender_in, sysex_in,
allnotesoff_out, rt_affection,
rt_out, rt_in,
timing_in_stop, data_in_stop,
rec_measure_end;
uint8_t prchg_buf[16];
uint16_t prchg_mask;
} filter;
struct {
int on;
uint8_t chan, trmask;
uint32_t key[4];
} chanref[5], inputref[16];
pc_timer_t mpu401_event_callback, mpu401_eoi_callback,
mpu401_reset_callback;
void (*ext_irq_update)(void *priv, int set);
int (*ext_irq_pending)(void *priv);
void *priv;
struct {
int all_thru, midi_thru,
sysex_thru, commonmsgs_thru,
modemsgs_in, commonmsgs_in,
bender_in, sysex_in,
allnotesoff_out, rt_affection,
rt_out, rt_in,
timing_in_stop, data_in_stop,
rec_measure_end;
uint8_t prchg_buf[16];
uint16_t prchg_mask;
} filter;
struct {
int on;
uint8_t chan, trmask;
uint32_t key[4];
} chanref[5], inputref[16];
pc_timer_t mpu401_event_callback, mpu401_eoi_callback,
mpu401_reset_callback;
void (*ext_irq_update)(void *priv, int set);
int (*ext_irq_pending)(void *priv);
void *priv;
} mpu_t;
extern int mpu401_standalone_enable, mpu401_already_loaded;
extern int mpu401_standalone_enable, mpu401_already_loaded;
extern const device_t mpu401_device;
extern const device_t mpu401_mca_device;
extern const device_t mpu401_device;
extern const device_t mpu401_mca_device;
extern uint8_t MPU401_ReadData(mpu_t *mpu);
extern void mpu401_write(uint16_t addr, uint8_t val, void *priv);
extern uint8_t mpu401_read(uint16_t addr, void *priv);
extern void mpu401_setirq(mpu_t *mpu, int irq);
extern void mpu401_change_addr(mpu_t *mpu, uint16_t addr);
extern void mpu401_init(mpu_t *mpu, uint16_t addr, int irq, int mode, int receive_input);
extern void mpu401_device_add(void);
extern void mpu401_irq_attach(mpu_t *mpu, void (*ext_irq_update)(void *priv, int set), int (*ext_irq_pending)(void *priv), void *priv);
extern uint8_t MPU401_ReadData(mpu_t *mpu);
extern void mpu401_write(uint16_t addr, uint8_t val, void *priv);
extern uint8_t mpu401_read(uint16_t addr, void *priv);
extern void mpu401_setirq(mpu_t *mpu, int irq);
extern void mpu401_change_addr(mpu_t *mpu, uint16_t addr);
extern void mpu401_init(mpu_t *mpu, uint16_t addr, int irq, int mode, int receive_input);
extern void mpu401_device_add(void);
extern void mpu401_irq_attach(mpu_t *mpu, void (*ext_irq_update)(void *priv, int set), int (*ext_irq_pending)(void *priv), void *priv);
extern int MPU401_InputSysex(void *p, uint8_t *buffer, uint32_t len, int abort);
extern void MPU401_InputMsg(void *p, uint8_t *msg, uint32_t len);
extern int MPU401_InputSysex(void *p, uint8_t *buffer, uint32_t len, int abort);
extern void MPU401_InputMsg(void *p, uint8_t *msg, uint32_t len);
#endif /*SOUND_MPU401_H*/
#endif /*SOUND_MPU401_H*/

View File

@@ -15,41 +15,40 @@
* Copyright 2016-2020 Miran Grca.
*/
#ifndef SOUND_OPL_H
# define SOUND_OPL_H
#define SOUND_OPL_H
typedef void (*tmrfunc)(void *priv, int timer, uint64_t period);
typedef void (*tmrfunc)(void *priv, int timer, uint64_t period);
/* Define an OPLx chip. */
typedef struct {
#ifdef SOUND_OPL_NUKED_H
nuked_t *opl;
nuked_t *opl;
#else
void *opl;
void *opl;
#endif
int8_t flags, pad;
int8_t flags, pad;
uint16_t port;
uint8_t status, timer_ctrl;
uint16_t timer_count[2],
timer_cur_count[2];
uint16_t port;
uint8_t status, timer_ctrl;
uint16_t timer_count[2],
timer_cur_count[2];
pc_timer_t timers[2];
pc_timer_t timers[2];
int pos;
int32_t buffer[SOUNDBUFLEN * 2];
int pos;
int32_t buffer[SOUNDBUFLEN * 2];
} opl_t;
extern void opl_set_do_cycles(opl_t *dev, int8_t do_cycles);
extern void opl_set_do_cycles(opl_t *dev, int8_t do_cycles);
extern uint8_t opl2_read(uint16_t port, void *);
extern void opl2_write(uint16_t port, uint8_t val, void *);
extern void opl2_init(opl_t *);
extern void opl2_update(opl_t *);
extern uint8_t opl2_read(uint16_t port, void *);
extern void opl2_write(uint16_t port, uint8_t val, void *);
extern void opl2_init(opl_t *);
extern void opl2_update(opl_t *);
extern uint8_t opl3_read(uint16_t port, void *);
extern void opl3_write(uint16_t port, uint8_t val, void *);
extern void opl3_init(opl_t *);
extern void opl3_update(opl_t *);
extern uint8_t opl3_read(uint16_t port, void *);
extern void opl3_write(uint16_t port, uint8_t val, void *);
extern void opl3_init(opl_t *);
extern void opl3_update(opl_t *);
#endif /*SOUND_OPL_H*/
#endif /*SOUND_OPL_H*/

View File

@@ -18,18 +18,17 @@
*/
#ifndef SOUND_OPL_NUKED_H
# define SOUND_OPL_NUKED_H
#define SOUND_OPL_NUKED_H
extern void *nuked_init(uint32_t sample_rate);
extern void nuked_close(void *);
extern void * nuked_init(uint32_t sample_rate);
extern void nuked_close(void *);
extern uint16_t nuked_write_addr(void *, uint16_t port, uint8_t val);
extern void nuked_write_reg(void *, uint16_t reg, uint8_t v);
extern void nuked_write_reg_buffered(void *, uint16_t reg, uint8_t v);
extern uint16_t nuked_write_addr(void *, uint16_t port, uint8_t val);
extern void nuked_write_reg(void *, uint16_t reg, uint8_t v);
extern void nuked_write_reg_buffered(void *, uint16_t reg, uint8_t v);
extern void nuked_generate(void *, int32_t *buf);
extern void nuked_generate_resampled(void *, int32_t *buf);
extern void nuked_generate_stream(void *, int32_t *sndptr, uint32_t num);
extern void nuked_generate(void *, int32_t *buf);
extern void nuked_generate_resampled(void *, int32_t *buf);
extern void nuked_generate_stream(void *, int32_t *sndptr, uint32_t num);
#endif /*SOUND_OPL_NUKED_H*/
#endif /*SOUND_OPL_NUKED_H*/

View File

@@ -1,15 +1,15 @@
#ifndef SOUND_RESID_H
# define SOUND_RESID_H
#define SOUND_RESID_H
#ifdef __cplusplus
extern "C" {
#endif
void *sid_init();
void sid_close(void *p);
void sid_reset(void *p);
uint8_t sid_read(uint16_t addr, void *p);
void sid_write(uint16_t addr, uint8_t val, void *p);
void sid_fillbuf(int16_t *buf, int len, void *p);
void *sid_init();
void sid_close(void *p);
void sid_reset(void *p);
uint8_t sid_read(uint16_t addr, void *p);
void sid_write(uint16_t addr, uint8_t val, void *p);
void sid_fillbuf(int16_t *buf, int len, void *p);
#ifdef __cplusplus
}
#endif

View File

@@ -1,143 +1,157 @@
/*
* 86Box A hypervisor and IBM PC system emulator that specializes in
* running old operating systems and software designed for IBM
* PC systems and compatibles from 1981 through fairly recent
* system designs based on the PCI bus.
* 86Box A hypervisor and IBM PC system emulator that specializes in
* running old operating systems and software designed for IBM
* PC systems and compatibles from 1981 through fairly recent
* system designs based on the PCI bus.
*
* This file is part of the 86Box distribution.
* This file is part of the 86Box distribution.
*
* Sound Blaster emulation.
* Sound Blaster emulation.
*
* Authors: Sarah Walker, <http://pcem-emulator.co.uk/>
* Miran Grca, <mgrca8@gmail.com>
* TheCollector1995, <mariogplayer@gmail.com>
* Authors: Sarah Walker, <http://pcem-emulator.co.uk/>
* Miran Grca, <mgrca8@gmail.com>
* TheCollector1995, <mariogplayer@gmail.com>
*
* Copyright 2008-2018 Sarah Walker.
* Copyright 2016-2018 Miran Grca.
* Copyright 2008-2018 Sarah Walker.
* Copyright 2016-2018 Miran Grca.
*/
#ifndef SOUND_SND_SB_H
# define SOUND_SND_SB_H
#define SOUND_SND_SB_H
#include <86box/snd_cms.h>
#include <86box/snd_emu8k.h>
#include <86box/snd_mpu401.h>
#include <86box/snd_opl.h>
#include <86box/snd_sb_dsp.h>
#include <86box/snd_cms.h>
#define SADLIB 1 /* No DSP */
#define SB1 2 /* DSP v1.05 */
#define SB15 3 /* DSP v2.00 */
#define SB2 4 /* DSP v2.01 - needed for high-speed DMA */
#define SBPRO 5 /* DSP v3.00 */
#define SBPRO2 6 /* DSP v3.02 + OPL3 */
#define SB16 7 /* DSP v4.05 + OPL3 */
#define SBAWE32 8 /* DSP v4.13 + OPL3 */
#define SBAWE64 9 /* DSP v4.16 + OPL3 */
#define SADLIB 1 /* No DSP */
#define SB1 2 /* DSP v1.05 */
#define SB15 3 /* DSP v2.00 */
#define SB2 4 /* DSP v2.01 - needed for high-speed DMA */
#define SBPRO 5 /* DSP v3.00 */
#define SBPRO2 6 /* DSP v3.02 + OPL3 */
#define SB16 7 /* DSP v4.05 + OPL3 */
#define SBAWE32 8 /* DSP v4.13 + OPL3 */
#define SBAWE64 9 /* DSP v4.16 + OPL3 */
/* SB 2.0 CD version */
typedef struct sb_ct1335_mixer_t
{
double master;
double voice;
double fm;
double cd;
typedef struct sb_ct1335_mixer_t {
double master;
double voice;
double fm;
double cd;
uint8_t index;
uint8_t regs[256];
uint8_t index;
uint8_t regs[256];
} sb_ct1335_mixer_t;
/* SB PRO */
typedef struct sb_ct1345_mixer_t
{
double master_l, master_r;
double voice_l, voice_r;
double fm_l, fm_r;
double cd_l, cd_r;
double line_l, line_r;
double mic;
/*see sb_ct1745_mixer for values for input selector*/
int32_t input_selector;
typedef struct sb_ct1345_mixer_t {
double master_l,
master_r;
double voice_l,
voice_r;
double fm_l,
fm_r;
double cd_l,
cd_r;
double line_l,
line_r;
double mic;
/*see sb_ct1745_mixer for values for input selector*/
int32_t input_selector;
int input_filter;
int in_filter_freq;
int output_filter;
int input_filter;
int in_filter_freq;
int output_filter;
int stereo;
int stereo_isleft;
int stereo;
int stereo_isleft;
uint8_t index;
uint8_t regs[256];
uint8_t index;
uint8_t regs[256];
} sb_ct1345_mixer_t;
/* SB16 and AWE32 */
typedef struct sb_ct1745_mixer_t
{
double master_l, master_r;
double voice_l, voice_r;
double fm_l, fm_r;
double cd_l, cd_r;
double line_l, line_r;
double mic;
double speaker;
typedef struct sb_ct1745_mixer_t {
double master_l,
master_r;
double voice_l,
voice_r;
double fm_l,
fm_r;
double cd_l,
cd_r;
double line_l,
line_r;
double mic;
double speaker;
int bass_l, bass_r;
int treble_l, treble_r;
int bass_l,
bass_r;
int treble_l,
treble_r;
int output_selector;
#define OUTPUT_MIC 1
#define OUTPUT_CD_R 2
#define OUTPUT_CD_L 4
#define OUTPUT_LINE_R 8
#define OUTPUT_LINE_L 16
int output_selector;
#define OUTPUT_MIC 1
#define OUTPUT_CD_R 2
#define OUTPUT_CD_L 4
#define OUTPUT_LINE_R 8
#define OUTPUT_LINE_L 16
int input_selector_left;
int input_selector_right;
#define INPUT_MIC 1
#define INPUT_CD_R 2
#define INPUT_CD_L 4
#define INPUT_LINE_R 8
#define INPUT_LINE_L 16
#define INPUT_MIDI_R 32
#define INPUT_MIDI_L 64
int input_selector_left;
int input_selector_right;
#define INPUT_MIC 1
#define INPUT_CD_R 2
#define INPUT_CD_L 4
#define INPUT_LINE_R 8
#define INPUT_LINE_L 16
#define INPUT_MIDI_R 32
#define INPUT_MIDI_L 64
int mic_agc;
int mic_agc;
int32_t input_gain_L;
int32_t input_gain_R;
double output_gain_L;
double output_gain_R;
int32_t input_gain_L;
int32_t input_gain_R;
double output_gain_L;
double output_gain_R;
uint8_t index;
uint8_t regs[256];
uint8_t index;
uint8_t regs[256];
int output_filter; /* for clones */
} sb_ct1745_mixer_t;
typedef struct sb_t
{
uint8_t cms_enabled, opl_enabled, mixer_enabled;
cms_t cms;
opl_t opl, opl2;
sb_dsp_t dsp;
union {
sb_ct1335_mixer_t mixer_sb2;
sb_ct1345_mixer_t mixer_sbpro;
sb_ct1745_mixer_t mixer_sb16;
};
mpu_t *mpu;
emu8k_t emu8k;
void *gameport;
typedef struct sb_t {
uint8_t cms_enabled,
opl_enabled,
mixer_enabled;
cms_t cms;
opl_t opl,
opl2;
sb_dsp_t dsp;
union {
sb_ct1335_mixer_t mixer_sb2;
sb_ct1345_mixer_t mixer_sbpro;
sb_ct1745_mixer_t mixer_sb16;
};
mpu_t *mpu;
emu8k_t emu8k;
void *gameport;
int pos;
int pos;
uint8_t pos_regs[8], pnp_rom[512];
uint8_t pos_regs[8],
pnp_rom[512];
uint16_t opl_pnp_addr;
uint16_t opl_pnp_addr;
} sb_t;
extern void sb_ct1345_mixer_write(uint16_t addr, uint8_t val, void *p);
extern void sb_ct1345_mixer_write(uint16_t addr, uint8_t val, void *p);
extern uint8_t sb_ct1345_mixer_read(uint16_t addr, void *p);
extern void sb_ct1345_mixer_reset(sb_t* sb);
extern void sb_ct1345_mixer_reset(sb_t *sb);
extern void sb_ct1745_mixer_write(uint16_t addr, uint8_t val, void *p);
extern uint8_t sb_ct1745_mixer_read(uint16_t addr, void *p);
@@ -149,4 +163,4 @@ extern void sb16_awe32_filter_cd_audio(int channel, double *buffer, void *p);
extern void sb_close(void *p);
extern void sb_speed_changed(void *p);
#endif /*SOUND_SND_SB_H*/
#endif /*SOUND_SND_SB_H*/

View File

@@ -1,5 +1,5 @@
#ifndef SOUND_SND_SB_DSP_H
# define SOUND_SND_SB_DSP_H
#define SOUND_SND_SB_DSP_H
/*Sound Blaster Clones, for quirks*/
#define SB_SUBTYPE_DEFAULT 0 /*Handle as a Creative card*/
@@ -7,101 +7,99 @@
#define SB_SUBTYPE_CLONE_AZT1605_0X0C 2 /*Aztech Sound Galaxy Nova 16 Extra / Packard Bell Forte 16, DSP 2.1 - SBPRO2 clone*/
/* aztech-related */
#define IS_AZTECH(dsp) ((dsp)->sb_subtype == SB_SUBTYPE_CLONE_AZT2316A_0X11 || (dsp)->sb_subtype == SB_SUBTYPE_CLONE_AZT1605_0X0C) /* check for future AZT cards here */
#define AZTECH_EEPROM_SIZE 16
#define IS_AZTECH(dsp) ((dsp)->sb_subtype == SB_SUBTYPE_CLONE_AZT2316A_0X11 || (dsp)->sb_subtype == SB_SUBTYPE_CLONE_AZT1605_0X0C) /* check for future AZT cards here */
#define AZTECH_EEPROM_SIZE 16
typedef struct sb_dsp_t
{
int sb_type;
int sb_subtype; /* which clone */
void *parent; /* "sb_t *" if default subtype, "azt2316a_t *" if aztech. */
typedef struct sb_dsp_t {
int sb_type;
int sb_subtype; /* which clone */
void *parent; /* "sb_t *" if default subtype, "azt2316a_t *" if aztech. */
int sb_8_length, sb_8_format, sb_8_autoinit, sb_8_pause, sb_8_enable, sb_8_autolen, sb_8_output;
int sb_8_dmanum;
int sb_16_length, sb_16_format, sb_16_autoinit, sb_16_pause, sb_16_enable, sb_16_autolen, sb_16_output;
int sb_16_dmanum;
int sb_pausetime;
int sb_8_length, sb_8_format, sb_8_autoinit, sb_8_pause, sb_8_enable, sb_8_autolen, sb_8_output;
int sb_8_dmanum;
int sb_16_length, sb_16_format, sb_16_autoinit, sb_16_pause, sb_16_enable, sb_16_autolen, sb_16_output;
int sb_16_dmanum;
int sb_pausetime;
uint8_t sb_read_data[256];
int sb_read_wp, sb_read_rp;
int sb_speaker;
int muted;
uint8_t sb_read_data[256];
int sb_read_wp, sb_read_rp;
int sb_speaker;
int muted;
int sb_data_stat;
int sb_data_stat;
int midi_in_sysex;
int midi_in_poll;
int uart_midi;
int uart_irq;
int onebyte_midi;
int midi_in_timestamp;
int midi_in_sysex;
int midi_in_poll;
int uart_midi;
int uart_irq;
int onebyte_midi;
int midi_in_timestamp;
int sb_irqnum;
int sb_irqnum;
uint8_t sbe2;
int sbe2count;
uint8_t sbe2;
int sbe2count;
uint8_t sb_data[8];
uint8_t sb_data[8];
int sb_freq;
int sb_freq;
int16_t sbdat;
int sbdat2;
int16_t sbdatl, sbdatr;
int16_t sbdat;
int sbdat2;
int16_t sbdatl, sbdatr;
uint8_t sbref;
int8_t sbstep;
uint8_t sbref;
int8_t sbstep;
int sbdacpos;
int sbdacpos;
int sbleftright;
int sbleftright;
int sbreset;
uint8_t sbreaddat;
uint8_t sb_command;
uint8_t sb_test;
int sb_timei, sb_timeo;
int sbreset;
uint8_t sbreaddat;
uint8_t sb_command;
uint8_t sb_test;
int sb_timei, sb_timeo;
int sb_irq8, sb_irq16, sb_irq401;
int sb_irqm8, sb_irqm16, sb_irqm401;
int sb_irq8, sb_irq16, sb_irq401;
int sb_irqm8, sb_irqm16, sb_irqm401;
uint8_t sb_asp_regs[256];
uint8_t sb_asp_mode;
uint8_t sb_asp_regs[256];
uint8_t sb_asp_mode;
uint8_t sb_asp_ram[2048];
int sb_asp_ram_index;
uint8_t sb_asp_ram[2048];
int sb_asp_ram_index;
uint8_t sb_8051_ram[256];
uint8_t sb_8051_ram[256];
int sbenable, sb_enable_i;
int sbenable, sb_enable_i;
pc_timer_t output_timer, input_timer;
pc_timer_t output_timer, input_timer;
uint64_t sblatcho, sblatchi;
uint64_t sblatcho, sblatchi;
uint16_t sb_addr;
uint16_t sb_addr;
int stereo;
int stereo;
int asp_data_len;
int asp_data_len;
pc_timer_t wb_timer;
int wb_full;
pc_timer_t wb_timer;
int wb_full;
int busy_count;
int busy_count;
int record_pos_read;
int record_pos_write;
int16_t record_buffer[0xFFFF];
int16_t buffer[SOUNDBUFLEN * 2];
int pos;
int record_pos_read;
int record_pos_write;
int16_t record_buffer[0xFFFF];
int16_t buffer[SOUNDBUFLEN * 2];
int pos;
uint8_t azt_eeprom[AZTECH_EEPROM_SIZE]; /* the eeprom in the Aztech cards is attached to the DSP */
uint8_t azt_eeprom[AZTECH_EEPROM_SIZE]; /* the eeprom in the Aztech cards is attached to the DSP */
mpu_t *mpu;
mpu_t *mpu;
} sb_dsp_t;
void sb_dsp_input_msg(void *p, uint8_t *msg, uint32_t len);
int sb_dsp_input_sysex(void *p, uint8_t *buffer, uint32_t len, int abort);

View File

@@ -1,11 +1,10 @@
#ifndef SOUND_SN76489_H
# define SOUND_SN76489_H
#define SOUND_SN76489_H
enum
{
SN76496,
NCR8496,
PSSJ
enum {
SN76496,
NCR8496,
PSSJ
};
extern const device_t sn76489_device;
@@ -13,23 +12,22 @@ extern const device_t ncr8496_device;
extern int sn76489_mute;
typedef struct sn76489_t
{
int stat[4];
int latch[4], count[4];
int freqlo[4], freqhi[4];
int vol[4];
uint32_t shift;
uint8_t noise;
int lasttone;
uint8_t firstdat;
int type;
int extra_divide;
typedef struct sn76489_t {
int stat[4];
int latch[4], count[4];
int freqlo[4], freqhi[4];
int vol[4];
uint32_t shift;
uint8_t noise;
int lasttone;
uint8_t firstdat;
int type;
int extra_divide;
int16_t buffer[SOUNDBUFLEN];
int pos;
int16_t buffer[SOUNDBUFLEN];
int pos;
double psgconst;
double psgconst;
} sn76489_t;
void sn76489_init(sn76489_t *sn76489, uint16_t base, uint16_t size, int type, int freq);

View File

@@ -18,17 +18,16 @@
*/
#ifndef SOUND_SPEAKER_H
# define SOUND_SPEAKER_H
#define SOUND_SPEAKER_H
extern int speaker_mute;
extern int speaker_mute;
extern int speaker_gated;
extern int speaker_enable, was_speaker_enable;
extern int speaker_gated;
extern int speaker_enable, was_speaker_enable;
extern void speaker_init();
extern void speaker_init();
extern void speaker_set_count(uint8_t new_m, int new_count);
extern void speaker_update(void);
extern void speaker_set_count(uint8_t new_m, int new_count);
extern void speaker_update(void);
#endif /*SOUND_SPEAKER_H*/

View File

@@ -1,26 +1,25 @@
#ifndef SOUND_YM7128_H
# define SOUND_YM7128_H
#define SOUND_YM7128_H
typedef struct ym7128_t
{
int a0, sci;
uint8_t dat;
typedef struct ym7128_t {
int a0, sci;
uint8_t dat;
int reg_sel;
uint8_t regs[32];
int reg_sel;
uint8_t regs[32];
int gl[8], gr[8];
int vm, vc, vl, vr;
int c0, c1;
int t[9];
int gl[8], gr[8];
int vm, vc, vl, vr;
int c0, c1;
int t[9];
int16_t filter_dat;
int16_t prev_l, prev_r;
int16_t filter_dat;
int16_t prev_l, prev_r;
int16_t delay_buffer[2400];
int delay_pos;
int16_t delay_buffer[2400];
int delay_pos;
int16_t last_samp;
int16_t last_samp;
} ym7128_t;
void ym7128_init(ym7128_t *ym7128);

View File

@@ -1,78 +1,76 @@
/*
* 86Box A hypervisor and IBM PC system emulator that specializes in
* running old operating systems and software designed for IBM
* PC systems and compatibles from 1981 through fairly recent
* system designs based on the PCI bus.
* 86Box A hypervisor and IBM PC system emulator that specializes in
* running old operating systems and software designed for IBM
* PC systems and compatibles from 1981 through fairly recent
* system designs based on the PCI bus.
*
* This file is part of the 86Box distribution.
* This file is part of the 86Box distribution.
*
* Sound emulation core.
* Sound emulation core.
*
*
*
* Authors: Sarah Walker, <http://pcem-emulator.co.uk/>
* Miran Grca, <mgrca8@gmail.com>
* Authors: Sarah Walker, <http://pcem-emulator.co.uk/>
* Miran Grca, <mgrca8@gmail.com>
*
* Copyright 2008-2018 Sarah Walker.
* Copyright 2016-2018 Miran Grca.
* Copyright 2008-2018 Sarah Walker.
* Copyright 2016-2018 Miran Grca.
*/
#ifndef EMU_SOUND_H
# define EMU_SOUND_H
#define EMU_SOUND_H
extern int sound_gain;
#define SOUNDBUFLEN (48000/50)
#define CD_FREQ 44100
#define CD_BUFLEN (CD_FREQ / 10)
#define SOUNDBUFLEN (48000 / 50)
#define CD_FREQ 44100
#define CD_BUFLEN (CD_FREQ / 10)
enum {
SOUND_NONE = 0,
SOUND_INTERNAL
};
extern int ppispeakon;
extern int gated,
speakval,
speakon;
extern int ppispeakon;
extern int gated,
speakval,
speakon;
extern int sound_pos_global;
extern int sound_card_current;
extern int sound_pos_global;
extern int sound_card_current;
extern void sound_add_handler(void (*get_buffer)(int32_t *buffer,
int len, void *p),
void *p);
extern void sound_set_cd_audio_filter(void (*filter)(int channel,
double *buffer, void *p),
void *p);
extern void sound_add_handler(void (*get_buffer)(int32_t *buffer, \
int len, void *p), void *p);
extern void sound_set_cd_audio_filter(void (*filter)(int channel, \
double *buffer, void *p), void *p);
extern int sound_card_available(int card);
extern int sound_card_available(int card);
#ifdef EMU_DEVICE_H
extern const device_t *sound_card_getdevice(int card);
extern const device_t *sound_card_getdevice(int card);
#endif
extern int sound_card_has_config(int card);
extern char *sound_card_get_internal_name(int card);
extern int sound_card_get_from_internal_name(char *s);
extern void sound_card_init(void);
extern void sound_set_cd_volume(unsigned int vol_l, unsigned int vol_r);
extern int sound_card_has_config(int card);
extern char *sound_card_get_internal_name(int card);
extern int sound_card_get_from_internal_name(char *s);
extern void sound_card_init(void);
extern void sound_set_cd_volume(unsigned int vol_l, unsigned int vol_r);
extern void sound_speed_changed(void);
extern void sound_speed_changed(void);
extern void sound_init(void);
extern void sound_reset(void);
extern void sound_init(void);
extern void sound_reset(void);
extern void sound_card_reset(void);
extern void sound_card_reset(void);
extern void sound_cd_thread_end(void);
extern void sound_cd_thread_reset(void);
extern void closeal(void);
extern void inital(void);
extern void givealbuffer(void *buf);
extern void givealbuffer_cd(void *buf);
extern void sound_cd_thread_end(void);
extern void sound_cd_thread_reset(void);
extern void closeal(void);
extern void inital(void);
extern void givealbuffer(void *buf);
extern void givealbuffer_cd(void *buf);
#ifdef EMU_DEVICE_H
/* AdLib and AdLib Gold */
@@ -94,20 +92,20 @@ extern const device_t cms_device;
/* Gravis UltraSound and UltraSound Max */
extern const device_t gus_device;
#if defined(DEV_BRANCH) && defined(USE_PAS16)
# if defined(DEV_BRANCH) && defined(USE_PAS16)
/* Pro Audio Spectrum 16 */
extern const device_t pas16_device;
#endif
# endif
/* IBM PS/1 Audio Card */
extern const device_t ps1snd_device;
/* Tandy PSSJ */
extern const device_t pssj_device;
#if defined(DEV_BRANCH) && defined(USE_TANDY_ISA)
# if defined(DEV_BRANCH) && defined(USE_TANDY_ISA)
extern const device_t pssj_isa_device;
extern const device_t tndy_device;
#endif
# endif
/* Creative Labs Sound Blaster */
extern const device_t sb_1_device;
@@ -121,6 +119,7 @@ extern const device_t sb_pro_compat_device;
extern const device_t sb_16_device;
extern const device_t sb_16_pnp_device;
extern const device_t sb_16_compat_device;
extern const device_t sb_16_compat_nompu_device;
extern const device_t sb_32_pnp_device;
extern const device_t sb_awe32_device;
extern const device_t sb_awe32_pnp_device;
@@ -149,4 +148,4 @@ extern const device_t cmi8738_device;
extern const device_t cmi8738_onboard_device;
#endif
#endif /*EMU_SOUND_H*/
#endif /*EMU_SOUND_H*/

View File

@@ -158,7 +158,8 @@ typedef struct svga_t
/*Force CRTC to dword mode, regardless of CR14/CR17. Required for S3 enhanced mode*/
int force_dword_mode;
int force_byte_mode;
int force_old_addr;
int remap_required;
uint32_t (*remap_func)(struct svga_t *svga, uint32_t in_addr);

View File

@@ -104,7 +104,7 @@ void svga_recalc_remap_func(svga_t *svga)
{
int func_nr;
if (svga->fb_only || svga->force_byte_mode)
if (svga->fb_only)
func_nr = 0;
else {
if (svga->force_dword_mode)

View File

@@ -21,19 +21,20 @@ static const struct {
const char *internal_name;
const lpt_device_t *device;
} lpt_devices[] = {
{"none", NULL},
{"dss", &dss_device},
{"lpt_dac", &lpt_dac_device},
{"lpt_dac_stereo", &lpt_dac_stereo_device},
{"text_prt", &lpt_prt_text_device},
{"dot_matrix", &lpt_prt_escp_device},
{"postscript", &lpt_prt_ps_device},
{"plip", &lpt_plip_device},
{"dongle_savquest", &lpt_hasp_savquest_device},
{"", NULL}
// clang-format off
{"none", NULL },
{"dss", &dss_device },
{"lpt_dac", &lpt_dac_device },
{"lpt_dac_stereo", &lpt_dac_stereo_device },
{"text_prt", &lpt_prt_text_device },
{"dot_matrix", &lpt_prt_escp_device },
{"postscript", &lpt_prt_ps_device },
{"plip", &lpt_plip_device },
{"dongle_savquest", &lpt_hasp_savquest_device },
{"", NULL }
// clang-format on
};
char *
lpt_device_get_name(int id)
{

View File

@@ -437,6 +437,13 @@ machine_at_cuv4xls_init(const machine_t *model)
}
const device_t *
at_cuv4xls_get_device(void)
{
return &cmi8738_onboard_device;
}
int
machine_at_6via90ap_init(const machine_t *model)
{

View File

@@ -913,7 +913,7 @@ const machine_t machines[] = {
{ "[VIA Apollo Pro 133A] Acorp 6VIA90AP", "6via90ap", MACHINE_TYPE_SOCKET370, CPU_PKG_SOCKET370, 0, 66666667, 150000000, 1300, 3500, MACHINE_MULTIPLIER_FIXED, MACHINE_AGP | MACHINE_BUS_PS2 | MACHINE_BUS_AC97 | MACHINE_IDE_DUAL | MACHINE_SOUND | MACHINE_GAMEPORT, 16384,3145728, 8192, 255, machine_at_6via90ap_init, NULL },
/* Has the VIA VT82C686B southbridge with on-chip KBC identical to the VIA
VT82C42N. */
{ "[VIA Apollo Pro 133A] ASUS CUV4X-LS", "cuv4xls", MACHINE_TYPE_SOCKET370, CPU_PKG_SOCKET370, 0, 66666667, 150000000, 1300, 3500, 1.5, 8.0, (MACHINE_AGP & ~MACHINE_AT) | MACHINE_BUS_PS2 | MACHINE_BUS_AC97 | MACHINE_IDE_DUAL | MACHINE_SOUND, 16384,4194304, 8192, 255, machine_at_cuv4xls_init, NULL },
{ "[VIA Apollo Pro 133A] ASUS CUV4X-LS", "cuv4xls", MACHINE_TYPE_SOCKET370, CPU_PKG_SOCKET370, 0, 66666667, 150000000, 1300, 3500, 1.5, 8.0, (MACHINE_AGP & ~MACHINE_AT) | MACHINE_BUS_PS2 | MACHINE_BUS_AC97 | MACHINE_IDE_DUAL | MACHINE_SOUND, 16384,4194304, 8192, 255, machine_at_cuv4xls_init, at_cuv4xls_get_device },
/* Has a Winbond W83977EF Super I/O chip with on-chip KBC with AMIKey-2 KBC
firmware. */
{ "[VIA Apollo Pro 133A] BCM GT694VA", "gt694va", MACHINE_TYPE_SOCKET370, CPU_PKG_SOCKET370, 0, 66666667, 133333333, 1300, 3500, 1.5, 8.0, MACHINE_AGP | MACHINE_BUS_PS2 | MACHINE_IDE_DUAL | MACHINE_SOUND, 16384,3145728, 8192, 255, machine_at_gt694va_init, at_gt694va_get_device },

View File

@@ -636,111 +636,61 @@ threec503_nic_close(void *priv)
}
static const device_config_t threec503_config[] =
{
static const device_config_t threec503_config[] = {
// clang-format off
{
"base", "Address", CONFIG_HEX16, "", 0x300, "", { 0 },
{
{
"0x250", 0x250
},
{
"0x280", 0x280
},
{
"0x2a0", 0x2a0
},
{
"0x2e0", 0x2e0
},
{
"0x300", 0x300
},
{
"0x310", 0x310
},
{
"0x330", 0x330
},
{
"0x350", 0x350
},
{
"", 0
}
},
"base", "Address", CONFIG_HEX16, "", 0x300, "", { 0 },
{
{ "0x250", 0x250 },
{ "0x280", 0x280 },
{ "0x2a0", 0x2a0 },
{ "0x2e0", 0x2e0 },
{ "0x300", 0x300 },
{ "0x310", 0x310 },
{ "0x330", 0x330 },
{ "0x350", 0x350 },
{ "", 0 }
},
},
{
"irq", "IRQ", CONFIG_SELECTION, "", 3, "", { 0 },
{
{
"IRQ 2", 2
},
{
"IRQ 3", 3
},
{
"IRQ 4", 4
},
{
"IRQ 5", 5
},
{
"", 0
}
},
"irq", "IRQ", CONFIG_SELECTION, "", 3, "", { 0 },
{
{ "IRQ 2", 2 },
{ "IRQ 3", 3 },
{ "IRQ 4", 4 },
{ "IRQ 5", 5 },
{ "", 0 }
},
},
{
"dma", "DMA", CONFIG_SELECTION, "", 3, "", { 0 },
{
{
"DMA 1", 1
},
{
"DMA 2", 2
},
{
"DMA 3", 3
},
{
"", 0
}
},
"dma", "DMA", CONFIG_SELECTION, "", 3, "", { 0 },
{
{ "DMA 1", 1 },
{ "DMA 2", 2 },
{ "DMA 3", 3 },
{ "", 0 }
},
},
{
"mac", "MAC Address", CONFIG_MAC, "", -1, "", { 0 },
{
{
"", 0
}
},
"mac", "MAC Address", CONFIG_MAC, "", -1, "", { 0 },
{
{ "", 0 }
},
},
{
"bios_addr", "BIOS address", CONFIG_HEX20, "", 0xCC000, "", { 0 },
{
{
"DC00", 0xDC000
},
{
"D800", 0xD8000
},
{
"C800", 0xC8000
},
{
"CC00", 0xCC000
},
{
"", 0
}
},
"bios_addr", "BIOS address", CONFIG_HEX20, "", 0xCC000, "", { 0 },
{
{ "DC00", 0xDC000 },
{ "D800", 0xD8000 },
{ "C800", 0xC8000 },
{ "CC00", 0xCC000 },
{ "", 0 }
},
},
{
"", "", -1
}
{ "", "", -1 }
// clang-format off
};
const device_t threec503_device = {
"3Com EtherLink II",
"3c503",

View File

@@ -1111,11 +1111,10 @@ dp8390_close(void *priv)
}
const device_t dp8390_device =
{
"DP8390 Network Interface Controller",
"dp8390",
0, 0,
dp8390_init, dp8390_close,
NULL, { NULL }, NULL, NULL
const device_t dp8390_device = {
"DP8390 Network Interface Controller",
"dp8390",
0, 0,
dp8390_init, dp8390_close,
NULL, { NULL }, NULL, NULL
};

View File

@@ -1139,185 +1139,91 @@ nic_close(void *priv)
free(dev);
}
static const device_config_t ne1000_config[] =
{
{
"base", "Address", CONFIG_HEX16, "", 0x300, "", { 0 },
{
{
"0x280", 0x280
},
{
"0x300", 0x300
},
{
"0x320", 0x320
},
{
"0x340", 0x340
},
{
"0x360", 0x360
},
{
"0x380", 0x380
},
{
""
}
},
},
{
"irq", "IRQ", CONFIG_SELECTION, "", 3, "", { 0 },
{
{
"IRQ 2", 2
},
{
"IRQ 3", 3
},
{
"IRQ 5", 5
},
{
"IRQ 7", 7
},
{
"IRQ 10", 10
},
{
"IRQ 11", 11
},
{
""
}
},
},
{
"mac", "MAC Address", CONFIG_MAC, "", -1
},
{
"", "", -1
}
// clang-format off
static const device_config_t ne1000_config[] = {
{
"base", "Address", CONFIG_HEX16, "", 0x300, "", { 0 },
{
{ "0x280", 0x280 },
{ "0x300", 0x300 },
{ "0x320", 0x320 },
{ "0x340", 0x340 },
{ "0x360", 0x360 },
{ "0x380", 0x380 },
{ "" }
},
},
{
"irq", "IRQ", CONFIG_SELECTION, "", 3, "", { 0 },
{
{ "IRQ 2", 2 },
{ "IRQ 3", 3 },
{ "IRQ 5", 5 },
{ "IRQ 7", 7 },
{ "IRQ 10", 10 },
{ "IRQ 11", 11 },
{ "" }
},
},
{ "mac", "MAC Address", CONFIG_MAC, "", -1 },
{ "", "", -1 }
};
static const device_config_t ne2000_config[] =
{
{
"base", "Address", CONFIG_HEX16, "", 0x300, "", { 0 },
{
{
"0x280", 0x280
},
{
"0x300", 0x300
},
{
"0x320", 0x320
},
{
"0x340", 0x340
},
{
"0x360", 0x360
},
{
"0x380", 0x380
},
{
""
}
},
},
{
"irq", "IRQ", CONFIG_SELECTION, "", 10, "", { 0 },
{
{
"IRQ 2", 2
},
{
"IRQ 3", 3
},
{
"IRQ 5", 5
},
{
"IRQ 7", 7
},
{
"IRQ 10", 10
},
{
"IRQ 11", 11
},
{
""
}
},
},
{
"mac", "MAC Address", CONFIG_MAC, "", -1
},
{
"bios_addr", "BIOS address", CONFIG_HEX20, "", 0, "", { 0 },
{
{
"Disabled", 0x00000
},
{
"D000", 0xD0000
},
{
"D800", 0xD8000
},
{
"C800", 0xC8000
},
{
""
}
},
},
{
"", "", -1
}
static const device_config_t ne2000_config[] = {
{
"base", "Address", CONFIG_HEX16, "", 0x300, "", { 0 },
{
{ "0x280", 0x280 },
{ "0x300", 0x300 },
{ "0x320", 0x320 },
{ "0x340", 0x340 },
{ "0x360", 0x360 },
{ "0x380", 0x380 },
{ "" }
},
},
{
"irq", "IRQ", CONFIG_SELECTION, "", 10, "", { 0 },
{
{ "IRQ 2", 2 },
{ "IRQ 3", 3 },
{ "IRQ 5", 5 },
{ "IRQ 7", 7 },
{ "IRQ 10", 10 },
{ "IRQ 11", 11 },
{ "" }
},
},
{ "mac", "MAC Address", CONFIG_MAC, "", -1 },
{
"bios_addr", "BIOS address", CONFIG_HEX20, "", 0, "", { 0 },
{
{ "Disabled", 0x00000 },
{ "D000", 0xD0000 },
{ "D800", 0xD8000 },
{ "C800", 0xC8000 },
{ "" }
},
},
{ "", "", -1 }
};
static const device_config_t rtl8019as_config[] =
{
{
"mac", "MAC Address", CONFIG_MAC, "", -1
},
{
"", "", -1
}
static const device_config_t rtl8019as_config[] = {
{ "mac", "MAC Address", CONFIG_MAC, "", -1 },
{ "", "", -1 }
};
static const device_config_t rtl8029as_config[] =
{
{
"bios", "Enable BIOS", CONFIG_BINARY, "", 0
},
{
"mac", "MAC Address", CONFIG_MAC, "", -1
},
{
"", "", -1
}
static const device_config_t rtl8029as_config[] = {
{ "bios", "Enable BIOS", CONFIG_BINARY, "", 0 },
{ "mac", "MAC Address", CONFIG_MAC, "", -1 },
{ "", "", -1 }
};
static const device_config_t mca_mac_config[] =
{
{
"mac", "MAC Address", CONFIG_MAC, "", -1
},
{
"", "", -1
}
static const device_config_t mca_mac_config[] = {
{ "mac", "MAC Address", CONFIG_MAC, "", -1 },
{ "", "", -1 }
};
// clang-format on
const device_t ne1000_device = {
"Novell NE1000",

View File

@@ -3076,137 +3076,72 @@ pcnet_close(void *priv)
}
}
static const device_config_t pcnet_pci_config[] =
{
{
"mac", "MAC Address", CONFIG_MAC, "", -1
},
{
"", "", -1
}
// clang-format off
static const device_config_t pcnet_pci_config[] = {
{ "mac", "MAC Address", CONFIG_MAC, "", -1 },
{ "", "", -1 }
};
static const device_config_t pcnet_isa_config[] =
{
{
"base", "Address", CONFIG_HEX16, "", 0x300, "", { 0 },
{
{
"0x300", 0x300
},
{
"0x320", 0x320
},
{
"0x340", 0x340
},
{
"0x360", 0x360
},
{
""
}
},
},
{
"irq", "IRQ", CONFIG_SELECTION, "", 3, "", { 0 },
{
{
"IRQ 3", 3
},
{
"IRQ 4", 4
},
{
"IRQ 5", 5
},
{
"IRQ 9", 9
},
{
""
}
},
},
{
"dma", "DMA channel", CONFIG_SELECTION, "", 5, "", { 0 },
{
{
"DMA 3", 3
},
{
"DMA 5", 5
},
{
"DMA 6", 6
},
{
"DMA 7", 7
},
{
""
}
},
},
{
"mac", "MAC Address", CONFIG_MAC, "", -1
},
{
"", "", -1
}
static const device_config_t pcnet_isa_config[] = {
{
"base", "Address", CONFIG_HEX16, "", 0x300, "", { 0 },
{
{ "0x300", 0x300 },
{ "0x320", 0x320 },
{ "0x340", 0x340 },
{ "0x360", 0x360 },
{ "" }
},
},
{
"irq", "IRQ", CONFIG_SELECTION, "", 3, "", { 0 },
{
{ "IRQ 3", 3 },
{ "IRQ 4", 4 },
{ "IRQ 5", 5 },
{ "IRQ 9", 9 },
{ "" }
},
},
{
"dma", "DMA channel", CONFIG_SELECTION, "", 5, "", { 0 },
{
{ "DMA 3", 3 },
{ "DMA 5", 5 },
{ "DMA 6", 6 },
{ "DMA 7", 7 },
{ "" }
},
},
{ "mac", "MAC Address", CONFIG_MAC, "", -1 },
{ "", "", -1 }
};
static const device_config_t pcnet_vlb_config[] =
{
{
"base", "Address", CONFIG_HEX16, "", 0x300, "", { 0 },
{
{
"0x300", 0x300
},
{
"0x320", 0x320
},
{
"0x340", 0x340
},
{
"0x360", 0x360
},
{
""
}
},
},
{
"irq", "IRQ", CONFIG_SELECTION, "", 3, "", { 0 },
{
{
"IRQ 3", 3
},
{
"IRQ 4", 4
},
{
"IRQ 5", 5
},
{
"IRQ 9", 9
},
{
""
}
},
},
{
"mac", "MAC Address", CONFIG_MAC, "", -1
},
{
"", "", -1
}
static const device_config_t pcnet_vlb_config[] = {
{
"base", "Address", CONFIG_HEX16, "", 0x300, "", { 0 },
{
{ "0x300", 0x300 },
{ "0x320", 0x320 },
{ "0x340", 0x340 },
{ "0x360", 0x360 },
{ "" }
},
},
{
"irq", "IRQ", CONFIG_SELECTION, "", 3, "", { 0 },
{
{ "IRQ 3", 3 },
{ "IRQ 4", 4 },
{ "IRQ 5", 5 },
{ "IRQ 9", 9 },
{ "" }
},
},
{ "mac", "MAC Address", CONFIG_MAC, "", -1 },
{ "", "", -1 }
};
// clang-format on
const device_t pcnet_am79c960_device = {
"AMD PCnet-ISA",

View File

@@ -735,335 +735,161 @@ wd_close(void *priv)
free(dev);
}
static const device_config_t wd8003_config[] =
{
{
"base", "Address", CONFIG_HEX16, "", 0x300, "", { 0 },
{
{
"0x240", 0x240
},
{
"0x280", 0x280
},
{
"0x300", 0x300
},
{
"0x380", 0x380
},
{
""
}
},
},
{
"irq", "IRQ", CONFIG_SELECTION, "", 3, "", { 0 },
{
{
"IRQ 2", 2
},
{
"IRQ 3", 3
},
{
"IRQ 5", 5
},
{
"IRQ 7", 7
},
{
""
}
},
},
{
"ram_addr", "RAM address", CONFIG_HEX20, "", 0xD0000, "", { 0 },
{
{
"C800", 0xC8000
},
{
"CC00", 0xCC000
},
{
"D000", 0xD0000
},
{
"D400", 0xD4000
},
{
"D800", 0xD8000
},
{
"DC00", 0xDC000
},
{
""
}
},
},
{
"mac", "MAC Address", CONFIG_MAC, "", -1
},
{
"", "", -1
}
// clang-format off
static const device_config_t wd8003_config[] = {
{
"base", "Address", CONFIG_HEX16, "", 0x300, "", { 0 },
{
{ "0x240", 0x240 },
{ "0x280", 0x280 },
{ "0x300", 0x300 },
{ "0x380", 0x380 },
{ "" }
},
},
{
"irq", "IRQ", CONFIG_SELECTION, "", 3, "", { 0 },
{
{ "IRQ 2", 2 },
{ "IRQ 3", 3 },
{ "IRQ 5", 5 },
{ "IRQ 7", 7 },
{ "" }
},
},
{
"ram_addr", "RAM address", CONFIG_HEX20, "", 0xD0000, "", { 0 },
{
{ "C800", 0xC8000 },
{ "CC00", 0xCC000 },
{ "D000", 0xD0000 },
{ "D400", 0xD4000 },
{ "D800", 0xD8000 },
{ "DC00", 0xDC000 },
{ "" }
},
},
{ "mac", "MAC Address", CONFIG_MAC, "", -1 },
{ "", "", -1 }
};
static const device_config_t wd8003eb_config[] =
{
{
"base", "Address", CONFIG_HEX16, "", 0x280, "", { 0 },
{
{
"0x200", 0x200
},
{
"0x220", 0x220
},
{
"0x240", 0x240
},
{
"0x260", 0x260
},
{
"0x280", 0x280
},
{
"0x2A0", 0x2A0
},
{
"0x2C0", 0x2C0
},
{
"0x300", 0x300
},
{
"0x340", 0x340
},
{
"0x380", 0x380
},
{
""
}
},
},
{
"irq", "IRQ", CONFIG_SELECTION, "", 3, "", { 0 },
{
{
"IRQ 2/9", 9
},
{
"IRQ 3", 3
},
{
"IRQ 4", 4
},
{
"IRQ 7", 7
},
{
""
}
},
},
{
"ram_addr", "RAM address", CONFIG_HEX20, "", 0xD0000, "", { 0 },
{
{
"C000", 0xC0000
},
{
"C400", 0xC4000
},
{
"C800", 0xC8000
},
{
"CC00", 0xCC000
},
{
"D000", 0xD0000
},
{
"D400", 0xD4000
},
{
"D800", 0xD8000
},
{
"DC00", 0xDC000
},
{
""
}
},
},
{
"ram_size", "RAM size", CONFIG_SELECTION, "", 8192, "", { 0 },
{
{
"8 kB", 8192
},
{
"32 kB", 32768
},
{
""
}
},
},
{
"mac", "MAC Address", CONFIG_MAC, "", -1
},
{
"", "", -1
}
static const device_config_t wd8003eb_config[] = {
{
"base", "Address", CONFIG_HEX16, "", 0x280, "", { 0 },
{
{ "0x200", 0x200 },
{ "0x220", 0x220 },
{ "0x240", 0x240 },
{ "0x260", 0x260 },
{ "0x280", 0x280 },
{ "0x2A0", 0x2A0 },
{ "0x2C0", 0x2C0 },
{ "0x300", 0x300 },
{ "0x340", 0x340 },
{ "0x380", 0x380 },
{ "" }
},
},
{
"irq", "IRQ", CONFIG_SELECTION, "", 3, "", { 0 },
{
{ "IRQ 2/9", 9 },
{ "IRQ 3", 3 },
{ "IRQ 4", 4 },
{ "IRQ 7", 7 },
{ "" }
},
},
{
"ram_addr", "RAM address", CONFIG_HEX20, "", 0xD0000, "", { 0 },
{
{ "C000", 0xC0000 },
{ "C400", 0xC4000 },
{ "C800", 0xC8000 },
{ "CC00", 0xCC000 },
{ "D000", 0xD0000 },
{ "D400", 0xD4000 },
{ "D800", 0xD8000 },
{ "DC00", 0xDC000 },
{ "" }
},
},
{
"ram_size", "RAM size", CONFIG_SELECTION, "", 8192, "", { 0 },
{
{ "8 kB", 8192 },
{ "32 kB", 32768 },
{ "" }
},
},
{ "mac", "MAC Address", CONFIG_MAC, "", -1 },
{ "", "", -1 }
};
/* WD8013EBT configuration and defaults set according to this site:
http://www.stack.nl/~marcolz/network/wd80x3.html#WD8013EBT */
static const device_config_t wd8013_config[] =
{
{
"base", "Address", CONFIG_HEX16, "", 0x280, "", { 0 },
{
{
"0x200", 0x200
},
{
"0x220", 0x220
},
{
"0x240", 0x240
},
{
"0x260", 0x260
},
{
"0x280", 0x280
},
{
"0x2A0", 0x2A0
},
{
"0x2C0", 0x2C0
},
{
"0x300", 0x300
},
{
"0x340", 0x340
},
{
"0x380", 0x380
},
{
""
}
},
},
{
"irq", "IRQ", CONFIG_SELECTION, "", 3, "", { 0 },
{
{
"IRQ 2/9", 9
},
{
"IRQ 3", 3
},
{
"IRQ 4", 4
},
{
"IRQ 5", 5
},
{
"IRQ 7", 7
},
{
"IRQ 10", 10
},
{
"IRQ 11", 11
},
{
"IRQ 15", 15
},
{
""
}
},
},
{
"ram_addr", "RAM address", CONFIG_HEX20, "", 0xD0000, "", { 0 },
{
{
"C000", 0xC0000
},
{
"C400", 0xC4000
},
{
"C800", 0xC8000
},
{
"CC00", 0xCC000
},
{
"D000", 0xD0000
},
{
"D400", 0xD4000
},
{
"D800", 0xD8000
},
{
"DC00", 0xDC000
},
{
""
}
},
},
{
"ram_size", "RAM size", CONFIG_SELECTION, "", 16384, "", { 0 },
{
{
"16 kB", 16384
},
{
"64 kB", 65536
},
{
""
}
},
},
{
"mac", "MAC Address", CONFIG_MAC, "", -1
},
{
"", "", -1
}
static const device_config_t wd8013_config[] = {
{
"base", "Address", CONFIG_HEX16, "", 0x280, "", { 0 },
{
{ "0x200", 0x200 },
{ "0x220", 0x220 },
{ "0x240", 0x240 },
{ "0x260", 0x260 },
{ "0x280", 0x280 },
{ "0x2A0", 0x2A0 },
{ "0x2C0", 0x2C0 },
{ "0x300", 0x300 },
{ "0x340", 0x340 },
{ "0x380", 0x380 },
{ "" }
},
},
{
"irq", "IRQ", CONFIG_SELECTION, "", 3, "", { 0 },
{
{ "IRQ 2/9", 9 },
{ "IRQ 3", 3 },
{ "IRQ 4", 4 },
{ "IRQ 5", 5 },
{ "IRQ 7", 7 },
{ "IRQ 10", 10 },
{ "IRQ 11", 11 },
{ "IRQ 15", 15 },
{ "" }
},
},
{
"ram_addr", "RAM address", CONFIG_HEX20, "", 0xD0000, "", { 0 },
{
{ "C000", 0xC0000 },
{ "C400", 0xC4000 },
{ "C800", 0xC8000 },
{ "CC00", 0xCC000 },
{ "D000", 0xD0000 },
{ "D400", 0xD4000 },
{ "D800", 0xD8000 },
{ "DC00", 0xDC000 },
{ "" }
},
},
{
"ram_size", "RAM size", CONFIG_SELECTION, "", 16384, "", { 0 },
{
{ "16 kB", 16384 },
{ "64 kB", 65536 },
{ "" }
},
},
{ "mac", "MAC Address", CONFIG_MAC, "", -1 },
{ "", "", -1 }
};
static const device_config_t mca_mac_config[] =
{
{
"mac", "MAC Address", CONFIG_MAC, "", -1
},
{
"", "", -1
}
static const device_config_t mca_mac_config[] = {
{ "mac", "MAC Address", CONFIG_MAC, "", -1 },
{ "", "", -1 }
};
// clang-format on
const device_t wd8003e_device = {
"Western Digital WD8003E",

View File

@@ -81,26 +81,28 @@ static const device_t net_none_device = {
static netcard_t net_cards[] = {
{ &net_none_device, NULL },
{ &threec503_device, NULL },
{ &pcnet_am79c960_device, NULL },
{ &pcnet_am79c961_device, NULL },
{ &ne1000_device, NULL },
{ &ne2000_device, NULL },
{ &pcnet_am79c960_eb_device, NULL },
{ &rtl8019as_device, NULL },
{ &wd8003e_device, NULL },
{ &wd8003eb_device, NULL },
{ &wd8013ebt_device, NULL },
{ &plip_device, NULL },
{ &ethernext_mc_device, NULL },
{ &wd8003eta_device, NULL },
{ &wd8003ea_device, NULL },
{ &pcnet_am79c973_device, NULL },
{ &pcnet_am79c970a_device, NULL },
{ &rtl8029as_device, NULL },
{ &pcnet_am79c960_vlb_device, NULL },
{ NULL, NULL }
// clang-format off
{ &net_none_device, NULL },
{ &threec503_device, NULL },
{ &pcnet_am79c960_device, NULL },
{ &pcnet_am79c961_device, NULL },
{ &ne1000_device, NULL },
{ &ne2000_device, NULL },
{ &pcnet_am79c960_eb_device, NULL },
{ &rtl8019as_device, NULL },
{ &wd8003e_device, NULL },
{ &wd8003eb_device, NULL },
{ &wd8013ebt_device, NULL },
{ &plip_device, NULL },
{ &ethernext_mc_device, NULL },
{ &wd8003eta_device, NULL },
{ &wd8003ea_device, NULL },
{ &pcnet_am79c973_device, NULL },
{ &pcnet_am79c970a_device, NULL },
{ &rtl8029as_device, NULL },
{ &pcnet_am79c960_vlb_device, NULL },
{ NULL, NULL }
// clang-format off
};

View File

@@ -69,12 +69,14 @@ static pcap_t *(*f_pcap_open_live)(const char *,int,int,int,char *);
static int (*f_pcap_next_ex)(pcap_t*,struct pcap_pkthdr**,const unsigned char**);
static void (*f_pcap_close)(pcap_t *);
static dllimp_t pcap_imports[] = {
{ "pcap_findalldevs", &f_pcap_findalldevs },
{ "pcap_freealldevs", &f_pcap_freealldevs },
{ "pcap_open_live", &f_pcap_open_live },
{ "pcap_next_ex", &f_pcap_next_ex },
{ "pcap_close", &f_pcap_close },
{ NULL, NULL },
// clang-format off
{ "pcap_findalldevs", &f_pcap_findalldevs },
{ "pcap_freealldevs", &f_pcap_freealldevs },
{ "pcap_open_live", &f_pcap_open_live },
{ "pcap_next_ex", &f_pcap_next_ex },
{ "pcap_close", &f_pcap_close },
{ NULL, NULL },
// clang-format on
};

View File

@@ -553,21 +553,23 @@ static const struct {
uint16_t code;
const uint16_t *map;
} maps[] = {
{ 437, cp437Map },
{ 737, cp737Map },
{ 775, cp775Map },
{ 850, cp850Map },
{ 852, cp852Map },
{ 855, cp855Map },
{ 857, cp857Map },
{ 860, cp860Map },
{ 861, cp861Map },
{ 862, cp862Map },
{ 863, cp863Map },
{ 864, cp864Map },
{ 865, cp865Map },
{ 866, cp866Map },
{ -1, NULL }
// clang-format off
{ 437, cp437Map },
{ 737, cp737Map },
{ 775, cp775Map },
{ 850, cp850Map },
{ 852, cp852Map },
{ 855, cp855Map },
{ 857, cp857Map },
{ 860, cp860Map },
{ 861, cp861Map },
{ 862, cp862Map },
{ 863, cp863Map },
{ 864, cp864Map },
{ 865, cp865Map },
{ 866, cp866Map },
{ -1, NULL }
// clang-format on
};

View File

@@ -100,13 +100,15 @@ static int (GSDLLAPI *gsapi_init_with_args)(void *instance, int argc, char **ar
static int (GSDLLAPI *gsapi_exit)(void *instance);
static dllimp_t ghostscript_imports[] = {
{ "gsapi_revision", &gsapi_revision },
{ "gsapi_new_instance", &gsapi_new_instance },
{ "gsapi_delete_instance", &gsapi_delete_instance },
{ "gsapi_set_arg_encoding", &gsapi_set_arg_encoding },
{ "gsapi_init_with_args", &gsapi_init_with_args },
{ "gsapi_exit", &gsapi_exit },
{ NULL, NULL }
// clang-format off
{ "gsapi_revision", &gsapi_revision },
{ "gsapi_new_instance", &gsapi_new_instance },
{ "gsapi_delete_instance", &gsapi_delete_instance },
{ "gsapi_set_arg_encoding", &gsapi_set_arg_encoding },
{ "gsapi_init_with_args", &gsapi_init_with_args },
{ "gsapi_exit", &gsapi_exit },
{ NULL, NULL }
// clang-format on
};
static void *ghostscript_handle = NULL;

View File

@@ -20,7 +20,7 @@ if(QT_STATIC AND MINGW)
endif()
find_package(Threads REQUIRED)
find_package(Qt${QT_MAJOR} COMPONENTS Core Widgets OpenGL REQUIRED)
find_package(Qt${QT_MAJOR} COMPONENTS Core Widgets Network OpenGL REQUIRED)
find_package(Qt${QT_MAJOR}LinguistTools REQUIRED)
add_library(plat STATIC
@@ -49,6 +49,13 @@ add_library(ui STATIC
qt_softwarerenderer.hpp
qt_hardwarerenderer.cpp
qt_hardwarerenderer.hpp
qt_openglrenderer.cpp
qt_openglrenderer.hpp
qt_opengloptions.cpp
qt_opengloptions.hpp
qt_opengloptionsdialog.cpp
qt_opengloptionsdialog.hpp
qt_opengloptionsdialog.ui
qt_settings.cpp
qt_settings.hpp
@@ -127,6 +134,9 @@ add_library(ui STATIC
qt_util.hpp
qt_util.cpp
qt_unixmanagerfilter.cpp
qt_unixmanagerfilter.hpp
../qt_resources.qrc
)
@@ -176,6 +186,7 @@ target_link_libraries(
PRIVATE
Qt${QT_MAJOR}::Widgets
Qt${QT_MAJOR}::Gui
Qt${QT_MAJOR}::Network
Threads::Threads
)
@@ -185,6 +196,7 @@ target_link_libraries(
Qt${QT_MAJOR}::Widgets
Qt${QT_MAJOR}::Gui
Qt${QT_MAJOR}::OpenGL
Qt${QT_MAJOR}::Network
Threads::Threads
)

View File

@@ -65,7 +65,7 @@ extern "C"
#include "qt_settings.hpp"
#include "cocoa_mouse.hpp"
#include "qt_styleoverride.hpp"
#include "qt_unixmanagerfilter.hpp"
// Void Cast
#define VC(x) const_cast<wchar_t*>(x)
@@ -238,6 +238,21 @@ int main(int argc, char* argv[]) {
}
#endif
UnixManagerSocket socket;
if (qgetenv("86BOX_MANAGER_SOCKET").size())
{
QObject::connect(&socket, &UnixManagerSocket::showsettings, main_window, &MainWindow::showSettings);
QObject::connect(&socket, &UnixManagerSocket::pause, main_window, &MainWindow::togglePause);
QObject::connect(&socket, &UnixManagerSocket::reset, main_window, &MainWindow::hardReset);
QObject::connect(&socket, &UnixManagerSocket::request_shutdown, main_window, &MainWindow::close);
QObject::connect(&socket, &UnixManagerSocket::force_shutdown, [](){
do_stop();
emit main_window->close();
});
QObject::connect(&socket, &UnixManagerSocket::ctrlaltdel, [](){ pc_send_cad(); });
main_window->installEventFilter(&socket);
socket.connectToServer(qgetenv("86BOX_MANAGER_SOCKET"));
}
pc_reset_hard_init();
/* Set the PAUSE mode depending on the renderer. */
@@ -272,5 +287,6 @@ int main(int argc, char* argv[]) {
cpu_thread_run = 0;
main_thread.join();
socket.close();
return ret;
}

View File

@@ -202,7 +202,7 @@ MainWindow::MainWindow(QWidget *parent) :
config_save();
if (QApplication::activeWindow() == this)
{
ui->stackedWidget->current->setFocus();
ui->stackedWidget->setFocusRenderer();
}
});
@@ -231,35 +231,54 @@ MainWindow::MainWindow(QWidget *parent) :
ui->actionHardware_Renderer_OpenGL_ES->setVisible(QOpenGLContext::openGLModuleType() == QOpenGLContext::LibGLES);
if (QOpenGLContext::openGLModuleType() != QOpenGLContext::LibGLES && vid_api == 2) vid_api = 1;
#endif
ui->actionHardware_Renderer_OpenGL->setVisible(QOpenGLContext::openGLModuleType() != QOpenGLContext::LibGLES);
if (QOpenGLContext::openGLModuleType() == QOpenGLContext::LibGLES && vid_api == 1) vid_api = 0;
if (QApplication::platformName().contains("eglfs") && vid_api >= 1) {
fprintf(stderr, "OpenGL renderers are unsupported on EGLFS.\n");
vid_api = 0;
}
QActionGroup* actGroup = nullptr;
switch (vid_api) {
case 0:
ui->stackedWidget->switchRenderer(RendererStack::Renderer::Software);
ui->actionSoftware_Renderer->setChecked(true);
break;
case 1:
ui->stackedWidget->switchRenderer(RendererStack::Renderer::OpenGL);
ui->actionHardware_Renderer_OpenGL->setChecked(true);
break;
case 2:
ui->stackedWidget->switchRenderer(RendererStack::Renderer::OpenGLES);
ui->actionHardware_Renderer_OpenGL_ES->setChecked(true);
break;
case 3:
ui->stackedWidget->switchRenderer(RendererStack::Renderer::OpenGL3);
ui->actionOpenGL_3_0_Core->setChecked(true);
break;
}
actGroup = new QActionGroup(this);
actGroup->addAction(ui->actionSoftware_Renderer);
actGroup->addAction(ui->actionHardware_Renderer_OpenGL);
actGroup->addAction(ui->actionHardware_Renderer_OpenGL_ES);
actGroup->addAction(ui->actionOpenGL_3_0_Core);
actGroup->setExclusive(true);
connect(actGroup, &QActionGroup::triggered, [this](QAction* action) {
vid_api = action->property("vid_api").toInt();
switch (vid_api)
{
case 0:
ui->stackedWidget->switchRenderer(RendererStack::Renderer::Software);
break;
case 1:
ui->stackedWidget->switchRenderer(RendererStack::Renderer::OpenGL);
break;
case 2:
ui->stackedWidget->switchRenderer(RendererStack::Renderer::OpenGLES);
break;
case 3:
ui->stackedWidget->switchRenderer(RendererStack::Renderer::OpenGL3);
break;
}
});
connect(ui->stackedWidget, &RendererStack::rendererChanged, [this]() {
ui->actionRenderer_options->setVisible(ui->stackedWidget->hasOptions());
});
/* Trigger initial renderer switch */
for (auto action : actGroup->actions())
if (action->property("vid_api").toInt() == vid_api) {
action->setChecked(true);
emit actGroup->triggered(action);
break;
}
switch (scale) {
case 0:
ui->action0_5x->setChecked(true);
@@ -424,7 +443,7 @@ void MainWindow::closeEvent(QCloseEvent *event) {
QCheckBox *chkbox = new QCheckBox(tr("Don't show this message again"));
questionbox.setCheckBox(chkbox);
chkbox->setChecked(!confirm_exit);
bool confirm_exit_temp = false;
QObject::connect(chkbox, &QCheckBox::stateChanged, [](int state) {
confirm_exit = (state == Qt::CheckState::Unchecked);
});
@@ -497,7 +516,7 @@ void MainWindow::on_actionHard_Reset_triggered() {
QCheckBox *chkbox = new QCheckBox(tr("Don't show this message again"));
questionbox.setCheckBox(chkbox);
chkbox->setChecked(!confirm_reset);
bool confirm_exit_temp = false;
QObject::connect(chkbox, &QCheckBox::stateChanged, [](int state) {
confirm_reset = (state == Qt::CheckState::Unchecked);
});
@@ -1099,21 +1118,21 @@ void MainWindow::on_actionFullscreen_triggered() {
QCheckBox *chkbox = new QCheckBox(tr("Don't show this message again"));
questionbox.setCheckBox(chkbox);
chkbox->setChecked(!video_fullscreen_first);
bool confirm_exit_temp = false;
QObject::connect(chkbox, &QCheckBox::stateChanged, [](int state) {
video_fullscreen_first = (state == Qt::CheckState::Unchecked);
});
questionbox.exec();
config_save();
}
video_fullscreen = 1;
setFixedSize(QWIDGETSIZE_MAX, QWIDGETSIZE_MAX);
ui->menubar->hide();
ui->statusbar->hide();
ui->toolBar->hide();
showFullScreen();
video_fullscreen = 1;
}
ui->stackedWidget->rendererWindow->onResize(width(), height());
ui->stackedWidget->onResize(width(), height());
}
void MainWindow::getTitle_(wchar_t *title)
@@ -1216,30 +1235,6 @@ QSize MainWindow::getRenderWidgetSize()
return ui->stackedWidget->size();
}
void MainWindow::on_actionSoftware_Renderer_triggered() {
ui->stackedWidget->switchRenderer(RendererStack::Renderer::Software);
ui->actionHardware_Renderer_OpenGL->setChecked(false);
ui->actionHardware_Renderer_OpenGL_ES->setChecked(false);
ui->actionOpenGL_3_0_Core->setChecked(false);
vid_api = 0;
}
void MainWindow::on_actionHardware_Renderer_OpenGL_triggered() {
ui->stackedWidget->switchRenderer(RendererStack::Renderer::OpenGL);
ui->actionSoftware_Renderer->setChecked(false);
ui->actionHardware_Renderer_OpenGL_ES->setChecked(false);
ui->actionOpenGL_3_0_Core->setChecked(false);
vid_api = 1;
}
void MainWindow::on_actionHardware_Renderer_OpenGL_ES_triggered() {
ui->stackedWidget->switchRenderer(RendererStack::Renderer::OpenGLES);
ui->actionSoftware_Renderer->setChecked(false);
ui->actionHardware_Renderer_OpenGL->setChecked(false);
ui->actionOpenGL_3_0_Core->setChecked(false);
vid_api = 2;
}
void MainWindow::focusInEvent(QFocusEvent* event)
{
this->grabKeyboard();
@@ -1335,8 +1330,7 @@ static void update_fullscreen_scale_checkboxes(Ui::MainWindow* ui, QAction* sele
if (video_fullscreen > 0) {
auto widget = ui->stackedWidget->currentWidget();
auto rc = ui->stackedWidget->rendererWindow;
rc->onResize(widget->width(), widget->height());
ui->stackedWidget->onResize(widget->width(), widget->height());
}
device_force_redraw();
@@ -1563,16 +1557,6 @@ void MainWindow::setSendKeyboardInput(bool enabled)
send_keyboard_input = enabled;
}
void MainWindow::on_actionOpenGL_3_0_Core_triggered()
{
ui->stackedWidget->switchRenderer(RendererStack::Renderer::OpenGL3);
ui->actionSoftware_Renderer->setChecked(false);
ui->actionHardware_Renderer_OpenGL->setChecked(false);
ui->actionHardware_Renderer_OpenGL_ES->setChecked(false);
ui->actionOpenGL_3_0_Core->setChecked(true);
vid_api = 3;
}
void MainWindow::on_actionPreferences_triggered()
{
ProgSettings progsettings(this);
@@ -1618,3 +1602,11 @@ void MainWindow::changeEvent(QEvent* event)
#endif
QWidget::changeEvent(event);
}
void MainWindow::on_actionRenderer_options_triggered()
{
auto dlg = ui->stackedWidget->getOptions(this);
if (dlg)
dlg->exec();
}

View File

@@ -61,9 +61,6 @@ private slots:
void on_actionHard_Reset_triggered();
void on_actionRight_CTRL_is_left_ALT_triggered();
void on_actionKeyboard_requires_capture_triggered();
void on_actionHardware_Renderer_OpenGL_ES_triggered();
void on_actionHardware_Renderer_OpenGL_triggered();
void on_actionSoftware_Renderer_triggered();
void on_actionResizable_window_triggered(bool checked);
void on_actionInverted_VGA_monitor_triggered();
void on_action0_5x_triggered();
@@ -96,19 +93,15 @@ private slots:
void on_actionHide_status_bar_triggered();
void on_actionHide_tool_bar_triggered();
void on_actionUpdate_status_bar_icons_triggered();
void on_actionTake_screenshot_triggered();
void on_actionSound_gain_triggered();
void on_actionPreferences_triggered();
void on_actionEnable_Discord_integration_triggered(bool checked);
void on_actionRenderer_options_triggered();
void refreshMediaMenu();
void showMessage_(const QString& header, const QString& message);
void getTitle_(wchar_t* title);
void on_actionTake_screenshot_triggered();
void on_actionSound_gain_triggered();
void on_actionOpenGL_3_0_Core_triggered();
void on_actionPreferences_triggered();
void on_actionEnable_Discord_integration_triggered(bool checked);
protected:
void keyPressEvent(QKeyEvent* event) override;

View File

@@ -15,7 +15,7 @@
</property>
<widget class="QWidget" name="centralwidget">
<property name="sizePolicy">
<sizepolicy hsizetype="Fixed" vsizetype="Fixed">
<sizepolicy hsizetype="Expanding" vsizetype="Expanding">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
@@ -37,7 +37,14 @@
<number>0</number>
</property>
<item>
<widget class="RendererStack" name="stackedWidget"/>
<widget class="RendererStack" name="stackedWidget">
<property name="sizePolicy">
<sizepolicy hsizetype="Expanding" vsizetype="Expanding">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
</widget>
</item>
</layout>
</widget>
@@ -154,6 +161,8 @@
<addaction name="actionRemember_size_and_position"/>
<addaction name="separator"/>
<addaction name="menuRenderer"/>
<addaction name="actionRenderer_options"/>
<addaction name="separator"/>
<addaction name="actionSpecify_dimensions"/>
<addaction name="actionForce_4_3_display_ratio"/>
<addaction name="menuWindow_scale_factor"/>
@@ -341,6 +350,9 @@
<property name="text">
<string>&amp;Qt (Software)</string>
</property>
<property name="vid_api" stdset="0">
<number>0</number>
</property>
</action>
<action name="actionHardware_Renderer_OpenGL">
<property name="checkable">
@@ -349,6 +361,9 @@
<property name="text">
<string>Qt (&amp;OpenGL)</string>
</property>
<property name="vid_api" stdset="0">
<number>1</number>
</property>
</action>
<action name="actionHardware_Renderer_OpenGL_ES">
<property name="checkable">
@@ -357,6 +372,9 @@
<property name="text">
<string>Qt (OpenGL &amp;ES)</string>
</property>
<property name="vid_api" stdset="0">
<number>2</number>
</property>
</action>
<action name="actionHide_status_bar">
<property name="checkable">
@@ -626,6 +644,9 @@
<property name="text">
<string>Open&amp;GL (3.0 Core)</string>
</property>
<property name="vid_api" stdset="0">
<number>3</number>
</property>
</action>
<action name="actionPreferences">
<property name="text">
@@ -700,6 +721,11 @@
<bool>false</bool>
</property>
</action>
<action name="actionRenderer_options">
<property name="text">
<string>Renderer options...</string>
</property>
</action>
</widget>
<customwidgets>
<customwidget>

View File

@@ -25,12 +25,16 @@
#include "qt_util.hpp"
extern "C" {
#include <86box/plat.h>
#include <86box/random.h>
#include <86box/scsi_device.h>
#include <86box/zip.h>
#include <86box/mo.h>
}
#include <cstdio>
#include <cstdlib>
#include <QFile>
#include <QFileInfo>
#include <QMessageBox>
@@ -236,6 +240,8 @@ void NewFloppyDialog::onCreate() {
bool NewFloppyDialog::create86f(const QString& filename, const disk_size_t& disk_size, uint8_t rpm_mode)
{
FILE *f;
uint32_t magic = 0x46423638;
uint16_t version = 0x020C;
uint16_t dflags = 0;
@@ -259,74 +265,77 @@ bool NewFloppyDialog::create86f(const QString& filename, const disk_size_t& disk
tflags |= (disk_size.rpm << 5); /* RPM. */
switch (disk_size.hole) {
case 0:
case 1:
default:
switch(rpm_mode) {
case 1:
array_size = 25250;
break;
case 2:
array_size = 25374;
break;
case 3:
array_size = 25750;
break;
default:
array_size = 25000;
break;
}
break;
case 2:
switch(rpm_mode) {
case 1:
array_size = 50500;
break;
case 2:
array_size = 50750;
break;
case 3:
array_size = 51000;
break;
default:
array_size = 50000;
break;
}
break;
case 0:
case 1:
default:
switch(rpm_mode) {
case 1:
array_size = 25250;
break;
case 2:
array_size = 25374;
break;
case 3:
array_size = 25750;
break;
default:
array_size = 25000;
break;
}
break;
case 2:
switch(rpm_mode) {
case 1:
array_size = 50500;
break;
case 2:
array_size = 50750;
break;
case 3:
array_size = 51000;
break;
default:
array_size = 50000;
break;
}
break;
}
QByteArray bytes(array_size, 0);
auto empty = (unsigned char *) malloc(array_size);
memset(tarray, 0, 2048);
memset(empty, 0, array_size);
QFile file(filename);
if (! file.open(QIODevice::WriteOnly)) {
return false;
}
QDataStream stream(&file);
stream.setByteOrder(QDataStream::LittleEndian);
f = plat_fopen(filename.toUtf8().data(), "wb");
if (!f)
return false;
stream << magic;
stream << version;
stream << dflags;
fwrite(&magic, 4, 1, f);
fwrite(&version, 2, 1, f);
fwrite(&dflags, 2, 1, f);
track_size = array_size + 6;
track_base = 8 + ((disk_size.sides == 2) ? 2048 : 1024);
if (disk_size.tracks <= 43)
shift = 1;
shift = 1;
for (i = 0; i < (disk_size.tracks * disk_size.sides) << shift; i++)
tarray[i] = track_base + (i * track_size);
tarray[i] = track_base + (i * track_size);
stream.writeRawData(reinterpret_cast<const char *>(tarray), (disk_size.sides == 2) ? 2048 : 1024);
fwrite(tarray, 1, (disk_size.sides == 2) ? 2048 : 1024, f);
int max = i < (disk_size.tracks * disk_size.sides) << shift;
for (i = 0; i < max; i++) {
stream << tflags;
stream << index_hole_pos;
stream.writeRawData(bytes, bytes.size());
for (i = 0; i < (disk_size.tracks * disk_size.sides) << shift; i++) {
fwrite(&tflags, 2, 1, f);
fwrite(&index_hole_pos, 4, 1, f);
fwrite(empty, 1, array_size, f);
}
free(empty);
fclose(f);
return true;
}

196
src/qt/qt_opengloptions.cpp Normal file
View File

@@ -0,0 +1,196 @@
/*
* 86Box A hypervisor and IBM PC system emulator that specializes in
* running old operating systems and software designed for IBM
* PC systems and compatibles from 1981 through fairly recent
* system designs based on the PCI bus.
*
* This file is part of the 86Box distribution.
*
* OpenGL renderer options for Qt
*
* Authors:
* Teemu Korhonen
*
* Copyright 2022 Teemu Korhonen
*/
#include <QFile>
#include <QRegularExpression>
#include <QStringBuilder>
#include <stdexcept>
#include "qt_opengloptions.hpp"
extern "C" {
#include <86box/86box.h>
}
/* Default vertex shader. */
static const GLchar *vertex_shader = "\
in vec2 VertexCoord;\n\
in vec2 TexCoord;\n\
out vec2 tex;\n\
void main(){\n\
gl_Position = vec4(VertexCoord, 0.0, 1.0);\n\
tex = TexCoord;\n\
}\n";
/* Default fragment shader. */
static const GLchar *fragment_shader = "\
in vec2 tex;\n\
uniform sampler2D texsampler;\n\
out vec4 color;\n\
void main() {\n\
color = texture(texsampler, tex);\n\
}\n";
OpenGLOptions::OpenGLOptions(QObject *parent, bool loadConfig)
: QObject(parent)
{
if (!loadConfig)
return;
/* Initialize with config. */
m_vsync = video_vsync != 0;
m_framerate = video_framerate;
m_renderBehavior = video_framerate == -1
? RenderBehaviorType::SyncWithVideo
: RenderBehaviorType::TargetFramerate;
m_filter = video_filter_method == 0
? FilterType::Nearest
: FilterType::Linear;
QString shaderPath(video_shader);
if (shaderPath.isEmpty()) {
addDefaultShader();
} else {
try {
addShader(shaderPath);
} catch (const std::runtime_error &) {
/* Fallback to default shader */
addDefaultShader();
}
}
}
void
OpenGLOptions::save() const
{
video_vsync = m_vsync ? 1 : 0;
video_framerate = m_renderBehavior == RenderBehaviorType::SyncWithVideo ? -1 : m_framerate;
video_filter_method = m_filter == FilterType::Nearest ? 0 : 1;
/* TODO: multiple shaders */
auto path = m_shaders.first().path().toLocal8Bit();
if (!path.isEmpty())
strcpy(video_shader, path.constData());
else
video_shader[0] = '\0';
}
OpenGLOptions::FilterType
OpenGLOptions::filter() const
{
/* Filter method is controlled externally */
return video_filter_method == 0
? FilterType::Nearest
: FilterType::Linear;
}
void
OpenGLOptions::setRenderBehavior(RenderBehaviorType value)
{
m_renderBehavior = value;
}
void
OpenGLOptions::setFrameRate(int value)
{
m_framerate = value;
}
void
OpenGLOptions::setVSync(bool value)
{
m_vsync = value;
}
void
OpenGLOptions::setFilter(FilterType value)
{
m_filter = value;
}
void
OpenGLOptions::addShader(const QString &path)
{
QFile shader_file(path);
if (!shader_file.open(QIODevice::ReadOnly | QIODevice::Text)) {
throw std::runtime_error(
QString(tr("Error opening \"%1\": %2"))
.arg(path)
.arg(shader_file.errorString())
.toStdString());
}
auto shader_text = QString(shader_file.readAll());
shader_file.close();
QRegularExpression version("^\\s*(#version\\s+\\w+)", QRegularExpression::MultilineOption);
auto match = version.match(shader_text);
QString version_line("#version 130");
if (match.hasMatch()) {
/* Extract existing version and remove it. */
version_line = match.captured(1);
shader_text.remove(version);
}
if (QOpenGLContext::currentContext() && QOpenGLContext::currentContext()->isOpenGLES()) {
/* Force #version 300 es (the default of #version 100 es is too old and too limited) */
version_line = "#version 300 es";
}
auto shader = new QOpenGLShaderProgram(this);
auto throw_shader_error = [path, shader](const QString &what) {
throw std::runtime_error(
QString(what % ":\n\n %2")
.arg(path)
.arg(shader->log())
.toStdString());
};
if (!shader->addShaderFromSourceCode(QOpenGLShader::Vertex, version_line % "\n#extension GL_ARB_shading_language_420pack : enable\n" % "\n#define VERTEX\n" % shader_text))
throw_shader_error(tr("Error compiling vertex shader in file \"%1\""));
if (!shader->addShaderFromSourceCode(QOpenGLShader::Fragment, version_line % "\n#extension GL_ARB_shading_language_420pack : enable\n" "\n#define FRAGMENT\n" % shader_text))
throw_shader_error(tr("Error compiling fragment shader in file \"%1\""));
if (!shader->link())
throw_shader_error(tr("Error linking shader program in file \"%1\""));
m_shaders << OpenGLShaderPass(shader, path);
}
void
OpenGLOptions::addDefaultShader()
{
QString version = QOpenGLContext::currentContext() && QOpenGLContext::currentContext()->isOpenGLES()
? "#version 300 es\n"
: "#version 130\n";
auto shader = new QOpenGLShaderProgram(this);
shader->addShaderFromSourceCode(QOpenGLShader::Vertex, version % vertex_shader);
shader->addShaderFromSourceCode(QOpenGLShader::Fragment, version % fragment_shader);
shader->link();
m_shaders << OpenGLShaderPass(shader, QString());
}

100
src/qt/qt_opengloptions.hpp Normal file
View File

@@ -0,0 +1,100 @@
/*
* 86Box A hypervisor and IBM PC system emulator that specializes in
* running old operating systems and software designed for IBM
* PC systems and compatibles from 1981 through fairly recent
* system designs based on the PCI bus.
*
* This file is part of the 86Box distribution.
*
* Header for OpenGL renderer options
*
* Authors:
* Teemu Korhonen
*
* Copyright 2022 Teemu Korhonen
*/
#ifndef QT_OPENGLOPTIONS_HPP
#define QT_OPENGLOPTIONS_HPP
#include <QList>
#include <QObject>
#include <QOpenGLContext>
#include <QOpenGLShaderProgram>
class OpenGLShaderPass {
public:
OpenGLShaderPass(QOpenGLShaderProgram *shader, const QString &path)
: m_shader(shader)
, m_path(path)
, m_vertex_coord(shader->attributeLocation("VertexCoord"))
, m_tex_coord(shader->attributeLocation("TexCoord"))
, m_color(shader->attributeLocation("Color"))
, m_mvp_matrix(shader->uniformLocation("MVPMatrix"))
, m_input_size(shader->uniformLocation("InputSize"))
, m_output_size(shader->uniformLocation("OutputSize"))
, m_texture_size(shader->uniformLocation("TextureSize"))
, m_frame_count(shader->uniformLocation("FrameCount"))
{
}
bool bind() const { return m_shader->bind(); }
const QString &path() const { return m_path; }
const GLint &vertex_coord() const { return m_vertex_coord; }
const GLint &tex_coord() const { return m_tex_coord; }
const GLint &color() const { return m_color; }
const GLint &mvp_matrix() const { return m_mvp_matrix; }
const GLint &input_size() const { return m_input_size; }
const GLint &output_size() const { return m_output_size; }
const GLint &texture_size() const { return m_texture_size; }
const GLint &frame_count() const { return m_frame_count; }
private:
QOpenGLShaderProgram *m_shader;
QString m_path;
GLint m_vertex_coord;
GLint m_tex_coord;
GLint m_color;
GLint m_mvp_matrix;
GLint m_input_size;
GLint m_output_size;
GLint m_texture_size;
GLint m_frame_count;
};
class OpenGLOptions : public QObject {
Q_OBJECT
public:
enum RenderBehaviorType { SyncWithVideo,
TargetFramerate };
enum FilterType { Nearest,
Linear };
OpenGLOptions(QObject *parent = nullptr, bool loadConfig = false);
RenderBehaviorType renderBehavior() const { return m_renderBehavior; }
int framerate() const { return m_framerate; }
bool vSync() const { return m_vsync; }
FilterType filter() const;
const QList<OpenGLShaderPass> &shaders() const { return m_shaders; };
void setRenderBehavior(RenderBehaviorType value);
void setFrameRate(int value);
void setVSync(bool value);
void setFilter(FilterType value);
void addShader(const QString &path);
void addDefaultShader();
void save() const;
private:
RenderBehaviorType m_renderBehavior = SyncWithVideo;
int m_framerate = -1;
bool m_vsync = false;
FilterType m_filter = Nearest;
QList<OpenGLShaderPass> m_shaders;
};
#endif

View File

@@ -0,0 +1,114 @@
/*
* 86Box A hypervisor and IBM PC system emulator that specializes in
* running old operating systems and software designed for IBM
* PC systems and compatibles from 1981 through fairly recent
* system designs based on the PCI bus.
*
* This file is part of the 86Box distribution.
*
* OpenGL renderer options dialog for Qt
*
* Authors:
* Teemu Korhonen
*
* Copyright 2022 Teemu Korhonen
*/
#include <QFileDialog>
#include <QMessageBox>
#include <QStringBuilder>
#include <stdexcept>
#include "qt_opengloptionsdialog.hpp"
#include "qt_util.hpp"
#include "ui_qt_opengloptionsdialog.h"
OpenGLOptionsDialog::OpenGLOptionsDialog(QWidget *parent, const OpenGLOptions &options)
: QDialog(parent)
, ui(new Ui::OpenGLOptionsDialog)
{
ui->setupUi(this);
if (options.renderBehavior() == OpenGLOptions::SyncWithVideo)
ui->syncWithVideo->setChecked(true);
else {
ui->syncToFramerate->setChecked(true);
ui->targetFps->setValue(options.framerate());
}
ui->vsync->setChecked(options.vSync());
if (!options.shaders().isEmpty()) {
auto path = options.shaders().first().path();
if (!path.isEmpty())
ui->shader->setPlainText(path);
}
}
OpenGLOptionsDialog::~OpenGLOptionsDialog()
{
delete ui;
}
void
OpenGLOptionsDialog::accept()
{
auto options = new OpenGLOptions();
options->setRenderBehavior(
ui->syncWithVideo->isChecked()
? OpenGLOptions::SyncWithVideo
: OpenGLOptions::TargetFramerate);
options->setFrameRate(ui->targetFps->value());
options->setVSync(ui->vsync->isChecked());
auto shader = ui->shader->toPlainText();
try {
if (!shader.isEmpty())
options->addShader(shader);
else
options->addDefaultShader();
} catch (const std::runtime_error &e) {
delete options;
QMessageBox msgBox(this);
msgBox.setWindowTitle(tr("Shader error"));
msgBox.setText(tr("Could not load shaders."));
msgBox.setInformativeText(tr("More information in details."));
msgBox.setDetailedText(e.what());
msgBox.setIcon(QMessageBox::Critical);
msgBox.setStandardButtons(QMessageBox::Close);
msgBox.setDefaultButton(QMessageBox::Close);
msgBox.setStyleSheet("QTextEdit { min-width: 45em; }");
msgBox.exec();
return;
}
options->save();
emit optionsChanged(options);
QDialog::accept();
}
void
OpenGLOptionsDialog::on_addShader_clicked()
{
auto shader = QFileDialog::getOpenFileName(
this,
QString(),
QString(),
tr("OpenGL Shaders") % util::DlgFilter({ "glsl" }, true));
if (shader.isNull())
return;
ui->shader->setPlainText(shader);
}

View File

@@ -0,0 +1,48 @@
/*
* 86Box A hypervisor and IBM PC system emulator that specializes in
* running old operating systems and software designed for IBM
* PC systems and compatibles from 1981 through fairly recent
* system designs based on the PCI bus.
*
* This file is part of the 86Box distribution.
*
* Header for OpenGL renderer options dialog
*
* Authors:
* Teemu Korhonen
*
* Copyright 2022 Teemu Korhonen
*/
#ifndef QT_OPENGLOPTIONSDIALOG_H
#define QT_OPENGLOPTIONSDIALOG_H
#include <QDialog>
#include "qt_opengloptions.hpp"
namespace Ui {
class OpenGLOptionsDialog;
}
class OpenGLOptionsDialog : public QDialog {
Q_OBJECT
public:
explicit OpenGLOptionsDialog(QWidget *parent, const OpenGLOptions &options);
~OpenGLOptionsDialog();
signals:
void optionsChanged(OpenGLOptions *options);
public slots:
void accept() override;
private:
Ui::OpenGLOptionsDialog *ui;
private slots:
void on_addShader_clicked();
};
#endif // QT_OPENGLOPTIONSDIALOG_H

View File

@@ -0,0 +1,280 @@
<?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0">
<class>OpenGLOptionsDialog</class>
<widget class="QDialog" name="OpenGLOptionsDialog">
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>400</width>
<height>320</height>
</rect>
</property>
<property name="windowTitle">
<string>OpenGL 3.0 renderer options</string>
</property>
<layout class="QVBoxLayout" name="verticalLayout">
<item>
<widget class="QGroupBox" name="groupBox">
<property name="title">
<string>Render behavior</string>
</property>
<layout class="QGridLayout" name="gridLayout_2" columnstretch="3,1">
<item row="1" column="0">
<widget class="QRadioButton" name="syncToFramerate">
<property name="text">
<string>Use target framerate:</string>
</property>
</widget>
</item>
<item row="2" column="1">
<widget class="QSpinBox" name="targetFps">
<property name="enabled">
<bool>false</bool>
</property>
<property name="suffix">
<string> fps</string>
</property>
<property name="minimum">
<number>15</number>
</property>
<property name="maximum">
<number>240</number>
</property>
<property name="value">
<number>60</number>
</property>
</widget>
</item>
<item row="3" column="0">
<widget class="QCheckBox" name="vsync">
<property name="text">
<string>VSync</string>
</property>
</widget>
</item>
<item row="0" column="0">
<widget class="QRadioButton" name="syncWithVideo">
<property name="toolTip">
<string>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p&gt;Render each frame immediately, in sync with the emulated display.&lt;/p&gt;&lt;p&gt;&lt;span style=&quot; font-style:italic;&quot;&gt;This is the recommended option if the shaders in use don't utilize frametime for animated effects.&lt;/span&gt;&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</string>
</property>
<property name="text">
<string>Synchronize with video</string>
</property>
<property name="checked">
<bool>true</bool>
</property>
</widget>
</item>
<item row="2" column="0">
<widget class="QSlider" name="fpsSlider">
<property name="enabled">
<bool>false</bool>
</property>
<property name="minimum">
<number>15</number>
</property>
<property name="maximum">
<number>240</number>
</property>
<property name="value">
<number>60</number>
</property>
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
<property name="invertedAppearance">
<bool>false</bool>
</property>
<property name="tickPosition">
<enum>QSlider::NoTicks</enum>
</property>
</widget>
</item>
</layout>
</widget>
</item>
<item>
<widget class="QGroupBox" name="groupBox_2">
<property name="title">
<string>Shaders</string>
</property>
<layout class="QGridLayout" name="gridLayout" columnstretch="3,1">
<item row="2" column="1">
<widget class="QPushButton" name="removeShader">
<property name="text">
<string>Remove</string>
</property>
</widget>
</item>
<item row="3" column="1">
<spacer name="verticalSpacer">
<property name="orientation">
<enum>Qt::Vertical</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>20</width>
<height>40</height>
</size>
</property>
</spacer>
</item>
<item row="1" column="0" rowspan="3">
<widget class="QTextEdit" name="shader">
<property name="readOnly">
<bool>true</bool>
</property>
<property name="placeholderText">
<string>No shader selected</string>
</property>
</widget>
</item>
<item row="1" column="1" alignment="Qt::AlignTop">
<widget class="QPushButton" name="addShader">
<property name="text">
<string>Browse...</string>
</property>
</widget>
</item>
</layout>
</widget>
</item>
<item>
<widget class="QDialogButtonBox" name="buttonBox">
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
<property name="standardButtons">
<set>QDialogButtonBox::Cancel|QDialogButtonBox::Ok</set>
</property>
</widget>
</item>
</layout>
</widget>
<tabstops>
<tabstop>syncWithVideo</tabstop>
<tabstop>syncToFramerate</tabstop>
<tabstop>fpsSlider</tabstop>
<tabstop>targetFps</tabstop>
<tabstop>vsync</tabstop>
<tabstop>shader</tabstop>
<tabstop>addShader</tabstop>
<tabstop>removeShader</tabstop>
</tabstops>
<resources/>
<connections>
<connection>
<sender>buttonBox</sender>
<signal>accepted()</signal>
<receiver>OpenGLOptionsDialog</receiver>
<slot>accept()</slot>
<hints>
<hint type="sourcelabel">
<x>257</x>
<y>310</y>
</hint>
<hint type="destinationlabel">
<x>157</x>
<y>274</y>
</hint>
</hints>
</connection>
<connection>
<sender>buttonBox</sender>
<signal>rejected()</signal>
<receiver>OpenGLOptionsDialog</receiver>
<slot>reject()</slot>
<hints>
<hint type="sourcelabel">
<x>325</x>
<y>310</y>
</hint>
<hint type="destinationlabel">
<x>286</x>
<y>274</y>
</hint>
</hints>
</connection>
<connection>
<sender>syncToFramerate</sender>
<signal>toggled(bool)</signal>
<receiver>targetFps</receiver>
<slot>setEnabled(bool)</slot>
<hints>
<hint type="sourcelabel">
<x>140</x>
<y>71</y>
</hint>
<hint type="destinationlabel">
<x>380</x>
<y>98</y>
</hint>
</hints>
</connection>
<connection>
<sender>syncToFramerate</sender>
<signal>toggled(bool)</signal>
<receiver>fpsSlider</receiver>
<slot>setEnabled(bool)</slot>
<hints>
<hint type="sourcelabel">
<x>158</x>
<y>66</y>
</hint>
<hint type="destinationlabel">
<x>168</x>
<y>87</y>
</hint>
</hints>
</connection>
<connection>
<sender>fpsSlider</sender>
<signal>valueChanged(int)</signal>
<receiver>targetFps</receiver>
<slot>setValue(int)</slot>
<hints>
<hint type="sourcelabel">
<x>252</x>
<y>90</y>
</hint>
<hint type="destinationlabel">
<x>308</x>
<y>89</y>
</hint>
</hints>
</connection>
<connection>
<sender>targetFps</sender>
<signal>valueChanged(int)</signal>
<receiver>fpsSlider</receiver>
<slot>setValue(int)</slot>
<hints>
<hint type="sourcelabel">
<x>364</x>
<y>93</y>
</hint>
<hint type="destinationlabel">
<x>134</x>
<y>93</y>
</hint>
</hints>
</connection>
<connection>
<sender>removeShader</sender>
<signal>clicked()</signal>
<receiver>shader</receiver>
<slot>clear()</slot>
<hints>
<hint type="sourcelabel">
<x>333</x>
<y>201</y>
</hint>
<hint type="destinationlabel">
<x>235</x>
<y>208</y>
</hint>
</hints>
</connection>
</connections>
</ui>

View File

@@ -0,0 +1,396 @@
/*
* 86Box A hypervisor and IBM PC system emulator that specializes in
* running old operating systems and software designed for IBM
* PC systems and compatibles from 1981 through fairly recent
* system designs based on the PCI bus.
*
* This file is part of the 86Box distribution.
*
* OpenGL renderer for Qt
*
* Authors:
* Teemu Korhonen
*
* Copyright 2022 Teemu Korhonen
*/
#include <QCoreApplication>
#include <QMessageBox>
#include <QOpenGLShaderProgram>
#include <QOpenGLTexture>
#include <QSurfaceFormat>
#include <QOpenGLTexture>
#include <cmath>
#include "qt_opengloptionsdialog.hpp"
#include "qt_openglrenderer.hpp"
OpenGLRenderer::OpenGLRenderer(QWidget *parent)
: QWindow(parent->windowHandle())
, renderTimer(new QTimer(this))
{
renderTimer->setTimerType(Qt::PreciseTimer);
/* TODO: need's more accuracy, maybe target 1ms earlier and spin yield */
connect(renderTimer, &QTimer::timeout, this, &OpenGLRenderer::render);
buf_usage = std::vector<std::atomic_flag>(BUFFERCOUNT);
for (auto &flag : buf_usage)
flag.clear();
setSurfaceType(QWindow::OpenGLSurface);
QSurfaceFormat format;
format.setProfile(QSurfaceFormat::OpenGLContextProfile::CoreProfile);
format.setMajorVersion(3);
format.setMinorVersion(0);
if (QOpenGLContext::openGLModuleType() == QOpenGLContext::LibGLES)
format.setRenderableType(QSurfaceFormat::OpenGLES);
setFormat(format);
context = new QOpenGLContext(this);
context->setFormat(format);
context->create();
parentWidget = parent;
source.setRect(0, 0, INIT_WIDTH, INIT_HEIGHT);
}
OpenGLRenderer::~OpenGLRenderer()
{
finalize();
}
void
OpenGLRenderer::exposeEvent(QExposeEvent *event)
{
Q_UNUSED(event);
if (!isInitialized)
initialize();
}
void
OpenGLRenderer::resizeEvent(QResizeEvent *event)
{
Q_UNUSED(event);
onResize(event->size().width(), event->size().height());
if (notReady())
return;
context->makeCurrent(this);
glViewport(
destination.x(),
destination.y(),
destination.width() * devicePixelRatio(),
destination.height() * devicePixelRatio());
}
bool
OpenGLRenderer::event(QEvent *event)
{
Q_UNUSED(event);
bool res = false;
if (!eventDelegate(event, res))
return QWindow::event(event);
return res;
}
void
OpenGLRenderer::initialize()
{
if (!context->makeCurrent(this)) {
/* TODO: This could be done much better */
QMessageBox::critical((QWidget *) qApp->findChild<QWindow *>(), tr("Error initializing OpenGL"), tr("Error setting OpenGL context. Falling back to software rendering."));
context->doneCurrent();
isFinalized = true;
isInitialized = true;
emit errorInitializing();
return;
}
initializeOpenGLFunctions();
setupExtensions();
setupBuffers();
/* Vertex, texture 2d coordinates and color (white) making a quad as triangle strip */
const GLfloat surface[] = {
-1.f, 1.f, 0.f, 0.f, 1.f, 1.f, 1.f, 1.f,
1.f, 1.f, 1.f, 0.f, 1.f, 1.f, 1.f, 1.f,
-1.f, -1.f, 0.f, 1.f, 1.f, 1.f, 1.f, 1.f,
1.f, -1.f, 1.f, 1.f, 1.f, 1.f, 1.f, 1.f
};
glGenVertexArrays(1, &vertexArrayID);
glBindVertexArray(vertexArrayID);
glGenBuffers(1, &vertexBufferID);
glBindBuffer(GL_ARRAY_BUFFER, vertexBufferID);
glBufferData(GL_ARRAY_BUFFER, sizeof(surface), surface, GL_STATIC_DRAW);
glGenTextures(1, &textureID);
glBindTexture(GL_TEXTURE_2D, textureID);
const GLfloat border_color[] = { 0.f, 0.f, 0.f, 1.f };
glTexParameterfv(GL_TEXTURE_2D, GL_TEXTURE_BORDER_COLOR, border_color);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_BORDER);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_BORDER);
glTexImage2D(GL_TEXTURE_2D, 0, QOpenGLTexture::RGBA8_UNorm, INIT_WIDTH, INIT_HEIGHT, 0, QOpenGLTexture::BGRA, QOpenGLTexture::UInt32_RGBA8_Rev, NULL);
options = new OpenGLOptions(this, true);
applyOptions();
glClearColor(0.f, 0.f, 0.f, 1.f);
glViewport(
destination.x(),
destination.y(),
destination.width(),
destination.height());
isInitialized = true;
emit initialized();
}
void
OpenGLRenderer::finalize()
{
if (isFinalized)
return;
context->makeCurrent(this);
if (hasBufferStorage)
glUnmapBuffer(GL_PIXEL_UNPACK_BUFFER);
glDeleteBuffers(1, &unpackBufferID);
glDeleteTextures(1, &textureID);
glDeleteBuffers(1, &vertexBufferID);
glDeleteVertexArrays(1, &vertexArrayID);
if (!hasBufferStorage && unpackBuffer)
free(unpackBuffer);
context->doneCurrent();
isFinalized = true;
}
QDialog *
OpenGLRenderer::getOptions(QWidget *parent)
{
auto dialog = new OpenGLOptionsDialog(parent, *options);
connect(dialog, &OpenGLOptionsDialog::optionsChanged, this, &OpenGLRenderer::updateOptions);
return dialog;
}
void
OpenGLRenderer::setupExtensions()
{
#ifndef NO_BUFFER_STORAGE
if (context->hasExtension("GL_ARB_buffer_storage")) {
hasBufferStorage = true;
glBufferStorage = (PFNGLBUFFERSTORAGEPROC) context->getProcAddress("glBufferStorage");
}
#endif
}
void
OpenGLRenderer::setupBuffers()
{
glGenBuffers(1, &unpackBufferID);
glBindBuffer(GL_PIXEL_UNPACK_BUFFER, unpackBufferID);
if (hasBufferStorage) {
#ifndef NO_BUFFER_STORAGE
/* Create persistent buffer for pixel transfer. */
glBufferStorage(GL_PIXEL_UNPACK_BUFFER, BUFFERBYTES * BUFFERCOUNT, NULL, GL_MAP_WRITE_BIT | GL_MAP_PERSISTENT_BIT | GL_MAP_COHERENT_BIT);
unpackBuffer = glMapBufferRange(GL_PIXEL_UNPACK_BUFFER, 0, BUFFERBYTES * BUFFERCOUNT, GL_MAP_WRITE_BIT | GL_MAP_PERSISTENT_BIT | GL_MAP_COHERENT_BIT);
#endif
} else {
/* Fallback; create our own buffer. */
unpackBuffer = malloc(BUFFERBYTES * BUFFERCOUNT);
glBufferData(GL_PIXEL_UNPACK_BUFFER, BUFFERBYTES * BUFFERCOUNT, NULL, GL_STREAM_DRAW);
}
}
void
OpenGLRenderer::applyOptions()
{
/* TODO: change detection in options */
if (options->framerate() > 0) {
int interval = (int) ceilf(1000.f / (float) options->framerate());
renderTimer->setInterval(std::chrono::milliseconds(interval));
}
if (options->renderBehavior() == OpenGLOptions::TargetFramerate)
renderTimer->start();
else
renderTimer->stop();
auto format = this->format();
int interval = options->vSync() ? 1 : 0;
if (format.swapInterval() != interval) {
format.setSwapInterval(interval);
setFormat(format);
context->setFormat(format);
}
GLint filter = options->filter() == OpenGLOptions::Linear ? GL_LINEAR : GL_NEAREST;
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, filter);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, filter);
currentFilter = options->filter();
}
void
OpenGLRenderer::applyShader(const OpenGLShaderPass &shader)
{
if (!shader.bind())
return;
if (shader.vertex_coord() != -1) {
glEnableVertexAttribArray(shader.vertex_coord());
glVertexAttribPointer(shader.vertex_coord(), 2, GL_FLOAT, GL_FALSE, 8 * sizeof(GLfloat), 0);
}
if (shader.tex_coord() != -1) {
glEnableVertexAttribArray(shader.tex_coord());
glVertexAttribPointer(shader.tex_coord(), 2, GL_FLOAT, GL_FALSE, 8 * sizeof(GLfloat), (void *) (2 * sizeof(GLfloat)));
}
if (shader.color() != -1) {
glEnableVertexAttribArray(shader.color());
glVertexAttribPointer(shader.color(), 4, GL_FLOAT, GL_FALSE, 8 * sizeof(GLfloat), (void *) (4 * sizeof(GLfloat)));
}
if (shader.mvp_matrix() != -1) {
static const GLfloat mvp[] = {
1.f, 0.f, 0.f, 0.f,
0.f, 1.f, 0.f, 0.f,
0.f, 0.f, 1.f, 0.f,
0.f, 0.f, 0.f, 1.f
};
glUniformMatrix4fv(shader.mvp_matrix(), 1, GL_FALSE, mvp);
}
if (shader.output_size() != -1)
glUniform2f(shader.output_size(), destination.width(), destination.height());
if (shader.input_size() != -1)
glUniform2f(shader.input_size(), source.width(), source.height());
if (shader.texture_size() != -1)
glUniform2f(shader.texture_size(), source.width(), source.height());
if (shader.frame_count() != -1)
glUniform1i(shader.frame_count(), frameCounter);
}
void
OpenGLRenderer::render()
{
context->makeCurrent(this);
if (options->filter() != currentFilter)
applyOptions();
/* TODO: multiple shader passes */
applyShader(options->shaders().first());
glClear(GL_COLOR_BUFFER_BIT);
glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
context->swapBuffers(this);
frameCounter = (frameCounter + 1) & 1023;
}
void
OpenGLRenderer::updateOptions(OpenGLOptions *newOptions)
{
context->makeCurrent(this);
glUseProgram(0);
delete options;
options = newOptions;
options->setParent(this);
applyOptions();
}
std::vector<std::tuple<uint8_t *, std::atomic_flag *>>
OpenGLRenderer::getBuffers()
{
std::vector<std::tuple<uint8_t *, std::atomic_flag *>> buffers;
if (notReady() || !unpackBuffer)
return buffers;
/* Split the buffer area */
for (int i = 0; i < BUFFERCOUNT; i++) {
buffers.push_back(std::make_tuple((uint8_t *) unpackBuffer + BUFFERBYTES * i, &buf_usage[i]));
}
return buffers;
}
void
OpenGLRenderer::onBlit(int buf_idx, int x, int y, int w, int h)
{
if (notReady())
return;
context->makeCurrent(this);
if (source.width() != w || source.height() != h) {
source.setRect(0, 0, w, h);
/* Resize the texture */
glBindBuffer(GL_PIXEL_UNPACK_BUFFER, 0);
glTexImage2D(GL_TEXTURE_2D, 0, (GLenum)QOpenGLTexture::RGBA8_UNorm, source.width(), source.height(), 0, (GLenum)QOpenGLTexture::BGRA, (GLenum)QOpenGLTexture::UInt32_RGBA8_Rev, NULL);
glBindBuffer(GL_PIXEL_UNPACK_BUFFER, unpackBufferID);
}
if (!hasBufferStorage)
glBufferSubData(GL_PIXEL_UNPACK_BUFFER, BUFFERBYTES * buf_idx, h * ROW_LENGTH * sizeof(uint32_t), (uint8_t *) unpackBuffer + BUFFERBYTES * buf_idx);
glPixelStorei(GL_UNPACK_SKIP_PIXELS, BUFFERPIXELS * buf_idx + y * ROW_LENGTH + x);
glPixelStorei(GL_UNPACK_ROW_LENGTH, ROW_LENGTH);
glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, w, h, (GLenum)QOpenGLTexture::BGRA, (GLenum)QOpenGLTexture::UInt32_RGBA8_Rev, NULL);
/* TODO: check if fence sync is implementable here and still has any benefit. */
glFinish();
buf_usage[buf_idx].clear();
if (options->renderBehavior() == OpenGLOptions::SyncWithVideo)
render();
}

View File

@@ -0,0 +1,110 @@
/*
* 86Box A hypervisor and IBM PC system emulator that specializes in
* running old operating systems and software designed for IBM
* PC systems and compatibles from 1981 through fairly recent
* system designs based on the PCI bus.
*
* This file is part of the 86Box distribution.
*
* Header file for OpenGL renderer
*
* Authors:
* Teemu Korhonen
*
* Copyright 2022 Teemu Korhonen
*/
#ifndef QT_OPENGLRENDERER_HPP
#define QT_OPENGLRENDERER_HPP
#if defined Q_OS_MACOS || __arm__
# define NO_BUFFER_STORAGE
#endif
#include <QOpenGLContext>
#include <QOpenGLExtraFunctions>
#include <QResizeEvent>
#include <QTimer>
#include <QWidget>
#include <QWindow>
#if !defined NO_BUFFER_STORAGE && !(QT_VERSION >= QT_VERSION_CHECK(6, 0, 0))
# include <QtOpenGLExtensions/QOpenGLExtensions>
#endif
#include <atomic>
#include <tuple>
#include <vector>
#include "qt_opengloptions.hpp"
#include "qt_renderercommon.hpp"
class OpenGLRenderer : public QWindow, protected QOpenGLExtraFunctions, public RendererCommon {
Q_OBJECT
public:
QOpenGLContext *context;
OpenGLRenderer(QWidget *parent = nullptr);
~OpenGLRenderer();
std::vector<std::tuple<uint8_t *, std::atomic_flag *>> getBuffers() override;
void finalize() override final;
bool hasOptions() const override { return true; }
QDialog *getOptions(QWidget *parent) override;
signals:
void initialized();
void errorInitializing();
public slots:
void onBlit(int buf_idx, int x, int y, int w, int h);
protected:
void exposeEvent(QExposeEvent *event) override;
void resizeEvent(QResizeEvent *event) override;
bool event(QEvent *event) override;
private:
static constexpr int INIT_WIDTH = 640;
static constexpr int INIT_HEIGHT = 400;
static constexpr int ROW_LENGTH = 2048;
static constexpr int BUFFERPIXELS = 4194304;
static constexpr int BUFFERBYTES = 16777216; /* Pixel is 4 bytes. */
static constexpr int BUFFERCOUNT = 3; /* How many buffers to use for pixel transfer (2-3 is commonly recommended). */
OpenGLOptions *options;
QTimer *renderTimer;
bool isInitialized = false;
bool isFinalized = false;
GLuint unpackBufferID = 0;
GLuint vertexArrayID = 0;
GLuint vertexBufferID = 0;
GLuint textureID = 0;
int frameCounter = 0;
OpenGLOptions::FilterType currentFilter;
void *unpackBuffer = nullptr;
void initialize();
void setupExtensions();
void setupBuffers();
void applyOptions();
void applyShader(const OpenGLShaderPass &shader);
bool notReady() const { return !isInitialized || isFinalized; }
/* GL_ARB_buffer_storage */
bool hasBufferStorage = false;
#ifndef NO_BUFFER_STORAGE
PFNGLBUFFERSTORAGEPROC glBufferStorage = nullptr;
#endif
private slots:
void render();
void updateOptions(OpenGLOptions *newOptions);
};
#endif

View File

@@ -32,6 +32,7 @@
#include <QTemporaryFile>
#include <QCoreApplication>
#include <QDateTime>
#include <QLocalSocket>
#include <QLibrary>
#include <QElapsedTimer>
@@ -234,15 +235,25 @@ plat_path_abs(char *path)
#endif
}
void
plat_path_normalize(char* path)
{
while (*path++ != 0)
{
if (*path == '\\') *path = '/';
}
}
void
plat_path_slash(char *path)
{
auto len = strlen(path);
auto separator = QDir::separator().toLatin1();
auto separator = '/';
if (path[len-1] != separator) {
path[len] = separator;
path[len+1] = 0;
}
plat_path_normalize(path);
}
void

View File

@@ -1,28 +1,37 @@
#pragma once
#include <QRect>
#include <QImage>
#include <QDialog>
#include <QEvent>
#include <QImage>
#include <QRect>
#include <QWidget>
#include <vector>
#include <tuple>
#include <atomic>
#include <memory>
#include <tuple>
#include <vector>
class QWidget;
class RendererCommon
{
class RendererCommon {
public:
RendererCommon();
void onResize(int width, int height);
virtual std::vector<std::tuple<uint8_t*, std::atomic_flag*>> getBuffers() = 0;
protected:
bool eventDelegate(QEvent* event, bool& result);
void onResize(int width, int height);
virtual void finalize() { }
QRect source, destination;
QWidget* parentWidget{nullptr};
virtual std::vector<std::tuple<uint8_t *, std::atomic_flag *>> getBuffers() = 0;
/* Does renderer implement options dialog */
virtual bool hasOptions() const { return false; }
/* Returns options dialog for renderer */
virtual QDialog *getOptions(QWidget *parent) { return nullptr; }
protected:
bool eventDelegate(QEvent *event, bool &result);
QRect source, destination;
QWidget *parentWidget { nullptr };
std::vector<std::atomic_flag> buf_usage;
};

View File

@@ -21,8 +21,9 @@
#include "qt_rendererstack.hpp"
#include "ui_qt_rendererstack.h"
#include "qt_softwarerenderer.hpp"
#include "qt_hardwarerenderer.hpp"
#include "qt_openglrenderer.hpp"
#include "qt_softwarerenderer.hpp"
#include "qt_mainwindow.hpp"
#include "qt_util.hpp"
@@ -32,34 +33,33 @@
#include <QScreen>
#ifdef __APPLE__
#include <CoreGraphics/CoreGraphics.h>
# include <CoreGraphics/CoreGraphics.h>
#endif
extern "C"
{
extern "C" {
#include <86box/mouse.h>
#include <86box/plat.h>
#include <86box/video.h>
}
extern MainWindow* main_window;
RendererStack::RendererStack(QWidget *parent) :
QStackedWidget(parent),
ui(new Ui::RendererStack)
extern MainWindow *main_window;
RendererStack::RendererStack(QWidget *parent)
: QStackedWidget(parent)
, ui(new Ui::RendererStack)
{
ui->setupUi(this);
#ifdef __unix__
#ifdef WAYLAND
# ifdef WAYLAND
if (QApplication::platformName().contains("wayland")) {
wl_init();
}
#endif
#ifdef EVDEV_INPUT
# endif
# ifdef EVDEV_INPUT
if (QApplication::platformName() == "eglfs") {
evdev_init();
}
#endif
# endif
if (QApplication::platformName() == "xcb") {
extern void xinput2_init();
xinput2_init();
@@ -76,8 +76,7 @@ extern "C" void macos_poll_mouse();
void
qt_mouse_capture(int on)
{
if (!on)
{
if (!on) {
mouse_capture = 0;
QApplication::setOverrideCursor(Qt::ArrowCursor);
#ifdef __APPLE__
@@ -93,162 +92,193 @@ qt_mouse_capture(int on)
return;
}
void RendererStack::mousePoll()
void
RendererStack::mousePoll()
{
#ifdef __APPLE__
return macos_poll_mouse();
#else /* !defined __APPLE__ */
mouse_x = mousedata.deltax;
mouse_y = mousedata.deltay;
mouse_z = mousedata.deltaz;
mouse_x = mousedata.deltax;
mouse_y = mousedata.deltay;
mouse_z = mousedata.deltaz;
mousedata.deltax = mousedata.deltay = mousedata.deltaz = 0;
mouse_buttons = mousedata.mousebuttons;
mouse_buttons = mousedata.mousebuttons;
#ifdef __unix__
#ifdef WAYLAND
# ifdef __unix__
# ifdef WAYLAND
if (QApplication::platformName().contains("wayland"))
wl_mouse_poll();
#endif
# endif
#ifdef EVDEV_INPUT
if (QApplication::platformName() == "eglfs") evdev_mouse_poll();
# ifdef EVDEV_INPUT
if (QApplication::platformName() == "eglfs")
evdev_mouse_poll();
else
#endif
if (QApplication::platformName() == "xcb")
{
# endif
if (QApplication::platformName() == "xcb") {
extern void xinput2_poll();
xinput2_poll();
}
#endif /* defined __unix__ */
#endif /* !defined __APPLE__ */
# endif /* defined __unix__ */
#endif /* !defined __APPLE__ */
}
int ignoreNextMouseEvent = 1;
void RendererStack::mouseReleaseEvent(QMouseEvent *event)
void
RendererStack::mouseReleaseEvent(QMouseEvent *event)
{
if (this->geometry().contains(event->pos()) && event->button() == Qt::LeftButton && !mouse_capture && (isMouseDown & 1))
{
if (this->geometry().contains(event->pos()) && event->button() == Qt::LeftButton && !mouse_capture && (isMouseDown & 1)) {
plat_mouse_capture(1);
this->setCursor(Qt::BlankCursor);
if (!ignoreNextMouseEvent) ignoreNextMouseEvent++; // Avoid jumping cursor when moved.
if (!ignoreNextMouseEvent)
ignoreNextMouseEvent++; // Avoid jumping cursor when moved.
isMouseDown &= ~1;
return;
}
if (mouse_capture && event->button() == Qt::MiddleButton && mouse_get_buttons() < 3)
{
if (mouse_capture && event->button() == Qt::MiddleButton && mouse_get_buttons() < 3) {
plat_mouse_capture(0);
this->setCursor(Qt::ArrowCursor);
isMouseDown &= ~1;
return;
}
if (mouse_capture)
{
if (mouse_capture) {
mousedata.mousebuttons &= ~event->button();
}
isMouseDown &= ~1;
}
void RendererStack::mousePressEvent(QMouseEvent *event)
void
RendererStack::mousePressEvent(QMouseEvent *event)
{
isMouseDown |= 1;
if (mouse_capture)
{
if (mouse_capture) {
mousedata.mousebuttons |= event->button();
}
event->accept();
}
void RendererStack::wheelEvent(QWheelEvent *event)
void
RendererStack::wheelEvent(QWheelEvent *event)
{
if (mouse_capture)
{
if (mouse_capture) {
mousedata.deltaz += event->pixelDelta().y();
}
}
void RendererStack::mouseMoveEvent(QMouseEvent *event)
void
RendererStack::mouseMoveEvent(QMouseEvent *event)
{
if (QApplication::platformName().contains("wayland"))
{
if (QApplication::platformName().contains("wayland")) {
event->accept();
return;
}
if (!mouse_capture) { event->ignore(); return; }
if (!mouse_capture) {
event->ignore();
return;
}
#ifdef __APPLE__
event->accept();
return;
#else
static QPoint oldPos = QCursor::pos();
if (ignoreNextMouseEvent) { oldPos = event->pos(); ignoreNextMouseEvent--; event->accept(); return; }
if (ignoreNextMouseEvent) {
oldPos = event->pos();
ignoreNextMouseEvent--;
event->accept();
return;
}
mousedata.deltax += event->pos().x() - oldPos.x();
mousedata.deltay += event->pos().y() - oldPos.y();
if (QApplication::platformName() == "eglfs")
{
leaveEvent((QEvent*)event);
if (QApplication::platformName() == "eglfs") {
leaveEvent((QEvent *) event);
ignoreNextMouseEvent--;
}
QCursor::setPos(mapToGlobal(QPoint(width() / 2, height() / 2)));
ignoreNextMouseEvent = 2;
oldPos = event->pos();
oldPos = event->pos();
#endif
}
void RendererStack::leaveEvent(QEvent* event)
void
RendererStack::leaveEvent(QEvent *event)
{
if (QApplication::platformName().contains("wayland"))
{
if (QApplication::platformName().contains("wayland")) {
event->accept();
return;
}
if (!mouse_capture) return;
if (!mouse_capture)
return;
ignoreNextMouseEvent = 2;
event->accept();
}
void RendererStack::switchRenderer(Renderer renderer) {
void
RendererStack::switchRenderer(Renderer renderer)
{
startblit();
if (current) {
rendererWindow->finalize();
removeWidget(current.get());
}
disconnect(this, &RendererStack::blitToRenderer, nullptr, nullptr);
/* Create new renderer only after previous is destroyed! */
connect(current.get(), &QObject::destroyed, [this, renderer](QObject *) { createRenderer(renderer); });
current.release()->deleteLater();
} else {
createRenderer(renderer);
}
}
void
RendererStack::createRenderer(Renderer renderer)
{
switch (renderer) {
case Renderer::Software:
{
auto sw = new SoftwareRenderer(this);
rendererWindow = sw;
connect(this, &RendererStack::blitToRenderer, sw, &SoftwareRenderer::onBlit, Qt::QueuedConnection);
current.reset(this->createWindowContainer(sw, this));
case Renderer::Software:
{
auto sw = new SoftwareRenderer(this);
rendererWindow = sw;
connect(this, &RendererStack::blitToRenderer, sw, &SoftwareRenderer::onBlit, Qt::QueuedConnection);
current.reset(this->createWindowContainer(sw, this));
}
break;
case Renderer::OpenGL:
{
this->createWinId();
auto hw = new HardwareRenderer(this);
rendererWindow = hw;
connect(this, &RendererStack::blitToRenderer, hw, &HardwareRenderer::onBlit, Qt::QueuedConnection);
current.reset(this->createWindowContainer(hw, this));
break;
}
case Renderer::OpenGLES:
{
this->createWinId();
auto hw = new HardwareRenderer(this, HardwareRenderer::RenderType::OpenGLES);
rendererWindow = hw;
connect(this, &RendererStack::blitToRenderer, hw, &HardwareRenderer::onBlit, Qt::QueuedConnection);
current.reset(this->createWindowContainer(hw, this));
break;
}
case Renderer::OpenGL3:
{
this->createWinId();
auto hw = new OpenGLRenderer(this);
rendererWindow = hw;
connect(this, &RendererStack::blitToRenderer, hw, &OpenGLRenderer::onBlit, Qt::QueuedConnection);
connect(hw, &OpenGLRenderer::initialized, [=]() {
/* Buffers are awailable only after initialization. */
imagebufs = rendererWindow->getBuffers();
endblit();
emit rendererChanged();
});
connect(hw, &OpenGLRenderer::errorInitializing, [=]() {
/* Renderer could initialize, fallback to software. */
endblit();
QTimer::singleShot(0, this, [this]() { switchRenderer(Renderer::Software); });
});
current.reset(this->createWindowContainer(hw, this));
break;
}
}
break;
case Renderer::OpenGL:
{
this->createWinId();
auto hw = new HardwareRenderer(this);
rendererWindow = hw;
connect(this, &RendererStack::blitToRenderer, hw, &HardwareRenderer::onBlit, Qt::QueuedConnection);
current.reset(this->createWindowContainer(hw, this));
break;
}
case Renderer::OpenGLES:
{
this->createWinId();
auto hw = new HardwareRenderer(this, HardwareRenderer::RenderType::OpenGLES);
rendererWindow = hw;
connect(this, &RendererStack::blitToRenderer, hw, &HardwareRenderer::onBlit, Qt::QueuedConnection);
current.reset(this->createWindowContainer(hw, this));
break;
}
case Renderer::OpenGL3:
{
this->createWinId();
auto hw = new HardwareRenderer(this, HardwareRenderer::RenderType::OpenGL3);
rendererWindow = hw;
connect(this, &RendererStack::blitToRenderer, hw, &HardwareRenderer::onBlit, Qt::QueuedConnection);
current.reset(this->createWindowContainer(hw, this));
break;
}
}
imagebufs = std::move(rendererWindow->getBuffers());
current->setFocusPolicy(Qt::NoFocus);
current->setFocusProxy(this);
@@ -256,31 +286,35 @@ void RendererStack::switchRenderer(Renderer renderer) {
this->setStyleSheet("background-color: black");
endblit();
currentBuf = 0;
if (renderer != Renderer::OpenGL3) {
imagebufs = rendererWindow->getBuffers();
endblit();
emit rendererChanged();
}
}
// called from blitter thread
void RendererStack::blit(int x, int y, int w, int h)
void
RendererStack::blit(int x, int y, int w, int h)
{
if ((w <= 0) || (h <= 0) || (w > 2048) || (h > 2048) || (buffer32 == NULL) || std::get<std::atomic_flag*>(imagebufs[currentBuf])->test_and_set())
{
if ((w <= 0) || (h <= 0) || (w > 2048) || (h > 2048) || (buffer32 == NULL) || std::get<std::atomic_flag *>(imagebufs[currentBuf])->test_and_set()) {
video_blit_complete();
return;
}
sx = x;
sy = y;
sw = this->w = w;
sh = this->h = h;
uint8_t* imagebits = std::get<uint8_t*>(imagebufs[currentBuf]);
for (int y1 = y; y1 < (y + h); y1++)
{
sh = this->h = h;
uint8_t *imagebits = std::get<uint8_t *>(imagebufs[currentBuf]);
for (int y1 = y; y1 < (y + h); y1++) {
auto scanline = imagebits + (y1 * (2048) * 4) + (x * 4);
video_copy(scanline, &(buffer32->line[y1][x]), w * 4);
}
if (screenshots)
{
video_screenshot((uint32_t *)imagebits, x, y, 2048);
if (screenshots) {
video_screenshot((uint32_t *) imagebits, x, y, 2048);
}
video_blit_complete();
emit blitToRenderer(currentBuf, sx, sy, sw, sh);

View File

@@ -1,37 +1,41 @@
#ifndef QT_RENDERERCONTAINER_HPP
#define QT_RENDERERCONTAINER_HPP
#include <QStackedWidget>
#include <QKeyEvent>
#include <QDialog>
#include <QEvent>
#include <memory>
#include <vector>
#include <QKeyEvent>
#include <QStackedWidget>
#include <QWidget>
#include <atomic>
#include <memory>
#include <tuple>
#include <vector>
#include "qt_renderercommon.hpp"
namespace Ui {
class RendererStack;
}
class RendererCommon;
class RendererStack : public QStackedWidget
{
class RendererStack : public QStackedWidget {
Q_OBJECT
public:
explicit RendererStack(QWidget *parent = nullptr);
~RendererStack();
void mousePressEvent(QMouseEvent* event) override;
void mouseReleaseEvent(QMouseEvent* event) override;
void mouseMoveEvent(QMouseEvent* event) override;
void mousePressEvent(QMouseEvent *event) override;
void mouseReleaseEvent(QMouseEvent *event) override;
void mouseMoveEvent(QMouseEvent *event) override;
void wheelEvent(QWheelEvent *event) override;
void leaveEvent(QEvent *event) override;
void keyPressEvent(QKeyEvent* event) override
void keyPressEvent(QKeyEvent *event) override
{
event->ignore();
}
void keyReleaseEvent(QKeyEvent* event) override
void keyReleaseEvent(QKeyEvent *event) override
{
event->ignore();
}
@@ -44,15 +48,33 @@ public:
};
void switchRenderer(Renderer renderer);
RendererCommon* rendererWindow{nullptr};
/* Does current renderer implement options dialog */
bool hasOptions() const { return rendererWindow ? rendererWindow->hasOptions() : false; }
/* Returns options dialog for current renderer */
QDialog *getOptions(QWidget *parent) { return rendererWindow ? rendererWindow->getOptions(parent) : nullptr; }
void setFocusRenderer()
{
if (current)
current->setFocus();
}
void onResize(int width, int height)
{
if (rendererWindow)
rendererWindow->onResize(width, height);
}
signals:
void blitToRenderer(int buf_idx, int x, int y, int w, int h);
void rendererChanged();
public slots:
void blit(int x, int y, int w, int h);
void mousePoll();
private:
void createRenderer(Renderer renderer);
Ui::RendererStack *ui;
struct mouseinputdata {
@@ -63,13 +85,13 @@ private:
int x, y, w, h, sx, sy, sw, sh;
int currentBuf = 0;
int currentBuf = 0;
int isMouseDown = 0;
std::vector<std::tuple<uint8_t*, std::atomic_flag*>> imagebufs;
std::vector<std::tuple<uint8_t *, std::atomic_flag *>> imagebufs;
RendererCommon *rendererWindow { nullptr };
std::unique_ptr<QWidget> current;
friend class MainWindow;
};
#endif // QT_RENDERERCONTAINER_HPP

View File

@@ -202,6 +202,12 @@
</item>
<item>
<widget class="QGroupBox" name="groupBox">
<property name="sizePolicy">
<sizepolicy hsizetype="Maximum" vsizetype="Preferred">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="title">
<string>Time synchronization</string>
</property>

View File

@@ -53,8 +53,8 @@ void SoftwareRenderer::onBlit(int buf_idx, int x, int y, int w, int h) {
cur_image = buf_idx;
buf_usage[(buf_idx + 1) % 2].clear();
source.setRect(x, y, w, h),
source.setRect(x, y, w, h);
update();
}

View File

@@ -0,0 +1,79 @@
/*
* 86Box A hypervisor and IBM PC system emulator that specializes in
* running old operating systems and software designed for IBM
* PC systems and compatibles from 1981 through fairly recent
* system designs based on the PCI bus.
*
* This file is part of the 86Box distribution.
*
* Source file for Unix VM-managers (client-side)
*
* Authors:
* Teemu Korhonen
Cacodemon345
*
* Copyright 2022 Teemu Korhonen
* Copyright 2022 Cacodemon345
*/
#include "qt_unixmanagerfilter.hpp"
UnixManagerSocket::UnixManagerSocket(QObject* obj)
: QLocalSocket(obj)
{
connect(this, &QLocalSocket::readyRead, this, &UnixManagerSocket::readyToRead);
}
void UnixManagerSocket::readyToRead()
{
if (canReadLine())
{
QByteArray line = readLine();
if (line.size())
{
line.resize(line.size() - 2);
line.push_back('\0');
if (line == "showsettings")
{
emit showsettings();
}
else if (line == "pause")
{
emit pause();
}
else if (line == "cad")
{
emit ctrlaltdel();
}
else if (line == "reset")
{
emit resetVM();
}
else if (line == "shutdownnoprompt")
{
emit force_shutdown();
}
else if (line == "shutdown")
{
emit request_shutdown();
}
}
}
}
bool UnixManagerSocket::eventFilter(QObject *obj, QEvent *event)
{
if (state() == QLocalSocket::ConnectedState)
{
if (event->type() == QEvent::WindowBlocked)
{
write(QByteArray{"1"});
}
else if (event->type() == QEvent::WindowUnblocked)
{
write(QByteArray{"0"});
}
}
return QObject::eventFilter(obj, event);
}

View File

@@ -0,0 +1,50 @@
/*
* 86Box A hypervisor and IBM PC system emulator that specializes in
* running old operating systems and software designed for IBM
* PC systems and compatibles from 1981 through fairly recent
* system designs based on the PCI bus.
*
* This file is part of the 86Box distribution.
*
* Header file for Unix VM-managers (client-side)
*
* Authors:
* Teemu Korhonen
Cacodemon345
*
* Copyright 2022 Teemu Korhonen
* Copyright 2022 Cacodemon345
*/
#ifndef QT_UNIXMANAGERFILTER_HPP
#define QT_UNIXMANAGERFILTER_HPP
#include <QObject>
#include <QLocalSocket>
#include <QEvent>
/*
* Filters messages from VM-manager and
* window blocked events to notify about open modal dialogs.
*/
class UnixManagerSocket : public QLocalSocket
{
Q_OBJECT
public:
UnixManagerSocket(QObject* object = nullptr);
signals:
void pause();
void ctrlaltdel();
void showsettings();
void resetVM();
void request_shutdown();
void force_shutdown();
void dialogstatus(bool open);
protected:
bool eventFilter(QObject *obj, QEvent *event) override;
protected slots:
void readyToRead();
};
#endif

View File

@@ -77,6 +77,7 @@ static SCSI_CARD scsi_cards[] = {
{ &buslogic_542bh_device, },
{ &buslogic_545s_device, },
{ &buslogic_545c_device, },
{ &scsi_ls2000_device, },
{ &scsi_lcs6821n_device, },
{ &scsi_rt1000b_device, },
{ &scsi_t128_device, },

View File

@@ -1138,366 +1138,186 @@ aha_init(const device_t *info)
return(dev);
}
// clang-format off
static const device_config_t aha_154xb_config[] = {
{
"base", "Address", CONFIG_HEX16, "", 0x334, "", { 0 },
{
"base", "Address", CONFIG_HEX16, "", 0x334, "", { 0 },
{
{
"None", 0
},
{
"0x330", 0x330
},
{
"0x334", 0x334
},
{
"0x230", 0x230
},
{
"0x234", 0x234
},
{
"0x130", 0x130
},
{
"0x134", 0x134
},
{
""
}
},
{ "None", 0 },
{ "0x330", 0x330 },
{ "0x334", 0x334 },
{ "0x230", 0x230 },
{ "0x234", 0x234 },
{ "0x130", 0x130 },
{ "0x134", 0x134 },
{ "" }
},
},
{
"irq", "IRQ", CONFIG_SELECTION, "", 11, "", { 0 },
{
"irq", "IRQ", CONFIG_SELECTION, "", 11, "", { 0 },
{
{
"IRQ 9", 9
},
{
"IRQ 10", 10
},
{
"IRQ 11", 11
},
{
"IRQ 12", 12
},
{
"IRQ 14", 14
},
{
"IRQ 15", 15
},
{
""
}
},
{ "IRQ 9", 9 },
{ "IRQ 10", 10 },
{ "IRQ 11", 11 },
{ "IRQ 12", 12 },
{ "IRQ 14", 14 },
{ "IRQ 15", 15 },
{ "" }
},
},
{
"dma", "DMA channel", CONFIG_SELECTION, "", 6, "", { 0 },
{
"dma", "DMA channel", CONFIG_SELECTION, "", 6, "", { 0 },
{
{
"DMA 5", 5
},
{
"DMA 6", 6
},
{
"DMA 7", 7
},
{
""
}
},
{ "DMA 5", 5 },
{ "DMA 6", 6 },
{ "DMA 7", 7 },
{ "" }
},
},
{
"hostid", "Host ID", CONFIG_SELECTION, "", 7, "", { 0 },
{
"hostid", "Host ID", CONFIG_SELECTION, "", 7, "", { 0 },
{
{
"0", 0
},
{
"1", 1
},
{
"2", 2
},
{
"3", 3
},
{
"4", 4
},
{
"5", 5
},
{
"6", 6
},
{
"7", 7
},
{
""
}
},
{ "0", 0 },
{ "1", 1 },
{ "2", 2 },
{ "3", 3 },
{ "4", 4 },
{ "5", 5 },
{ "6", 6 },
{ "7", 7 },
{ "" }
},
},
{
"bios_addr", "BIOS Address", CONFIG_HEX20, "", 0, "", { 0 },
{
"bios_addr", "BIOS Address", CONFIG_HEX20, "", 0, "", { 0 },
{
{
"Disabled", 0
},
{
"C800H", 0xc8000
},
{
"D000H", 0xd0000
},
{
"D800H", 0xd8000
},
{
"DC00H", 0xdc000
},
{
""
}
},
{ "Disabled", 0 },
{ "C800H", 0xc8000 },
{ "D000H", 0xd0000 },
{ "D800H", 0xd8000 },
{ "DC00H", 0xdc000 },
{ "" }
},
{
"", "", -1
}
},
{
"", "", -1
}
};
static const device_config_t aha_154x_config[] = {
{
"base", "Address", CONFIG_HEX16, "", 0x334, "", { 0 },
{
"base", "Address", CONFIG_HEX16, "", 0x334, "", { 0 },
{
{
"None", 0
},
{
"0x330", 0x330
},
{
"0x334", 0x334
},
{
"0x230", 0x230
},
{
"0x234", 0x234
},
{
"0x130", 0x130
},
{
"0x134", 0x134
},
{
""
}
},
{ "None", 0 },
{ "0x330", 0x330 },
{ "0x334", 0x334 },
{ "0x230", 0x230 },
{ "0x234", 0x234 },
{ "0x130", 0x130 },
{ "0x134", 0x134 },
{ "" }
},
},
{
"irq", "IRQ", CONFIG_SELECTION, "", 11, "", { 0 },
{
"irq", "IRQ", CONFIG_SELECTION, "", 11, "", { 0 },
{
{
"IRQ 9", 9
},
{
"IRQ 10", 10
},
{
"IRQ 11", 11
},
{
"IRQ 12", 12
},
{
"IRQ 14", 14
},
{
"IRQ 15", 15
},
{
""
}
},
{ "IRQ 9", 9 },
{ "IRQ 10", 10 },
{ "IRQ 11", 11 },
{ "IRQ 12", 12 },
{ "IRQ 14", 14 },
{ "IRQ 15", 15 },
{ "" }
},
},
{
"dma", "DMA channel", CONFIG_SELECTION, "", 6, "", { 0 },
{
"dma", "DMA channel", CONFIG_SELECTION, "", 6, "", { 0 },
{
{
"DMA 5", 5
},
{
"DMA 6", 6
},
{
"DMA 7", 7
},
{
""
}
},
{ "DMA 5", 5 },
{ "DMA 6", 6 },
{ "DMA 7", 7 },
{ "" }
},
},
{
"bios_addr", "BIOS Address", CONFIG_HEX20, "", 0, "", { 0 },
{
"bios_addr", "BIOS Address", CONFIG_HEX20, "", 0, "", { 0 },
{
{
"Disabled", 0
},
{
"C800H", 0xc8000
},
{
"D000H", 0xd0000
},
{
"D800H", 0xd8000
},
{
"DC00H", 0xdc000
},
{
""
}
},
{ "Disabled", 0 },
{ "C800H", 0xc8000 },
{ "D000H", 0xd0000 },
{ "D800H", 0xd8000 },
{ "DC00H", 0xdc000 },
{ "" }
},
},
{
"", "", -1
}
{
"", "", -1
}
};
static const device_config_t aha_154xcf_config[] = {
{
"base", "Address", CONFIG_HEX16, "", 0x334, "", { 0 },
{
"base", "Address", CONFIG_HEX16, "", 0x334, "", { 0 },
{
{
"None", 0
},
{
"0x330", 0x330
},
{
"0x334", 0x334
},
{
"0x230", 0x230
},
{
"0x234", 0x234
},
{
"0x130", 0x130
},
{
"0x134", 0x134
},
{
""
}
},
{ "None", 0 },
{ "0x330", 0x330 },
{ "0x334", 0x334 },
{ "0x230", 0x230 },
{ "0x234", 0x234 },
{ "0x130", 0x130 },
{ "0x134", 0x134 },
{ "" }
},
},
{
"irq", "IRQ", CONFIG_SELECTION, "", 11, "", { 0 },
{
"irq", "IRQ", CONFIG_SELECTION, "", 11, "", { 0 },
{
{
"IRQ 9", 9
},
{
"IRQ 10", 10
},
{
"IRQ 11", 11
},
{
"IRQ 12", 12
},
{
"IRQ 14", 14
},
{
"IRQ 15", 15
},
{
""
}
},
{ "IRQ 9", 9 },
{ "IRQ 10", 10 },
{ "IRQ 11", 11 },
{ "IRQ 12", 12 },
{ "IRQ 14", 14 },
{ "IRQ 15", 15 },
{ "" }
},
},
{
"dma", "DMA channel", CONFIG_SELECTION, "", 6, "", { 0 },
{
"dma", "DMA channel", CONFIG_SELECTION, "", 6, "", { 0 },
{
{
"DMA 5", 5
},
{
"DMA 6", 6
},
{
"DMA 7", 7
},
{
""
}
},
{ "DMA 5", 5 },
{ "DMA 6", 6 },
{ "DMA 7", 7 },
{ "" }
},
},
{
"bios_addr", "BIOS Address", CONFIG_HEX20, "", 0, "", { 0 },
{
"bios_addr", "BIOS Address", CONFIG_HEX20, "", 0, "", { 0 },
{
{
"Disabled", 0
},
{
"C800H", 0xc8000
},
{
"CC00H", 0xcc000
},
{
"D000H", 0xd0000
},
{
"D400H", 0xd4000
},
{
"D800H", 0xd8000
},
{
"DC00H", 0xdc000
},
{
""
}
},
{ "Disabled", 0 },
{ "C800H", 0xc8000 },
{ "CC00H", 0xcc000 },
{ "D000H", 0xd0000 },
{ "D400H", 0xd4000 },
{ "D800H", 0xd8000 },
{ "DC00H", 0xdc000 },
{ "" }
},
{
},
{
"fdc_addr", "FDC address", CONFIG_HEX16, "", 0, "", { 0 },
{
{
"None", 0
},
{
"0x3f0", 0x3f0
},
{
"0x370", 0x370
},
{
""
}
},
{
{ "None", 0 },
{ "0x3f0", 0x3f0 },
{ "0x370", 0x370 },
{ "" }
},
{
"", "", -1
}
},
{
"", "", -1
}
};
// clang-format on
const device_t aha154xa_device = {
"Adaptec AHA-154xA",

View File

@@ -1802,111 +1802,59 @@ buslogic_init(const device_t *info)
return(dev);
}
// clang-format off
static const device_config_t BT_ISA_Config[] = {
{
"base", "Address", CONFIG_HEX16, "", 0x334, "", { 0 },
{
"base", "Address", CONFIG_HEX16, "", 0x334, "", { 0 },
{
{
"0x330", 0x330
},
{
"0x334", 0x334
},
{
"0x230", 0x230
},
{
"0x234", 0x234
},
{
"0x130", 0x130
},
{
"0x134", 0x134
},
{
"", 0
}
},
{ "0x330", 0x330 },
{ "0x334", 0x334 },
{ "0x230", 0x230 },
{ "0x234", 0x234 },
{ "0x130", 0x130 },
{ "0x134", 0x134 },
{ "", 0 }
},
},
{
"irq", "IRQ", CONFIG_SELECTION, "", 11, "", { 0 },
{
"irq", "IRQ", CONFIG_SELECTION, "", 11, "", { 0 },
{
{
"IRQ 9", 9
},
{
"IRQ 10", 10
},
{
"IRQ 11", 11
},
{
"IRQ 12", 12
},
{
"IRQ 14", 14
},
{
"IRQ 15", 15
},
{
"", 0
}
},
{ "IRQ 9", 9 },
{ "IRQ 10", 10 },
{ "IRQ 11", 11 },
{ "IRQ 12", 12 },
{ "IRQ 14", 14 },
{ "IRQ 15", 15 },
{ "", 0 }
},
},
{
"dma", "DMA channel", CONFIG_SELECTION, "", 6, "", { 0 },
{
"dma", "DMA channel", CONFIG_SELECTION, "", 6, "", { 0 },
{
{
"DMA 5", 5
},
{
"DMA 6", 6
},
{
"DMA 7", 7
},
{
"", 0
}
},
{ "DMA 5", 5 },
{ "DMA 6", 6 },
{ "DMA 7", 7 },
{ "", 0 }
},
},
{
"bios_addr", "BIOS Address", CONFIG_HEX20, "", 0, "", { 0 },
{
"bios_addr", "BIOS Address", CONFIG_HEX20, "", 0, "", { 0 },
{
{
"Disabled", 0
},
{
"C800H", 0xc8000
},
{
"D000H", 0xd0000
},
{
"D800H", 0xd8000
},
{
"", 0
}
},
{ "Disabled", 0 },
{ "C800H", 0xc8000 },
{ "D000H", 0xd0000 },
{ "D800H", 0xd8000 },
{ "", 0 }
},
{
"", "", -1
}
},
{ "", "", -1 }
};
static const device_config_t BT958D_Config[] = {
{
"bios", "Enable BIOS", CONFIG_BINARY, "", 0
},
{
"", "", -1
}
{ "bios", "Enable BIOS", CONFIG_BINARY, "", 0 },
{ "", "", -1 }
};
// clang-format on
const device_t buslogic_542b_device = {
"BusLogic BT-542B ISA",

View File

@@ -48,6 +48,7 @@
#define RT1000B_820R_ROM "roms/scsi/ncr5380/RTBIOS82.ROM"
#define T130B_ROM "roms/scsi/ncr5380/trantor_t130b_bios_v2.14.bin"
#define T128_ROM "roms/scsi/ncr5380/trantor_t128_bios_v1.12.bin"
#define COREL_LS2000_ROM "roms/scsi/ncr5380/Corel LS2000 - BIOS ROM - Ver 1.65.bin"
#define NCR_CURDATA 0 /* current SCSI data (read only) */
@@ -657,14 +658,16 @@ ncr_write(uint16_t port, uint8_t val, void *priv)
/*a Write 6/10 has occurred, start the timer when the block count is loaded*/
ncr->dma_mode = DMA_SEND;
if (ncr_dev->type == 3) {
memset(ncr_dev->t128.buffer, 0, MIN(512, dev->buffer_length));
if (dev->buffer_length > 0) {
memset(ncr_dev->t128.buffer, 0, MIN(512, dev->buffer_length));
ncr_log("DMA send timer start, enabled? = %i\n", timer_is_enabled(&ncr_dev->timer));
ncr_dev->t128.block_count = dev->buffer_length >> 9;
ncr_dev->t128.block_loaded = 1;
ncr_log("DMA send timer start, enabled? = %i\n", timer_is_enabled(&ncr_dev->timer));
ncr_dev->t128.block_count = dev->buffer_length >> 9;
ncr_dev->t128.block_loaded = 1;
ncr_dev->t128.host_pos = 0;
ncr_dev->t128.status |= 0x04;
ncr_dev->t128.host_pos = 0;
ncr_dev->t128.status |= 0x04;
}
} else {
if ((ncr->mode & MODE_DMA) && !timer_is_enabled(&ncr_dev->timer)) {
memset(ncr_dev->buffer, 0, MIN(128, dev->buffer_length));
@@ -680,19 +683,21 @@ ncr_write(uint16_t port, uint8_t val, void *priv)
/*a Read 6/10 has occurred, start the timer when the block count is loaded*/
ncr->dma_mode = DMA_INITIATOR_RECEIVE;
if (ncr_dev->type == 3) {
ncr_log("DMA receive timer start, enabled? = %i, cdb[0] = %02x\n", timer_is_enabled(&ncr_dev->timer), ncr->command[0]);
memset(ncr_dev->t128.buffer, 0, MIN(512, dev->buffer_length));
ncr_log("DMA receive timer start, enabled? = %i, cdb[0] = %02x, buflen = %i\n", timer_is_enabled(&ncr_dev->timer), ncr->command[0], dev->buffer_length);
if (dev->buffer_length > 0) {
memset(ncr_dev->t128.buffer, 0, MIN(512, dev->buffer_length));
ncr_dev->t128.block_count = dev->buffer_length >> 9;
ncr_dev->t128.block_count = dev->buffer_length >> 9;
if (dev->buffer_length < 512)
ncr_dev->t128.block_count = 1;
if (dev->buffer_length < 512)
ncr_dev->t128.block_count = 1;
ncr_dev->t128.block_loaded = 1;
ncr_dev->t128.block_loaded = 1;
ncr_dev->t128.host_pos = MIN(512, dev->buffer_length);
ncr_dev->t128.status |= 0x04;
timer_on_auto(&ncr_dev->timer, 0.02);
ncr_dev->t128.host_pos = MIN(512, dev->buffer_length);
ncr_dev->t128.status |= 0x04;
timer_on_auto(&ncr_dev->timer, 0.02);
}
} else {
if ((ncr->mode & MODE_DMA) && !timer_is_enabled(&ncr_dev->timer)) {
memset(ncr_dev->buffer, 0, MIN(128, dev->buffer_length));
@@ -708,7 +713,7 @@ ncr_write(uint16_t port, uint8_t val, void *priv)
break;
}
if (ncr->dma_mode == DMA_IDLE || ncr_dev->type == 0 || ncr_dev->type == 3) {
if (ncr->dma_mode == DMA_IDLE || ncr_dev->type == 0 || ncr_dev->type >= 3) {
bus_host = get_bus_host(ncr);
ncr_bus_update(priv, bus_host);
}
@@ -1075,9 +1080,9 @@ ncr_dma_send(ncr5380_t *ncr_dev, ncr_t *ncr, scsi_device_t *dev)
}
/* Data ready. */
if (ncr_dev->type == 3) {
if (ncr_dev->type == 3)
data = ncr_dev->t128.buffer[ncr_dev->t128.pos];
} else
else
data = ncr_dev->buffer[ncr_dev->buffer_pos];
bus = get_bus_host(ncr) & ~BUS_DATAMASK;
bus |= BUS_SETDATA(data);
@@ -1502,6 +1507,18 @@ ncr_init(const device_t *info)
t128_write, NULL, NULL,
ncr_dev->bios_rom.rom, MEM_MAPPING_EXTERNAL, ncr_dev);
break;
case 4: /* Corel LS2000 */
ncr_dev->rom_addr = device_get_config_hex20("bios_addr");
ncr_dev->irq = device_get_config_int("irq");
rom_init(&ncr_dev->bios_rom, COREL_LS2000_ROM,
ncr_dev->rom_addr, 0x4000, 0x3fff, 0, MEM_MAPPING_EXTERNAL);
mem_mapping_add(&ncr_dev->mapping, ncr_dev->rom_addr, 0x4000,
memio_read, NULL, NULL,
memio_write, NULL, NULL,
ncr_dev->bios_rom.rom, MEM_MAPPING_EXTERNAL, ncr_dev);
break;
}
sprintf(temp, "%s: BIOS=%05X", ncr_dev->name, ncr_dev->rom_addr);
@@ -1512,7 +1529,7 @@ ncr_init(const device_t *info)
ncr_log("%s\n", temp);
ncr_reset(ncr_dev, &ncr_dev->ncr);
if (ncr_dev->type < 3) {
if (ncr_dev->type < 3 || ncr_dev->type == 4) {
ncr_dev->status_ctrl = STATUS_BUFFER_NOT_READY;
ncr_dev->buffer_host_pos = 128;
} else {
@@ -1568,220 +1585,127 @@ t128_available(void)
return(rom_present(T128_ROM));
}
static const device_config_t ncr5380_mmio_config[] = {
{
"bios_addr", "BIOS Address", CONFIG_HEX20, "", 0xD8000, "", { 0 },
{
{
"C800H", 0xc8000
},
{
"CC00H", 0xcc000
},
{
"D800H", 0xd8000
},
{
"DC00H", 0xdc000
},
{
""
}
},
static int
corel_ls2000_available(void)
{
return(rom_present(COREL_LS2000_ROM));
}
},
// clang-format off
static const device_config_t ncr5380_mmio_config[] = {
{
"bios_addr", "BIOS Address", CONFIG_HEX20, "", 0xD8000, "", { 0 },
{
"irq", "IRQ", CONFIG_SELECTION, "", 5, "", { 0 },
{
{
"IRQ 3", 3
},
{
"IRQ 5", 5
},
{
"IRQ 7", 7
},
{
""
}
},
{ "C800H", 0xc8000 },
{ "CC00H", 0xcc000 },
{ "D800H", 0xd8000 },
{ "DC00H", 0xdc000 },
{ "" }
},
{
"", "", -1
}
},
{
"irq", "IRQ", CONFIG_SELECTION, "", 5, "", { 0 },
{
{ "IRQ 3", 3 },
{ "IRQ 5", 5 },
{ "IRQ 7", 7 },
{ "" }
},
},
{ "", "", -1 }
};
static const device_config_t rancho_config[] = {
{
"bios_addr", "BIOS Address", CONFIG_HEX20, "", 0xD8000, "", { 0 },
{
"bios_addr", "BIOS Address", CONFIG_HEX20, "", 0xD8000, "", { 0 },
{
{
"C800H", 0xc8000
},
{
"CC00H", 0xcc000
},
{
"D800H", 0xd8000
},
{
"DC00H", 0xdc000
},
{
""
}
},
{ "C800H", 0xc8000 },
{ "CC00H", 0xcc000 },
{ "D800H", 0xd8000 },
{ "DC00H", 0xdc000 },
{ "" }
},
},
{
"irq", "IRQ", CONFIG_SELECTION, "", 5, "", { 0 },
{
"irq", "IRQ", CONFIG_SELECTION, "", 5, "", { 0 },
{
{
"IRQ 3", 3
},
{
"IRQ 5", 5
},
{
"IRQ 7", 7
},
{
""
}
},
{ "IRQ 3", 3 },
{ "IRQ 5", 5 },
{ "IRQ 7", 7 },
{ "" }
},
},
{
"bios_ver", "BIOS Version", CONFIG_SELECTION, "", 1, "", { 0 },
{
"bios_ver", "BIOS Version", CONFIG_SELECTION, "", 1, "", { 0 },
{
{
"8.20R", 1
},
{
"8.10R", 0
},
{
""
}
},
{ "8.20R", 1 },
{ "8.10R", 0 },
{ "" }
},
{
"", "", -1
}
},
{ "", "", -1 }
};
static const device_config_t t130b_config[] = {
{
"bios_addr", "BIOS Address", CONFIG_HEX20, "", 0xD8000, "", { 0 },
{
"bios_addr", "BIOS Address", CONFIG_HEX20, "", 0xD8000, "", { 0 },
{
{
"Disabled", 0
},
{
"C800H", 0xc8000
},
{
"CC00H", 0xcc000
},
{
"D800H", 0xd8000
},
{
"DC00H", 0xdc000
},
{
""
}
},
{ "Disabled", 0 },
{ "C800H", 0xc8000 },
{ "CC00H", 0xcc000 },
{ "D800H", 0xd8000 },
{ "DC00H", 0xdc000 },
{ "" }
},
},
{
"base", "Address", CONFIG_HEX16, "", 0x0350, "", { 0 },
{
"base", "Address", CONFIG_HEX16, "", 0x0350, "", { 0 },
{
{
"240H", 0x0240
},
{
"250H", 0x0250
},
{
"340H", 0x0340
},
{
"350H", 0x0350
},
{
""
}
},
{ "240H", 0x0240 },
{ "250H", 0x0250 },
{ "340H", 0x0340 },
{ "350H", 0x0350 },
{ "" }
},
},
{
"irq", "IRQ", CONFIG_SELECTION, "", 5, "", { 0 },
{
"irq", "IRQ", CONFIG_SELECTION, "", 5, "", { 0 },
{
{
"IRQ 3", 3
},
{
"IRQ 5", 5
},
{
"IRQ 7", 7
},
{
""
}
},
{ "IRQ 3", 3 },
{ "IRQ 5", 5 },
{ "IRQ 7", 7 },
{ "" }
},
{
"", "", -1
}
},
{ "", "", -1 }
};
static const device_config_t t128_config[] = {
{
"bios_addr", "BIOS Address", CONFIG_HEX20, "", 0xD8000, "", { 0 },
{
"bios_addr", "BIOS Address", CONFIG_HEX20, "", 0xD8000, "", { 0 },
{
{
"C800H", 0xc8000
},
{
"CC00H", 0xcc000
},
{
"D800H", 0xd8000
},
{
"DC00H", 0xdc000
},
{
""
}
},
{ "C800H", 0xc8000 },
{ "CC00H", 0xcc000 },
{ "D800H", 0xd8000 },
{ "DC00H", 0xdc000 },
{ "" }
},
},
{
"irq", "IRQ", CONFIG_SELECTION, "", 5, "", { 0 },
{
"irq", "IRQ", CONFIG_SELECTION, "", 5, "", { 0 },
{
{
"IRQ 3", 3
},
{
"IRQ 5", 5
},
{
"IRQ 7", 7
},
{
""
}
},
{ "IRQ 3", 3 },
{ "IRQ 5", 5 },
{ "IRQ 7", 7 },
{ "" }
},
{
"boot", "Enable Boot ROM", CONFIG_BINARY, "", 1
},
{
"", "", -1
}
},
{
"boot", "Enable Boot ROM", CONFIG_BINARY, "", 1
},
{ "", "", -1 }
};
// clang-format on
const device_t scsi_lcs6821n_device =
{
@@ -1830,3 +1754,15 @@ const device_t scsi_t128_device =
NULL, NULL,
t128_config
};
const device_t scsi_ls2000_device =
{
"Corel LS2000",
"ls2000",
DEVICE_ISA,
4,
ncr_init, ncr_close, NULL,
{ corel_ls2000_available },
NULL, NULL,
ncr5380_mmio_config
};

View File

@@ -2634,26 +2634,18 @@ ncr53c8xx_close(void *priv)
}
static const device_config_t ncr53c8xx_pci_config[] = {
// clang-format off
{
"bios", "BIOS", CONFIG_SELECTION, "", 1, "", { 0 },
{
"bios", "BIOS", CONFIG_SELECTION, "", 1, "", { 0 },
{
{
"SDMS 4.x BIOS", 2
},
{
"SDMS 3.x BIOS", 1
},
{
"Disable BIOS", 0
},
{
""
}
},
{ "SDMS 4.x BIOS", 2 },
{ "SDMS 3.x BIOS", 1 },
{ "Disable BIOS", 0 },
{ "" }
},
{
"", "", -1
}
},
{ "", "", -1 }
// clang-format on
};

View File

@@ -2000,15 +2000,16 @@ esp_close(void *priv)
static const device_config_t bios_enable_config[] = {
{
"bios", "Enable BIOS", CONFIG_BINARY, "", 0
},
{
"", "", -1
}
// clang-format off
{
"bios", "Enable BIOS", CONFIG_BINARY, "", 0
},
{
"", "", -1
}
// clang-format on
};
const device_t dc390_pci_device =
{
"Tekram DC-390 PCI",

View File

@@ -1157,23 +1157,17 @@ spock_available(void)
}
static const device_config_t spock_rom_config[] = {
// clang-format off
{
"bios_ver", "BIOS Version", CONFIG_SELECTION, "", 1, "", { 0 },
{
"bios_ver", "BIOS Version", CONFIG_SELECTION, "", 1, "", { 0 },
{
{
"1991 BIOS (>1GB)", 1
},
{
"1990 BIOS", 0
},
{
""
}
},
{ "1991 BIOS (>1GB)", 1 },
{ "1990 BIOS", 0 },
{ "" }
},
{
"", "", -1
}
},
{ "", "", -1 }
// clang-format on
};
const device_t spock_device =

View File

@@ -94,7 +94,7 @@ static const isapnp_device_config_t um8669f_pnp_defaults[] = {
}
};
#define ENABLE_UM8669F_LOG 1
#ifdef ENABLE_UM8669F_LOG
int um8669f_do_log = ENABLE_UM8669F_LOG;

View File

@@ -1,69 +1,69 @@
/*
* 86Box A hypervisor and IBM PC system emulator that specializes in
* running old operating systems and software designed for IBM
* PC systems and compatibles from 1981 through fairly recent
* system designs based on the PCI bus.
* 86Box A hypervisor and IBM PC system emulator that specializes in
* running old operating systems and software designed for IBM
* PC systems and compatibles from 1981 through fairly recent
* system designs based on the PCI bus.
*
* This file is part of the 86Box distribution.
* This file is part of the 86Box distribution.
*
* MIDI device core module.
* MIDI device core module.
*
*
*
* Authors: Sarah Walker, <http://pcem-emulator.co.uk/>
* Miran Grca, <mgrca8@gmail.com>
* Bit,
* DOSBox Team,
* Authors: Sarah Walker, <http://pcem-emulator.co.uk/>
* Miran Grca, <mgrca8@gmail.com>
* Bit,
* DOSBox Team,
*
* Copyright 2008-2020 Sarah Walker.
* Copyright 2016-2020 Miran Grca.
* Copyright 2016-2020 Bit.
* Copyright 2008-2020 DOSBox Team.
* Copyright 2008-2020 Sarah Walker.
* Copyright 2016-2020 Miran Grca.
* Copyright 2016-2020 Bit.
* Copyright 2008-2020 DOSBox Team.
*/
#include <stdio.h>
#include <stdint.h>
#include <string.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <wchar.h>
#include <86box/86box.h>
#include <86box/device.h>
#include <86box/plat.h>
#include <86box/midi.h>
#include <86box/plat.h>
int midi_device_current = 0;
static int midi_device_last = 0;
int midi_input_device_current = 0;
static int midi_input_device_last = 0;
int midi_device_current = 0;
static int midi_device_last = 0;
int midi_input_device_current = 0;
static int midi_input_device_last = 0;
midi_t *midi = NULL, *midi_in = NULL;
midi_in_handler_t *mih_first = NULL, *mih_last = NULL,
*mih_cur = NULL;
*mih_cur = NULL;
uint8_t MIDI_InSysexBuf[SYSEX_SIZE];
uint8_t MIDI_evt_len[256] = {
0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0, /* 0x00 */
0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0, /* 0x10 */
0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0, /* 0x20 */
0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0, /* 0x30 */
0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0, /* 0x40 */
0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0, /* 0x50 */
0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0, /* 0x60 */
0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0, /* 0x70 */
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 0x00 */
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 0x10 */
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 0x20 */
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 0x30 */
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 0x40 */
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 0x50 */
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 0x60 */
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 0x70 */
3,3,3,3, 3,3,3,3, 3,3,3,3, 3,3,3,3, /* 0x80 */
3,3,3,3, 3,3,3,3, 3,3,3,3, 3,3,3,3, /* 0x90 */
3,3,3,3, 3,3,3,3, 3,3,3,3, 3,3,3,3, /* 0xa0 */
3,3,3,3, 3,3,3,3, 3,3,3,3, 3,3,3,3, /* 0xb0 */
3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, /* 0x80 */
3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, /* 0x90 */
3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, /* 0xa0 */
3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, /* 0xb0 */
2,2,2,2, 2,2,2,2, 2,2,2,2, 2,2,2,2, /* 0xc0 */
2,2,2,2, 2,2,2,2, 2,2,2,2, 2,2,2,2, /* 0xd0 */
2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, /* 0xc0 */
2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, /* 0xd0 */
3,3,3,3, 3,3,3,3, 3,3,3,3, 3,3,3,3, /* 0xe0 */
3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, /* 0xe0 */
0,2,3,2, 0,0,1,0, 1,0,1,1, 1,0,1,0 /* 0xf0 */
0, 2, 3, 2, 0, 0, 1, 0, 1, 0, 1, 1, 1, 0, 1, 0 /* 0xf0 */
};
typedef struct
@@ -72,104 +72,109 @@ typedef struct
} MIDI_DEVICE, MIDI_IN_DEVICE;
static const device_t midi_none_device = {
"None",
"none",
0, 0,
NULL, NULL, NULL,
{ NULL }, NULL, NULL,
NULL
"None",
"none",
0,
0,
NULL,
NULL,
NULL,
{ NULL },
NULL,
NULL,
NULL
};
static const MIDI_DEVICE devices[] =
{
{ &midi_none_device },
static const MIDI_DEVICE devices[] = {
// clang-format off
{ &midi_none_device },
#ifdef USE_FLUIDSYNTH
{ &fluidsynth_device },
{ &fluidsynth_device },
#endif
#ifdef USE_MUNT
{ &mt32_device },
{ &cm32l_device },
{ &mt32_device },
{ &cm32l_device },
#endif
{ &rtmidi_device },
{ NULL }
{ &rtmidi_device },
{ NULL }
// clang-format on
};
static const device_t midi_in_none_device = {
"None",
"none",
0, 0,
NULL, NULL, NULL,
{ NULL }, NULL, NULL,
NULL
"None",
"none",
0,
0,
NULL,
NULL,
NULL,
{ NULL },
NULL,
NULL,
NULL
};
static const MIDI_IN_DEVICE midi_in_devices[] =
{
{ &midi_in_none_device },
{ &rtmidi_input_device },
{ NULL }
static const MIDI_IN_DEVICE midi_in_devices[] = {
// clang-format off
{ &midi_in_none_device },
{ &rtmidi_input_device },
{ NULL }
// clang-format on
};
int
midi_device_available(int card)
{
if (devices[card].device)
return device_available(devices[card].device);
return device_available(devices[card].device);
return 1;
}
const device_t *
midi_device_getdevice(int card)
{
return devices[card].device;
}
int
midi_device_has_config(int card)
{
if (!devices[card].device)
return 0;
return 0;
return devices[card].device->config ? 1 : 0;
}
char *
midi_device_get_internal_name(int card)
{
return device_get_internal_name(devices[card].device);
}
int
midi_device_get_from_internal_name(char *s)
{
int c = 0;
while (devices[c].device != NULL) {
if (!strcmp(devices[c].device->internal_name, s))
return c;
c++;
if (!strcmp(devices[c].device->internal_name, s))
return c;
c++;
}
return 0;
}
void
midi_device_init()
{
if (devices[midi_device_current].device)
device_add(devices[midi_device_current].device);
device_add(devices[midi_device_current].device);
midi_device_last = midi_device_current;
}
void
midi_init(midi_device_t* device)
midi_init(midi_device_t *device)
{
midi = (midi_t *) malloc(sizeof(midi_t));
memset(midi, 0, sizeof(midi_t));
@@ -178,26 +183,25 @@ midi_init(midi_device_t* device)
}
void
midi_in_init(midi_device_t* device, midi_t **mididev)
midi_in_init(midi_device_t *device, midi_t **mididev)
{
*mididev = (midi_t *)malloc(sizeof(midi_t));
*mididev = (midi_t *) malloc(sizeof(midi_t));
memset(*mididev, 0, sizeof(midi_t));
(*mididev)->m_in_device = device;
}
void
midi_close(void)
{
if (midi && midi->m_out_device) {
free(midi->m_out_device);
midi->m_out_device = NULL;
free(midi->m_out_device);
midi->m_out_device = NULL;
}
if (midi) {
free(midi);
midi = NULL;
free(midi);
midi = NULL;
}
}
@@ -205,416 +209,394 @@ void
midi_in_close(void)
{
if (midi_in && midi_in->m_in_device) {
free(midi_in->m_in_device);
midi_in->m_in_device = NULL;
free(midi_in->m_in_device);
midi_in->m_in_device = NULL;
}
if (midi_in) {
free(midi_in);
midi_in = NULL;
free(midi_in);
midi_in = NULL;
}
}
void
midi_poll(void)
{
if (midi && midi->m_out_device && midi->m_out_device->poll)
midi->m_out_device->poll();
midi->m_out_device->poll();
}
void
play_msg(uint8_t *msg)
{
if (midi->m_out_device->play_msg)
midi->m_out_device->play_msg(msg);
midi->m_out_device->play_msg(msg);
}
void
play_sysex(uint8_t *sysex, unsigned int len)
{
if (midi->m_out_device->play_sysex)
midi->m_out_device->play_sysex(sysex, len);
midi->m_out_device->play_sysex(sysex, len);
}
int
midi_in_device_available(int card)
{
if (midi_in_devices[card].device)
return device_available(midi_in_devices[card].device);
return device_available(midi_in_devices[card].device);
return 1;
}
const device_t *
midi_in_device_getdevice(int card)
{
return midi_in_devices[card].device;
}
int
midi_in_device_has_config(int card)
{
if (!midi_in_devices[card].device)
return 0;
return 0;
return midi_in_devices[card].device->config ? 1 : 0;
}
char *
midi_in_device_get_internal_name(int card)
{
return device_get_internal_name(midi_in_devices[card].device);
}
int
midi_in_device_get_from_internal_name(char *s)
{
int c = 0;
while (midi_in_devices[c].device != NULL) {
if (!strcmp(midi_in_devices[c].device->internal_name, s))
return c;
c++;
if (!strcmp(midi_in_devices[c].device->internal_name, s))
return c;
c++;
}
return 0;
}
void
midi_in_device_init()
{
if (midi_in_devices[midi_input_device_current].device)
device_add(midi_in_devices[midi_input_device_current].device);
device_add(midi_in_devices[midi_input_device_current].device);
midi_input_device_last = midi_input_device_current;
}
void
midi_raw_out_rt_byte(uint8_t val)
{
if (!midi_in)
return;
return;
if (!midi_in->midi_realtime)
return;
return;
if ((!midi_in->midi_clockout && (val == 0xf8)))
return;
return;
midi_in->midi_cmd_r = val << 24;
/* pclog("Play RT Byte msg\n"); */
play_msg((uint8_t *)&midi_in->midi_cmd_r);
play_msg((uint8_t *) &midi_in->midi_cmd_r);
}
void
midi_raw_out_thru_rt_byte(uint8_t val)
{
if (midi_in && midi_in->thruchan)
midi_raw_out_rt_byte(val);
midi_raw_out_rt_byte(val);
}
void
midi_raw_out_byte(uint8_t val)
{
uint32_t passed_ticks;
if (!midi || !midi->m_out_device)
return;
return;
if ((midi->m_out_device->write && midi->m_out_device->write(val)))
return;
return;
if (midi->midi_sysex_start) {
passed_ticks = plat_get_ticks() - midi->midi_sysex_start;
if (passed_ticks < midi->midi_sysex_delay)
plat_delay_ms(midi->midi_sysex_delay - passed_ticks);
passed_ticks = plat_get_ticks() - midi->midi_sysex_start;
if (passed_ticks < midi->midi_sysex_delay)
plat_delay_ms(midi->midi_sysex_delay - passed_ticks);
}
/* Test for a realtime MIDI message */
if (val >= 0xf8) {
midi->midi_rt_buf[0] = val;
play_msg(midi->midi_rt_buf);
return;
midi->midi_rt_buf[0] = val;
play_msg(midi->midi_rt_buf);
return;
}
/* Test for a active sysex transfer */
if (midi->midi_status == 0xf0) {
if (!(val & 0x80)) {
if (midi->midi_pos < (SYSEX_SIZE-1))
midi->midi_sysex_data[midi->midi_pos++] = val;
return;
} else {
midi->midi_sysex_data[midi->midi_pos++] = 0xf7;
if (!(val & 0x80)) {
if (midi->midi_pos < (SYSEX_SIZE - 1))
midi->midi_sysex_data[midi->midi_pos++] = val;
return;
} else {
midi->midi_sysex_data[midi->midi_pos++] = 0xf7;
if ((midi->midi_sysex_start) && (midi->midi_pos >= 4) && (midi->midi_pos <= 9) &&
(midi->midi_sysex_data[1] == 0x41) && (midi->midi_sysex_data[3] == 0x16)) {
/* pclog("MIDI: Skipping invalid MT-32 SysEx MIDI message\n"); */
} else {
play_sysex(midi->midi_sysex_data, midi->midi_pos);
if (midi->midi_sysex_start) {
if (midi-> midi_sysex_data[5] == 0x7f)
midi->midi_sysex_delay = 290; /* All parameters reset */
else if ((midi->midi_sysex_data[5] == 0x10) && (midi->midi_sysex_data[6] == 0x00) &&
(midi->midi_sysex_data[7] == 0x04))
midi->midi_sysex_delay = 145; /* Viking Child */
else if ((midi->midi_sysex_data[5] == 0x10) && (midi->midi_sysex_data[6] == 0x00) &&
(midi->midi_sysex_data[7] == 0x01))
midi->midi_sysex_delay = 30; /* Dark Sun 1 */
else
midi->midi_sysex_delay = (unsigned int) (((float) (midi->midi_pos) * 1.25f) * 1000.0f / 3125.0f) + 2;
if ((midi->midi_sysex_start) && (midi->midi_pos >= 4) && (midi->midi_pos <= 9) && (midi->midi_sysex_data[1] == 0x41) && (midi->midi_sysex_data[3] == 0x16)) {
/* pclog("MIDI: Skipping invalid MT-32 SysEx MIDI message\n"); */
} else {
play_sysex(midi->midi_sysex_data, midi->midi_pos);
if (midi->midi_sysex_start) {
if (midi->midi_sysex_data[5] == 0x7f)
midi->midi_sysex_delay = 290; /* All parameters reset */
else if ((midi->midi_sysex_data[5] == 0x10) && (midi->midi_sysex_data[6] == 0x00) && (midi->midi_sysex_data[7] == 0x04))
midi->midi_sysex_delay = 145; /* Viking Child */
else if ((midi->midi_sysex_data[5] == 0x10) && (midi->midi_sysex_data[6] == 0x00) && (midi->midi_sysex_data[7] == 0x01))
midi->midi_sysex_delay = 30; /* Dark Sun 1 */
else
midi->midi_sysex_delay = (unsigned int) (((float) (midi->midi_pos) * 1.25f) * 1000.0f / 3125.0f) + 2;
midi->midi_sysex_start = plat_get_ticks();
}
}
}
midi->midi_sysex_start = plat_get_ticks();
}
}
}
}
if (val & 0x80) {
midi->midi_status = val;
midi->midi_cmd_pos = 0;
midi->midi_cmd_len = MIDI_evt_len[val];
if (midi->midi_status == 0xf0) {
midi->midi_sysex_data[0] = 0xf0;
midi->midi_pos = 1;
}
midi->midi_status = val;
midi->midi_cmd_pos = 0;
midi->midi_cmd_len = MIDI_evt_len[val];
if (midi->midi_status == 0xf0) {
midi->midi_sysex_data[0] = 0xf0;
midi->midi_pos = 1;
}
}
if (midi->midi_cmd_len) {
midi->midi_cmd_buf[midi->midi_cmd_pos++] = val;
if (midi->midi_cmd_pos >= midi->midi_cmd_len) {
play_msg(midi->midi_cmd_buf);
midi->midi_cmd_pos = 1;
}
midi->midi_cmd_buf[midi->midi_cmd_pos++] = val;
if (midi->midi_cmd_pos >= midi->midi_cmd_len) {
play_msg(midi->midi_cmd_buf);
midi->midi_cmd_pos = 1;
}
}
}
void
midi_clear_buffer(void)
{
if (!midi)
return;
return;
midi->midi_pos = 0;
midi->midi_status = 0x00;
midi->midi_pos = 0;
midi->midi_status = 0x00;
midi->midi_cmd_pos = 0;
midi->midi_cmd_len = 0;
}
void
midi_in_handler(int set, void (*msg)(void *p, uint8_t *msg, uint32_t len), int (*sysex)(void *p, uint8_t *buffer, uint32_t len, int abort), void *p)
{
midi_in_handler_t *temp = NULL, *next;
if (set) {
/* Add MIDI IN handler. */
if ((mih_first == NULL) && (mih_last != NULL))
fatal("Last MIDI IN handler present with no first MIDI IN handler\n");
/* Add MIDI IN handler. */
if ((mih_first == NULL) && (mih_last != NULL))
fatal("Last MIDI IN handler present with no first MIDI IN handler\n");
if ((mih_first != NULL) && (mih_last == NULL))
fatal("First MIDI IN handler present with no last MIDI IN handler\n");
if ((mih_first != NULL) && (mih_last == NULL))
fatal("First MIDI IN handler present with no last MIDI IN handler\n");
temp = (midi_in_handler_t *) malloc(sizeof(midi_in_handler_t));
memset(temp, 0, sizeof(midi_in_handler_t));
temp->msg = msg;
temp->sysex = sysex;
temp->p = p;
temp = (midi_in_handler_t *) malloc(sizeof(midi_in_handler_t));
memset(temp, 0, sizeof(midi_in_handler_t));
temp->msg = msg;
temp->sysex = sysex;
temp->p = p;
if (mih_last == NULL)
mih_first = mih_last = temp;
else {
temp->prev = mih_last;
mih_last = temp;
}
if (mih_last == NULL)
mih_first = mih_last = temp;
else {
temp->prev = mih_last;
mih_last = temp;
}
} else if ((mih_first != NULL) && (mih_last != NULL)) {
temp = mih_first;
temp = mih_first;
while(1) {
if (temp == NULL)
break;
while (1) {
if (temp == NULL)
break;
if ((temp->msg == msg) && (temp->sysex == sysex) && (temp->p == p)) {
if (temp->prev != NULL)
temp->prev->next = temp->next;
if ((temp->msg == msg) && (temp->sysex == sysex) && (temp->p == p)) {
if (temp->prev != NULL)
temp->prev->next = temp->next;
if (temp->next != NULL)
temp->next->prev = temp->prev;
if (temp->next != NULL)
temp->next->prev = temp->prev;
next = temp->next;
next = temp->next;
if (temp == mih_first) {
mih_first = NULL;
if (next == NULL)
mih_last = NULL;
}
if (temp == mih_first) {
mih_first = NULL;
if (next == NULL)
mih_last = NULL;
}
if (temp == mih_last)
mih_last = NULL;
if (temp == mih_last)
mih_last = NULL;
free(temp);
temp = next;
free(temp);
temp = next;
if (next == NULL)
break;
}
}
if (next == NULL)
break;
}
}
}
}
void
midi_in_handlers_clear(void)
{
midi_in_handler_t *temp = mih_first, *next;
while(1) {
if (temp == NULL)
break;
while (1) {
if (temp == NULL)
break;
next = temp->next;
free(temp);
next = temp->next;
free(temp);
temp = next;
temp = next;
if (next == NULL)
break;
if (next == NULL)
break;
}
mih_first = mih_last = NULL;
}
void
midi_in_msg(uint8_t *msg, uint32_t len)
{
midi_in_handler_t *temp = mih_first;
while(1) {
if (temp == NULL)
break;
while (1) {
if (temp == NULL)
break;
if (temp->msg)
temp->msg(temp->p, msg, len);
if (temp->msg)
temp->msg(temp->p, msg, len);
temp = temp->next;
temp = temp->next;
if (temp == NULL)
break;
if (temp == NULL)
break;
}
}
static void
midi_start_sysex(uint8_t *buffer, uint32_t len)
{
midi_in_handler_t *temp = mih_first;
while(1) {
if (temp == NULL)
break;
while (1) {
if (temp == NULL)
break;
temp->cnt = 5;
temp->buf = buffer;
temp->len = len;
temp->cnt = 5;
temp->buf = buffer;
temp->len = len;
temp = temp->next;
temp = temp->next;
if (temp == NULL)
break;
if (temp == NULL)
break;
}
}
/* Returns:
0 = All handlers have returnd 0;
1 = There are still handlers to go. */
0 = All handlers have returnd 0;
1 = There are still handlers to go. */
static int
midi_do_sysex(void)
{
midi_in_handler_t *temp = mih_first;
int ret, cnt_acc = 0;
int ret, cnt_acc = 0;
while(1) {
if (temp == NULL)
break;
while (1) {
if (temp == NULL)
break;
/* Do nothing if the handler has a zero count. */
if ((temp->cnt > 0) || (temp->len > 0)) {
ret = 0;
if (temp->sysex) {
if (temp->cnt == 0)
ret = temp->sysex(temp->p, temp->buf, 0, 0);
else
ret = temp->sysex(temp->p, temp->buf, temp->len, 0);
}
/* Do nothing if the handler has a zero count. */
if ((temp->cnt > 0) || (temp->len > 0)) {
ret = 0;
if (temp->sysex) {
if (temp->cnt == 0)
ret = temp->sysex(temp->p, temp->buf, 0, 0);
else
ret = temp->sysex(temp->p, temp->buf, temp->len, 0);
}
/* If count is 0 and length is 0, then this is just a finishing
call to temp->sysex(), so skip this entire block. */
if (temp->cnt > 0) {
if (ret) {
/* Decrease or reset the counter. */
if (temp->len == ret)
temp->cnt--;
else
temp->cnt = 5;
/* If count is 0 and length is 0, then this is just a finishing
call to temp->sysex(), so skip this entire block. */
if (temp->cnt > 0) {
if (ret) {
/* Decrease or reset the counter. */
if (temp->len == ret)
temp->cnt--;
else
temp->cnt = 5;
/* Advance the buffer pointer and remember the
remaining length. */
temp->buf += (temp->len - ret);
temp->len = ret;
} else {
/* Set count to 0 so that this handler will be
ignored on the next interation. */
temp->cnt = 0;
/* Advance the buffer pointer and remember the
remaining length. */
temp->buf += (temp->len - ret);
temp->len = ret;
} else {
/* Set count to 0 so that this handler will be
ignored on the next interation. */
temp->cnt = 0;
/* Reset the buffer pointer and length. */
temp->buf = NULL;
temp->len = 0;
}
/* Reset the buffer pointer and length. */
temp->buf = NULL;
temp->len = 0;
}
/* If the remaining count is above zero, add it to the
accumulator. */
if (temp->cnt > 0)
cnt_acc |= temp->cnt;
}
}
/* If the remaining count is above zero, add it to the
accumulator. */
if (temp->cnt > 0)
cnt_acc |= temp->cnt;
}
}
temp = temp->next;
temp = temp->next;
if (temp == NULL)
break;
if (temp == NULL)
break;
}
/* Return 0 if all handlers have returned 0 or all the counts are otherwise 0. */
if (cnt_acc == 0)
return 0;
return 0;
else
return 1;
return 1;
}
void
midi_in_sysex(uint8_t *buffer, uint32_t len)
{
midi_start_sysex(buffer, len);
while (1) {
/* This will return 0 if all theh handlers have either
timed out or otherwise indicated it is time to stop. */
if (midi_do_sysex())
plat_delay_ms(5); /* msec */
else
break;
/* This will return 0 if all theh handlers have either
timed out or otherwise indicated it is time to stop. */
if (midi_do_sysex())
plat_delay_ms(5); /* msec */
else
break;
}
}

File diff suppressed because it is too large Load Diff

View File

@@ -1,18 +1,18 @@
#include <stdio.h>
#include <stdint.h>
#include <string.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <wchar.h>
#include <mt32emu/c_interface/c_interface.h>
#include <86box/86box.h>
#include <86box/device.h>
#include <86box/mem.h>
#include <86box/rom.h>
#include <86box/plat.h>
#include <86box/ui.h>
#include <86box/sound.h>
#include <86box/midi.h>
#include <86box/plat.h>
#include <86box/rom.h>
#include <86box/sound.h>
#include <86box/ui.h>
#include <mt32emu/c_interface/c_interface.h>
extern void givealbuffer_midi(void *buf, uint32_t size);
extern void al_set_midi(int freq, int buf_size);
@@ -20,375 +20,384 @@ extern void al_set_midi(int freq, int buf_size);
static void display_mt32_message(void *instance_data, const char *message);
static const mt32emu_report_handler_i_v0 handler_mt32_v0 = {
/** Returns the actual interface version ID */
NULL, //mt32emu_report_handler_version (*getVersionID)(mt32emu_report_handler_i i);
/** Returns the actual interface version ID */
NULL, // mt32emu_report_handler_version (*getVersionID)(mt32emu_report_handler_i i);
/** Callback for debug messages, in vprintf() format */
NULL, //void (*printDebug)(void *instance_data, const char *fmt, va_list list);
/** Callbacks for reporting errors */
NULL, //void (*onErrorControlROM)(void *instance_data);
NULL, //void (*onErrorPCMROM)(void *instance_data);
/** Callback for reporting about displaying a new custom message on LCD */
display_mt32_message, //void (*showLCDMessage)(void *instance_data, const char *message);
/** Callback for reporting actual processing of a MIDI message */
NULL, //void (*onMIDIMessagePlayed)(void *instance_data);
/**
* Callback for reporting an overflow of the input MIDI queue.
* Returns MT32EMU_BOOL_TRUE if a recovery action was taken
* and yet another attempt to enqueue the MIDI event is desired.
*/
NULL, //mt32emu_boolean (*onMIDIQueueOverflow)(void *instance_data);
/**
* Callback invoked when a System Realtime MIDI message is detected in functions
* mt32emu_parse_stream and mt32emu_play_short_message and the likes.
*/
NULL, //void (*onMIDISystemRealtime)(void *instance_data, mt32emu_bit8u system_realtime);
/** Callbacks for reporting system events */
NULL, //void (*onDeviceReset)(void *instance_data);
NULL, //void (*onDeviceReconfig)(void *instance_data);
/** Callbacks for reporting changes of reverb settings */
NULL, //void (*onNewReverbMode)(void *instance_data, mt32emu_bit8u mode);
NULL, //void (*onNewReverbTime)(void *instance_data, mt32emu_bit8u time);
NULL, //void (*onNewReverbLevel)(void *instance_data, mt32emu_bit8u level);
/** Callbacks for reporting various information */
NULL, //void (*onPolyStateChanged)(void *instance_data, mt32emu_bit8u part_num);
NULL, //void (*onProgramChanged)(void *instance_data, mt32emu_bit8u part_num, const char *sound_group_name, const char *patch_name);
/** Callback for debug messages, in vprintf() format */
NULL, // void (*printDebug)(void *instance_data, const char *fmt, va_list list);
/** Callbacks for reporting errors */
NULL, // void (*onErrorControlROM)(void *instance_data);
NULL, // void (*onErrorPCMROM)(void *instance_data);
/** Callback for reporting about displaying a new custom message on LCD */
display_mt32_message, // void (*showLCDMessage)(void *instance_data, const char *message);
/** Callback for reporting actual processing of a MIDI message */
NULL, // void (*onMIDIMessagePlayed)(void *instance_data);
/**
* Callback for reporting an overflow of the input MIDI queue.
* Returns MT32EMU_BOOL_TRUE if a recovery action was taken
* and yet another attempt to enqueue the MIDI event is desired.
*/
NULL, // mt32emu_boolean (*onMIDIQueueOverflow)(void *instance_data);
/**
* Callback invoked when a System Realtime MIDI message is detected in functions
* mt32emu_parse_stream and mt32emu_play_short_message and the likes.
*/
NULL, // void (*onMIDISystemRealtime)(void *instance_data, mt32emu_bit8u system_realtime);
/** Callbacks for reporting system events */
NULL, // void (*onDeviceReset)(void *instance_data);
NULL, // void (*onDeviceReconfig)(void *instance_data);
/** Callbacks for reporting changes of reverb settings */
NULL, // void (*onNewReverbMode)(void *instance_data, mt32emu_bit8u mode);
NULL, // void (*onNewReverbTime)(void *instance_data, mt32emu_bit8u time);
NULL, // void (*onNewReverbLevel)(void *instance_data, mt32emu_bit8u level);
/** Callbacks for reporting various information */
NULL, // void (*onPolyStateChanged)(void *instance_data, mt32emu_bit8u part_num);
NULL, // void (*onProgramChanged)(void *instance_data, mt32emu_bit8u part_num, const char *sound_group_name, const char *patch_name);
};
/** Alternate report handler for Roland CM-32L */
static const mt32emu_report_handler_i_v0 handler_cm32l_v0 = {
/** Returns the actual interface version ID */
NULL, //mt32emu_report_handler_version (*getVersionID)(mt32emu_report_handler_i i);
/** Returns the actual interface version ID */
NULL, // mt32emu_report_handler_version (*getVersionID)(mt32emu_report_handler_i i);
/** Callback for debug messages, in vprintf() format */
NULL, //void (*printDebug)(void *instance_data, const char *fmt, va_list list);
/** Callbacks for reporting errors */
NULL, //void (*onErrorControlROM)(void *instance_data);
NULL, //void (*onErrorPCMROM)(void *instance_data);
/** Callback for reporting about displaying a new custom message on LCD */
NULL, //void (*showLCDMessage)(void *instance_data, const char *message);
/** Callback for reporting actual processing of a MIDI message */
NULL, //void (*onMIDIMessagePlayed)(void *instance_data);
/**
* Callback for reporting an overflow of the input MIDI queue.
* Returns MT32EMU_BOOL_TRUE if a recovery action was taken
* and yet another attempt to enqueue the MIDI event is desired.
*/
NULL, //mt32emu_boolean (*onMIDIQueueOverflow)(void *instance_data);
/**
* Callback invoked when a System Realtime MIDI message is detected in functions
* mt32emu_parse_stream and mt32emu_play_short_message and the likes.
*/
NULL, //void (*onMIDISystemRealtime)(void *instance_data, mt32emu_bit8u system_realtime);
/** Callbacks for reporting system events */
NULL, //void (*onDeviceReset)(void *instance_data);
NULL, //void (*onDeviceReconfig)(void *instance_data);
/** Callbacks for reporting changes of reverb settings */
NULL, //void (*onNewReverbMode)(void *instance_data, mt32emu_bit8u mode);
NULL, //void (*onNewReverbTime)(void *instance_data, mt32emu_bit8u time);
NULL, //void (*onNewReverbLevel)(void *instance_data, mt32emu_bit8u level);
/** Callbacks for reporting various information */
NULL, //void (*onPolyStateChanged)(void *instance_data, mt32emu_bit8u part_num);
NULL, //void (*onProgramChanged)(void *instance_data, mt32emu_bit8u part_num, const char *sound_group_name, const char *patch_name);
/** Callback for debug messages, in vprintf() format */
NULL, // void (*printDebug)(void *instance_data, const char *fmt, va_list list);
/** Callbacks for reporting errors */
NULL, // void (*onErrorControlROM)(void *instance_data);
NULL, // void (*onErrorPCMROM)(void *instance_data);
/** Callback for reporting about displaying a new custom message on LCD */
NULL, // void (*showLCDMessage)(void *instance_data, const char *message);
/** Callback for reporting actual processing of a MIDI message */
NULL, // void (*onMIDIMessagePlayed)(void *instance_data);
/**
* Callback for reporting an overflow of the input MIDI queue.
* Returns MT32EMU_BOOL_TRUE if a recovery action was taken
* and yet another attempt to enqueue the MIDI event is desired.
*/
NULL, // mt32emu_boolean (*onMIDIQueueOverflow)(void *instance_data);
/**
* Callback invoked when a System Realtime MIDI message is detected in functions
* mt32emu_parse_stream and mt32emu_play_short_message and the likes.
*/
NULL, // void (*onMIDISystemRealtime)(void *instance_data, mt32emu_bit8u system_realtime);
/** Callbacks for reporting system events */
NULL, // void (*onDeviceReset)(void *instance_data);
NULL, // void (*onDeviceReconfig)(void *instance_data);
/** Callbacks for reporting changes of reverb settings */
NULL, // void (*onNewReverbMode)(void *instance_data, mt32emu_bit8u mode);
NULL, // void (*onNewReverbTime)(void *instance_data, mt32emu_bit8u time);
NULL, // void (*onNewReverbLevel)(void *instance_data, mt32emu_bit8u level);
/** Callbacks for reporting various information */
NULL, // void (*onPolyStateChanged)(void *instance_data, mt32emu_bit8u part_num);
NULL, // void (*onProgramChanged)(void *instance_data, mt32emu_bit8u part_num, const char *sound_group_name, const char *patch_name);
};
static const mt32emu_report_handler_i handler_mt32 = { &handler_mt32_v0 };
static const mt32emu_report_handler_i handler_mt32 = { &handler_mt32_v0 };
static const mt32emu_report_handler_i handler_cm32l = { &handler_cm32l_v0 };
static mt32emu_context context = NULL;
static int roms_present[2] = {-1, -1};
static mt32emu_context context = NULL;
static int roms_present[2] = { -1, -1 };
mt32emu_return_code mt32_check(const char* func, mt32emu_return_code ret, mt32emu_return_code expected)
mt32emu_return_code
mt32_check(const char *func, mt32emu_return_code ret, mt32emu_return_code expected)
{
if (ret != expected)
{
return 0;
}
return 1;
if (ret != expected) {
return 0;
}
return 1;
}
int mt32_available()
int
mt32_available()
{
if (roms_present[0] < 0)
roms_present[0] = (rom_present("roms/sound/mt32/MT32_CONTROL.ROM") && rom_present("roms/sound/mt32/MT32_PCM.ROM"));
return roms_present[0];
if (roms_present[0] < 0)
roms_present[0] = (rom_present("roms/sound/mt32/MT32_CONTROL.ROM") && rom_present("roms/sound/mt32/MT32_PCM.ROM"));
return roms_present[0];
}
int cm32l_available()
int
cm32l_available()
{
if (roms_present[1] < 0)
roms_present[1] = (rom_present("roms/sound/cm32l/CM32L_CONTROL.ROM") && rom_present("roms/sound/cm32l/CM32L_PCM.ROM"));
return roms_present[1];
if (roms_present[1] < 0)
roms_present[1] = (rom_present("roms/sound/cm32l/CM32L_CONTROL.ROM") && rom_present("roms/sound/cm32l/CM32L_PCM.ROM"));
return roms_present[1];
}
static thread_t *thread_h = NULL;
static event_t *event = NULL;
static event_t *start_event = NULL;
static int mt32_on = 0;
static thread_t *thread_h = NULL;
static event_t *event = NULL;
static event_t *start_event = NULL;
static int mt32_on = 0;
#define RENDER_RATE 100
#define RENDER_RATE 100
#define BUFFER_SEGMENTS 10
static uint32_t samplerate = 44100;
static int buf_size = 0;
static float* buffer = NULL;
static int16_t* buffer_int16 = NULL;
static int midi_pos = 0;
static uint32_t samplerate = 44100;
static int buf_size = 0;
static float *buffer = NULL;
static int16_t *buffer_int16 = NULL;
static int midi_pos = 0;
static void display_mt32_message(void *instance_data, const char *message)
static void
display_mt32_message(void *instance_data, const char *message)
{
int sz = 0;
char* ui_msg = NULL;
int sz = 0;
char *ui_msg = NULL;
sz = snprintf(NULL, 0, "MT-32: %s", message);
sz = snprintf(NULL, 0, "MT-32: %s", message);
ui_msg = calloc(sz + 1, 1);
if (ui_msg)
{
if (ui_msg) {
snprintf(ui_msg, sz, "MT-32: %s", message);
ui_sb_mt32lcd(ui_msg);
}
}
void mt32_stream(float* stream, int len)
void
mt32_stream(float *stream, int len)
{
if (context) mt32emu_render_float(context, stream, len);
if (context)
mt32emu_render_float(context, stream, len);
}
void mt32_stream_int16(int16_t* stream, int len)
void
mt32_stream_int16(int16_t *stream, int len)
{
if (context) mt32emu_render_bit16s(context, stream, len);
if (context)
mt32emu_render_bit16s(context, stream, len);
}
void mt32_poll()
void
mt32_poll()
{
midi_pos++;
if (midi_pos == 48000/RENDER_RATE)
{
midi_pos = 0;
thread_set_event(event);
midi_pos++;
if (midi_pos == 48000 / RENDER_RATE) {
midi_pos = 0;
thread_set_event(event);
}
}
static void
mt32_thread(void *param)
{
int buf_pos = 0;
int bsize = buf_size / BUFFER_SEGMENTS;
float *buf;
int16_t *buf16;
thread_set_event(start_event);
while (mt32_on) {
thread_wait_event(event, -1);
thread_reset_event(event);
if (sound_is_float) {
buf = (float *) ((uint8_t *) buffer + buf_pos);
memset(buf, 0, bsize);
mt32_stream(buf, bsize / (2 * sizeof(float)));
buf_pos += bsize;
if (buf_pos >= buf_size) {
givealbuffer_midi(buffer, buf_size / sizeof(float));
buf_pos = 0;
}
} else {
buf16 = (int16_t *) ((uint8_t *) buffer_int16 + buf_pos);
memset(buf16, 0, bsize);
mt32_stream_int16(buf16, bsize / (2 * sizeof(int16_t)));
buf_pos += bsize;
if (buf_pos >= buf_size) {
givealbuffer_midi(buffer_int16, buf_size / sizeof(int16_t));
buf_pos = 0;
}
}
}
}
static void mt32_thread(void *param)
void
mt32_msg(uint8_t *val)
{
int buf_pos = 0;
int bsize = buf_size / BUFFER_SEGMENTS;
float *buf;
int16_t *buf16;
thread_set_event(start_event);
while (mt32_on)
{
thread_wait_event(event, -1);
thread_reset_event(event);
if (sound_is_float)
{
buf = (float *) ((uint8_t*)buffer + buf_pos);
memset(buf, 0, bsize);
mt32_stream(buf, bsize / (2 * sizeof(float)));
buf_pos += bsize;
if (buf_pos >= buf_size)
{
givealbuffer_midi(buffer, buf_size / sizeof(float));
buf_pos = 0;
}
}
else
{
buf16 = (int16_t *) ((uint8_t*)buffer_int16 + buf_pos);
memset(buf16, 0, bsize);
mt32_stream_int16(buf16, bsize / (2 * sizeof(int16_t)));
buf_pos += bsize;
if (buf_pos >= buf_size)
{
givealbuffer_midi(buffer_int16, buf_size / sizeof(int16_t));
buf_pos = 0;
}
}
}
if (context)
mt32_check("mt32emu_play_msg", mt32emu_play_msg(context, *(uint32_t *) val), MT32EMU_RC_OK);
}
void mt32_msg(uint8_t* val)
void
mt32_sysex(uint8_t *data, unsigned int len)
{
if (context) mt32_check("mt32emu_play_msg", mt32emu_play_msg(context, *(uint32_t*)val), MT32EMU_RC_OK);
if (context)
mt32_check("mt32emu_play_sysex", mt32emu_play_sysex(context, data, len), MT32EMU_RC_OK);
}
void mt32_sysex(uint8_t* data, unsigned int len)
void *
mt32emu_init(char *control_rom, char *pcm_rom)
{
if (context) mt32_check("mt32emu_play_sysex", mt32emu_play_sysex(context, data, len), MT32EMU_RC_OK);
}
midi_device_t *dev;
char fn[512];
void* mt32emu_init(char *control_rom, char *pcm_rom)
{
midi_device_t* dev;
char fn[512];
context = mt32emu_create_context(strstr(control_rom, "CM32L_CONTROL.ROM") ? handler_cm32l : handler_mt32, NULL);
context = mt32emu_create_context(strstr(control_rom, "CM32L_CONTROL.ROM") ? handler_cm32l : handler_mt32, NULL);
if (!rom_getfile(control_rom, fn, 512))
return 0;
if (!mt32_check("mt32emu_add_rom_file", mt32emu_add_rom_file(context, fn), MT32EMU_RC_ADDED_CONTROL_ROM))
return 0;
if (!rom_getfile(pcm_rom, fn, 512))
return 0;
if (!mt32_check("mt32emu_add_rom_file", mt32emu_add_rom_file(context, fn), MT32EMU_RC_ADDED_PCM_ROM))
return 0;
if (!rom_getfile(control_rom, fn, 512)) return 0;
if (!mt32_check("mt32emu_add_rom_file", mt32emu_add_rom_file(context, fn), MT32EMU_RC_ADDED_CONTROL_ROM)) return 0;
if (!rom_getfile(pcm_rom, fn, 512)) return 0;
if (!mt32_check("mt32emu_add_rom_file", mt32emu_add_rom_file(context, fn), MT32EMU_RC_ADDED_PCM_ROM)) return 0;
if (!mt32_check("mt32emu_open_synth", mt32emu_open_synth(context), MT32EMU_RC_OK))
return 0;
if (!mt32_check("mt32emu_open_synth", mt32emu_open_synth(context), MT32EMU_RC_OK)) return 0;
samplerate = mt32emu_get_actual_stereo_output_samplerate(context);
/* buf_size = samplerate/RENDER_RATE*2; */
if (sound_is_float)
{
buf_size = (samplerate/RENDER_RATE)*2*BUFFER_SEGMENTS*sizeof(float);
buffer = malloc(buf_size);
buffer_int16 = NULL;
}
else
{
buf_size = (samplerate/RENDER_RATE)*2*BUFFER_SEGMENTS*sizeof(int16_t);
buffer = NULL;
buffer_int16 = malloc(buf_size);
}
mt32emu_set_output_gain(context, device_get_config_int("output_gain")/100.0f);
mt32emu_set_reverb_enabled(context, device_get_config_int("reverb"));
mt32emu_set_reverb_output_gain(context, device_get_config_int("reverb_output_gain")/100.0f);
mt32emu_set_reversed_stereo_enabled(context, device_get_config_int("reversed_stereo"));
mt32emu_set_nice_amp_ramp_enabled(context, device_get_config_int("nice_ramp"));
al_set_midi(samplerate, buf_size);
dev = malloc(sizeof(midi_device_t));
memset(dev, 0, sizeof(midi_device_t));
dev->play_msg = mt32_msg;
dev->play_sysex = mt32_sysex;
dev->poll = mt32_poll;
midi_init(dev);
mt32_on = 1;
start_event = thread_create_event();
event = thread_create_event();
thread_h = thread_create(mt32_thread, 0);
thread_wait_event(start_event, -1);
thread_reset_event(start_event);
return dev;
}
void *mt32_init(const device_t *info)
{
return mt32emu_init("roms/sound/mt32/MT32_CONTROL.ROM", "roms/sound/mt32/MT32_PCM.ROM");
}
void *cm32l_init(const device_t *info)
{
return mt32emu_init("roms/sound/cm32l/CM32L_CONTROL.ROM", "roms/sound/cm32l/CM32L_PCM.ROM");
}
void mt32_close(void* p)
{
if (!p) return;
mt32_on = 0;
thread_set_event(event);
thread_wait(thread_h);
event = NULL;
start_event = NULL;
thread_h = NULL;
if (context) {
mt32emu_close_synth(context);
mt32emu_free_context(context);
}
context = NULL;
if (buffer)
free(buffer);
buffer = NULL;
if (buffer_int16)
free(buffer_int16);
samplerate = mt32emu_get_actual_stereo_output_samplerate(context);
/* buf_size = samplerate/RENDER_RATE*2; */
if (sound_is_float) {
buf_size = (samplerate / RENDER_RATE) * 2 * BUFFER_SEGMENTS * sizeof(float);
buffer = malloc(buf_size);
buffer_int16 = NULL;
} else {
buf_size = (samplerate / RENDER_RATE) * 2 * BUFFER_SEGMENTS * sizeof(int16_t);
buffer = NULL;
buffer_int16 = malloc(buf_size);
}
mt32emu_set_output_gain(context, device_get_config_int("output_gain") / 100.0f);
mt32emu_set_reverb_enabled(context, device_get_config_int("reverb"));
mt32emu_set_reverb_output_gain(context, device_get_config_int("reverb_output_gain") / 100.0f);
mt32emu_set_reversed_stereo_enabled(context, device_get_config_int("reversed_stereo"));
mt32emu_set_nice_amp_ramp_enabled(context, device_get_config_int("nice_ramp"));
al_set_midi(samplerate, buf_size);
dev = malloc(sizeof(midi_device_t));
memset(dev, 0, sizeof(midi_device_t));
dev->play_msg = mt32_msg;
dev->play_sysex = mt32_sysex;
dev->poll = mt32_poll;
midi_init(dev);
mt32_on = 1;
start_event = thread_create_event();
event = thread_create_event();
thread_h = thread_create(mt32_thread, 0);
thread_wait_event(start_event, -1);
thread_reset_event(start_event);
return dev;
}
static const device_config_t mt32_config[] =
void *
mt32_init(const device_t *info)
{
{
.name = "output_gain",
.description = "Output Gain",
.type = CONFIG_SPINNER,
.spinner =
{
.min = 0,
.max = 100
},
.default_int = 100
return mt32emu_init("roms/sound/mt32/MT32_CONTROL.ROM", "roms/sound/mt32/MT32_PCM.ROM");
}
void *
cm32l_init(const device_t *info)
{
return mt32emu_init("roms/sound/cm32l/CM32L_CONTROL.ROM", "roms/sound/cm32l/CM32L_PCM.ROM");
}
void
mt32_close(void *p)
{
if (!p)
return;
mt32_on = 0;
thread_set_event(event);
thread_wait(thread_h);
event = NULL;
start_event = NULL;
thread_h = NULL;
if (context) {
mt32emu_close_synth(context);
mt32emu_free_context(context);
}
context = NULL;
if (buffer)
free(buffer);
buffer = NULL;
if (buffer_int16)
free(buffer_int16);
buffer_int16 = NULL;
}
static const device_config_t mt32_config[] = {
// clang-format off
{
.name = "output_gain",
.description = "Output Gain",
.type = CONFIG_SPINNER,
.spinner = {
.min = 0,
.max = 100
},
{
.name = "reverb",
.description = "Reverb",
.type = CONFIG_BINARY,
.default_int = 1
.default_int = 100
},
{
.name = "reverb",
.description = "Reverb",
.type = CONFIG_BINARY,
.default_int = 1
},
{
.name = "reverb_output_gain",
.description = "Reverb Output Gain",
.type = CONFIG_SPINNER,
.spinner = {
.min = 0,
.max = 100
},
{
.name = "reverb_output_gain",
.description = "Reverb Output Gain",
.type = CONFIG_SPINNER,
.spinner =
{
.min = 0,
.max = 100
},
.default_int = 100
},
{
.name = "reversed_stereo",
.description = "Reversed stereo",
.type = CONFIG_BINARY,
.default_int = 0
},
{
.name = "nice_ramp",
.description = "Nice ramp",
.type = CONFIG_BINARY,
.default_int = 1
},
{
.type = -1
}
.default_int = 100
},
{
.name = "reversed_stereo",
.description = "Reversed stereo",
.type = CONFIG_BINARY,
.default_int = 0
},
{
.name = "nice_ramp",
.description = "Nice ramp",
.type = CONFIG_BINARY,
.default_int = 1
},
{
.type = -1
}
// clang-format on
};
const device_t mt32_device =
{
"Roland MT-32 Emulation",
"mt32",
0,
0,
mt32_init,
mt32_close,
NULL,
{ mt32_available },
NULL,
NULL,
mt32_config
const device_t mt32_device = {
"Roland MT-32 Emulation",
"mt32",
0,
0,
mt32_init,
mt32_close,
NULL,
{ mt32_available },
NULL,
NULL,
mt32_config
};
const device_t cm32l_device =
{
"Roland CM-32L Emulation",
"cm32l",
0,
0,
cm32l_init,
mt32_close,
NULL,
{ cm32l_available },
NULL,
NULL,
mt32_config
const device_t cm32l_device = {
"Roland CM-32L Emulation",
"cm32l",
0,
0,
cm32l_init,
mt32_close,
NULL,
{ cm32l_available },
NULL,
NULL,
mt32_config
};

View File

@@ -1,17 +1,17 @@
/*
* 86Box A hypervisor and IBM PC system emulator that specializes in
* running old operating systems and software designed for IBM
* PC systems and compatibles from 1981 through fairly recent
* system designs based on the PCI bus.
* 86Box A hypervisor and IBM PC system emulator that specializes in
* running old operating systems and software designed for IBM
* PC systems and compatibles from 1981 through fairly recent
* system designs based on the PCI bus.
*
* This file is part of the 86Box distribution.
* This file is part of the 86Box distribution.
*
* MIDI backend implemented using the RtMidi library.
* MIDI backend implemented using the RtMidi library.
*
* Author: Cacodemon345,
* Miran Grca, <mgrca8@gmail.com>
* Copyright 2021 Cacodemon345.
* Copyright 2021 Miran Grca.
* Author: Cacodemon345,
* Miran Grca, <mgrca8@gmail.com>
* Copyright 2021 Cacodemon345.
* Copyright 2021 Miran Grca.
*/
#if defined __has_include
# if __has_include (<RtMidi.h>)
@@ -36,10 +36,10 @@ extern "C"
#include <86box/config.h>
static RtMidiOut * midiout = nullptr;
static RtMidiIn * midiin = nullptr;
static int midi_out_id = 0, midi_in_id = 0;
static const int midi_lengths[8] = {3, 3, 3, 3, 2, 2, 3, 1};
static RtMidiOut * midiout = nullptr;
static RtMidiIn * midiin = nullptr;
static int midi_out_id = 0, midi_in_id = 0;
static const int midi_lengths[8] = {3, 3, 3, 3, 2, 2, 3, 1};
int
@@ -53,7 +53,7 @@ void
rtmidi_play_msg(uint8_t *msg)
{
if (midiout)
midiout->sendMessage(msg, midi_lengths[(msg[0] >> 4) & 7]);
midiout->sendMessage(msg, midi_lengths[(msg[0] >> 4) & 7]);
}
@@ -61,7 +61,7 @@ void
rtmidi_play_sysex(uint8_t *sysex, unsigned int len)
{
if (midiout)
midiout->sendMessage(sysex, len);
midiout->sendMessage(sysex, len);
}
@@ -76,27 +76,27 @@ rtmidi_init(const device_t *info)
dev->write = rtmidi_write;
try {
if (!midiout) midiout = new RtMidiOut;
if (!midiout) midiout = new RtMidiOut;
} catch (RtMidiError& error) {
pclog("Failed to initialize MIDI output: %s\n", error.getMessage().c_str());
return nullptr;
pclog("Failed to initialize MIDI output: %s\n", error.getMessage().c_str());
return nullptr;
}
midi_out_id = config_get_int((char*)SYSTEM_MIDI_NAME, (char*)"midi", 0);
try {
midiout->openPort(midi_out_id);
midiout->openPort(midi_out_id);
} catch (RtMidiError& error) {
pclog("Fallback to default MIDI output port: %s\n", error.getMessage().c_str());
pclog("Fallback to default MIDI output port: %s\n", error.getMessage().c_str());
try {
midiout->openPort(0);
} catch (RtMidiError& error) {
pclog("Failed to initialize MIDI output: %s\n", error.getMessage().c_str());
delete midiout;
midiout = nullptr;
return nullptr;
}
try {
midiout->openPort(0);
} catch (RtMidiError& error) {
pclog("Failed to initialize MIDI output: %s\n", error.getMessage().c_str());
delete midiout;
midiout = nullptr;
return nullptr;
}
}
midi_init(dev);
@@ -109,7 +109,7 @@ void
rtmidi_close(void *p)
{
if (!midiout)
return;
return;
midiout->closePort();
@@ -124,11 +124,11 @@ int
rtmidi_get_num_devs(void)
{
if (!midiout) {
try {
midiout = new RtMidiOut;
} catch (RtMidiError& error) {
pclog("Failed to initialize MIDI output: %s\n", error.getMessage().c_str());
}
try {
midiout = new RtMidiOut;
} catch (RtMidiError& error) {
pclog("Failed to initialize MIDI output: %s\n", error.getMessage().c_str());
}
}
return midiout ? midiout->getPortCount() : 0;
@@ -148,7 +148,7 @@ rtmidi_input_callback(double timeStamp, std::vector<unsigned char> *message, voi
if (message->front() == 0xF0)
midi_in_sysex(message->data(), message->size());
else
midi_in_msg(message->data(), message->size());
midi_in_msg(message->data(), message->size());
}
@@ -159,28 +159,28 @@ rtmidi_input_init(const device_t *info)
memset(dev, 0, sizeof(midi_device_t));
try {
if (!midiin)
midiin = new RtMidiIn;
if (!midiin)
midiin = new RtMidiIn;
} catch (RtMidiError& error) {
pclog("Failed to initialize MIDI input: %s\n", error.getMessage().c_str());
return nullptr;
pclog("Failed to initialize MIDI input: %s\n", error.getMessage().c_str());
return nullptr;
}
midi_in_id = config_get_int((char*)MIDI_INPUT_NAME, (char*)"midi_input", 0);
try {
midiin->openPort(midi_in_id);
midiin->openPort(midi_in_id);
} catch (RtMidiError& error) {
pclog("Fallback to default MIDI input port: %s\n", error.getMessage().c_str());
pclog("Fallback to default MIDI input port: %s\n", error.getMessage().c_str());
try {
midiin->openPort(0);
} catch (RtMidiError& error) {
pclog("Failed to initialize MIDI input: %s\n", error.getMessage().c_str());
delete midiin;
midiin = nullptr;
return nullptr;
}
try {
midiin->openPort(0);
} catch (RtMidiError& error) {
pclog("Failed to initialize MIDI input: %s\n", error.getMessage().c_str());
delete midiin;
midiin = nullptr;
return nullptr;
}
}
midiin->setCallback(&rtmidi_input_callback);
@@ -215,11 +215,11 @@ int
rtmidi_in_get_num_devs(void)
{
if (!midiin) {
try {
midiin = new RtMidiIn;
} catch (RtMidiError& error) {
pclog("Failed to initialize MIDI input: %s\n", error.getMessage().c_str());
}
try {
midiin = new RtMidiIn;
} catch (RtMidiError& error) {
pclog("Failed to initialize MIDI input: %s\n", error.getMessage().c_str());
}
}
return midiin ? midiin->getPortCount() : 0;
@@ -235,29 +235,29 @@ rtmidi_in_get_dev_name(int num, char *s)
static const device_config_t system_midi_config[] =
{
{
"midi", "MIDI out device", CONFIG_MIDI_OUT, "", 0
"midi", "MIDI out device", CONFIG_MIDI_OUT, "", 0
},
{
"", "", -1
"", "", -1
}
};
static const device_config_t midi_input_config[] =
{
{
"midi_input", "MIDI in device", CONFIG_MIDI_IN, "", 0
"midi_input", "MIDI in device", CONFIG_MIDI_IN, "", 0
},
{
"realtime", "MIDI Real time", CONFIG_BINARY, "", 0
"realtime", "MIDI Real time", CONFIG_BINARY, "", 0
},
{
"thruchan", "MIDI Thru", CONFIG_BINARY, "", 1
"thruchan", "MIDI Thru", CONFIG_BINARY, "", 1
},
{
"clockout", "MIDI Clockout", CONFIG_BINARY, "", 1
"clockout", "MIDI Clockout", CONFIG_BINARY, "", 1
},
{
"", "", -1
"", "", -1
}
};

View File

@@ -1,109 +1,105 @@
/*
* 86Box A hypervisor and IBM PC system emulator that specializes in
* running old operating systems and software designed for IBM
* PC systems and compatibles from 1981 through fairly recent
* system designs based on the PCI bus.
* 86Box A hypervisor and IBM PC system emulator that specializes in
* running old operating systems and software designed for IBM
* PC systems and compatibles from 1981 through fairly recent
* system designs based on the PCI bus.
*
* This file is part of the 86Box distribution.
* This file is part of the 86Box distribution.
*
* Interface to the OpenAL sound processing library.
* Interface to the OpenAL sound processing library.
*
*
*
* Authors: Sarah Walker, <http://pcem-emulator.co.uk/>
* Miran Grca, <mgrca8@gmail.com>
* Authors: Sarah Walker, <http://pcem-emulator.co.uk/>
* Miran Grca, <mgrca8@gmail.com>
*
* Copyright 2008-2019 Sarah Walker.
* Copyright 2016-2019 Miran Grca.
* Copyright 2008-2019 Sarah Walker.
* Copyright 2016-2019 Miran Grca.
*/
#include <math.h>
#include <stdio.h>
#include <stdint.h>
#include <string.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <wchar.h>
# undef AL_API
# undef ALC_API
# define AL_LIBTYPE_STATIC
# define ALC_LIBTYPE_STATIC
# include "AL/al.h"
# include "AL/alc.h"
# include "AL/alext.h"
#undef AL_API
#undef ALC_API
#define AL_LIBTYPE_STATIC
#define ALC_LIBTYPE_STATIC
#include "AL/al.h"
#include "AL/alc.h"
#include "AL/alext.h"
#include <86box/86box.h>
#include <86box/sound.h>
#include <86box/midi.h>
#include <86box/sound.h>
#define FREQ 48000
#define BUFLEN SOUNDBUFLEN
#define FREQ 48000
#define BUFLEN SOUNDBUFLEN
ALuint buffers[4]; /* front and back buffers */
ALuint buffers_cd[4]; /* front and back buffers */
ALuint buffers_midi[4]; /* front and back buffers */
static ALuint source[3]; /* audio source */
ALuint buffers[4]; /* front and back buffers */
ALuint buffers_cd[4]; /* front and back buffers */
ALuint buffers_midi[4]; /* front and back buffers */
static ALuint source[3]; /* audio source */
static int midi_freq = 44100;
static int midi_buf_size = 4410;
static int initialized = 0;
static int sources = 2;
static int midi_freq = 44100;
static int midi_buf_size = 4410;
static int initialized = 0;
static int sources = 2;
static ALCcontext *Context;
static ALCdevice *Device;
static ALCdevice *Device;
void
al_set_midi(int freq, int buf_size)
{
midi_freq = freq;
midi_freq = freq;
midi_buf_size = buf_size;
}
void closeal(void);
ALvoid alutInit(ALint *argc,ALbyte **argv)
ALvoid
alutInit(ALint *argc, ALbyte **argv)
{
/* Open device */
Device = alcOpenDevice((ALCchar *)"");
Device = alcOpenDevice((ALCchar *) "");
if (Device != NULL) {
/* Create context(s) */
Context = alcCreateContext(Device, NULL);
if (Context != NULL) {
/* Set active context */
alcMakeContextCurrent(Context);
}
/* Create context(s) */
Context = alcCreateContext(Device, NULL);
if (Context != NULL) {
/* Set active context */
alcMakeContextCurrent(Context);
}
}
}
ALvoid
alutExit(ALvoid)
{
if (Context != NULL) {
/* Disable context */
alcMakeContextCurrent(NULL);
/* Disable context */
alcMakeContextCurrent(NULL);
/* Release context(s) */
alcDestroyContext(Context);
/* Release context(s) */
alcDestroyContext(Context);
if (Device != NULL) {
/* Close device */
alcCloseDevice(Device);
}
if (Device != NULL) {
/* Close device */
alcCloseDevice(Device);
}
}
}
void
closeal(void)
{
if (!initialized)
return;
return;
alSourceStopv(sources, source);
alDeleteSources(sources, source);
if (sources == 3)
alDeleteBuffers(4, buffers_midi);
alDeleteBuffers(4, buffers_midi);
alDeleteBuffers(4, buffers_cd);
alDeleteBuffers(4, buffers);
@@ -112,168 +108,163 @@ closeal(void)
initialized = 0;
}
void
inital(void)
{
float *buf = NULL, *cd_buf = NULL, *midi_buf = NULL;
float *buf = NULL, *cd_buf = NULL, *midi_buf = NULL;
int16_t *buf_int16 = NULL, *cd_buf_int16 = NULL, *midi_buf_int16 = NULL;
int c;
int c;
char *mdn;
int init_midi = 0;
int init_midi = 0;
if (initialized)
return;
return;
alutInit(0, 0);
atexit(closeal);
mdn = midi_device_get_internal_name(midi_device_current);
if (strcmp(mdn, "none") && strcmp(mdn, SYSTEM_MIDI_INTERNAL_NAME))
init_midi = 1; /* If the device is neither none, nor system MIDI, initialize the
MIDI buffer and source, otherwise, do not. */
init_midi = 1; /* If the device is neither none, nor system MIDI, initialize the
MIDI buffer and source, otherwise, do not. */
sources = 2 + !!init_midi;
if (sound_is_float) {
buf = (float *) malloc((BUFLEN << 1) * sizeof(float));
cd_buf = (float *) malloc((CD_BUFLEN << 1) * sizeof(float));
if (init_midi)
midi_buf = (float *) malloc(midi_buf_size * sizeof(float));
buf = (float *) malloc((BUFLEN << 1) * sizeof(float));
cd_buf = (float *) malloc((CD_BUFLEN << 1) * sizeof(float));
if (init_midi)
midi_buf = (float *) malloc(midi_buf_size * sizeof(float));
} else {
buf_int16 = (int16_t *) malloc((BUFLEN << 1) * sizeof(int16_t));
cd_buf_int16 = (int16_t *) malloc((CD_BUFLEN << 1) * sizeof(int16_t));
if (init_midi)
midi_buf_int16 = (int16_t *) malloc(midi_buf_size * sizeof(int16_t));
buf_int16 = (int16_t *) malloc((BUFLEN << 1) * sizeof(int16_t));
cd_buf_int16 = (int16_t *) malloc((CD_BUFLEN << 1) * sizeof(int16_t));
if (init_midi)
midi_buf_int16 = (int16_t *) malloc(midi_buf_size * sizeof(int16_t));
}
alGenBuffers(4, buffers);
alGenBuffers(4, buffers_cd);
if (init_midi)
alGenBuffers(4, buffers_midi);
alGenBuffers(4, buffers_midi);
if (init_midi)
alGenSources(3, source);
alGenSources(3, source);
else
alGenSources(2, source);
alGenSources(2, source);
alSource3f(source[0], AL_POSITION, 0.0, 0.0, 0.0);
alSource3f(source[0], AL_VELOCITY, 0.0, 0.0, 0.0);
alSource3f(source[0], AL_DIRECTION, 0.0, 0.0, 0.0);
alSourcef (source[0], AL_ROLLOFF_FACTOR, 0.0 );
alSourcei (source[0], AL_SOURCE_RELATIVE, AL_TRUE );
alSource3f(source[1], AL_POSITION, 0.0, 0.0, 0.0);
alSource3f(source[1], AL_VELOCITY, 0.0, 0.0, 0.0);
alSource3f(source[1], AL_DIRECTION, 0.0, 0.0, 0.0);
alSourcef (source[1], AL_ROLLOFF_FACTOR, 0.0 );
alSourcei (source[1], AL_SOURCE_RELATIVE, AL_TRUE );
alSource3f(source[0], AL_POSITION, 0.0, 0.0, 0.0);
alSource3f(source[0], AL_VELOCITY, 0.0, 0.0, 0.0);
alSource3f(source[0], AL_DIRECTION, 0.0, 0.0, 0.0);
alSourcef(source[0], AL_ROLLOFF_FACTOR, 0.0);
alSourcei(source[0], AL_SOURCE_RELATIVE, AL_TRUE);
alSource3f(source[1], AL_POSITION, 0.0, 0.0, 0.0);
alSource3f(source[1], AL_VELOCITY, 0.0, 0.0, 0.0);
alSource3f(source[1], AL_DIRECTION, 0.0, 0.0, 0.0);
alSourcef(source[1], AL_ROLLOFF_FACTOR, 0.0);
alSourcei(source[1], AL_SOURCE_RELATIVE, AL_TRUE);
if (init_midi) {
alSource3f(source[2], AL_POSITION, 0.0, 0.0, 0.0);
alSource3f(source[2], AL_VELOCITY, 0.0, 0.0, 0.0);
alSource3f(source[2], AL_DIRECTION, 0.0, 0.0, 0.0);
alSourcef (source[2], AL_ROLLOFF_FACTOR, 0.0 );
alSourcei (source[2], AL_SOURCE_RELATIVE, AL_TRUE );
alSource3f(source[2], AL_POSITION, 0.0, 0.0, 0.0);
alSource3f(source[2], AL_VELOCITY, 0.0, 0.0, 0.0);
alSource3f(source[2], AL_DIRECTION, 0.0, 0.0, 0.0);
alSourcef(source[2], AL_ROLLOFF_FACTOR, 0.0);
alSourcei(source[2], AL_SOURCE_RELATIVE, AL_TRUE);
}
if (sound_is_float) {
memset(buf,0,BUFLEN*2*sizeof(float));
memset(cd_buf,0,BUFLEN*2*sizeof(float));
if (init_midi)
memset(midi_buf,0,midi_buf_size*sizeof(float));
memset(buf, 0, BUFLEN * 2 * sizeof(float));
memset(cd_buf, 0, BUFLEN * 2 * sizeof(float));
if (init_midi)
memset(midi_buf, 0, midi_buf_size * sizeof(float));
} else {
memset(buf_int16,0,BUFLEN*2*sizeof(int16_t));
memset(cd_buf_int16,0,BUFLEN*2*sizeof(int16_t));
if (init_midi)
memset(midi_buf_int16,0,midi_buf_size*sizeof(int16_t));
memset(buf_int16, 0, BUFLEN * 2 * sizeof(int16_t));
memset(cd_buf_int16, 0, BUFLEN * 2 * sizeof(int16_t));
if (init_midi)
memset(midi_buf_int16, 0, midi_buf_size * sizeof(int16_t));
}
for (c=0; c<4; c++) {
if (sound_is_float) {
alBufferData(buffers[c], AL_FORMAT_STEREO_FLOAT32, buf, BUFLEN*2*sizeof(float), FREQ);
alBufferData(buffers_cd[c], AL_FORMAT_STEREO_FLOAT32, cd_buf, CD_BUFLEN*2*sizeof(float), CD_FREQ);
if (init_midi)
alBufferData(buffers_midi[c], AL_FORMAT_STEREO_FLOAT32, midi_buf, midi_buf_size*sizeof(float), midi_freq);
} else {
alBufferData(buffers[c], AL_FORMAT_STEREO16, buf_int16, BUFLEN*2*sizeof(int16_t), FREQ);
alBufferData(buffers_cd[c], AL_FORMAT_STEREO16, cd_buf_int16, CD_BUFLEN*2*sizeof(int16_t), CD_FREQ);
if (init_midi)
alBufferData(buffers_midi[c], AL_FORMAT_STEREO16, midi_buf_int16, midi_buf_size*sizeof(int16_t), midi_freq);
}
for (c = 0; c < 4; c++) {
if (sound_is_float) {
alBufferData(buffers[c], AL_FORMAT_STEREO_FLOAT32, buf, BUFLEN * 2 * sizeof(float), FREQ);
alBufferData(buffers_cd[c], AL_FORMAT_STEREO_FLOAT32, cd_buf, CD_BUFLEN * 2 * sizeof(float), CD_FREQ);
if (init_midi)
alBufferData(buffers_midi[c], AL_FORMAT_STEREO_FLOAT32, midi_buf, midi_buf_size * sizeof(float), midi_freq);
} else {
alBufferData(buffers[c], AL_FORMAT_STEREO16, buf_int16, BUFLEN * 2 * sizeof(int16_t), FREQ);
alBufferData(buffers_cd[c], AL_FORMAT_STEREO16, cd_buf_int16, CD_BUFLEN * 2 * sizeof(int16_t), CD_FREQ);
if (init_midi)
alBufferData(buffers_midi[c], AL_FORMAT_STEREO16, midi_buf_int16, midi_buf_size * sizeof(int16_t), midi_freq);
}
}
alSourceQueueBuffers(source[0], 4, buffers);
alSourceQueueBuffers(source[1], 4, buffers_cd);
if (init_midi)
alSourceQueueBuffers(source[2], 4, buffers_midi);
alSourceQueueBuffers(source[2], 4, buffers_midi);
alSourcePlay(source[0]);
alSourcePlay(source[1]);
if (init_midi)
alSourcePlay(source[2]);
alSourcePlay(source[2]);
if (sound_is_float) {
if (init_midi)
free(midi_buf);
free(cd_buf);
free(buf);
if (init_midi)
free(midi_buf);
free(cd_buf);
free(buf);
} else {
if (init_midi)
free(midi_buf_int16);
free(cd_buf_int16);
free(buf_int16);
if (init_midi)
free(midi_buf_int16);
free(cd_buf_int16);
free(buf_int16);
}
initialized = 1;
}
void
givealbuffer_common(void *buf, uint8_t src, int size, int freq)
{
int processed;
int state;
int processed;
int state;
ALuint buffer;
double gain;
if (!initialized)
return;
return;
alGetSourcei(source[src], AL_SOURCE_STATE, &state);
if (state == 0x1014) {
alSourcePlay(source[src]);
alSourcePlay(source[src]);
}
alGetSourcei(source[src], AL_BUFFERS_PROCESSED, &processed);
if (processed >= 1) {
gain = pow(10.0, (double)sound_gain / 20.0);
alListenerf(AL_GAIN, gain);
gain = pow(10.0, (double) sound_gain / 20.0);
alListenerf(AL_GAIN, gain);
alSourceUnqueueBuffers(source[src], 1, &buffer);
alSourceUnqueueBuffers(source[src], 1, &buffer);
if (sound_is_float)
alBufferData(buffer, AL_FORMAT_STEREO_FLOAT32, buf, size * sizeof(float), freq);
else
alBufferData(buffer, AL_FORMAT_STEREO16, buf, size * sizeof(int16_t), freq);
if (sound_is_float)
alBufferData(buffer, AL_FORMAT_STEREO_FLOAT32, buf, size * sizeof(float), freq);
else
alBufferData(buffer, AL_FORMAT_STEREO16, buf, size * sizeof(int16_t), freq);
alSourceQueueBuffers(source[src], 1, &buffer);
alSourceQueueBuffers(source[src], 1, &buffer);
}
}
void
givealbuffer(void *buf)
{
givealbuffer_common(buf, 0, BUFLEN << 1, FREQ);
}
void
givealbuffer_cd(void *buf)
{
givealbuffer_common(buf, 1, CD_BUFLEN << 1, CD_FREQ);
}
void
givealbuffer_midi(void *buf, uint32_t size)
{

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@@ -1,28 +1,29 @@
/*
* 86Box A hypervisor and IBM PC system emulator that specializes in
* running old operating systems and software designed for IBM
* PC systems and compatibles from 1981 through fairly recent
* system designs based on the PCI bus.
* 86Box A hypervisor and IBM PC system emulator that specializes in
* running old operating systems and software designed for IBM
* PC systems and compatibles from 1981 through fairly recent
* system designs based on the PCI bus.
*
* This file is part of the 86Box distribution.
* This file is part of the 86Box distribution.
*
* AD1848 / CS4248 / CS4231 (Windows Sound System) codec emulation.
* AD1848 / CS4248 / CS4231 (Windows Sound System) codec emulation.
*
*
*
* Authors: Sarah Walker, <http://pcem-emulator.co.uk/>
* TheCollector1995, <mariogplayer@gmail.com>
* RichardG, <richardg867@gmail.com>
* Authors: Sarah Walker, <http://pcem-emulator.co.uk/>
* TheCollector1995, <mariogplayer@gmail.com>
* RichardG, <richardg867@gmail.com>
*
* Copyright 2008-2020 Sarah Walker.
* Copyright 2018-2020 TheCollector1995.
* Copyright 2021-2022 RichardG.
* Copyright 2008-2020 Sarah Walker.
* Copyright 2018-2020 TheCollector1995.
* Copyright 2021-2022 RichardG.
*/
#include <stdio.h>
#include <math.h>
#include <stdint.h>
#include <stdio.h>
#include <string.h>
#include <wchar.h>
#include <math.h>
#include <86box/86box.h>
#include <86box/dma.h>
#include <86box/pic.h>
@@ -30,14 +31,11 @@
#include <86box/sound.h>
#include <86box/snd_ad1848.h>
#define CS4231 0x80
#define CS4236 0x03
#define CS4231 0x80
#define CS4236 0x03
static int ad1848_vols_7bits[128];
static double ad1848_vols_5bits_aux_gain[32];
static int ad1848_vols_7bits[128];
static double ad1848_vols_5bits_aux_gain[32];
void
ad1848_setirq(ad1848_t *ad1848, int irq)
@@ -45,485 +43,519 @@ ad1848_setirq(ad1848_t *ad1848, int irq)
ad1848->irq = irq;
}
void
ad1848_setdma(ad1848_t *ad1848, int dma)
{
ad1848->dma = dma;
}
void
ad1848_updatevolmask(ad1848_t *ad1848)
{
if ((ad1848->type >= AD1848_TYPE_CS4235) && ((ad1848->xregs[4] & 0x10) || ad1848->wten))
ad1848->wave_vol_mask = 0x3f;
ad1848->wave_vol_mask = 0x3f;
else
ad1848->wave_vol_mask = 0x7f;
ad1848->wave_vol_mask = 0x7f;
}
static void
ad1848_updatefreq(ad1848_t *ad1848)
{
double freq;
double freq;
uint8_t set = 0;
if (ad1848->type >= AD1848_TYPE_CS4235) {
if (ad1848->xregs[11] & 0x20) {
freq = 16934400LL;
switch (ad1848->xregs[13]) {
case 1: freq /= 353; break;
case 2: freq /= 529; break;
case 3: freq /= 617; break;
case 4: freq /= 1058; break;
case 5: freq /= 1764; break;
case 6: freq /= 2117; break;
case 7: freq /= 2558; break;
default: freq /= 16 * MAX(ad1848->xregs[13], 21); break;
}
set = 1;
} else if (ad1848->regs[22] & 0x80) {
freq = (ad1848->regs[22] & 1) ? 33868800LL : 49152000LL;
set = (ad1848->regs[22] >> 1) & 0x3f;
switch (ad1848->regs[10] & 0x30) {
case 0x00: freq /= 128 * set; break;
case 0x10: freq /= 64 * set; break;
case 0x20: freq /= 256 * set; break;
}
set = 1;
}
if (ad1848->xregs[11] & 0x20) {
freq = 16934400LL;
switch (ad1848->xregs[13]) {
case 1:
freq /= 353;
break;
case 2:
freq /= 529;
break;
case 3:
freq /= 617;
break;
case 4:
freq /= 1058;
break;
case 5:
freq /= 1764;
break;
case 6:
freq /= 2117;
break;
case 7:
freq /= 2558;
break;
default:
freq /= 16 * MAX(ad1848->xregs[13], 21);
break;
}
set = 1;
} else if (ad1848->regs[22] & 0x80) {
freq = (ad1848->regs[22] & 1) ? 33868800LL : 49152000LL;
set = (ad1848->regs[22] >> 1) & 0x3f;
switch (ad1848->regs[10] & 0x30) {
case 0x00:
freq /= 128 * set;
break;
case 0x10:
freq /= 64 * set;
break;
case 0x20:
freq /= 256 * set;
break;
}
set = 1;
}
}
if (!set) {
freq = (ad1848->regs[8] & 1) ? 16934400LL : 24576000LL;
switch ((ad1848->regs[8] >> 1) & 7) {
case 0: freq /= 3072; break;
case 1: freq /= 1536; break;
case 2: freq /= 896; break;
case 3: freq /= 768; break;
case 4: freq /= 448; break;
case 5: freq /= 384; break;
case 6: freq /= 512; break;
case 7: freq /= 2560; break;
}
freq = (ad1848->regs[8] & 1) ? 16934400LL : 24576000LL;
switch ((ad1848->regs[8] >> 1) & 7) {
case 0:
freq /= 3072;
break;
case 1:
freq /= 1536;
break;
case 2:
freq /= 896;
break;
case 3:
freq /= 768;
break;
case 4:
freq /= 448;
break;
case 5:
freq /= 384;
break;
case 6:
freq /= 512;
break;
case 7:
freq /= 2560;
break;
}
}
ad1848->freq = freq;
ad1848->freq = freq;
ad1848->timer_latch = (uint64_t) ((double) TIMER_USEC * (1000000.0 / (double) ad1848->freq));
}
uint8_t
ad1848_read(uint16_t addr, void *priv)
{
ad1848_t *ad1848 = (ad1848_t *) priv;
uint8_t ret = 0xff;
uint8_t ret = 0xff;
switch (addr & 3) {
case 0: /* Index */
ret = ad1848->index | ad1848->trd | ad1848->mce;
break;
case 0: /* Index */
ret = ad1848->index | ad1848->trd | ad1848->mce;
break;
case 1:
ret = ad1848->regs[ad1848->index];
switch (ad1848->index) {
case 11:
ret ^= 0x20;
ad1848->regs[ad1848->index] = ret;
break;
case 1:
ret = ad1848->regs[ad1848->index];
switch (ad1848->index) {
case 11:
ret ^= 0x20;
ad1848->regs[ad1848->index] = ret;
break;
case 18: case 19:
if (ad1848->type >= AD1848_TYPE_CS4235) {
if ((ad1848->xregs[4] & 0x14) == 0x14) /* FM remapping */
ret = ad1848->xregs[ad1848->index - 12]; /* real FM volume on registers 6 and 7 */
else if (ad1848->wten && !(ad1848->xregs[4] & 0x08)) /* wavetable remapping */
ret = ad1848->xregs[ad1848->index - 2]; /* real wavetable volume on registers 16 and 17 */
}
break;
case 18:
case 19:
if (ad1848->type >= AD1848_TYPE_CS4235) {
if ((ad1848->xregs[4] & 0x14) == 0x14) /* FM remapping */
ret = ad1848->xregs[ad1848->index - 12]; /* real FM volume on registers 6 and 7 */
else if (ad1848->wten && !(ad1848->xregs[4] & 0x08)) /* wavetable remapping */
ret = ad1848->xregs[ad1848->index - 2]; /* real wavetable volume on registers 16 and 17 */
}
break;
case 20: case 21:
/* Backdoor to the Control/RAM registers on CS4235. */
if ((ad1848->type == AD1848_TYPE_CS4235) && (ad1848->xregs[18] & 0x80))
ret = ad1848->cram_read(ad1848->index - 15, ad1848->cram_priv);
break;
case 20:
case 21:
/* Backdoor to the Control/RAM registers on CS4235. */
if ((ad1848->type == AD1848_TYPE_CS4235) && (ad1848->xregs[18] & 0x80))
ret = ad1848->cram_read(ad1848->index - 15, ad1848->cram_priv);
break;
case 23:
if ((ad1848->type >= AD1848_TYPE_CS4235) && (ad1848->regs[23] & 0x08)) {
if ((ad1848->xindex & 0xfe) == 0x00) /* remapped line volume */
ret = ad1848->regs[18 + ad1848->xindex];
else
ret = ad1848->xregs[ad1848->xindex];
}
break;
}
break;
case 23:
if ((ad1848->type >= AD1848_TYPE_CS4235) && (ad1848->regs[23] & 0x08)) {
if ((ad1848->xindex & 0xfe) == 0x00) /* remapped line volume */
ret = ad1848->regs[18 + ad1848->xindex];
else
ret = ad1848->xregs[ad1848->xindex];
}
break;
}
break;
case 2:
ret = ad1848->status;
break;
case 2:
ret = ad1848->status;
break;
}
return ret;
}
void
ad1848_write(uint16_t addr, uint8_t val, void *priv)
{
ad1848_t *ad1848 = (ad1848_t *) priv;
uint8_t temp = 0, updatefreq = 0;
uint8_t temp = 0, updatefreq = 0;
switch (addr & 3) {
case 0: /* Index */
if ((ad1848->regs[12] & 0x40) && (ad1848->type >= AD1848_TYPE_CS4231))
ad1848->index = val & 0x1f; /* cs4231a extended mode enabled */
else
ad1848->index = val & 0x0f; /* ad1848/cs4248 mode TODO: some variants/clones DO NOT mirror, just ignore the writes? */
if (ad1848->type >= AD1848_TYPE_CS4235)
ad1848->regs[23] &= ~0x08; /* clear XRAE */
ad1848->trd = val & 0x20;
ad1848->mce = val & 0x40;
break;
case 0: /* Index */
if ((ad1848->regs[12] & 0x40) && (ad1848->type >= AD1848_TYPE_CS4231))
ad1848->index = val & 0x1f; /* cs4231a extended mode enabled */
else
ad1848->index = val & 0x0f; /* ad1848/cs4248 mode TODO: some variants/clones DO NOT mirror, just ignore the writes? */
if (ad1848->type >= AD1848_TYPE_CS4235)
ad1848->regs[23] &= ~0x08; /* clear XRAE */
ad1848->trd = val & 0x20;
ad1848->mce = val & 0x40;
break;
case 1:
switch (ad1848->index) {
case 10:
if (ad1848->type < AD1848_TYPE_CS4235)
break;
/* fall-through */
case 1:
switch (ad1848->index) {
case 10:
if (ad1848->type < AD1848_TYPE_CS4235)
break;
/* fall-through */
case 8:
updatefreq = 1;
break;
case 8:
updatefreq = 1;
break;
case 9:
if (!ad1848->enable && (val & 0x41) == 0x01) {
if (ad1848->timer_latch)
timer_set_delay_u64(&ad1848->timer_count, ad1848->timer_latch);
else
timer_set_delay_u64(&ad1848->timer_count, TIMER_USEC);
}
ad1848->enable = ((val & 0x41) == 0x01);
if (!ad1848->enable) {
timer_disable(&ad1848->timer_count);
ad1848->out_l = ad1848->out_r = 0;
}
break;
case 9:
if (!ad1848->enable && (val & 0x41) == 0x01) {
if (ad1848->timer_latch)
timer_set_delay_u64(&ad1848->timer_count, ad1848->timer_latch);
else
timer_set_delay_u64(&ad1848->timer_count, TIMER_USEC);
}
ad1848->enable = ((val & 0x41) == 0x01);
if (!ad1848->enable) {
timer_disable(&ad1848->timer_count);
ad1848->out_l = ad1848->out_r = 0;
}
break;
case 11:
return;
case 11:
return;
case 12:
if (ad1848->type != AD1848_TYPE_DEFAULT)
ad1848->regs[12] = ((ad1848->regs[12] & 0x0f) + (val & 0xf0)) | 0x80;
return;
case 12:
if (ad1848->type != AD1848_TYPE_DEFAULT)
ad1848->regs[12] = ((ad1848->regs[12] & 0x0f) + (val & 0xf0)) | 0x80;
return;
case 14:
ad1848->count = ad1848->regs[15] | (val << 8);
break;
case 14:
ad1848->count = ad1848->regs[15] | (val << 8);
break;
case 17:
if (ad1848->type >= AD1848_TYPE_CS4231) /* enable additional data formats on modes 2 and 3 */
ad1848->fmt_mask = (val & 0x40) ? 0xf0 : 0x70;
break;
case 17:
if (ad1848->type >= AD1848_TYPE_CS4231) /* enable additional data formats on modes 2 and 3 */
ad1848->fmt_mask = (val & 0x40) ? 0xf0 : 0x70;
break;
case 18: case 19:
if (ad1848->type >= AD1848_TYPE_CS4235) {
if ((ad1848->xregs[4] & 0x14) == 0x14) { /* FM remapping */
ad1848->xregs[ad1848->index - 12] = val; /* real FM volume on extended registers 6 and 7 */
temp = 1;
case 18:
case 19:
if (ad1848->type >= AD1848_TYPE_CS4235) {
if ((ad1848->xregs[4] & 0x14) == 0x14) { /* FM remapping */
ad1848->xregs[ad1848->index - 12] = val; /* real FM volume on extended registers 6 and 7 */
temp = 1;
if (ad1848->index == 18) {
if (val & 0x80)
ad1848->fm_vol_l = 0;
else
ad1848->fm_vol_l = ad1848_vols_7bits[val & 0x3f];
} else {
if (val & 0x80)
ad1848->fm_vol_r = 0;
else
ad1848->fm_vol_r = ad1848_vols_7bits[val & 0x3f];
}
}
if (ad1848->wten && !(ad1848->xregs[4] & 0x08)) { /* wavetable remapping */
ad1848->xregs[ad1848->index - 2] = val; /* real wavetable volume on extended registers 16 and 17 */
temp = 1;
}
if (ad1848->index == 18) {
if (val & 0x80)
ad1848->fm_vol_l = 0;
else
ad1848->fm_vol_l = ad1848_vols_7bits[val & 0x3f];
} else {
if (val & 0x80)
ad1848->fm_vol_r = 0;
else
ad1848->fm_vol_r = ad1848_vols_7bits[val & 0x3f];
}
}
if (ad1848->wten && !(ad1848->xregs[4] & 0x08)) { /* wavetable remapping */
ad1848->xregs[ad1848->index - 2] = val; /* real wavetable volume on extended registers 16 and 17 */
temp = 1;
}
/* Stop here if any remapping is enabled. */
if (temp)
return;
/* Stop here if any remapping is enabled. */
if (temp)
return;
/* HACK: the Windows 9x driver's "Synth" control writes to this
register with no remapping, even if internal FM is enabled. */
if (ad1848->index == 18) {
if (val & 0x80)
ad1848->fm_vol_l = 0;
else
ad1848->fm_vol_l = (int) ad1848_vols_5bits_aux_gain[val & 0x1f];
} else {
if (val & 0x80)
ad1848->fm_vol_r = 0;
else
ad1848->fm_vol_r = (int) ad1848_vols_5bits_aux_gain[val & 0x1f];
}
}
break;
/* HACK: the Windows 9x driver's "Synth" control writes to this
register with no remapping, even if internal FM is enabled. */
if (ad1848->index == 18) {
if (val & 0x80)
ad1848->fm_vol_l = 0;
else
ad1848->fm_vol_l = (int) ad1848_vols_5bits_aux_gain[val & 0x1f];
} else {
if (val & 0x80)
ad1848->fm_vol_r = 0;
else
ad1848->fm_vol_r = (int) ad1848_vols_5bits_aux_gain[val & 0x1f];
}
}
break;
case 20: case 21:
/* Backdoor to the Control/RAM registers on CS4235. */
if ((ad1848->type == AD1848_TYPE_CS4235) && (ad1848->xregs[18] & 0x80)) {
ad1848->cram_write(ad1848->index - 15, val, ad1848->cram_priv);
val = ad1848->regs[ad1848->index];
}
break;
case 20:
case 21:
/* Backdoor to the Control/RAM registers on CS4235. */
if ((ad1848->type == AD1848_TYPE_CS4235) && (ad1848->xregs[18] & 0x80)) {
ad1848->cram_write(ad1848->index - 15, val, ad1848->cram_priv);
val = ad1848->regs[ad1848->index];
}
break;
case 22:
updatefreq = 1;
break;
case 22:
updatefreq = 1;
break;
case 23:
if ((ad1848->type >= AD1848_TYPE_CS4235) && ((ad1848->regs[12] & 0x60) == 0x60)) {
if (!(ad1848->regs[23] & 0x08)) { /* existing (not new) XRAE is clear */
ad1848->xindex = ((val & 0x04) << 2) | (val >> 4);
break;
}
case 23:
if ((ad1848->type >= AD1848_TYPE_CS4235) && ((ad1848->regs[12] & 0x60) == 0x60)) {
if (!(ad1848->regs[23] & 0x08)) { /* existing (not new) XRAE is clear */
ad1848->xindex = ((val & 0x04) << 2) | (val >> 4);
break;
}
switch (ad1848->xindex) {
case 0: case 1: /* remapped line volume */
ad1848->regs[18 + ad1848->xindex] = val;
return;
switch (ad1848->xindex) {
case 0:
case 1: /* remapped line volume */
ad1848->regs[18 + ad1848->xindex] = val;
return;
case 6:
if (val & 0x80)
ad1848->fm_vol_l = 0;
else
ad1848->fm_vol_l = ad1848_vols_7bits[val & 0x3f];
break;
case 6:
if (val & 0x80)
ad1848->fm_vol_l = 0;
else
ad1848->fm_vol_l = ad1848_vols_7bits[val & 0x3f];
break;
case 7:
if (val & 0x80)
ad1848->fm_vol_r = 0;
else
ad1848->fm_vol_r = ad1848_vols_7bits[val & 0x3f];
break;
case 7:
if (val & 0x80)
ad1848->fm_vol_r = 0;
else
ad1848->fm_vol_r = ad1848_vols_7bits[val & 0x3f];
break;
case 11: case 13:
updatefreq = 1;
break;
case 11:
case 13:
updatefreq = 1;
break;
case 25:
return;
}
ad1848->xregs[ad1848->xindex] = val;
case 25:
return;
}
ad1848->xregs[ad1848->xindex] = val;
if (updatefreq)
ad1848_updatefreq(ad1848);
if (updatefreq)
ad1848_updatefreq(ad1848);
return;
}
break;
return;
}
break;
case 24:
val = ad1848->regs[24] & ((val & 0x70) | 0x0f);
if (!(val & 0x70)) {
ad1848->status &= 0xfe;
picintc(1 << ad1848->irq);
}
break;
case 24:
val = ad1848->regs[24] & ((val & 0x70) | 0x0f);
if (!(val & 0x70)) {
ad1848->status &= 0xfe;
picintc(1 << ad1848->irq);
}
break;
case 25:
return;
}
ad1848->regs[ad1848->index] = val;
case 25:
return;
}
ad1848->regs[ad1848->index] = val;
if (updatefreq)
ad1848_updatefreq(ad1848);
if (updatefreq)
ad1848_updatefreq(ad1848);
if (ad1848->type >= AD1848_TYPE_CS4231) { /* TODO: configure CD volume for CS4248/AD1848 too */
temp = (ad1848->type == AD1848_TYPE_CS4231) ? 18 : 4;
if (ad1848->regs[temp] & 0x80)
ad1848->cd_vol_l = 0;
else
ad1848->cd_vol_l = ad1848_vols_5bits_aux_gain[ad1848->regs[temp] & 0x1f];
temp++;
if (ad1848->regs[temp] & 0x80)
ad1848->cd_vol_r = 0;
else
ad1848->cd_vol_r = ad1848_vols_5bits_aux_gain[ad1848->regs[temp] & 0x1f];
}
break;
if (ad1848->type >= AD1848_TYPE_CS4231) { /* TODO: configure CD volume for CS4248/AD1848 too */
temp = (ad1848->type == AD1848_TYPE_CS4231) ? 18 : 4;
if (ad1848->regs[temp] & 0x80)
ad1848->cd_vol_l = 0;
else
ad1848->cd_vol_l = ad1848_vols_5bits_aux_gain[ad1848->regs[temp] & 0x1f];
temp++;
if (ad1848->regs[temp] & 0x80)
ad1848->cd_vol_r = 0;
else
ad1848->cd_vol_r = ad1848_vols_5bits_aux_gain[ad1848->regs[temp] & 0x1f];
}
break;
case 2:
ad1848->status &= 0xfe;
ad1848->regs[24] &= 0x0f;
break;
case 2:
ad1848->status &= 0xfe;
ad1848->regs[24] &= 0x0f;
break;
}
}
void
ad1848_speed_changed(ad1848_t *ad1848)
{
ad1848->timer_latch = (uint64_t) ((double) TIMER_USEC * (1000000.0 / (double) ad1848->freq));
}
void
ad1848_update(ad1848_t *ad1848)
{
for (; ad1848->pos < sound_pos_global; ad1848->pos++) {
ad1848->buffer[ad1848->pos*2] = ad1848->out_l;
ad1848->buffer[ad1848->pos*2 + 1] = ad1848->out_r;
ad1848->buffer[ad1848->pos * 2] = ad1848->out_l;
ad1848->buffer[ad1848->pos * 2 + 1] = ad1848->out_r;
}
}
static void
ad1848_poll(void *priv)
{
ad1848_t *ad1848 = (ad1848_t *) priv;
if (ad1848->timer_latch)
timer_advance_u64(&ad1848->timer_count, ad1848->timer_latch);
timer_advance_u64(&ad1848->timer_count, ad1848->timer_latch);
else
timer_advance_u64(&ad1848->timer_count, TIMER_USEC * 1000);
timer_advance_u64(&ad1848->timer_count, TIMER_USEC * 1000);
ad1848_update(ad1848);
if (ad1848->enable) {
int32_t temp;
int32_t temp;
switch (ad1848->regs[8] & ad1848->fmt_mask) {
case 0x00: /* Mono, 8-bit PCM */
ad1848->out_l = ad1848->out_r = (dma_channel_read(ad1848->dma) ^ 0x80) * 256;
break;
switch (ad1848->regs[8] & ad1848->fmt_mask) {
case 0x00: /* Mono, 8-bit PCM */
ad1848->out_l = ad1848->out_r = (dma_channel_read(ad1848->dma) ^ 0x80) * 256;
break;
case 0x10: /* Stereo, 8-bit PCM */
ad1848->out_l = (dma_channel_read(ad1848->dma) ^ 0x80) * 256;
ad1848->out_r = (dma_channel_read(ad1848->dma) ^ 0x80) * 256;
break;
case 0x10: /* Stereo, 8-bit PCM */
ad1848->out_l = (dma_channel_read(ad1848->dma) ^ 0x80) * 256;
ad1848->out_r = (dma_channel_read(ad1848->dma) ^ 0x80) * 256;
break;
case 0x40: /* Mono, 16-bit PCM little endian */
temp = dma_channel_read(ad1848->dma);
ad1848->out_l = ad1848->out_r = (dma_channel_read(ad1848->dma) << 8) | temp;
break;
case 0x40: /* Mono, 16-bit PCM little endian */
temp = dma_channel_read(ad1848->dma);
ad1848->out_l = ad1848->out_r = (dma_channel_read(ad1848->dma) << 8) | temp;
break;
case 0x50: /* Stereo, 16-bit PCM little endian */
temp = dma_channel_read(ad1848->dma);
ad1848->out_l = (dma_channel_read(ad1848->dma) << 8) | temp;
temp = dma_channel_read(ad1848->dma);
ad1848->out_r = (dma_channel_read(ad1848->dma) << 8) | temp;
break;
case 0x50: /* Stereo, 16-bit PCM little endian */
temp = dma_channel_read(ad1848->dma);
ad1848->out_l = (dma_channel_read(ad1848->dma) << 8) | temp;
temp = dma_channel_read(ad1848->dma);
ad1848->out_r = (dma_channel_read(ad1848->dma) << 8) | temp;
break;
case 0xc0: /* Mono, 16-bit PCM big endian */
temp = dma_channel_read(ad1848->dma);
ad1848->out_l = ad1848->out_r = dma_channel_read(ad1848->dma) | (temp << 8);
break;
case 0xc0: /* Mono, 16-bit PCM big endian */
temp = dma_channel_read(ad1848->dma);
ad1848->out_l = ad1848->out_r = dma_channel_read(ad1848->dma) | (temp << 8);
break;
case 0xd0: /* Stereo, 16-bit PCM big endian */
temp = dma_channel_read(ad1848->dma);
ad1848->out_l = dma_channel_read(ad1848->dma) | (temp << 8);
temp = dma_channel_read(ad1848->dma);
ad1848->out_r = dma_channel_read(ad1848->dma) | (temp << 8);
break;
}
case 0xd0: /* Stereo, 16-bit PCM big endian */
temp = dma_channel_read(ad1848->dma);
ad1848->out_l = dma_channel_read(ad1848->dma) | (temp << 8);
temp = dma_channel_read(ad1848->dma);
ad1848->out_r = dma_channel_read(ad1848->dma) | (temp << 8);
break;
}
if (ad1848->regs[6] & 0x80)
ad1848->out_l = 0;
else
ad1848->out_l = (ad1848->out_l * ad1848_vols_7bits[ad1848->regs[6] & ad1848->wave_vol_mask]) >> 16;
if (ad1848->regs[6] & 0x80)
ad1848->out_l = 0;
else
ad1848->out_l = (ad1848->out_l * ad1848_vols_7bits[ad1848->regs[6] & ad1848->wave_vol_mask]) >> 16;
if (ad1848->regs[7] & 0x80)
ad1848->out_r = 0;
else
ad1848->out_r = (ad1848->out_r * ad1848_vols_7bits[ad1848->regs[7] & ad1848->wave_vol_mask]) >> 16;
if (ad1848->regs[7] & 0x80)
ad1848->out_r = 0;
else
ad1848->out_r = (ad1848->out_r * ad1848_vols_7bits[ad1848->regs[7] & ad1848->wave_vol_mask]) >> 16;
if (ad1848->count < 0) {
ad1848->count = ad1848->regs[15] | (ad1848->regs[14] << 8);
if (!(ad1848->status & 0x01)) {
ad1848->status |= 0x01;
ad1848->regs[24] |= 0x10;
if (ad1848->regs[10] & 2)
picint(1 << ad1848->irq);
}
}
if (ad1848->count < 0) {
ad1848->count = ad1848->regs[15] | (ad1848->regs[14] << 8);
if (!(ad1848->status & 0x01)) {
ad1848->status |= 0x01;
ad1848->regs[24] |= 0x10;
if (ad1848->regs[10] & 2)
picint(1 << ad1848->irq);
}
}
ad1848->count--;
ad1848->count--;
} else {
ad1848->out_l = ad1848->out_r = 0;
ad1848->cd_vol_l = ad1848->cd_vol_r = 0;
ad1848->out_l = ad1848->out_r = 0;
ad1848->cd_vol_l = ad1848->cd_vol_r = 0;
}
}
void
ad1848_filter_cd_audio(int channel, double *buffer, void *priv)
{
ad1848_t *ad1848 = (ad1848_t *) priv;
double c;
double volume = channel ? ad1848->cd_vol_r : ad1848->cd_vol_l;
double c;
double volume = channel ? ad1848->cd_vol_r : ad1848->cd_vol_l;
c = ((*buffer) * volume) / 65536.0;
c = ((*buffer) * volume) / 65536.0;
*buffer = c;
}
void
ad1848_init(ad1848_t *ad1848, uint8_t type)
{
uint8_t c;
double attenuation;
double attenuation;
ad1848->status = 0xcc;
ad1848->index = ad1848->trd = 0;
ad1848->mce = 0x40;
ad1848->wten = 0;
ad1848->mce = 0x40;
ad1848->wten = 0;
ad1848->regs[0] = ad1848->regs[1] = 0;
ad1848->regs[2] = ad1848->regs[3] = 0x80; /* Line-in */
ad1848->regs[4] = ad1848->regs[5] = 0x80;
ad1848->regs[6] = ad1848->regs[7] = 0x80; /* Left/right Output */
ad1848->regs[8] = 0;
ad1848->regs[9] = 0x08;
ad1848->regs[8] = 0;
ad1848->regs[9] = 0x08;
ad1848->regs[10] = ad1848->regs[11] = 0;
if ((type == AD1848_TYPE_CS4248) || (type == AD1848_TYPE_CS4231) || (type >= AD1848_TYPE_CS4235))
ad1848->regs[12] = 0x8a;
ad1848->regs[12] = 0x8a;
else
ad1848->regs[12] = 0xa;
ad1848->regs[12] = 0xa;
ad1848->regs[13] = 0;
ad1848->regs[14] = ad1848->regs[15] = 0;
if (type == AD1848_TYPE_CS4231) {
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->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;
} else if (type >= AD1848_TYPE_CS4235) {
ad1848->regs[16] = ad1848->regs[17] = 0;
ad1848->regs[18] = ad1848->regs[19] = 0;
ad1848->regs[20] = ad1848->regs[21] = 0;
ad1848->regs[22] = ad1848->regs[23] = 0;
ad1848->regs[24] = 0;
ad1848->regs[25] = CS4236;
ad1848->regs[26] = 0xa0;
ad1848->regs[27] = ad1848->regs[29] = 0;
ad1848->regs[30] = ad1848->regs[31] = 0;
ad1848->regs[16] = ad1848->regs[17] = 0;
ad1848->regs[18] = ad1848->regs[19] = 0;
ad1848->regs[20] = ad1848->regs[21] = 0;
ad1848->regs[22] = ad1848->regs[23] = 0;
ad1848->regs[24] = 0;
ad1848->regs[25] = CS4236;
ad1848->regs[26] = 0xa0;
ad1848->regs[27] = ad1848->regs[29] = 0;
ad1848->regs[30] = ad1848->regs[31] = 0;
ad1848->xregs[0] = ad1848->xregs[1] = 0xe8;
ad1848->xregs[2] = ad1848->xregs[3] = 0xcf;
ad1848->xregs[4] = 0x84;
ad1848->xregs[5] = 0;
ad1848->xregs[6] = ad1848->xregs[7] = 0x80;
ad1848->xregs[8] = ad1848->xregs[9] = 0;
ad1848->xregs[10] = 0x3f;
ad1848->xregs[11] = 0xc0;
ad1848->xregs[14] = ad1848->xregs[15] = 0;
ad1848->xregs[16] = ad1848->xregs[17] = 0;
ad1848->xregs[0] = ad1848->xregs[1] = 0xe8;
ad1848->xregs[2] = ad1848->xregs[3] = 0xcf;
ad1848->xregs[4] = 0x84;
ad1848->xregs[5] = 0;
ad1848->xregs[6] = ad1848->xregs[7] = 0x80;
ad1848->xregs[8] = ad1848->xregs[9] = 0;
ad1848->xregs[10] = 0x3f;
ad1848->xregs[11] = 0xc0;
ad1848->xregs[14] = ad1848->xregs[15] = 0;
ad1848->xregs[16] = ad1848->xregs[17] = 0;
}
ad1848_updatefreq(ad1848);
@@ -534,34 +566,46 @@ ad1848_init(ad1848_t *ad1848, uint8_t type)
ad1848->fmt_mask = 0x70;
for (c = 0; c < 128; c++) {
attenuation = 0.0;
if (c & 0x40) {
if (c < 72) attenuation = (c - 72) * -1.5;
} else {
if (c & 0x01) attenuation -= 1.5;
if (c & 0x02) attenuation -= 3.0;
if (c & 0x04) attenuation -= 6.0;
if (c & 0x08) attenuation -= 12.0;
if (c & 0x10) attenuation -= 24.0;
if (c & 0x20) attenuation -= 48.0;
}
attenuation = 0.0;
if (c & 0x40) {
if (c < 72)
attenuation = (c - 72) * -1.5;
} else {
if (c & 0x01)
attenuation -= 1.5;
if (c & 0x02)
attenuation -= 3.0;
if (c & 0x04)
attenuation -= 6.0;
if (c & 0x08)
attenuation -= 12.0;
if (c & 0x10)
attenuation -= 24.0;
if (c & 0x20)
attenuation -= 48.0;
}
attenuation = pow(10, attenuation / 10);
attenuation = pow(10, attenuation / 10);
ad1848_vols_7bits[c] = (int) (attenuation * 65536);
ad1848_vols_7bits[c] = (int) (attenuation * 65536);
}
for (c = 0; c < 32; c++) {
attenuation = 12.0;
if (c & 0x01) attenuation -= 1.5;
if (c & 0x02) attenuation -= 3.0;
if (c & 0x04) attenuation -= 6.0;
if (c & 0x08) attenuation -= 12.0;
if (c & 0x10) attenuation -= 24.0;
attenuation = 12.0;
if (c & 0x01)
attenuation -= 1.5;
if (c & 0x02)
attenuation -= 3.0;
if (c & 0x04)
attenuation -= 6.0;
if (c & 0x08)
attenuation -= 12.0;
if (c & 0x10)
attenuation -= 24.0;
attenuation = pow(10, attenuation / 10);
attenuation = pow(10, attenuation / 10);
ad1848_vols_5bits_aux_gain[c] = (attenuation * 65536);
ad1848_vols_5bits_aux_gain[c] = (attenuation * 65536);
}
ad1848->type = type;
@@ -569,5 +613,5 @@ ad1848_init(ad1848_t *ad1848, uint8_t type)
timer_add(&ad1848->timer_count, ad1848_poll, ad1848, 0);
if ((ad1848->type != AD1848_TYPE_DEFAULT) && (ad1848->type != AD1848_TYPE_CS4248))
sound_set_cd_audio_filter(ad1848_filter_cd_audio, ad1848);
sound_set_cd_audio_filter(ad1848_filter_cd_audio, ad1848);
}

View File

@@ -1,147 +1,170 @@
#include <stdarg.h>
#include <stdint.h>
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <string.h>
#include <wchar.h>
#define HAVE_STDARG_H
#include <86box/86box.h>
#include <86box/io.h>
#include <86box/timer.h>
#include <86box/mca.h>
#include <86box/device.h>
#include <86box/sound.h>
#include <86box/snd_opl.h>
#include <86box/86box.h>
#include <86box/device.h>
#include <86box/io.h>
#include <86box/mca.h>
#include <86box/sound.h>
#include <86box/timer.h>
#include <86box/snd_opl.h>
#ifdef ENABLE_ADLIB_LOG
int adlib_do_log = ENABLE_ADLIB_LOG;
static void
adlib_log(const char *fmt, ...)
{
va_list ap;
if (adlib_do_log) {
va_start(ap, fmt);
pclog_ex(fmt, ap);
va_end(ap);
va_start(ap, fmt);
pclog_ex(fmt, ap);
va_end(ap);
}
}
#else
#define adlib_log(fmt, ...)
# define adlib_log(fmt, ...)
#endif
typedef struct adlib_t {
opl_t opl;
typedef struct adlib_t
{
opl_t opl;
uint8_t pos_regs[8];
uint8_t pos_regs[8];
} adlib_t;
static void adlib_get_buffer(int32_t *buffer, int len, void *p)
static void
adlib_get_buffer(int32_t *buffer, int len, void *p)
{
adlib_t *adlib = (adlib_t *)p;
int c;
adlib_t *adlib = (adlib_t *) p;
int c;
opl2_update(&adlib->opl);
opl2_update(&adlib->opl);
for (c = 0; c < len * 2; c++)
buffer[c] += (int32_t)adlib->opl.buffer[c];
for (c = 0; c < len * 2; c++)
buffer[c] += (int32_t) adlib->opl.buffer[c];
adlib->opl.pos = 0;
adlib->opl.pos = 0;
}
uint8_t adlib_mca_read(int port, void *p)
uint8_t
adlib_mca_read(int port, void *p)
{
adlib_t *adlib = (adlib_t *)p;
adlib_t *adlib = (adlib_t *) p;
adlib_log("adlib_mca_read: port=%04x\n", port);
adlib_log("adlib_mca_read: port=%04x\n", port);
return adlib->pos_regs[port & 7];
return adlib->pos_regs[port & 7];
}
void adlib_mca_write(int port, uint8_t val, void *p)
void
adlib_mca_write(int port, uint8_t val, void *p)
{
adlib_t *adlib = (adlib_t *)p;
adlib_t *adlib = (adlib_t *) p;
if (port < 0x102)
return;
if (port < 0x102)
return;
adlib_log("adlib_mca_write: port=%04x val=%02x\n", port, val);
adlib_log("adlib_mca_write: port=%04x val=%02x\n", port, val);
switch (port)
{
case 0x102:
if ((adlib->pos_regs[2] & 1) && !(val & 1))
io_removehandler(0x0388, 0x0002, opl2_read, NULL, NULL, opl2_write, NULL, NULL, &adlib->opl);
if (!(adlib->pos_regs[2] & 1) && (val & 1))
io_sethandler(0x0388, 0x0002, opl2_read, NULL, NULL, opl2_write, NULL, NULL, &adlib->opl);
break;
}
adlib->pos_regs[port & 7] = val;
switch (port) {
case 0x102:
if ((adlib->pos_regs[2] & 1) && !(val & 1))
io_removehandler(0x0388, 0x0002,
opl2_read, NULL, NULL,
opl2_write, NULL, NULL,
&adlib->opl);
if (!(adlib->pos_regs[2] & 1) && (val & 1))
io_sethandler(0x0388, 0x0002,
opl2_read, NULL, NULL,
opl2_write, NULL, NULL,
&adlib->opl);
break;
}
adlib->pos_regs[port & 7] = val;
}
uint8_t adlib_mca_feedb(void *p)
uint8_t
adlib_mca_feedb(void *p)
{
adlib_t *adlib = (adlib_t *)p;
adlib_t *adlib = (adlib_t *) p;
return (adlib->pos_regs[2] & 1);
return (adlib->pos_regs[2] & 1);
}
void *adlib_init(const device_t *info)
void *
adlib_init(const device_t *info)
{
adlib_t *adlib = malloc(sizeof(adlib_t));
memset(adlib, 0, sizeof(adlib_t));
adlib_t *adlib = malloc(sizeof(adlib_t));
memset(adlib, 0, sizeof(adlib_t));
adlib_log("adlib_init\n");
opl2_init(&adlib->opl);
io_sethandler(0x0388, 0x0002, opl2_read, NULL, NULL, opl2_write, NULL, NULL, &adlib->opl);
sound_add_handler(adlib_get_buffer, adlib);
return adlib;
adlib_log("adlib_init\n");
opl2_init(&adlib->opl);
io_sethandler(0x0388, 0x0002,
opl2_read, NULL, NULL,
opl2_write, NULL, NULL,
&adlib->opl);
sound_add_handler(adlib_get_buffer, adlib);
return adlib;
}
void *adlib_mca_init(const device_t *info)
void *
adlib_mca_init(const device_t *info)
{
adlib_t *adlib = adlib_init(info);
adlib_t *adlib = adlib_init(info);
io_removehandler(0x0388, 0x0002, opl2_read, NULL, NULL, opl2_write, NULL, NULL, &adlib->opl);
mca_add(adlib_mca_read, adlib_mca_write, adlib_mca_feedb, NULL, adlib);
adlib->pos_regs[0] = 0xd7;
adlib->pos_regs[1] = 0x70;
io_removehandler(0x0388, 0x0002,
opl2_read, NULL, NULL,
opl2_write, NULL, NULL,
&adlib->opl);
mca_add(adlib_mca_read,
adlib_mca_write,
adlib_mca_feedb,
NULL,
adlib);
adlib->pos_regs[0] = 0xd7;
adlib->pos_regs[1] = 0x70;
return adlib;
return adlib;
}
void adlib_close(void *p)
void
adlib_close(void *p)
{
adlib_t *adlib = (adlib_t *)p;
adlib_t *adlib = (adlib_t *) p;
free(adlib);
free(adlib);
}
const device_t adlib_device =
{
"AdLib",
"adlib",
DEVICE_ISA,
0,
adlib_init, adlib_close, NULL,
{ NULL }, NULL, NULL,
NULL
const device_t adlib_device = {
"AdLib",
"adlib",
DEVICE_ISA,
0,
adlib_init,
adlib_close,
NULL,
{ NULL },
NULL,
NULL,
NULL
};
const device_t adlib_mca_device =
{
"AdLib (MCA)",
"adlib_mca",
DEVICE_MCA,
0,
adlib_init, adlib_close, NULL,
{ NULL }, NULL, NULL,
NULL
const device_t adlib_mca_device = {
"AdLib (MCA)",
"adlib_mca",
DEVICE_MCA,
0,
adlib_init,
adlib_close,
NULL,
{ NULL },
NULL,
NULL,
NULL
};

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@@ -30,11 +30,17 @@
#include <86box/sound.h>
#include <86box/snd_sb.h>
#include <86box/gameport.h>
#include <86box/ui.h>
enum {
CMEDIA_CMI8338 = 0x00,
CMEDIA_CMI8738 = 0x11
/* [23:16] = reg 0F [7:0] (reg 0C [31:24])
[13] = onboard flag
[12:8] = reg 0B [4:0] (reg 08 [28:24])
[7:0] = PCI device ID [7:0] */
CMEDIA_CMI8338 = 0x000000,
CMEDIA_CMI8738_4CH = 0x040011, /* chip version 039 with 4-channel output */
CMEDIA_CMI8738_6CH = 0x080011 /* chip version 055 with 6-channel output */
};
typedef struct {
@@ -55,8 +61,9 @@ typedef struct {
} cmi8x38_dma_t;
typedef struct _cmi8x38_ {
uint32_t type;
uint16_t io_base, sb_base, opl_base, mpu_base;
uint8_t type, pci_regs[256], io_regs[256], mixer_ext_regs[16];
uint8_t pci_regs[256], io_regs[256], mixer_ext_regs[16];
int slot;
sb_t *sb;
@@ -96,7 +103,7 @@ static void cmi8x38_speed_changed(void *priv);
static void
cmi8x38_update_irqs(cmi8x38_t *dev)
{
/* Calculate and use the any interrupt flag. */
/* Calculate and use the INTR flag. */
if (*((uint32_t *) &dev->io_regs[0x10]) & 0x0401c003) {
dev->io_regs[0x13] |= 0x80;
pci_set_irq(dev->slot, PCI_INTA);
@@ -108,6 +115,26 @@ cmi8x38_update_irqs(cmi8x38_t *dev)
}
static void
cmi8x38_mpu_irq_update(void *priv, int set)
{
cmi8x38_t *dev = (cmi8x38_t *) priv;
if (set)
dev->io_regs[0x12] |= 0x01;
else
dev->io_regs[0x12] &= ~0x01;
cmi8x38_update_irqs(dev);
}
static int
cmi8x38_mpu_irq_pending(void *priv)
{
cmi8x38_t *dev = (cmi8x38_t *) priv;
return dev->io_regs[0x12] & 0x01;
}
static void
cmi8x38_remap_sb(cmi8x38_t *dev)
{
@@ -154,7 +181,7 @@ cmi8x38_remap_opl(cmi8x38_t *dev)
opl3_write, NULL, NULL, &dev->sb->opl);
}
if (dev->io_regs[0x04] & 0x08) {
if (dev->io_regs[0x1a] & 0x08) {
if (dev->type == CMEDIA_CMI8338)
dev->opl_base = 0x388;
else
@@ -178,10 +205,9 @@ cmi8x38_remap_mpu(cmi8x38_t *dev)
mpu401_change_addr(dev->sb->mpu, 0);
if (dev->io_regs[0x04] & 0x04) {
if (dev->type == CMEDIA_CMI8338)
dev->mpu_base = 0x300 + ((dev->io_regs[0x17] & 0x60) >> 1);
else
dev->mpu_base = 0x330 - ((dev->io_regs[0x17] & 0x60) >> 1);
/* The CMI8338 datasheet's port range of [300:330] is
inaccurate. Drivers expect [330:300] like CMI8738. */
dev->mpu_base = 0x330 - ((dev->io_regs[0x17] & 0x60) >> 1);
} else {
dev->mpu_base = 0;
}
@@ -338,7 +364,6 @@ cmi8x38_write(uint16_t addr, uint8_t val, void *priv)
/* Enable or disable the legacy devices. */
dev->io_regs[addr] = val;
cmi8x38_remap_sb(dev);
cmi8x38_remap_opl(dev);
cmi8x38_remap_mpu(dev);
break;
@@ -418,7 +443,6 @@ cmi8x38_write(uint16_t addr, uint8_t val, void *priv)
/* Remap the legacy devices. */
dev->io_regs[addr] = val;
cmi8x38_remap_sb(dev);
cmi8x38_remap_opl(dev);
cmi8x38_remap_mpu(dev);
break;
@@ -438,6 +462,10 @@ cmi8x38_write(uint16_t addr, uint8_t val, void *priv)
case 0x1a:
val &= 0xfd;
/* Enable or disable the OPL. */
dev->io_regs[addr] = val;
cmi8x38_remap_opl(dev);
break;
case 0x1b:
@@ -666,10 +694,10 @@ cmi8x38_dma_process(void *priv)
nothing consumes it, so it's implemented as an assumption. */
dma->restart = 0;
dma->sample_ptr = *((uint32_t *) &dev->io_regs[dma->reg]);
dma->frame_count_dma = dma->sample_count_out = *((uint16_t *) &dev->io_regs[dma->reg | 0x4]);
dma->frame_count_fragment = *((uint16_t *) &dev->io_regs[dma->reg | 0x6]);
dma->frame_count_dma = dma->sample_count_out = *((uint16_t *) &dev->io_regs[dma->reg | 0x4]) + 1;
dma->frame_count_fragment = *((uint16_t *) &dev->io_regs[dma->reg | 0x6]) + 1;
cmi8x38_log("CMI8x38: Starting DMA %d at %08X\n", dma->id, dma->sample_ptr);
cmi8x38_log("CMI8x38: Starting DMA %d at %08X (count %04X fragment %04X)\n", dma->id, dma->sample_ptr, dma->frame_count_dma, dma->frame_count_fragment);
}
if (dma_status & 0x01) {
@@ -687,7 +715,7 @@ cmi8x38_dma_process(void *priv)
cmi8x38_log("CMI8x38: DMA %d fragment size reached at %04X frames left", dma->id, dma->frame_count_dma - 1);
/* Reset fragment counter. */
dma->frame_count_fragment = *((uint16_t *) &dev->io_regs[dma->reg | 0x6]);
dma->frame_count_fragment = *((uint16_t *) &dev->io_regs[dma->reg | 0x6]) + 1;
/* Fire interrupt if requested. */
if (dev->io_regs[0x0e] & dma_bit) {
@@ -705,6 +733,7 @@ cmi8x38_dma_process(void *priv)
/* Check if the buffer's end was reached. */
if (--dma->frame_count_dma <= 0) {
dma->frame_count_dma = 0;
cmi8x38_log("CMI8x38: DMA %d end reached, restarting\n", dma->id);
/* Restart DMA on the next run. */
@@ -719,6 +748,7 @@ cmi8x38_poll(void *priv)
{
cmi8x38_dma_t *dma = (cmi8x38_dma_t *) priv;
cmi8x38_t *dev = dma->dev;
int16_t *out_l, *out_r, *out_ol, *out_or; /* o = opposite */
/* Schedule next run if playback is enabled. */
if (dev->io_regs[0x00] & (1 << dma->id))
@@ -729,31 +759,45 @@ cmi8x38_poll(void *priv)
/* Update audio buffer. */
cmi8x38_update(dev, dma);
/* Swap stereo pair if this is the rear DMA channel according to ENDBDAC and XCHGDAC. */
if ((dev->io_regs[0x1a] & 0x80) && (!!(dev->io_regs[0x1a] & 0x40) ^ dma->id)) {
out_l = &dma->out_rl;
out_r = &dma->out_rr;
out_ol = &dma->out_fl;
out_or = &dma->out_fr;
} else {
out_l = &dma->out_fl;
out_r = &dma->out_fr;
out_ol = &dma->out_rl;
out_or = &dma->out_rr;
}
*out_ol = *out_or = dma->out_c = dma->out_lfe = 0;
/* Feed next sample from the FIFO. */
switch ((dev->io_regs[0x08] >> (dma->id << 1)) & 0x03) {
case 0x00: /* Mono, 8-bit PCM */
if ((dma->fifo_end - dma->fifo_pos) >= 1) {
dma->out_fl = dma->out_fr = (dma->fifo[dma->fifo_pos++ & (sizeof(dma->fifo) - 1)] ^ 0x80) << 8;
*out_l = *out_r = (dma->fifo[dma->fifo_pos++ & (sizeof(dma->fifo) - 1)] ^ 0x80) << 8;
dma->sample_count_out--;
return;
goto n4spk3d;
}
break;
case 0x01: /* Stereo, 8-bit PCM */
if ((dma->fifo_end - dma->fifo_pos) >= 2) {
dma->out_fl = (dma->fifo[dma->fifo_pos++ & (sizeof(dma->fifo) - 1)] ^ 0x80) << 8;
dma->out_fr = (dma->fifo[dma->fifo_pos++ & (sizeof(dma->fifo) - 1)] ^ 0x80) << 8;
*out_l = (dma->fifo[dma->fifo_pos++ & (sizeof(dma->fifo) - 1)] ^ 0x80) << 8;
*out_r = (dma->fifo[dma->fifo_pos++ & (sizeof(dma->fifo) - 1)] ^ 0x80) << 8;
dma->sample_count_out -= 2;
return;
goto n4spk3d;
}
break;
case 0x02: /* Mono, 16-bit PCM */
if ((dma->fifo_end - dma->fifo_pos) >= 2) {
dma->out_fl = dma->out_fr = *((uint16_t *) &dma->fifo[dma->fifo_pos & (sizeof(dma->fifo) - 1)]);
*out_l = *out_r = *((uint16_t *) &dma->fifo[dma->fifo_pos & (sizeof(dma->fifo) - 1)]);
dma->fifo_pos += 2;
dma->sample_count_out -= 2;
return;
goto n4spk3d;
}
break;
@@ -761,13 +805,12 @@ cmi8x38_poll(void *priv)
switch (dma->channels) {
case 2:
if ((dma->fifo_end - dma->fifo_pos) >= 4) {
dma->out_fl = *((uint16_t *) &dma->fifo[dma->fifo_pos & (sizeof(dma->fifo) - 1)]);
*out_l = *((uint16_t *) &dma->fifo[dma->fifo_pos & (sizeof(dma->fifo) - 1)]);
dma->fifo_pos += 2;
dma->out_fr = *((uint16_t *) &dma->fifo[dma->fifo_pos & (sizeof(dma->fifo) - 1)]);
*out_r = *((uint16_t *) &dma->fifo[dma->fifo_pos & (sizeof(dma->fifo) - 1)]);
dma->fifo_pos += 2;
dma->out_c = dma->out_lfe = dma->out_rl = dma->out_rr = 0;
dma->sample_count_out -= 4;
return;
goto n4spk3d;
}
break;
@@ -781,26 +824,42 @@ cmi8x38_poll(void *priv)
dma->fifo_pos += 2;
dma->out_rr = *((uint16_t *) &dma->fifo[dma->fifo_pos & (sizeof(dma->fifo) - 1)]);
dma->fifo_pos += 2;
dma->out_c = dma->out_lfe = 0;
dma->sample_count_out -= 8;
return;
}
break;
case 5: /* not supported by WDM and Linux drivers; channel layout assumed */
if ((dma->fifo_end - dma->fifo_pos) >= 10) {
dma->out_fl = *((uint16_t *) &dma->fifo[dma->fifo_pos & (sizeof(dma->fifo) - 1)]);
dma->fifo_pos += 2;
dma->out_fr = *((uint16_t *) &dma->fifo[dma->fifo_pos & (sizeof(dma->fifo) - 1)]);
dma->fifo_pos += 2;
dma->out_rl = *((uint16_t *) &dma->fifo[dma->fifo_pos & (sizeof(dma->fifo) - 1)]);
dma->fifo_pos += 2;
dma->out_rr = *((uint16_t *) &dma->fifo[dma->fifo_pos & (sizeof(dma->fifo) - 1)]);
dma->fifo_pos += 2;
dma->out_c = *((uint16_t *) &dma->fifo[dma->fifo_pos & (sizeof(dma->fifo) - 1)]);
dma->fifo_pos += 2;
dma->sample_count_out -= 10;
return;
}
break;
case 6:
if ((dma->fifo_end - dma->fifo_pos) >= 12) {
dma->out_fl = *((uint16_t *) &dma->fifo[dma->fifo_pos & (sizeof(dma->fifo) - 1)]);
dma->fifo_pos += 2;
dma->out_fr = *((uint16_t *) &dma->fifo[dma->fifo_pos & (sizeof(dma->fifo) - 1)]);
dma->fifo_pos += 2;
dma->out_c = *((uint16_t *) &dma->fifo[dma->fifo_pos & (sizeof(dma->fifo) - 1)]);
dma->fifo_pos += 2;
dma->out_lfe = *((uint16_t *) &dma->fifo[dma->fifo_pos & (sizeof(dma->fifo) - 1)]);
dma->fifo_pos += 2;
dma->out_rl = *((uint16_t *) &dma->fifo[dma->fifo_pos & (sizeof(dma->fifo) - 1)]);
dma->fifo_pos += 2;
dma->out_rr = *((uint16_t *) &dma->fifo[dma->fifo_pos & (sizeof(dma->fifo) - 1)]);
dma->fifo_pos += 2;
dma->out_c = *((uint16_t *) &dma->fifo[dma->fifo_pos & (sizeof(dma->fifo) - 1)]);
dma->fifo_pos += 2;
dma->out_lfe= *((uint16_t *) &dma->fifo[dma->fifo_pos & (sizeof(dma->fifo) - 1)]);
dma->fifo_pos += 2;
dma->sample_count_out -= 12;
return;
}
@@ -810,7 +869,15 @@ cmi8x38_poll(void *priv)
}
/* Feed silence if the FIFO is empty. */
dma->out_fl = dma->out_fr = 0;
*out_l = *out_r = 0;
return;
n4spk3d:
/* Mirror front and rear channels if requested. */
if (dev->io_regs[0x1b] & 0x04) {
*out_ol = *out_l;
*out_or = *out_r;
}
}
@@ -842,17 +909,20 @@ cmi8x38_speed_changed(void *priv)
cmi8x38_t *dev = (cmi8x38_t *) priv;
double freq;
uint8_t dsr = dev->io_regs[0x09], freqreg = dev->io_regs[0x05] >> 2,
chfmt45 = dev->io_regs[0x0b], chfmt6 = dev->io_regs[0x15];
chfmt45 = dev->io_regs[0x0b], chfmt6 = dev->io_regs[0x15];
#ifdef ENABLE_CMI8X38_LOG
char buf[256];
sprintf(buf, "%02X-%02X-%02X-%02X", dsr, freqreg, chfmt45, chfmt6);
#endif
/* CMI8338 claims the frequency controls are for DAC (playback) and ADC (recording)
respectively, while CMI8738 claims they're for channel 0 and channel 1. The Linux
driver just assumes the latter definition, so that's what we're going to use here. */
for (int i = 0; i < (sizeof(dev->dma) / sizeof(dev->dma[0])); i++) {
/* More confusion. The Linux driver implies the sample rate doubling
bits take precedence over any configured sample rate. It also
supports 128K with both doubling bits set, which is undocumented. */
bits take precedence over any configured sample rate. 128K with both
doubling bits set is also supported there, but that's for newer chips. */
switch (dsr & 0x03) {
case 0x01: freq = 88200.0; break;
case 0x02: freq = 96000.0; break;
@@ -865,7 +935,7 @@ cmi8x38_speed_changed(void *priv)
dev->dma[i].timer_latch = (uint64_t) ((double) TIMER_USEC * freq);
/* Calculate channel count and set DMA timer period. */
if (dev->type == CMEDIA_CMI8338) {
if ((dev->type == CMEDIA_CMI8338) || (i == 0)) {
stereo: dev->dma[i].channels = 2;
} else {
if (chfmt45 & 0x80)
@@ -878,11 +948,17 @@ stereo: dev->dma[i].channels = 2;
dev->dma[i].dma_latch = freq / dev->dma[i].channels; /* frequency / approximately(dwords * 2) */
/* Shift sample rate configuration registers. */
#ifdef ENABLE_CMI8X38_LOG
sprintf(&buf[strlen(buf)], " %d:%X-%X-%.0f-%dC", i, dsr & 0x03, freqreg & 0x07, 1000000.0 / freq, dev->dma[i].channels);
#endif
dsr >>= 2;
freqreg >>= 3;
}
ui_sb_bugui(buf);
#ifdef ENABLE_CMI8X38_LOG
if (cmi8x38_do_log)
ui_sb_bugui(buf);
#endif
}
@@ -913,8 +989,8 @@ cmi8x38_reset(void *priv)
/* Reset I/O space registers. */
memset(dev->io_regs, 0, sizeof(dev->io_regs));
if (dev->type == CMEDIA_CMI8738)
dev->io_regs[0x0f] = 0x04; /* chip version 039 with 4-channel support */
dev->io_regs[0x0b] = (dev->type >> 8) & 0x1f;
dev->io_regs[0x0f] = dev->type >> 16;
/* Reset DMA channels. */
for (int i = 0; i < (sizeof(dev->dma) / sizeof(dev->dma[0])); i++) {
@@ -936,14 +1012,20 @@ cmi8x38_init(const device_t *info)
memset(dev, 0, sizeof(cmi8x38_t));
/* Set the chip type. */
cmi8x38_log("CMI8x38: init(%03X)\n", info->local);
dev->type = info->local & 0xff;
if ((info->local == CMEDIA_CMI8738_6CH) && !device_get_config_int("six_channel"))
dev->type = CMEDIA_CMI8738_4CH;
else
dev->type = info->local;
cmi8x38_log("CMI8x38: init(%06X)\n", dev->type);
/* Initialize Sound Blaster 16. */
dev->sb = device_add_inst(&sb_16_compat_device, 1);
dev->sb = device_add_inst(device_get_config_int("receive_input") ? &sb_16_compat_device : &sb_16_compat_nompu_device, 1);
dev->sb->opl_enabled = 1; /* let snd_sb.c handle the OPL3 */
dev->sb->mixer_sb16.output_filter = 0; /* no output filtering */
/* Initialize MPU-401 interrupt handler. */
mpu401_irq_attach(dev->sb->mpu, cmi8x38_mpu_irq_update, cmi8x38_mpu_irq_pending, dev);
/* Initialize DMA channels. */
for (int i = 0; i < (sizeof(dev->dma) / sizeof(dev->dma[0])); i++) {
dev->dma[i].id = i;
@@ -963,7 +1045,7 @@ cmi8x38_init(const device_t *info)
dev->gameport = gameport_add(&gameport_pnp_device);
/* Add PCI card. */
dev->slot = pci_add_card((info->local & 0x100) ? PCI_ADD_SOUND : PCI_ADD_NORMAL, cmi8x38_pci_read, cmi8x38_pci_write, dev);
dev->slot = pci_add_card((info->local & (1 << 13)) ? PCI_ADD_SOUND : PCI_ADD_NORMAL, cmi8x38_pci_read, cmi8x38_pci_write, dev);
/* Perform initial reset. */
cmi8x38_reset(dev);
@@ -982,9 +1064,18 @@ cmi8x38_close(void *priv)
free(dev);
}
static const device_config_t cmi8x38_config[] = {
{ "receive_input", "Receive input (MPU-401)", CONFIG_BINARY, "", 1 },
{ "", "", -1 }
};
const device_t cmi8338_device =
{
static const device_config_t cmi8738_config[] = {
{ "six_channel", "MX variant (6-channel)", CONFIG_BINARY, "", 1 },
{ "receive_input", "Receive input (MPU-401)", CONFIG_BINARY, "", 1 },
{ "", "", -1 }
};
const device_t cmi8338_device = {
"C-Media CMI8338",
"cmi8338",
DEVICE_PCI,
@@ -993,44 +1084,41 @@ const device_t cmi8338_device =
{ NULL },
cmi8x38_speed_changed,
NULL,
NULL
cmi8x38_config
};
const device_t cmi8338_onboard_device =
{
const device_t cmi8338_onboard_device = {
"C-Media CMI8338 (On-Board)",
"cmi8338_onboard",
DEVICE_PCI,
CMEDIA_CMI8338 | 0x100,
CMEDIA_CMI8338 | (1 << 13),
cmi8x38_init, cmi8x38_close, cmi8x38_reset,
{ NULL },
cmi8x38_speed_changed,
NULL,
NULL
cmi8x38_config
};
const device_t cmi8738_device =
{
const device_t cmi8738_device = {
"C-Media CMI8738",
"cmi8738",
DEVICE_PCI,
CMEDIA_CMI8738,
CMEDIA_CMI8738_6CH,
cmi8x38_init, cmi8x38_close, cmi8x38_reset,
{ NULL },
cmi8x38_speed_changed,
NULL,
NULL
cmi8738_config
};
const device_t cmi8738_onboard_device =
{
const device_t cmi8738_onboard_device = {
"C-Media CMI8738 (On-Board)",
"cmi8738_onboard",
DEVICE_PCI,
CMEDIA_CMI8738 | 0x100,
CMEDIA_CMI8738_4CH | (1 << 13),
cmi8x38_init, cmi8x38_close, cmi8x38_reset,
{ NULL },
cmi8x38_speed_changed,
NULL,
NULL
cmi8x38_config
};

View File

@@ -1,215 +1,221 @@
#include <stdarg.h>
#include <stdint.h>
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <string.h>
#include <wchar.h>
#define HAVE_STDARG_H
#include <86box/86box.h>
#include <86box/io.h>
#include <86box/device.h>
#include <86box/sound.h>
#include <86box/io.h>
#include <86box/snd_cms.h>
#include <86box/sound.h>
void cms_update(cms_t *cms)
void
cms_update(cms_t *cms)
{
for (; cms->pos < sound_pos_global; cms->pos++)
{
int c, d;
int16_t out_l = 0, out_r = 0;
for (; cms->pos < sound_pos_global; cms->pos++) {
int c, d;
int16_t out_l = 0, out_r = 0;
for (c = 0; c < 4; c++)
{
switch (cms->noisetype[c >> 1][c & 1])
{
case 0: cms->noisefreq[c >> 1][c & 1] = MASTER_CLOCK/256; break;
case 1: cms->noisefreq[c >> 1][c & 1] = MASTER_CLOCK/512; break;
case 2: cms->noisefreq[c >> 1][c & 1] = MASTER_CLOCK/1024; break;
case 3: cms->noisefreq[c >> 1][c & 1] = cms->freq[c >> 1][(c & 1) * 3]; break;
}
}
for (c = 0; c < 2; c ++)
{
if (cms->regs[c][0x1C] & 1)
{
for (d = 0; d < 6; d++)
{
if (cms->regs[c][0x14] & (1 << d))
{
if (cms->stat[c][d]) out_l += (cms->vol[c][d][0] * 90);
if (cms->stat[c][d]) out_r += (cms->vol[c][d][1] * 90);
cms->count[c][d] += cms->freq[c][d];
if (cms->count[c][d] >= 24000)
{
cms->count[c][d] -= 24000;
cms->stat[c][d] ^= 1;
}
}
else if (cms->regs[c][0x15] & (1 << d))
{
if (cms->noise[c][d / 3] & 1) out_l += (cms->vol[c][d][0] * 90);
if (cms->noise[c][d / 3] & 1) out_r += (cms->vol[c][d][0] * 90);
}
}
for (d = 0; d < 2; d++)
{
cms->noisecount[c][d] += cms->noisefreq[c][d];
while (cms->noisecount[c][d] >= 24000)
{
cms->noisecount[c][d] -= 24000;
cms->noise[c][d] <<= 1;
if (!(((cms->noise[c][d] & 0x4000) >> 8) ^ (cms->noise[c][d] & 0x40)))
cms->noise[c][d] |= 1;
}
}
}
}
cms->buffer[(cms->pos << 1)] = out_l;
cms->buffer[(cms->pos << 1) + 1] = out_r;
}
}
void cms_get_buffer(int32_t *buffer, int len, void *p)
{
cms_t *cms = (cms_t *)p;
int c;
cms_update(cms);
for (c = 0; c < len * 2; c++)
buffer[c] += cms->buffer[c];
cms->pos = 0;
}
void cms_write(uint16_t addr, uint8_t val, void *p)
{
cms_t *cms = (cms_t *)p;
int voice;
int chip = (addr & 2) >> 1;
switch (addr & 0xf)
{
for (c = 0; c < 4; c++) {
switch (cms->noisetype[c >> 1][c & 1]) {
case 0:
cms->noisefreq[c >> 1][c & 1] = MASTER_CLOCK / 256;
break;
case 1:
cms->addrs[0] = val & 31;
break;
cms->noisefreq[c >> 1][c & 1] = MASTER_CLOCK / 512;
break;
case 2:
cms->noisefreq[c >> 1][c & 1] = MASTER_CLOCK / 1024;
break;
case 3:
cms->addrs[1] = val & 31;
break;
case 0: case 2:
cms_update(cms);
cms->regs[chip][cms->addrs[chip] & 31] = val;
switch (cms->addrs[chip] & 31)
{
case 0x00: case 0x01: case 0x02: /*Volume*/
case 0x03: case 0x04: case 0x05:
voice = cms->addrs[chip] & 7;
cms->vol[chip][voice][0] = val & 0xf;
cms->vol[chip][voice][1] = val >> 4;
break;
case 0x08: case 0x09: case 0x0A: /*Frequency*/
case 0x0B: case 0x0C: case 0x0D:
voice = cms->addrs[chip] & 7;
cms->latch[chip][voice] = (cms->latch[chip][voice] & 0x700) | val;
cms->freq[chip][voice] = (MASTER_CLOCK/512 << (cms->latch[chip][voice] >> 8)) / (511 - (cms->latch[chip][voice] & 255));
break;
case 0x10: case 0x11: case 0x12: /*Octave*/
voice = (cms->addrs[chip] & 3) << 1;
cms->latch[chip][voice] = (cms->latch[chip][voice] & 0xFF) | ((val & 7) << 8);
cms->latch[chip][voice + 1] = (cms->latch[chip][voice + 1] & 0xFF) | ((val & 0x70) << 4);
cms->freq[chip][voice] = (MASTER_CLOCK/512 << (cms->latch[chip][voice] >> 8)) / (511 - (cms->latch[chip][voice] & 255));
cms->freq[chip][voice + 1] = (MASTER_CLOCK/512 << (cms->latch[chip][voice + 1] >> 8)) / (511 - (cms->latch[chip][voice + 1] & 255));
break;
case 0x16: /*Noise*/
cms->noisetype[chip][0] = val & 3;
cms->noisetype[chip][1] = (val >> 4) & 3;
break;
}
break;
case 0x6: case 0x7:
cms->latched_data = val;
break;
cms->noisefreq[c >> 1][c & 1] = cms->freq[c >> 1][(c & 1) * 3];
break;
}
}
}
uint8_t cms_read(uint16_t addr, void *p)
{
cms_t *cms = (cms_t *)p;
switch (addr & 0xf)
{
case 0x1:
return cms->addrs[0];
case 0x3:
return cms->addrs[1];
case 0x4:
return 0x7f;
case 0xa: case 0xb:
return cms->latched_data;
}
return 0xff;
}
void *cms_init(const device_t *info)
{
cms_t *cms = malloc(sizeof(cms_t));
memset(cms, 0, sizeof(cms_t));
uint16_t addr = device_get_config_hex16("base");
io_sethandler(addr, 0x0010, cms_read, NULL, NULL, cms_write, NULL, NULL, cms);
sound_add_handler(cms_get_buffer, cms);
return cms;
}
void cms_close(void *p)
{
cms_t *cms = (cms_t *)p;
free(cms);
}
static const device_config_t cms_config[] =
{
{
"base", "Address", CONFIG_HEX16, "", 0x220, "", { 0 },
{
{
"0x210", 0x210
},
{
"0x220", 0x220
},
{
"0x230", 0x230
},
{
"0x240", 0x240
},
{
"0x250", 0x250
},
{
"0x260", 0x260
},
{
""
for (c = 0; c < 2; c++) {
if (cms->regs[c][0x1C] & 1) {
for (d = 0; d < 6; d++) {
if (cms->regs[c][0x14] & (1 << d)) {
if (cms->stat[c][d])
out_l += (cms->vol[c][d][0] * 90);
if (cms->stat[c][d])
out_r += (cms->vol[c][d][1] * 90);
cms->count[c][d] += cms->freq[c][d];
if (cms->count[c][d] >= 24000) {
cms->count[c][d] -= 24000;
cms->stat[c][d] ^= 1;
}
} else if (cms->regs[c][0x15] & (1 << d)) {
if (cms->noise[c][d / 3] & 1)
out_l += (cms->vol[c][d][0] * 90);
if (cms->noise[c][d / 3] & 1)
out_r += (cms->vol[c][d][0] * 90);
}
}
},
{
"", "", -1
for (d = 0; d < 2; d++) {
cms->noisecount[c][d] += cms->noisefreq[c][d];
while (cms->noisecount[c][d] >= 24000) {
cms->noisecount[c][d] -= 24000;
cms->noise[c][d] <<= 1;
if (!(((cms->noise[c][d] & 0x4000) >> 8) ^ (cms->noise[c][d] & 0x40)))
cms->noise[c][d] |= 1;
}
}
}
}
cms->buffer[(cms->pos << 1)] = out_l;
cms->buffer[(cms->pos << 1) + 1] = out_r;
}
}
void
cms_get_buffer(int32_t *buffer, int len, void *p)
{
cms_t *cms = (cms_t *) p;
int c;
cms_update(cms);
for (c = 0; c < len * 2; c++)
buffer[c] += cms->buffer[c];
cms->pos = 0;
}
void
cms_write(uint16_t addr, uint8_t val, void *p)
{
cms_t *cms = (cms_t *) p;
int voice;
int chip = (addr & 2) >> 1;
switch (addr & 0xf) {
case 1:
cms->addrs[0] = val & 31;
break;
case 3:
cms->addrs[1] = val & 31;
break;
case 0:
case 2:
cms_update(cms);
cms->regs[chip][cms->addrs[chip] & 31] = val;
switch (cms->addrs[chip] & 31) {
case 0x00:
case 0x01:
case 0x02: /*Volume*/
case 0x03:
case 0x04:
case 0x05:
voice = cms->addrs[chip] & 7;
cms->vol[chip][voice][0] = val & 0xf;
cms->vol[chip][voice][1] = val >> 4;
break;
case 0x08:
case 0x09:
case 0x0A: /*Frequency*/
case 0x0B:
case 0x0C:
case 0x0D:
voice = cms->addrs[chip] & 7;
cms->latch[chip][voice] = (cms->latch[chip][voice] & 0x700) | val;
cms->freq[chip][voice] = (MASTER_CLOCK / 512 << (cms->latch[chip][voice] >> 8)) / (511 - (cms->latch[chip][voice] & 255));
break;
case 0x10:
case 0x11:
case 0x12: /*Octave*/
voice = (cms->addrs[chip] & 3) << 1;
cms->latch[chip][voice] = (cms->latch[chip][voice] & 0xFF) | ((val & 7) << 8);
cms->latch[chip][voice + 1] = (cms->latch[chip][voice + 1] & 0xFF) | ((val & 0x70) << 4);
cms->freq[chip][voice] = (MASTER_CLOCK / 512 << (cms->latch[chip][voice] >> 8)) / (511 - (cms->latch[chip][voice] & 255));
cms->freq[chip][voice + 1] = (MASTER_CLOCK / 512 << (cms->latch[chip][voice + 1] >> 8)) / (511 - (cms->latch[chip][voice + 1] & 255));
break;
case 0x16: /*Noise*/
cms->noisetype[chip][0] = val & 3;
cms->noisetype[chip][1] = (val >> 4) & 3;
break;
}
break;
case 0x6:
case 0x7:
cms->latched_data = val;
break;
}
}
uint8_t
cms_read(uint16_t addr, void *p)
{
cms_t *cms = (cms_t *) p;
switch (addr & 0xf) {
case 0x1:
return cms->addrs[0];
case 0x3:
return cms->addrs[1];
case 0x4:
return 0x7f;
case 0xa:
case 0xb:
return cms->latched_data;
}
return 0xff;
}
void *
cms_init(const device_t *info)
{
cms_t *cms = malloc(sizeof(cms_t));
memset(cms, 0, sizeof(cms_t));
uint16_t addr = device_get_config_hex16("base");
io_sethandler(addr, 0x0010, cms_read, NULL, NULL, cms_write, NULL, NULL, cms);
sound_add_handler(cms_get_buffer, cms);
return cms;
}
void
cms_close(void *p)
{
cms_t *cms = (cms_t *) p;
free(cms);
}
static const device_config_t cms_config[] = {
// clang-format off
{
"base", "Address", CONFIG_HEX16, "", 0x220, "", { 0 },
{
{ "0x210", 0x210 },
{ "0x220", 0x220 },
{ "0x230", 0x230 },
{ "0x240", 0x240 },
{ "0x250", 0x250 },
{ "0x260", 0x260 },
{ "" }
}
},
{
"", "", -1
}
// clang-format on
};
const device_t cms_device =
{
"Creative Music System / Game Blaster",
"cms",
DEVICE_ISA, 0,
cms_init, cms_close, NULL,
{ NULL }, NULL, NULL,
cms_config
const device_t cms_device = {
"Creative Music System / Game Blaster",
"cms",
DEVICE_ISA,
0,
cms_init,
cms_close,
NULL,
{ NULL },
NULL,
NULL,
cms_config
};

File diff suppressed because it is too large Load Diff

Some files were not shown because too many files have changed in this diff Show More