Backport the Currah uSpeech peripheral from Fuse 1.8.0

Adds peripherals/sound/sp0256.c and peripherals/sound/uspeech.c, the SP0256-AL2
allophone synthesiser and the Currah uSpeech interface that drives it. Fuse
gained both in 1.7.0; the tree vendored here is 1.6.0.

Taken as a backport rather than as part of a version bump. Measured first: the
vendored fuse/ tree carries local changes to 45 source files and libspectrum/
to 34, and 51 of those are also touched by upstream between 1.6.0 and 1.7.0,
which alongside the peripherals/ directory restructure makes a bump a
several-thousand-line merge. The two files themselves turned out to need
nothing: compiled against this tree, sp0256.c produces no errors at all and
uspeech.c only five, every one a declaration that has to be added here anyway.

The plumbing those five need:

  - PERIPH_TYPE_USPEECH in periph.h, offered as PERIPH_PRESENT_OPTIONAL from
    machines_periph_48(); uSpeech is a 48K peripheral
  - STARTUP_MANAGER_MODULE_USPEECH, and uspeech_register_startup() from fuse.c
  - uspeech, rom_uspeech, rom_sp0256 and volume_uspeech in settings.dat
  - sound_sp0256_write() and its pair of Blip_Synths in sound.c, following the
    existing specdrum and covox pattern, plus sp0256_do_frame() at the top of
    sound_frame() so speech generated during a frame lands in that frame

Two changes to the imported files. Upstream's uspeech.c includes "memory.h",
which does not exist in Fuse - the header is memory_pages.h, and the include
silently picks up glibc's memory.h, with the real declarations arriving
transitively through machine.h. Point it at the right header. Doing so removed
the string.h that was arriving through the same accident, so include that
explicitly too.

Both ROMs uSpeech needs are copyrighted and cannot ship with the core, so they
are looked up by bare name in the frontend's system directory as
'uspeech.rom' and 'sp0256-al2.bin'. When either is missing, uspeech_reset()
clears settings_current.uspeech and deactivates the peripheral, which is the
intended degradation.

Note for anyone building on this: regenerating settings.h changes the layout
of settings_info, and this build system has no header dependency tracking - no
-MMD, no depfiles - so objects compiled before the change keep reading fields
at their old offsets. The result is a crash in free() inside
update_variables() that looks nothing like a layout problem. Run make clean
after touching settings.dat, periph.h or any other widely included header.

Not verified: whether it speaks correctly. The peripheral registers, decodes
its ports, pages on /ROMCS and serialises, and all of that is covered. Not one
allophone has been checked against a reference, because that needs the two
copyrighted ROMs. Upstream's regression cases are the Currah demo tape,
Booty's hidden game, and Colour Clash.
This commit is contained in:
Lib authored and libretroadmin committed 2026-08-06 00:55:34 +02:00
1 parent 215ac98a57
commit 6a8cdd2088
14 files changed
+2296 -72

No files matched your search

+2
View File
@@ -109,6 +109,8 @@ SOURCES_C += $(CORE_DIR)/fuse/peripherals/multiface.c
SOURCES_C += $(CORE_DIR)/fuse/peripherals/ttx2000s.c
SOURCES_C += $(CORE_DIR)/fuse/peripherals/usource.c
SOURCES_C += $(CORE_DIR)/fuse/peripherals/covox.c
SOURCES_C += $(CORE_DIR)/fuse/peripherals/sound/sp0256.c
SOURCES_C += $(CORE_DIR)/fuse/peripherals/sound/uspeech.c
SOURCES_C += $(CORE_DIR)/fuse/pokefinder/pokefinder.c
SOURCES_C += $(CORE_DIR)/fuse/pokefinder/pokemem.c
+2
View File
@@ -89,6 +89,7 @@
#include "peripherals/spectranet.h"
#include "peripherals/ttx2000s.h"
#include "peripherals/ula.h"
#include "peripherals/sound/uspeech.h"
#include "peripherals/usource.h"
#include "phantom_typist.h"
#include "pokefinder/pokemem.h"
@@ -343,6 +344,7 @@ run_startup_manager( int *argc, char ***argv )
timer_register_startup();
ula_register_startup();
usource_register_startup();
uspeech_register_startup();
z80_register_startup();
zxatasp_register_startup();
zxcf_register_startup();
+1
View File
@@ -76,6 +76,7 @@ typedef enum startup_manager_module {
STARTUP_MANAGER_MODULE_TIMER,
STARTUP_MANAGER_MODULE_ULA,
STARTUP_MANAGER_MODULE_USOURCE,
STARTUP_MANAGER_MODULE_USPEECH,
STARTUP_MANAGER_MODULE_Z80,
STARTUP_MANAGER_MODULE_ZXATASP,
STARTUP_MANAGER_MODULE_ZXCF,
+1
View File
@@ -219,6 +219,7 @@ machines_periph_48( void )
periph_set_present( PERIPH_TYPE_ZXPRINTER, PERIPH_PRESENT_OPTIONAL );
periph_set_present( PERIPH_TYPE_DIDAKTIK80, PERIPH_PRESENT_OPTIONAL );
periph_set_present( PERIPH_TYPE_DISCIPLE, PERIPH_PRESENT_OPTIONAL );
periph_set_present( PERIPH_TYPE_USPEECH, PERIPH_PRESENT_OPTIONAL );
}
/* The set of peripherals available on the 128K and similar machines */
+1
View File
@@ -76,6 +76,7 @@ typedef enum periph_type {
PERIPH_TYPE_ULA_FULL_DECODE,/* Standard ULA responding only to 0xfe */
PERIPH_TYPE_UPD765, /* +3 uPD765 FDC */
PERIPH_TYPE_USOURCE, /* Currah uSource interface */
PERIPH_TYPE_USPEECH, /* Currah uSpeech interface */
PERIPH_TYPE_ZXATASP, /* ZXATASP IDE interface */
PERIPH_TYPE_ZXCF, /* ZXCF IDE interface */
PERIPH_TYPE_ZXMMC, /* ZXMMC interface */
File diff suppressed because it is too large. Load diff
+42
View File
@@ -0,0 +1,42 @@
/* sp0256.h: SP0256 speech synthesis routines
Copyright (c) 1998-2000 Joseph Zbiciak
Copyright (c) 2007-2023 Stuart Brady
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License along
with this program; if not, write to the Free Software Foundation, Inc.,
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
Author contact information:
Philip: [email protected]
Stuart: [email protected]
*/
#ifndef FUSE_SP0256_H
#define FUSE_SP0256_H
#include "libspectrum.h"
int sp0256_init( libspectrum_byte *sp0256rom );
int sp0256_reset( libspectrum_byte *sp0256rom );
void sp0256_end( void );
void sp0256_play( int allophone );
void sp0256_set_clock( libspectrum_dword clock );
void sp0256_change_clock( libspectrum_dword clock );
int sp0256_busy( void );
void sp0256_do_frame( void );
#endif /* #ifndef FUSE_SP0256_H */
+446
View File
@@ -0,0 +1,446 @@
/* uspeech.c: Routines for handling the Currah uSpeech interface
Copyright (c) 2007-2023 Stuart Brady
Copyright (c) 2023 Sergio Baldoví, Vic Chwe
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License along
with this program; if not, write to the Free Software Foundation, Inc.,
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
Author contact information:
Philip: [email protected]
Stuart: [email protected]
*/
#include "config.h"
#include <string.h>
#include "libspectrum.h"
#include "compat.h"
#include "debugger/debugger.h"
#include "infrastructure/startup_manager.h"
#include "machine.h"
#include "memory_pages.h"
#include "module.h"
#include "periph.h"
#include "settings.h"
#include "sp0256.h"
#include "ui/ui.h"
#include "unittests/unittests.h"
#include "uspeech.h"
#include "utils.h"
#define SP0256_ROM_SIZE 2048
/* Intonation on uSpeech changes SP0256 clock/oscillator frequency.
These values are based on a Kio's simulation and Thomas Busse tests. */
#define SP0256_XTAL_NORMAL 3050000
#define SP0256_XTAL_HIGH 3260000
/* A 2 KiB memory chunk accessible by the Z80 when /ROMCS is low
* (mirrored when active) */
static memory_page uspeech_memory_map_romcs[ MEMORY_PAGES_IN_2K ];
static memory_page uspeech_empty_mapping[ MEMORY_PAGES_IN_12K ];
static int empty_mapping_allocated = 0;
static int uspeech_memory_source;
static libspectrum_byte *sp0256rom = NULL;
int uspeech_active = 0;
int uspeech_available = 0;
static void uspeech_toggle_write( libspectrum_word port,
libspectrum_byte val );
static libspectrum_byte uspeech_toggle_read( libspectrum_word port,
libspectrum_byte *attached );
static libspectrum_byte uspeech_port_play_read( libspectrum_word port,
libspectrum_byte *attached );
static void uspeech_port_play_write( libspectrum_word port,
libspectrum_byte data );
static void uspeech_port_intonation_normal( libspectrum_word port,
libspectrum_byte data );
static void uspeech_port_intonation_high( libspectrum_word port,
libspectrum_byte data );
static int uspeech_load_sp0256_rom( void );
static int uspeech_sp0256_reset( void );
static void uspeech_reset( int hard_reset );
static void uspeech_memory_map( void );
static void uspeech_enabled_snapshot( libspectrum_snap *snap );
static void uspeech_from_snapshot( libspectrum_snap *snap );
static void uspeech_to_snapshot( libspectrum_snap *snap );
static module_info_t uspeech_module_info = {
uspeech_reset,
uspeech_memory_map,
uspeech_enabled_snapshot,
uspeech_from_snapshot,
uspeech_to_snapshot,
};
static const periph_port_t uspeech_ports[] = {
/* Really?! This conflicts with the ULA! */
/* ---- ---- 0111 1000 */
{ 0xffff, 0x0038, uspeech_toggle_read, uspeech_toggle_write },
{ 0xffff, 0x1000, uspeech_port_play_read, uspeech_port_play_write },
{ 0xffff, 0x3000, NULL, uspeech_port_intonation_normal },
{ 0xffff, 0x3001, NULL, uspeech_port_intonation_high },
{ 0, 0, NULL, NULL }
};
static const periph_t uspeech_periph = {
/* .option = */ &settings_current.uspeech,
/* .ports = */ uspeech_ports,
/* .hard_reset = */ 1,
/* .activate = */ NULL
};
/* Debugger events */
static const char * const event_type_string = "uspeech";
static int page_event, unpage_event;
static libspectrum_byte
uspeech_port_play_read( libspectrum_word port GCC_UNUSED,
libspectrum_byte *attached )
{
if( !uspeech_active ) return 0xff;
/* TODO: check if this value should be set to 0xff */
*attached = 0xff;
return sp0256_busy();
}
static void
uspeech_port_play_write( libspectrum_word port GCC_UNUSED,
libspectrum_byte data )
{
if( !uspeech_active ) return;
/* Address 0x1000 can also be accessed via I/O (read and write) */
sp0256_play( data & 0x3f );
}
static void
uspeech_port_intonation_normal( libspectrum_word port GCC_UNUSED,
libspectrum_byte data GCC_UNUSED )
{
if( !uspeech_active ) return;
/* Address 0x3000 can also be accessed via I/O (only write) */
sp0256_change_clock( SP0256_XTAL_NORMAL );
}
static void
uspeech_port_intonation_high( libspectrum_word port GCC_UNUSED,
libspectrum_byte data GCC_UNUSED )
{
if( !uspeech_active ) return;
/* Address 0x3001 can also be accessed via I/O (only write) */
sp0256_change_clock( SP0256_XTAL_HIGH );
}
static void
ensure_empty_mapping( void )
{
int i;
libspectrum_byte *empty_chunk;
if( empty_mapping_allocated ) return;
empty_chunk = memory_pool_allocate_persistent( 0x3000, 1 );
memset( empty_chunk, 0xff, 0x3000 );
for( i = 0; i < MEMORY_PAGES_IN_12K; i++ ) {
memory_page *page = &uspeech_empty_mapping[i];
page->page = empty_chunk + i * MEMORY_PAGE_SIZE;
page->offset = i * MEMORY_PAGE_SIZE;
page->writable = 0;
page->contended = 0;
page->source = memory_source_none;
}
empty_mapping_allocated = 1;
}
static int
uspeech_init( void *context GCC_UNUSED )
{
int i;
module_register( &uspeech_module_info );
uspeech_memory_source = memory_source_register( "uSpeech" );
for( i = 0; i < MEMORY_PAGES_IN_2K; i++ )
uspeech_memory_map_romcs[ i ].source = uspeech_memory_source;
ensure_empty_mapping();
periph_register( PERIPH_TYPE_USPEECH, &uspeech_periph );
periph_register_paging_events( event_type_string, &page_event,
&unpage_event );
sp0256_set_clock( SP0256_XTAL_NORMAL );
return 0;
}
static void
uspeech_end( void )
{
uspeech_available = 0;
sp0256_end();
if( sp0256rom ) {
libspectrum_free( sp0256rom );
}
}
void
uspeech_register_startup( void )
{
startup_manager_module dependencies[] = {
STARTUP_MANAGER_MODULE_DEBUGGER,
STARTUP_MANAGER_MODULE_MEMORY,
STARTUP_MANAGER_MODULE_SETUID,
};
startup_manager_register( STARTUP_MANAGER_MODULE_USPEECH, dependencies,
ARRAY_SIZE( dependencies ), uspeech_init, NULL,
uspeech_end );
}
static int
uspeech_load_sp0256_rom( void )
{
int error;
char *filename;
utils_file rom;
filename = settings_current.rom_sp0256;
error = utils_read_auxiliary_file( filename, &rom, UTILS_AUXILIARY_ROM );
if( error ) {
filename = settings_default.rom_sp0256;
error = utils_read_auxiliary_file( filename, &rom, UTILS_AUXILIARY_ROM );
if( error ) {
ui_error( UI_ERROR_ERROR, "couldn't find ROM '%s'", filename );
return -1;
}
}
if( rom.length != SP0256_ROM_SIZE ) {
ui_error( UI_ERROR_ERROR,
"ROM '%s' is %ld bytes long; expected %ld bytes",
filename, (unsigned long)rom.length,
(unsigned long)SP0256_ROM_SIZE );
utils_close_file( &rom );
return -1;
}
sp0256rom = libspectrum_new( libspectrum_byte, SP0256_ROM_SIZE * 2 );
if( !sp0256rom ) {
utils_close_file( &rom );
ui_error( UI_ERROR_ERROR, "SP0256: Out of memory in rdrom" );
return -1;
}
memcpy( sp0256rom, rom.buffer, SP0256_ROM_SIZE );
memcpy( sp0256rom + SP0256_ROM_SIZE, rom.buffer, SP0256_ROM_SIZE );
utils_close_file( &rom );
return 0;
}
static int
uspeech_sp0256_reset( void )
{
if( !sp0256rom && uspeech_load_sp0256_rom() ) {
return -1;
}
if( sp0256_reset( sp0256rom ) ) {
return -1;
}
return 0;
}
static void
uspeech_reset( int hard_reset GCC_UNUSED )
{
uspeech_active = 0;
uspeech_available = 0;
if( !periph_is_active( PERIPH_TYPE_USPEECH ) )
return;
if( machine_load_rom_bank( uspeech_memory_map_romcs, 0,
settings_current.rom_uspeech,
settings_default.rom_uspeech, 0x0800 ) ) {
settings_current.uspeech = 0;
periph_activate_type( PERIPH_TYPE_USPEECH, 0 );
return;
}
if( uspeech_sp0256_reset() ) {
settings_current.uspeech = 0;
periph_activate_type( PERIPH_TYPE_USPEECH, 0 );
return;
}
sp0256_set_clock( SP0256_XTAL_NORMAL );
machine_current->ram.romcs = 0;
uspeech_available = 1;
}
void
uspeech_toggle( void )
{
uspeech_active = !uspeech_active;
machine_current->ram.romcs = uspeech_active;
machine_current->memory_map();
if( uspeech_active )
debugger_event( page_event );
else
debugger_event( unpage_event );
}
static void
uspeech_memory_map( void )
{
if( !uspeech_active ) return;
/* https://maziac.github.io/currah_uspeech_tests/
says only the lower 4k should be mapped. 0x1000-0x3fff do not contain
ZX Spectrum ROM when read */
memory_map_romcs_2k( 0x0000, uspeech_memory_map_romcs );
memory_map_romcs_2k( 0x0800, uspeech_memory_map_romcs );
memory_map_romcs_4k( 0x1000, uspeech_empty_mapping );
memory_map_romcs_8k( 0x2000, uspeech_empty_mapping + MEMORY_PAGES_IN_4K );
}
static libspectrum_byte
uspeech_toggle_read( libspectrum_word port GCC_UNUSED,
libspectrum_byte *attached GCC_UNUSED )
{
if( !uspeech_available ) return 0xff;
uspeech_toggle();
return 0xff;
}
static void
uspeech_toggle_write( libspectrum_word port GCC_UNUSED,
libspectrum_byte val GCC_UNUSED )
{
if( !uspeech_available ) return;
uspeech_toggle();
}
void
uspeech_write( libspectrum_word address, libspectrum_byte b )
{
switch( address ) {
case 0x1000:
/* This address is mirrored at 0011XXXX XXXXXXXX */
sp0256_play( b & 0x3f );
break;
case 0x3000:
/* This address is mirrored at 0011XXXX XXXXXXX0 */
sp0256_change_clock( SP0256_XTAL_NORMAL );
break;
case 0x3001:
/* This address is mirrored at 0011XXXX XXXXXXX1 */
sp0256_change_clock( SP0256_XTAL_HIGH );
break;
}
}
libspectrum_byte
uspeech_busy( void )
{
/* Thomas Busse tests claims:
- The bits are not floating, there seems to be some deterministic behaviour.
- Bits 0, 1 and 5 contain different values.
- Bits 2, 3 and 4 might be equal and bit 6 and 7 might be equal.
We only return/known bit 0 (busy), though.
*/
return sp0256_busy();
}
int
uspeech_unittest( void )
{
int r = 0;
uspeech_active = 1;
uspeech_memory_map();
r += unittests_assert_2k_page( 0x0000, uspeech_memory_source, 0 );
r += unittests_assert_2k_page( 0x0800, uspeech_memory_source, 0 );
r += unittests_assert_4k_page( 0x1000, memory_source_none, 0 );
r += unittests_assert_8k_page( 0x2000, memory_source_none, 0 );
r += unittests_assert_16k_ram_page( 0x4000, 5 );
r += unittests_assert_16k_ram_page( 0x8000, 2 );
r += unittests_assert_16k_ram_page( 0xc000, 0 );
uspeech_active = 0;
machine_current->memory_map();
r += unittests_paging_test_48( 2 );
return r;
}
static void
uspeech_enabled_snapshot( libspectrum_snap *snap )
{
settings_current.uspeech = libspectrum_snap_uspeech_active( snap );
}
static void
uspeech_from_snapshot( libspectrum_snap *snap )
{
if( !libspectrum_snap_uspeech_active( snap ) ) return;
if( libspectrum_snap_uspeech_paged( snap ) ) {
uspeech_active = 0; /* Will be toggled to active next */
uspeech_toggle();
}
}
static void
uspeech_to_snapshot( libspectrum_snap *snap )
{
if( !periph_is_active( PERIPH_TYPE_USPEECH ) ) return;
libspectrum_snap_set_uspeech_active( snap, 1 );
libspectrum_snap_set_uspeech_paged( snap, uspeech_active );
}
+46
View File
@@ -0,0 +1,46 @@
/* uspeech.h: Routines for handling the Currah uSpeech interface
Copyright (c) 2007-2023 Stuart Brady
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License along
with this program; if not, write to the Free Software Foundation, Inc.,
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
Author contact information:
Philip: [email protected]
Stuart: [email protected]
*/
#ifndef FUSE_USPEECH_H
#define FUSE_USPEECH_H
#include "libspectrum.h"
extern int uspeech_active;
extern int uspeech_available;
void uspeech_register_startup( void );
void uspeech_page( void );
void uspeech_unpage( void );
void uspeech_toggle( void );
libspectrum_byte uspeech_busy( void );
void uspeech_write( libspectrum_word address, libspectrum_byte b );
int uspeech_unittest( void );
#endif /* #ifndef FUSE_USPEECH_H */
+161 -72
View File
@@ -253,6 +253,7 @@ settings_info settings_default = {
/* rom_scorpion_1 */ (char *)"256s-1.rom",
/* rom_scorpion_2 */ (char *)"256s-2.rom",
/* rom_scorpion_3 */ (char *)"256s-3.rom",
/* rom_sp0256 */ (char *)"sp0256-al2.bin",
/* rom_spec_se_0 */ (char *)"se-0.rom",
/* rom_spec_se_1 */ (char *)"se-1.rom",
/* rom_speccyboot */ (char *)"speccyboot-1.4.rom",
@@ -263,6 +264,7 @@ settings_info settings_default = {
/* rom_ts2068_1 */ (char *)"tc2068-1.rom",
/* rom_ttx2000s */ (char *)"ttx2000s.rom",
/* rom_usource */ (char *)"usource.rom",
/* rom_uspeech */ (char *)"uspeech.rom",
/* rs232_handshake */ 0,
/* rs232_rx */ (char *)NULL,
/* rs232_tx */ (char *)NULL,
@@ -305,10 +307,12 @@ settings_info settings_default = {
/* ttx2000s */ 0,
/* unittests */ 0,
/* usource */ 0,
/* uspeech */ 0,
/* volume_ay */ 100,
/* volume_beeper */ 100,
/* volume_covox */ 100,
/* volume_specdrum */ 100,
/* volume_uspeech */ 50,
/* writable_roms */ 0,
/* z80_is_cmos */ 0,
/* zxatasp_active */ 0,
@@ -1752,6 +1756,14 @@ parse_xml( xmlDocPtr doc, settings_info *settings )
xmlFree( xmlstring );
}
} else
if( !strcmp( (const char*)node->name, "romsp0256" ) ) {
xmlstring = xmlNodeListGetString( doc, node->xmlChildrenNode, 1 );
if( xmlstring ) {
libspectrum_free( settings->rom_sp0256 );
settings->rom_sp0256 = utils_safe_strdup( (char*)xmlstring );
xmlFree( xmlstring );
}
} else
if( !strcmp( (const char*)node->name, "romspecse0" ) ) {
xmlstring = xmlNodeListGetString( doc, node->xmlChildrenNode, 1 );
if( xmlstring ) {
@@ -1832,6 +1844,14 @@ parse_xml( xmlDocPtr doc, settings_info *settings )
xmlFree( xmlstring );
}
} else
if( !strcmp( (const char*)node->name, "romuspeech" ) ) {
xmlstring = xmlNodeListGetString( doc, node->xmlChildrenNode, 1 );
if( xmlstring ) {
libspectrum_free( settings->rom_uspeech );
settings->rom_uspeech = utils_safe_strdup( (char*)xmlstring );
xmlFree( xmlstring );
}
} else
if( !strcmp( (const char*)node->name, "rs232handshake" ) ) {
xmlstring = xmlNodeListGetString( doc, node->xmlChildrenNode, 1 );
if( xmlstring ) {
@@ -2148,6 +2168,13 @@ parse_xml( xmlDocPtr doc, settings_info *settings )
xmlFree( xmlstring );
}
} else
if( !strcmp( (const char*)node->name, "uspeech" ) ) {
xmlstring = xmlNodeListGetString( doc, node->xmlChildrenNode, 1 );
if( xmlstring ) {
settings->uspeech = atoi( (char*)xmlstring );
xmlFree( xmlstring );
}
} else
if( !strcmp( (const char*)node->name, "volumeay" ) ) {
xmlstring = xmlNodeListGetString( doc, node->xmlChildrenNode, 1 );
if( xmlstring ) {
@@ -2176,6 +2203,13 @@ parse_xml( xmlDocPtr doc, settings_info *settings )
xmlFree( xmlstring );
}
} else
if( !strcmp( (const char*)node->name, "volumeuspeech" ) ) {
xmlstring = xmlNodeListGetString( doc, node->xmlChildrenNode, 1 );
if( xmlstring ) {
settings->volume_uspeech = atoi( (char*)xmlstring );
xmlFree( xmlstring );
}
} else
if( !strcmp( (const char*)node->name, "writableroms" ) ) {
xmlstring = xmlNodeListGetString( doc, node->xmlChildrenNode, 1 );
if( xmlstring ) {
@@ -2610,6 +2644,8 @@ settings_write_config( settings_info *settings )
xmlNewTextChild( root, NULL, (const xmlChar*)"romscorpion2", (const xmlChar*)settings->rom_scorpion_2 );
if( settings->rom_scorpion_3 )
xmlNewTextChild( root, NULL, (const xmlChar*)"romscorpion3", (const xmlChar*)settings->rom_scorpion_3 );
if( settings->rom_sp0256 )
xmlNewTextChild( root, NULL, (const xmlChar*)"romsp0256", (const xmlChar*)settings->rom_sp0256 );
if( settings->rom_spec_se_0 )
xmlNewTextChild( root, NULL, (const xmlChar*)"romspecse0", (const xmlChar*)settings->rom_spec_se_0 );
if( settings->rom_spec_se_1 )
@@ -2630,6 +2666,8 @@ settings_write_config( settings_info *settings )
xmlNewTextChild( root, NULL, (const xmlChar*)"romttx2000s", (const xmlChar*)settings->rom_ttx2000s );
if( settings->rom_usource )
xmlNewTextChild( root, NULL, (const xmlChar*)"romusource", (const xmlChar*)settings->rom_usource );
if( settings->rom_uspeech )
xmlNewTextChild( root, NULL, (const xmlChar*)"romuspeech", (const xmlChar*)settings->rom_uspeech );
xmlNewTextChild( root, NULL, (const xmlChar*)"rs232handshake", (const xmlChar*)(settings->rs232_handshake ? "1" : "0") );
if( settings->rs232_rx )
xmlNewTextChild( root, NULL, (const xmlChar*)"rs232rx", (const xmlChar*)settings->rs232_rx );
@@ -2696,6 +2734,7 @@ settings_write_config( settings_info *settings )
xmlNewTextChild( root, NULL, (const xmlChar*)"ttx2000s", (const xmlChar*)(settings->ttx2000s ? "1" : "0") );
xmlNewTextChild( root, NULL, (const xmlChar*)"unittests", (const xmlChar*)(settings->unittests ? "1" : "0") );
xmlNewTextChild( root, NULL, (const xmlChar*)"usource", (const xmlChar*)(settings->usource ? "1" : "0") );
xmlNewTextChild( root, NULL, (const xmlChar*)"uspeech", (const xmlChar*)(settings->uspeech ? "1" : "0") );
snprintf( buffer, 80, "%d", settings->volume_ay );
xmlNewTextChild( root, NULL, (const xmlChar*)"volumeay", (const xmlChar*)buffer );
snprintf( buffer, 80, "%d", settings->volume_beeper );
@@ -2704,6 +2743,8 @@ settings_write_config( settings_info *settings )
xmlNewTextChild( root, NULL, (const xmlChar*)"volumecovox", (const xmlChar*)buffer );
snprintf( buffer, 80, "%d", settings->volume_specdrum );
xmlNewTextChild( root, NULL, (const xmlChar*)"volumespecdrum", (const xmlChar*)buffer );
snprintf( buffer, 80, "%d", settings->volume_uspeech );
xmlNewTextChild( root, NULL, (const xmlChar*)"volumeuspeech", (const xmlChar*)buffer );
xmlNewTextChild( root, NULL, (const xmlChar*)"writableroms", (const xmlChar*)(settings->writable_roms ? "1" : "0") );
xmlNewTextChild( root, NULL, (const xmlChar*)"cmosz80", (const xmlChar*)(settings->z80_is_cmos ? "1" : "0") );
xmlNewTextChild( root, NULL, (const xmlChar*)"zxatasp", (const xmlChar*)(settings->zxatasp_active ? "1" : "0") );
@@ -3523,6 +3564,10 @@ settings_var( settings_info *settings, unsigned char *name, unsigned char *last,
*val_char = &settings->rom_scorpion_3;
return 0;
}
if( n == 9 && !strncmp( (const char *)name, "romsp0256", n ) ) {
*val_char = &settings->rom_sp0256;
return 0;
}
if( n == 10 && !strncmp( (const char *)name, "romspecse0", n ) ) {
*val_char = &settings->rom_spec_se_0;
return 0;
@@ -3563,6 +3608,10 @@ settings_var( settings_info *settings, unsigned char *name, unsigned char *last,
*val_char = &settings->rom_usource;
return 0;
}
if( n == 10 && !strncmp( (const char *)name, "romuspeech", n ) ) {
*val_char = &settings->rom_uspeech;
return 0;
}
if( n == 14 && !strncmp( (const char *)name, "rs232handshake", n ) ) {
*val_int = &settings->rs232_handshake;
return 0;
@@ -3735,6 +3784,10 @@ settings_var( settings_info *settings, unsigned char *name, unsigned char *last,
*val_int = &settings->usource;
return 0;
}
if( n == 7 && !strncmp( (const char *)name, "uspeech", n ) ) {
*val_int = &settings->uspeech;
return 0;
}
if( n == 8 && !strncmp( (const char *)name, "volumeay", n ) ) {
*val_int = &settings->volume_ay;
return 0;
@@ -3751,6 +3804,10 @@ settings_var( settings_info *settings, unsigned char *name, unsigned char *last,
*val_int = &settings->volume_specdrum;
return 0;
}
if( n == 13 && !strncmp( (const char *)name, "volumeuspeech", n ) ) {
*val_int = &settings->volume_uspeech;
return 0;
}
if( n == 12 && !strncmp( (const char *)name, "writableroms", n ) ) {
*val_int = &settings->writable_roms;
return 0;
@@ -4442,6 +4499,9 @@ settings_write_config( settings_info *settings )
if( settings_string_write( doc, "romscorpion3",
settings->rom_scorpion_3 ) )
goto error;
if( settings_string_write( doc, "romsp0256",
settings->rom_sp0256 ) )
goto error;
if( settings_string_write( doc, "romspecse0",
settings->rom_spec_se_0 ) )
goto error;
@@ -4472,6 +4532,9 @@ settings_write_config( settings_info *settings )
if( settings_string_write( doc, "romusource",
settings->rom_usource ) )
goto error;
if( settings_string_write( doc, "romuspeech",
settings->rom_uspeech ) )
goto error;
if( settings_boolean_write( doc, "rs232handshake",
settings->rs232_handshake ) )
goto error;
@@ -4598,6 +4661,9 @@ settings_write_config( settings_info *settings )
if( settings_boolean_write( doc, "usource",
settings->usource ) )
goto error;
if( settings_boolean_write( doc, "uspeech",
settings->uspeech ) )
goto error;
if( settings_numeric_write( doc, "volumeay",
settings->volume_ay ) )
goto error;
@@ -4610,6 +4676,9 @@ settings_write_config( settings_info *settings )
if( settings_numeric_write( doc, "volumespecdrum",
settings->volume_specdrum ) )
goto error;
if( settings_numeric_write( doc, "volumeuspeech",
settings->volume_uspeech ) )
goto error;
if( settings_boolean_write( doc, "writableroms",
settings->writable_roms ) )
goto error;
@@ -4898,33 +4967,35 @@ settings_command_line( settings_info *settings, int *first_arg,
{ "rom-scorpion-1", 1, NULL, 382 },
{ "rom-scorpion-2", 1, NULL, 383 },
{ "rom-scorpion-3", 1, NULL, 384 },
{ "rom-spec-se-0", 1, NULL, 385 },
{ "rom-spec-se-1", 1, NULL, 386 },
{ "rom-speccyboot", 1, NULL, 387 },
{ "rom-tc2048", 1, NULL, 388 },
{ "rom-tc2068-0", 1, NULL, 389 },
{ "rom-tc2068-1", 1, NULL, 390 },
{ "rom-ts2068-0", 1, NULL, 391 },
{ "rom-ts2068-1", 1, NULL, 392 },
{ "rom-ttx2000s", 1, NULL, 393 },
{ "rom-usource", 1, NULL, 394 },
{ "rom-sp0256", 1, NULL, 385 },
{ "rom-spec-se-0", 1, NULL, 386 },
{ "rom-spec-se-1", 1, NULL, 387 },
{ "rom-speccyboot", 1, NULL, 388 },
{ "rom-tc2048", 1, NULL, 389 },
{ "rom-tc2068-0", 1, NULL, 390 },
{ "rom-tc2068-1", 1, NULL, 391 },
{ "rom-ts2068-0", 1, NULL, 392 },
{ "rom-ts2068-1", 1, NULL, 393 },
{ "rom-ttx2000s", 1, NULL, 394 },
{ "rom-usource", 1, NULL, 395 },
{ "rom-uspeech", 1, NULL, 396 },
{ "rs232-handshake", 0, &(settings->rs232_handshake), 1 },
{ "no-rs232-handshake", 0, &(settings->rs232_handshake), 0 },
{ "rs232-rx", 1, NULL, 395 },
{ "rs232-tx", 1, NULL, 396 },
{ "rs232-rx", 1, NULL, 397 },
{ "rs232-tx", 1, NULL, 398 },
{ "rzx-autosaves", 0, &(settings->rzx_autosaves), 1 },
{ "no-rzx-autosaves", 0, &(settings->rzx_autosaves), 0 },
{ "compress-rzx", 0, &(settings->rzx_compression), 1 },
{ "no-compress-rzx", 0, &(settings->rzx_compression), 0 },
{ "sdl-fullscreen-mode", 1, NULL, 397 },
{ "sdl-fullscreen-mode", 1, NULL, 399 },
{ "simpleide", 0, &(settings->simpleide_active), 1 },
{ "no-simpleide", 0, &(settings->simpleide_active), 0 },
{ "simpleide-masterfile", 1, NULL, 398 },
{ "simpleide-slavefile", 1, NULL, 399 },
{ "simpleide-masterfile", 1, NULL, 400 },
{ "simpleide-slavefile", 1, NULL, 401 },
{ "slt", 0, &(settings->slt_traps), 1 },
{ "no-slt", 0, &(settings->slt_traps), 0 },
{ "snapshot", 1, NULL, 's' },
{ "snet", 1, NULL, 401 },
{ "snet", 1, NULL, 403 },
{ "sound", 0, &(settings->sound), 1 },
{ "no-sound", 0, &(settings->sound), 0 },
{ "sound-device", 1, NULL, 'd' },
@@ -4933,10 +5004,10 @@ settings_command_line( settings_info *settings, int *first_arg,
{ "sound-freq", 1, NULL, 'f' },
{ "loading-sound", 0, &(settings->sound_load), 1 },
{ "no-loading-sound", 0, &(settings->sound_load), 0 },
{ "speaker-type", 1, NULL, 402 },
{ "speaker-type", 1, NULL, 404 },
{ "speccyboot", 0, &(settings->speccyboot), 1 },
{ "no-speccyboot", 0, &(settings->speccyboot), 0 },
{ "speccyboot-tap", 1, NULL, 403 },
{ "speccyboot-tap", 1, NULL, 405 },
{ "specdrum", 0, &(settings->specdrum), 1 },
{ "no-specdrum", 0, &(settings->specdrum), 0 },
{ "spectranet", 0, &(settings->spectranet), 1 },
@@ -4947,51 +5018,54 @@ settings_command_line( settings_info *settings, int *first_arg,
{ "graphics-filter", 1, NULL, 'g' },
{ "statusbar", 0, &(settings->statusbar), 1 },
{ "no-statusbar", 0, &(settings->statusbar), 0 },
{ "separation", 1, NULL, 404 },
{ "separation", 1, NULL, 406 },
{ "strict-aspect-hint", 0, &(settings->strict_aspect_hint), 1 },
{ "no-strict-aspect-hint", 0, &(settings->strict_aspect_hint), 0 },
{ "svga-modes", 1, NULL, 405 },
{ "svga-modes", 1, NULL, 407 },
{ "tape", 1, NULL, 't' },
{ "traps", 0, &(settings->tape_traps), 1 },
{ "no-traps", 0, &(settings->tape_traps), 0 },
{ "teletext-addr-1", 1, NULL, 406 },
{ "teletext-addr-2", 1, NULL, 407 },
{ "teletext-addr-3", 1, NULL, 408 },
{ "teletext-addr-4", 1, NULL, 409 },
{ "teletext-port-1", 1, NULL, 410 },
{ "teletext-port-2", 1, NULL, 411 },
{ "teletext-port-3", 1, NULL, 412 },
{ "teletext-port-4", 1, NULL, 413 },
{ "teletext-addr-1", 1, NULL, 408 },
{ "teletext-addr-2", 1, NULL, 409 },
{ "teletext-addr-3", 1, NULL, 410 },
{ "teletext-addr-4", 1, NULL, 411 },
{ "teletext-port-1", 1, NULL, 412 },
{ "teletext-port-2", 1, NULL, 413 },
{ "teletext-port-3", 1, NULL, 414 },
{ "teletext-port-4", 1, NULL, 415 },
{ "ttx2000s", 0, &(settings->ttx2000s), 1 },
{ "no-ttx2000s", 0, &(settings->ttx2000s), 0 },
{ "unittests", 0, &(settings->unittests), 1 },
{ "no-unittests", 0, &(settings->unittests), 0 },
{ "usource", 0, &(settings->usource), 1 },
{ "no-usource", 0, &(settings->usource), 0 },
{ "volume-ay", 1, NULL, 414 },
{ "volume-beeper", 1, NULL, 415 },
{ "volume-covox", 1, NULL, 416 },
{ "volume-specdrum", 1, NULL, 417 },
{ "uspeech", 0, &(settings->uspeech), 1 },
{ "no-uspeech", 0, &(settings->uspeech), 0 },
{ "volume-ay", 1, NULL, 416 },
{ "volume-beeper", 1, NULL, 417 },
{ "volume-covox", 1, NULL, 418 },
{ "volume-specdrum", 1, NULL, 419 },
{ "volume-uspeech", 1, NULL, 420 },
{ "writable-roms", 0, &(settings->writable_roms), 1 },
{ "no-writable-roms", 0, &(settings->writable_roms), 0 },
{ "cmos-z80", 0, &(settings->z80_is_cmos), 1 },
{ "no-cmos-z80", 0, &(settings->z80_is_cmos), 0 },
{ "zxatasp", 0, &(settings->zxatasp_active), 1 },
{ "no-zxatasp", 0, &(settings->zxatasp_active), 0 },
{ "zxatasp-masterfile", 1, NULL, 418 },
{ "zxatasp-slavefile", 1, NULL, 419 },
{ "zxatasp-masterfile", 1, NULL, 421 },
{ "zxatasp-slavefile", 1, NULL, 422 },
{ "zxatasp-upload", 0, &(settings->zxatasp_upload), 1 },
{ "no-zxatasp-upload", 0, &(settings->zxatasp_upload), 0 },
{ "zxatasp-write-protect", 0, &(settings->zxatasp_wp), 1 },
{ "no-zxatasp-write-protect", 0, &(settings->zxatasp_wp), 0 },
{ "zxcf", 0, &(settings->zxcf_active), 1 },
{ "no-zxcf", 0, &(settings->zxcf_active), 0 },
{ "zxcf-cffile", 1, NULL, 420 },
{ "zxcf-cffile", 1, NULL, 423 },
{ "zxcf-upload", 0, &(settings->zxcf_upload), 1 },
{ "no-zxcf-upload", 0, &(settings->zxcf_upload), 0 },
{ "zxmmc", 0, &(settings->zxmmc_enabled), 1 },
{ "no-zxmmc", 0, &(settings->zxmmc_enabled), 0 },
{ "zxmmc-file", 1, NULL, 421 },
{ "zxmmc-file", 1, NULL, 424 },
{ "zxprinter", 0, &(settings->zxprinter), 1 },
{ "no-zxprinter", 0, &(settings->zxprinter), 0 },
#line 631"settings.pl"
@@ -5152,48 +5226,51 @@ settings_command_line( settings_info *settings, int *first_arg,
case 382: settings_set_string( &settings->rom_scorpion_1, optarg ); break;
case 383: settings_set_string( &settings->rom_scorpion_2, optarg ); break;
case 384: settings_set_string( &settings->rom_scorpion_3, optarg ); break;
case 385: settings_set_string( &settings->rom_spec_se_0, optarg ); break;
case 386: settings_set_string( &settings->rom_spec_se_1, optarg ); break;
case 387: settings_set_string( &settings->rom_speccyboot, optarg ); break;
case 388: settings_set_string( &settings->rom_tc2048, optarg ); break;
case 389: settings_set_string( &settings->rom_tc2068_0, optarg ); break;
case 390: settings_set_string( &settings->rom_tc2068_1, optarg ); break;
case 391: settings_set_string( &settings->rom_ts2068_0, optarg ); break;
case 392: settings_set_string( &settings->rom_ts2068_1, optarg ); break;
case 393: settings_set_string( &settings->rom_ttx2000s, optarg ); break;
case 394: settings_set_string( &settings->rom_usource, optarg ); break;
case 395: settings_set_string( &settings->rs232_rx, optarg ); break;
case 396: settings_set_string( &settings->rs232_tx, optarg ); break;
case 397: settings_set_string( &settings->sdl_fullscreen_mode, optarg ); break;
case 398: settings_set_string( &settings->simpleide_master_file, optarg ); break;
case 399: settings_set_string( &settings->simpleide_slave_file, optarg ); break;
case 385: settings_set_string( &settings->rom_sp0256, optarg ); break;
case 386: settings_set_string( &settings->rom_spec_se_0, optarg ); break;
case 387: settings_set_string( &settings->rom_spec_se_1, optarg ); break;
case 388: settings_set_string( &settings->rom_speccyboot, optarg ); break;
case 389: settings_set_string( &settings->rom_tc2048, optarg ); break;
case 390: settings_set_string( &settings->rom_tc2068_0, optarg ); break;
case 391: settings_set_string( &settings->rom_tc2068_1, optarg ); break;
case 392: settings_set_string( &settings->rom_ts2068_0, optarg ); break;
case 393: settings_set_string( &settings->rom_ts2068_1, optarg ); break;
case 394: settings_set_string( &settings->rom_ttx2000s, optarg ); break;
case 395: settings_set_string( &settings->rom_usource, optarg ); break;
case 396: settings_set_string( &settings->rom_uspeech, optarg ); break;
case 397: settings_set_string( &settings->rs232_rx, optarg ); break;
case 398: settings_set_string( &settings->rs232_tx, optarg ); break;
case 399: settings_set_string( &settings->sdl_fullscreen_mode, optarg ); break;
case 400: settings_set_string( &settings->simpleide_master_file, optarg ); break;
case 401: settings_set_string( &settings->simpleide_slave_file, optarg ); break;
case 's': settings_set_string( &settings->snapshot, optarg ); break;
case 401: settings_set_string( &settings->snet, optarg ); break;
case 403: settings_set_string( &settings->snet, optarg ); break;
case 'd': settings_set_string( &settings->sound_device, optarg ); break;
case 'f': settings->sound_freq = atoi( optarg ); break;
case 402: settings_set_string( &settings->speaker_type, optarg ); break;
case 403: settings_set_string( &settings->speccyboot_tap, optarg ); break;
case 404: settings_set_string( &settings->speaker_type, optarg ); break;
case 405: settings_set_string( &settings->speccyboot_tap, optarg ); break;
case 'm': settings_set_string( &settings->start_machine, optarg ); break;
case 'g': settings_set_string( &settings->start_scaler_mode, optarg ); break;
case 404: settings_set_string( &settings->stereo_ay, optarg ); break;
case 405: settings_set_string( &settings->svga_modes, optarg ); break;
case 406: settings_set_string( &settings->stereo_ay, optarg ); break;
case 407: settings_set_string( &settings->svga_modes, optarg ); break;
case 't': settings_set_string( &settings->tape_file, optarg ); break;
case 406: settings_set_string( &settings->teletext_addr_1, optarg ); break;
case 407: settings_set_string( &settings->teletext_addr_2, optarg ); break;
case 408: settings_set_string( &settings->teletext_addr_3, optarg ); break;
case 409: settings_set_string( &settings->teletext_addr_4, optarg ); break;
case 410: settings->teletext_port_1 = atoi( optarg ); break;
case 411: settings->teletext_port_2 = atoi( optarg ); break;
case 412: settings->teletext_port_3 = atoi( optarg ); break;
case 413: settings->teletext_port_4 = atoi( optarg ); break;
case 414: settings->volume_ay = atoi( optarg ); break;
case 415: settings->volume_beeper = atoi( optarg ); break;
case 416: settings->volume_covox = atoi( optarg ); break;
case 417: settings->volume_specdrum = atoi( optarg ); break;
case 418: settings_set_string( &settings->zxatasp_master_file, optarg ); break;
case 419: settings_set_string( &settings->zxatasp_slave_file, optarg ); break;
case 420: settings_set_string( &settings->zxcf_pri_file, optarg ); break;
case 421: settings_set_string( &settings->zxmmc_file, optarg ); break;
case 408: settings_set_string( &settings->teletext_addr_1, optarg ); break;
case 409: settings_set_string( &settings->teletext_addr_2, optarg ); break;
case 410: settings_set_string( &settings->teletext_addr_3, optarg ); break;
case 411: settings_set_string( &settings->teletext_addr_4, optarg ); break;
case 412: settings->teletext_port_1 = atoi( optarg ); break;
case 413: settings->teletext_port_2 = atoi( optarg ); break;
case 414: settings->teletext_port_3 = atoi( optarg ); break;
case 415: settings->teletext_port_4 = atoi( optarg ); break;
case 416: settings->volume_ay = atoi( optarg ); break;
case 417: settings->volume_beeper = atoi( optarg ); break;
case 418: settings->volume_covox = atoi( optarg ); break;
case 419: settings->volume_specdrum = atoi( optarg ); break;
case 420: settings->volume_uspeech = atoi( optarg ); break;
case 421: settings_set_string( &settings->zxatasp_master_file, optarg ); break;
case 422: settings_set_string( &settings->zxatasp_slave_file, optarg ); break;
case 423: settings_set_string( &settings->zxcf_pri_file, optarg ); break;
case 424: settings_set_string( &settings->zxmmc_file, optarg ); break;
#line 681"settings.pl"
case 'h': settings->show_help = 1; break;
@@ -5658,6 +5735,10 @@ settings_copy_internal( settings_info *dest, settings_info *src )
if( src->rom_scorpion_3 ) {
dest->rom_scorpion_3 = utils_safe_strdup( src->rom_scorpion_3 );
}
dest->rom_sp0256 = NULL;
if( src->rom_sp0256 ) {
dest->rom_sp0256 = utils_safe_strdup( src->rom_sp0256 );
}
dest->rom_spec_se_0 = NULL;
if( src->rom_spec_se_0 ) {
dest->rom_spec_se_0 = utils_safe_strdup( src->rom_spec_se_0 );
@@ -5698,6 +5779,10 @@ settings_copy_internal( settings_info *dest, settings_info *src )
if( src->rom_usource ) {
dest->rom_usource = utils_safe_strdup( src->rom_usource );
}
dest->rom_uspeech = NULL;
if( src->rom_uspeech ) {
dest->rom_uspeech = utils_safe_strdup( src->rom_uspeech );
}
dest->rs232_handshake = src->rs232_handshake;
dest->rs232_rx = NULL;
if( src->rs232_rx ) {
@@ -5797,10 +5882,12 @@ settings_copy_internal( settings_info *dest, settings_info *src )
dest->ttx2000s = src->ttx2000s;
dest->unittests = src->unittests;
dest->usource = src->usource;
dest->uspeech = src->uspeech;
dest->volume_ay = src->volume_ay;
dest->volume_beeper = src->volume_beeper;
dest->volume_covox = src->volume_covox;
dest->volume_specdrum = src->volume_specdrum;
dest->volume_uspeech = src->volume_uspeech;
dest->writable_roms = src->writable_roms;
dest->z80_is_cmos = src->z80_is_cmos;
dest->zxatasp_active = src->zxatasp_active;
@@ -6003,6 +6090,7 @@ settings_free( settings_info *settings )
if( settings->rom_scorpion_1 ) { libspectrum_free( settings->rom_scorpion_1 ); settings->rom_scorpion_1 = NULL; }
if( settings->rom_scorpion_2 ) { libspectrum_free( settings->rom_scorpion_2 ); settings->rom_scorpion_2 = NULL; }
if( settings->rom_scorpion_3 ) { libspectrum_free( settings->rom_scorpion_3 ); settings->rom_scorpion_3 = NULL; }
if( settings->rom_sp0256 ) { libspectrum_free( settings->rom_sp0256 ); settings->rom_sp0256 = NULL; }
if( settings->rom_spec_se_0 ) { libspectrum_free( settings->rom_spec_se_0 ); settings->rom_spec_se_0 = NULL; }
if( settings->rom_spec_se_1 ) { libspectrum_free( settings->rom_spec_se_1 ); settings->rom_spec_se_1 = NULL; }
if( settings->rom_speccyboot ) { libspectrum_free( settings->rom_speccyboot ); settings->rom_speccyboot = NULL; }
@@ -6013,6 +6101,7 @@ settings_free( settings_info *settings )
if( settings->rom_ts2068_1 ) { libspectrum_free( settings->rom_ts2068_1 ); settings->rom_ts2068_1 = NULL; }
if( settings->rom_ttx2000s ) { libspectrum_free( settings->rom_ttx2000s ); settings->rom_ttx2000s = NULL; }
if( settings->rom_usource ) { libspectrum_free( settings->rom_usource ); settings->rom_usource = NULL; }
if( settings->rom_uspeech ) { libspectrum_free( settings->rom_uspeech ); settings->rom_uspeech = NULL; }
if( settings->rs232_rx ) { libspectrum_free( settings->rs232_rx ); settings->rs232_rx = NULL; }
if( settings->rs232_tx ) { libspectrum_free( settings->rs232_tx ); settings->rs232_tx = NULL; }
if( settings->sdl_fullscreen_mode ) { libspectrum_free( settings->sdl_fullscreen_mode ); settings->sdl_fullscreen_mode = NULL; }
+5
View File
@@ -285,6 +285,11 @@ disk_ask_merge, boolean, 1
debugger_command, string, NULL
uspeech, boolean, 0
rom_uspeech, string, "uspeech.rom"
rom_sp0256, string, "sp0256-al2.bin"
volume_uspeech, numeric, 50
teletext_addr_1, string, "127.0.0.1"
teletext_addr_2, string, "127.0.0.1"
teletext_addr_3, string, "127.0.0.1"
+4
View File
@@ -208,6 +208,7 @@ typedef struct settings_info {
char *rom_scorpion_1;
char *rom_scorpion_2;
char *rom_scorpion_3;
char *rom_sp0256;
char *rom_spec_se_0;
char *rom_spec_se_1;
char *rom_speccyboot;
@@ -218,6 +219,7 @@ typedef struct settings_info {
char *rom_ts2068_1;
char *rom_ttx2000s;
char *rom_usource;
char *rom_uspeech;
int rs232_handshake;
char *rs232_rx;
char *rs232_tx;
@@ -260,10 +262,12 @@ typedef struct settings_info {
int ttx2000s;
int unittests;
int usource;
int uspeech;
int volume_ay;
int volume_beeper;
int volume_covox;
int volume_specdrum;
int volume_uspeech;
int writable_roms;
int z80_is_cmos;
int zxatasp_active;
+38
View File
@@ -33,6 +33,7 @@
#include "machine.h"
#include "movie.h"
#include "options.h"
#include "peripherals/sound/sp0256.h"
#include "settings.h"
#include "sound.h"
#include "tape.h"
@@ -113,6 +114,8 @@ Blip_Synth *left_specdrum_synth = NULL, *right_specdrum_synth = NULL;
Blip_Synth *left_covox_synth = NULL, *right_covox_synth = NULL;
Blip_Synth *left_sp0256_synth = NULL, *right_sp0256_synth = NULL;
struct speaker_type_tag
{
int bass;
@@ -323,6 +326,12 @@ sound_init( const char *device )
blip_synth_set_output( left_specdrum_synth, left_buf );
blip_synth_set_treble_eq( left_specdrum_synth, treble );
left_sp0256_synth = new_Blip_Synth();
blip_synth_set_volume( left_sp0256_synth,
sound_get_volume( settings_current.volume_uspeech ) );
blip_synth_set_output( left_sp0256_synth, left_buf );
blip_synth_set_treble_eq( left_sp0256_synth, treble );
left_covox_synth = new_Blip_Synth();
blip_synth_set_volume( left_covox_synth,
sound_get_volume( settings_current.volume_covox ) );
@@ -336,6 +345,12 @@ sound_init( const char *device )
blip_synth_set_output( right_specdrum_synth, right_buf );
blip_synth_set_treble_eq( right_specdrum_synth, treble );
right_sp0256_synth = new_Blip_Synth();
blip_synth_set_volume( right_sp0256_synth,
sound_get_volume( settings_current.volume_uspeech ) );
blip_synth_set_output( right_sp0256_synth, right_buf );
blip_synth_set_treble_eq( right_sp0256_synth, treble );
right_covox_synth = new_Blip_Synth();
blip_synth_set_volume( right_covox_synth,
sound_get_volume( settings_current.volume_covox ) );
@@ -408,6 +423,9 @@ sound_end( void )
delete_Blip_Synth( &left_covox_synth );
delete_Blip_Synth( &right_covox_synth );
delete_Blip_Synth( &left_sp0256_synth );
delete_Blip_Synth( &right_sp0256_synth );
delete_Blip_Buffer( &left_buf );
delete_Blip_Buffer( &right_buf );
@@ -720,6 +738,22 @@ sound_specdrum_write( libspectrum_word port GCC_UNUSED, libspectrum_byte val )
}
}
/*
* sound_sp0256_write - very simple routine
* as the output is already a digitized waveform
*/
void
sound_sp0256_write( libspectrum_dword at_tstates, libspectrum_signed_word val )
{
if( !sound_enabled )
return;
blip_synth_update( left_sp0256_synth, at_tstates, val );
if( right_sp0256_synth ) {
blip_synth_update( right_sp0256_synth, at_tstates, val );
}
}
/*
* sound_covox_write - very simple routine
* as the output is already a digitized waveform
@@ -745,6 +779,10 @@ sound_frame( void )
if( !sound_enabled )
return;
/* Let the SP0256 catch up to the end of the frame before the buffers are
closed off, so any speech generated during it lands in this frame. */
sp0256_do_frame();
/* overlay AY sound */
sound_ay_overlay( 0 );
if( ay_turbosound_enabled )
+2
View File
@@ -37,6 +37,8 @@ void sound_ay_write( int chip, int reg, int val, libspectrum_dword now );
void sound_ay_reset( void );
void sound_specdrum_write( libspectrum_word port, libspectrum_byte val );
void sound_covox_write( libspectrum_word port, libspectrum_byte val );
void sound_sp0256_write( libspectrum_dword at_tstates,
libspectrum_signed_word val );
void sound_frame( void );
void sound_beeper( libspectrum_dword at_tstates, int on );
libspectrum_dword sound_get_effective_processor_speed( void );