1
0
mirror of https://git.code.sf.net/p/fuse-emulator/fuse-utils synced 2025-12-08 09:42:18 +03:00
Files
fuse-utils/tzxlist.c
2003-07-17 13:44:04 +00:00

298 lines
8.6 KiB
C

/* tzxlist.c: Produce a listing of the blocks in a .tzx file
Copyright (c) 2001-2002 Philip Kendall, Darren Salt
$Id$
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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
Author contact information:
E-mail: pak21-fuse@srcf.ucam.org
Postal address: 15 Crescent Road, Wokingham, Berks, RG40 2DB, England
*/
#include <config.h>
#include <errno.h>
#include <fcntl.h>
#include <stdio.h>
#include <string.h>
#include <sys/mman.h>
#include <sys/stat.h>
#include <unistd.h>
#include <libspectrum.h>
#include "utils.h"
#define DESCRIPTION_LENGTH 80
const char *progname;
static const char*
hardware_desc( int type, int id )
{
switch( type ) {
case 0:
switch( id ) {
case 0: return "16K Spectrum";
case 1: return "48K Spectrum/Spectrum +";
case 2: return "48K Spectrum (Issue 1)";
case 3: return "128K Spectrum";
case 4: return "Spectrum +2";
case 5: return "Spectrum +2A/+3";
default: return "Unknown machine";
}
case 3:
switch( id ) {
case 0: return "AY-3-8192";
default: return "Unknown sound device";
}
case 4:
switch( id ) {
case 0: return "Kempston joystick";
case 1: return "Cursor/Protek/AGF joystick";
case 2: return "Sinclair joystick (Left)";
case 3: return "Sinclair joystick (Right)";
case 4: return "Fuller joystick";
default: return "Unknown joystick";
}
default: return "Unknown type";
}
}
static int
process_tzx( char *filename )
{
int error;
unsigned char *buffer; size_t length;
libspectrum_tape *tape;
GSList *ptr;
size_t i;
error = mmap_file( filename, &buffer, &length ); if( error ) return error;
error = libspectrum_tape_alloc( &tape );
if( error != LIBSPECTRUM_ERROR_NONE ) {
munmap( buffer, length );
return 1;
}
error = libspectrum_tzx_read( tape, buffer, length );
if( error != LIBSPECTRUM_ERROR_NONE ) {
munmap( buffer, length );
libspectrum_tape_free( tape );
return error;
}
if( munmap( buffer, length ) == -1 ) {
fprintf( stderr, "%s: couldn't munmap `%s': %s\n", progname, filename,
strerror( errno ) );
return 1;
}
printf("Listing of `%s':\n\n", filename );
ptr = tape->blocks;
while( ptr ) {
libspectrum_tape_block *block = (libspectrum_tape_block*)ptr->data;
char description[ DESCRIPTION_LENGTH ];
error =
libspectrum_tape_block_description( description, DESCRIPTION_LENGTH,
block );
if( error ) return 1;
printf( "Block type 0x%02x (%s)\n", libspectrum_tape_block_type( block ),
description );
switch( libspectrum_tape_block_type( block ) ) {
case LIBSPECTRUM_TAPE_BLOCK_ROM:
printf(" Data length: %ld bytes\n",
(unsigned long)libspectrum_tape_block_data_length( block ) );
printf(" Pause length: %d ms\n",
libspectrum_tape_block_pause( block ) );
break;
case LIBSPECTRUM_TAPE_BLOCK_TURBO:
printf(" %ld pilot pulses of %d tstates\n",
(unsigned long)libspectrum_tape_block_pilot_pulses( block ),
libspectrum_tape_block_pilot_length( block ) );
printf(" Sync pulses of %d and %d tstates\n",
libspectrum_tape_block_sync1_length( block ),
libspectrum_tape_block_sync2_length( block ) );
/* Fall through */
case LIBSPECTRUM_TAPE_BLOCK_PURE_DATA:
printf(" Data bits are %d (reset) and %d (set) tstates\n",
libspectrum_tape_block_bit0_length( block ),
libspectrum_tape_block_bit1_length( block ) );
printf(" Data length: %ld bytes (%ld bits in last byte used)\n",
(unsigned long)libspectrum_tape_block_data_length( block ),
(unsigned long)libspectrum_tape_block_bits_in_last_byte(block) );
printf(" Pause length: %d ms\n",
libspectrum_tape_block_pause( block ) );
break;
case LIBSPECTRUM_TAPE_BLOCK_PURE_TONE:
printf(" %ld pulses of %ld tstates\n",
(unsigned long)libspectrum_tape_block_count( block ),
(unsigned long)libspectrum_tape_block_pulse_length( block ) );
break;
case LIBSPECTRUM_TAPE_BLOCK_PULSES:
for( i=0; i < libspectrum_tape_block_count( block ); i++ )
printf(" Pulse %3ld: length %d tstates\n",
(unsigned long)i,
libspectrum_tape_block_pulse_lengths( block, i ) );
break;
case LIBSPECTRUM_TAPE_BLOCK_RAW_DATA:
printf(" Length: %ld bytes\n", (unsigned long)
libspectrum_tape_block_data_length( block ) );
printf(" Bits in last byte: %ld\n",
(unsigned long)libspectrum_tape_block_bits_in_last_byte(block) );
printf(" Each bit is %d tstates\n",
libspectrum_tape_block_bit_length( block ) );
printf(" Pause length: %d ms\n",
libspectrum_tape_block_pause( block ) );
break;
case LIBSPECTRUM_TAPE_BLOCK_PAUSE:
printf(" Length: %d ms\n", libspectrum_tape_block_pause( block ) );
break;
case LIBSPECTRUM_TAPE_BLOCK_GROUP_START:
printf(" Name: %s\n", libspectrum_tape_block_text( block ) );
break;
case LIBSPECTRUM_TAPE_BLOCK_GROUP_END:
case LIBSPECTRUM_TAPE_BLOCK_LOOP_END:
case LIBSPECTRUM_TAPE_BLOCK_STOP48:
/* Do nothing */
break;
case LIBSPECTRUM_TAPE_BLOCK_JUMP:
printf(" Offset: %d\n", libspectrum_tape_block_offset( block ) );
break;
case LIBSPECTRUM_TAPE_BLOCK_LOOP_START:
printf(" Count: %lu\n",
(unsigned long)libspectrum_tape_block_count( block ) );
break;
case LIBSPECTRUM_TAPE_BLOCK_SELECT:
for( i = 0; i < libspectrum_tape_block_count( block ); i++ ) {
printf(" Choice %2ld: Offset %d: %s\n", (unsigned long)i,
libspectrum_tape_block_offsets( block, i ),
libspectrum_tape_block_texts( block, i ) );
}
break;
case LIBSPECTRUM_TAPE_BLOCK_MESSAGE:
printf(" Display for %d seconds\n",
libspectrum_tape_block_pause( block ) );
/* Fall through */
case LIBSPECTRUM_TAPE_BLOCK_COMMENT:
printf(" Comment: %s\n", libspectrum_tape_block_text( block ) );
break;
case LIBSPECTRUM_TAPE_BLOCK_ARCHIVE_INFO:
for( i = 0; i < libspectrum_tape_block_count( block ); i++ ) {
printf(" ");
switch( libspectrum_tape_block_ids( block, i ) ) {
case 0: printf("Full Title:"); break;
case 1: printf(" Publisher:"); break;
case 2: printf(" Author:"); break;
case 3: printf(" Year:"); break;
case 4: printf(" Langugage:"); break;
case 5: printf(" Category:"); break;
case 6: printf(" Price:"); break;
case 7: printf(" Loader:"); break;
case 8: printf(" Origin:"); break;
case 255: printf(" Comment:"); break;
default: printf("(Unknown string): "); break;
}
printf(" %s\n", libspectrum_tape_block_texts( block, i ) );
}
break;
case LIBSPECTRUM_TAPE_BLOCK_HARDWARE:
for( i = 0; i < libspectrum_tape_block_count( block ); i++ ) {
printf( " %s: ",
hardware_desc( libspectrum_tape_block_types( block, i ),
libspectrum_tape_block_ids( block, i )
)
);
switch( libspectrum_tape_block_values( block, i ) ) {
case 0: printf("runs"); break;
case 1: printf("runs, using hardware"); break;
case 2: printf("runs, does not use hardware"); break;
case 3: printf("does not run"); break;
}
printf("\n");
}
break;
case LIBSPECTRUM_TAPE_BLOCK_CUSTOM:
printf( " Description: %s\n", libspectrum_tape_block_text( block ) );
printf( " Length: %ld bytes\n",
(unsigned long)libspectrum_tape_block_data_length( block ) );
break;
default:
printf(" (Sorry -- %s can't handle that kind of block. Skipping it)\n",
progname );
break;
}
ptr = ptr->next;
}
error = libspectrum_tape_free( tape );
if( error != LIBSPECTRUM_ERROR_NONE ) {
munmap( buffer, length );
return error;
}
return 0;
}
int
main( int argc, char **argv )
{
int ret = 0;
int arg = 0;
progname = argv[0];
if( argc < 2 ) {
fprintf( stderr, "%s: usage: %s <tzx files>...\n", progname, progname );
return 1;
}
while( ++arg < argc )
ret |= process_tzx( argv[arg] );
return ret;
}