mirror of
https://github.com/libretro/fuse-libretro.git
synced 2026-11-07 10:36:03 -10:00
libspectrum: read and write the SZX uSpeech chunk
Groundwork for Currah uSpeech emulation. Fuse gained uSpeech in 1.7.0 and
libspectrum gained the snapshot support for it in 1.6.0; the vendored trees
here are 1.6.0 and 1.5.0 respectively, so neither side has it. Backport the
libspectrum half.
szx.c already had ZXSTBID_USPEECH ("USPE") defined and wired into the chunk
table, but pointed at skip_chunk, so the chunk was parsed and discarded.
Point it at a real reader and add the matching writer, both taken from
libspectrum 1.6.0. The payload is a single byte holding the paged flag;
presence of the chunk is itself the active flag.
The two accessors this needs, uspeech_active and uspeech_paged, are added to
snap_accessors.txt. Getting them into the generated snap_accessors.c meant
fixing that file's own drift first: the TurboSound accessors had been wrapped
in "#ifdef __LIBRETRO__" by hand in the output, which accessor.pl could not
express and would therefore have dropped on the next regeneration. Add an
%ifdef/%endif directive to accessor.pl, mark the TurboSound block with it in
snap_accessors.txt, and regenerate, so the file is reproducible again:
perl accessor.pl snap_accessors.txt > snap_accessors.c
Nothing sets uspeech_active yet - the peripheral itself does not exist in the
vendored Fuse tree - so no snapshot written by this core changes by a single
byte until it does. That matters here: retro_serialize_size() is sampled once
by frontends to size the rewind ring buffer and never resampled, so when the
peripheral does land, this chunk must be written under a session-constant
condition rather than gated on uspeech_active, the way write_amxm_chunk() and
write_ay2_chunk() already are for exactly this reason.
Verified by round-tripping real SZX data rather than by checking the accessors
against themselves: the chunk id appears in the written buffer, its length
field reads 1, its payload byte matches the paged flag for both values, both
fields survive a read back, an inactive snapshot emits no chunk at all, and an
SZX carrying no USPE chunk still loads with uspeech reported inactive. Clean
under ASan and UBSan with -fno-sanitize-recover=all.
This commit is contained in:
1 parent
60b60fb887
commit
3027d0921c
5 files changed
+108
-9
No files matched your search
+18
-1
@@ -41,8 +41,17 @@ while(<>) {
|
||||
|
||||
my $item = { };
|
||||
|
||||
# Preprocessor guard around a run of fields, written as
|
||||
# %ifdef SYMBOL
|
||||
# ...
|
||||
# %endif
|
||||
# in snap_accessors.txt. Emitted verbatim into every generated section,
|
||||
# so a field set that only exists in some builds stays expressible in the
|
||||
# input file instead of being hand-patched into the output.
|
||||
if( /^\s*%(ifdef|endif)\s*(\S*)/ ) {
|
||||
$item->{guard} = ( $1 eq "ifdef" ) ? "#ifdef $2\n" : "#endif\n";
|
||||
# Leading C comment
|
||||
if( /^\s*\/\*/ ) {
|
||||
} elsif( /^\s*\/\*/ ) {
|
||||
$item->{section_comment} = $_;
|
||||
} else {
|
||||
# Trailing C comment
|
||||
@@ -140,6 +149,8 @@ CODE
|
||||
foreach my $item ( @accessors ) {
|
||||
next if $item->{section_comment};
|
||||
|
||||
if( $item->{guard} ) { print $item->{guard}; next; }
|
||||
|
||||
if( $item->{indexed} ) {
|
||||
dump_accessor_indexed( $item->{type}, $item->{name} );
|
||||
} else {
|
||||
@@ -151,6 +162,8 @@ sub dump_accessor_declaration ($) {
|
||||
|
||||
my( $item ) = @_;
|
||||
|
||||
if( $item->{guard} ) { print $item->{guard}; return; }
|
||||
|
||||
if( $item->{section_comment} ) {
|
||||
print "\n ", $item->{section_comment};
|
||||
return;
|
||||
@@ -175,6 +188,8 @@ sub dump_accessor_initialisation ($) {
|
||||
|
||||
my( $item ) = @_;
|
||||
|
||||
if( $item->{guard} ) { print $item->{guard}; return; }
|
||||
|
||||
if( $item->{section_comment} ) {
|
||||
print "\n ", $item->{section_comment};
|
||||
return;
|
||||
@@ -206,6 +221,8 @@ sub dump_accessor_free ($) {
|
||||
|
||||
my( $item ) = @_;
|
||||
|
||||
if( $item->{guard} ) { print $item->{guard}; return; }
|
||||
|
||||
if( $item->{section_comment} ) {
|
||||
$new_section = 1;
|
||||
return;
|
||||
|
||||
@@ -79,9 +79,9 @@ struct libspectrum_snap {
|
||||
libspectrum_byte out_plus3_memoryport; /* Used for both the +3's and the Scorpion's 0x1ffd port */
|
||||
libspectrum_byte out_ay_registerport;
|
||||
libspectrum_byte ay_registers[ 16 ];
|
||||
|
||||
#ifdef __LIBRETRO__
|
||||
/* TurboSound: second AY-3-8912 chip */
|
||||
|
||||
/* TurboSound: second AY-3-8912 chip (fuse-libretro only) */
|
||||
int turbosound_active;
|
||||
libspectrum_byte out_ay2_registerport;
|
||||
libspectrum_byte ay2_registers[ 16 ];
|
||||
@@ -249,6 +249,10 @@ struct libspectrum_snap {
|
||||
libspectrum_byte* usource_rom[1];
|
||||
size_t usource_rom_length[1]; /* Length of the ROM */
|
||||
|
||||
/* uSpeech emulation */
|
||||
int uspeech_active;
|
||||
int uspeech_paged;
|
||||
|
||||
/* DISCiPLE emulation */
|
||||
int disciple_active;
|
||||
int disciple_paged;
|
||||
@@ -375,9 +379,9 @@ libspectrum_snap_alloc( void )
|
||||
libspectrum_snap_set_out_ay_registerport( snap, 0x0e );
|
||||
for( i = 0; i < 16; i++ )
|
||||
libspectrum_snap_set_ay_registers( snap, i, 0 );
|
||||
|
||||
#ifdef __LIBRETRO__
|
||||
/* TurboSound: second AY-3-8912 chip */
|
||||
|
||||
/* TurboSound: second AY-3-8912 chip (fuse-libretro only) */
|
||||
libspectrum_snap_set_turbosound_active( snap, 0 );
|
||||
libspectrum_snap_set_out_ay2_registerport( snap, 0 );
|
||||
for( i = 0; i < 16; i++ )
|
||||
@@ -556,6 +560,10 @@ libspectrum_snap_alloc( void )
|
||||
libspectrum_snap_set_usource_rom( snap, 0, NULL );
|
||||
libspectrum_snap_set_usource_rom_length( snap, 0, 0 );
|
||||
|
||||
/* uSpeech emulation */
|
||||
libspectrum_snap_set_uspeech_active( snap, 0 );
|
||||
libspectrum_snap_set_uspeech_paged( snap, 0 );
|
||||
|
||||
/* DISCiPLE emulation */
|
||||
libspectrum_snap_set_disciple_active( snap, 0 );
|
||||
libspectrum_snap_set_disciple_paged( snap, 0 );
|
||||
@@ -634,6 +642,8 @@ libspectrum_snap_free( libspectrum_snap *snap )
|
||||
for( i = 0; i < SNAPSHOT_SLT_PAGES; i++ )
|
||||
libspectrum_free( libspectrum_snap_slt( snap, i ) );
|
||||
libspectrum_free( libspectrum_snap_slt_screen( snap ) );
|
||||
#ifdef __LIBRETRO__
|
||||
#endif
|
||||
|
||||
libspectrum_free( libspectrum_snap_interface1_rom( snap, 0 ) );
|
||||
|
||||
@@ -1155,7 +1165,6 @@ libspectrum_snap_set_ay_registers( libspectrum_snap *snap, int idx, libspectrum_
|
||||
{
|
||||
snap->ay_registers[idx] = ay_registers;
|
||||
}
|
||||
|
||||
#ifdef __LIBRETRO__
|
||||
|
||||
int
|
||||
@@ -1205,8 +1214,7 @@ libspectrum_snap_set_out_ay2_active_chip( libspectrum_snap *snap, libspectrum_by
|
||||
{
|
||||
snap->out_ay2_active_chip = out_ay2_active_chip;
|
||||
}
|
||||
|
||||
#endif /* #ifdef __LIBRETRO__ */
|
||||
#endif
|
||||
|
||||
libspectrum_byte
|
||||
libspectrum_snap_out_scld_hsr( libspectrum_snap *snap )
|
||||
@@ -2612,6 +2620,30 @@ libspectrum_snap_set_usource_rom_length( libspectrum_snap *snap, int idx, size_t
|
||||
snap->usource_rom_length[idx] = usource_rom_length;
|
||||
}
|
||||
|
||||
int
|
||||
libspectrum_snap_uspeech_active( libspectrum_snap *snap )
|
||||
{
|
||||
return snap->uspeech_active;
|
||||
}
|
||||
|
||||
void
|
||||
libspectrum_snap_set_uspeech_active( libspectrum_snap *snap, int uspeech_active )
|
||||
{
|
||||
snap->uspeech_active = uspeech_active;
|
||||
}
|
||||
|
||||
int
|
||||
libspectrum_snap_uspeech_paged( libspectrum_snap *snap )
|
||||
{
|
||||
return snap->uspeech_paged;
|
||||
}
|
||||
|
||||
void
|
||||
libspectrum_snap_set_uspeech_paged( libspectrum_snap *snap, int uspeech_paged )
|
||||
{
|
||||
snap->uspeech_paged = uspeech_paged;
|
||||
}
|
||||
|
||||
int
|
||||
libspectrum_snap_disciple_active( libspectrum_snap *snap )
|
||||
{
|
||||
|
||||
@@ -80,11 +80,13 @@ libspectrum_byte out_plus3_memoryport 0 0x08 /* Used for both the +3's and the S
|
||||
libspectrum_byte out_ay_registerport 0 0x0e
|
||||
libspectrum_byte ay_registers 16
|
||||
|
||||
%ifdef __LIBRETRO__
|
||||
/* TurboSound: second AY-3-8912 chip (fuse-libretro only) */
|
||||
int turbosound_active
|
||||
libspectrum_byte out_ay2_registerport
|
||||
libspectrum_byte ay2_registers 16
|
||||
libspectrum_byte out_ay2_active_chip
|
||||
%endif
|
||||
|
||||
/* Timex-specific bits */
|
||||
libspectrum_byte out_scld_hsr
|
||||
@@ -247,6 +249,10 @@ int usource_custom_rom
|
||||
libspectrum_byte* usource_rom 1
|
||||
size_t usource_rom_length 1 /* Length of the ROM */
|
||||
|
||||
/* uSpeech emulation */
|
||||
int uspeech_active
|
||||
int uspeech_paged
|
||||
|
||||
/* DISCiPLE emulation */
|
||||
int disciple_active
|
||||
int disciple_paged
|
||||
|
||||
+41
-1
@@ -350,6 +350,9 @@ write_mfce_chunk( libspectrum_buffer *buffer, libspectrum_buffer *data,
|
||||
static void
|
||||
write_zmmc_chunk( libspectrum_buffer *buffer, libspectrum_buffer *data,
|
||||
libspectrum_snap *snap );
|
||||
static void
|
||||
write_uspe_chunk( libspectrum_buffer *buffer, libspectrum_buffer *data,
|
||||
libspectrum_snap *snap );
|
||||
|
||||
#ifdef HAVE_ZLIB_H
|
||||
|
||||
@@ -2523,6 +2526,29 @@ read_zmmc_chunk( libspectrum_snap *snap, libspectrum_word version GCC_UNUSED,
|
||||
return LIBSPECTRUM_ERROR_NONE;
|
||||
}
|
||||
|
||||
static libspectrum_error
|
||||
read_uspe_chunk( libspectrum_snap *snap, libspectrum_word version GCC_UNUSED,
|
||||
const libspectrum_byte **buffer,
|
||||
const libspectrum_byte *end GCC_UNUSED, size_t data_length,
|
||||
szx_context *ctx GCC_UNUSED )
|
||||
{
|
||||
libspectrum_byte paged;
|
||||
|
||||
if( data_length != 1 ) {
|
||||
libspectrum_print_error( LIBSPECTRUM_ERROR_UNKNOWN,
|
||||
"%s:read_uspe_chunk: unknown length %lu",
|
||||
__FILE__, (unsigned long)data_length );
|
||||
return LIBSPECTRUM_ERROR_UNKNOWN;
|
||||
}
|
||||
|
||||
paged = *(*buffer)++;
|
||||
|
||||
libspectrum_snap_set_uspeech_paged( snap, paged );
|
||||
libspectrum_snap_set_uspeech_active( snap, 1 );
|
||||
|
||||
return LIBSPECTRUM_ERROR_NONE;
|
||||
}
|
||||
|
||||
static libspectrum_error
|
||||
skip_chunk( libspectrum_snap *snap GCC_UNUSED,
|
||||
libspectrum_word version GCC_UNUSED,
|
||||
@@ -2584,7 +2610,7 @@ static struct read_chunk_t read_chunks[] = {
|
||||
{ ZXSTBID_SPECTRANETFLASHPAGE, read_snef_chunk },
|
||||
{ ZXSTBID_SPECTRANETRAMPAGE, read_sner_chunk },
|
||||
{ ZXSTBID_TIMEXREGS, read_scld_chunk },
|
||||
{ ZXSTBID_USPEECH, skip_chunk },
|
||||
{ ZXSTBID_USPEECH, read_uspe_chunk },
|
||||
{ ZXSTBID_Z80REGS, read_z80r_chunk },
|
||||
{ ZXSTBID_ZXATASPRAMPAGE, read_atrp_chunk },
|
||||
{ ZXSTBID_ZXATASP, read_zxat_chunk },
|
||||
@@ -3052,6 +3078,10 @@ libspectrum_szx_write( libspectrum_buffer *buffer, int *out_flags,
|
||||
write_zmmc_chunk( buffer, block_data, snap );
|
||||
}
|
||||
|
||||
if( libspectrum_snap_uspeech_active( snap ) ) {
|
||||
write_uspe_chunk( buffer, block_data, snap );
|
||||
}
|
||||
|
||||
libspectrum_buffer_free( block_data );
|
||||
|
||||
return LIBSPECTRUM_ERROR_NONE;
|
||||
@@ -4311,6 +4341,16 @@ write_zmmc_chunk( libspectrum_buffer *buffer, libspectrum_buffer *data,
|
||||
write_chunk( buffer, ZXSTBID_ZXMMC, NULL );
|
||||
}
|
||||
|
||||
static void
|
||||
write_uspe_chunk( libspectrum_buffer *buffer, libspectrum_buffer *data,
|
||||
libspectrum_snap *snap )
|
||||
{
|
||||
libspectrum_buffer_write_byte( data,
|
||||
libspectrum_snap_uspeech_paged( snap ) );
|
||||
|
||||
write_chunk( buffer, ZXSTBID_USPEECH, data );
|
||||
}
|
||||
|
||||
static void
|
||||
write_chunk( libspectrum_buffer *buffer, const char *id,
|
||||
libspectrum_buffer *block_data )
|
||||
|
||||
@@ -1110,6 +1110,10 @@ LIBSPECTRUM_API int libspectrum_snap_usource_active( libspectrum_snap *snap );
|
||||
LIBSPECTRUM_API void libspectrum_snap_set_usource_active( libspectrum_snap *snap, int usource_active );
|
||||
LIBSPECTRUM_API int libspectrum_snap_usource_paged( libspectrum_snap *snap );
|
||||
LIBSPECTRUM_API void libspectrum_snap_set_usource_paged( libspectrum_snap *snap, int usource_paged );
|
||||
LIBSPECTRUM_API int libspectrum_snap_uspeech_active( libspectrum_snap *snap );
|
||||
LIBSPECTRUM_API void libspectrum_snap_set_uspeech_active( libspectrum_snap *snap, int uspeech_active );
|
||||
LIBSPECTRUM_API int libspectrum_snap_uspeech_paged( libspectrum_snap *snap );
|
||||
LIBSPECTRUM_API void libspectrum_snap_set_uspeech_paged( libspectrum_snap *snap, int uspeech_paged );
|
||||
LIBSPECTRUM_API int libspectrum_snap_usource_custom_rom( libspectrum_snap *snap );
|
||||
LIBSPECTRUM_API void libspectrum_snap_set_usource_custom_rom( libspectrum_snap *snap, int usource_custom_rom );
|
||||
LIBSPECTRUM_API libspectrum_byte * libspectrum_snap_usource_rom( libspectrum_snap *snap, int idx );
|
||||
|
||||
Reference in new issue
Block a user