src/mess/formats/trs_cas.c
| r0 | r3288 | |
| 1 | /******************************************************************** |
| 2 | |
| 3 | Support for TRS80 .cas cassette images |
| 4 | |
| 5 | ********************************************************************/ |
| 6 | |
| 7 | #include "formats/trs_cas.h" |
| 8 | |
| 9 | #define SILENCE 0 |
| 10 | #define SMPLO -32768 |
| 11 | #define SMPHI 32768 |
| 12 | |
| 13 | |
| 14 | static int cas_size; |
| 15 | |
| 16 | |
| 17 | /******************************************************************* |
| 18 | Generate one high-low cycle of sample data |
| 19 | ********************************************************************/ |
| 20 | INLINE int trs80l2_cas_cycle(INT16 *buffer, int sample_pos, int silence, int high, int low) |
| 21 | { |
| 22 | int i = 0; |
| 23 | |
| 24 | if ( buffer ) |
| 25 | { |
| 26 | while( i < silence ) |
| 27 | { |
| 28 | buffer[ sample_pos + i ] = SILENCE; |
| 29 | i++; |
| 30 | } |
| 31 | while( i < silence + high) |
| 32 | { |
| 33 | buffer[ sample_pos + i ] = SMPHI; |
| 34 | i++; |
| 35 | } |
| 36 | |
| 37 | while( i < silence + high + low ) |
| 38 | { |
| 39 | buffer[ sample_pos + i ] = SMPLO; |
| 40 | i++; |
| 41 | } |
| 42 | } |
| 43 | return silence + high + low; |
| 44 | } |
| 45 | |
| 46 | |
| 47 | static int trs80l2_handle_cas(INT16 *buffer, const UINT8 *casdata) |
| 48 | { |
| 49 | int data_pos, sample_count; |
| 50 | |
| 51 | data_pos = 0; |
| 52 | sample_count = 0; |
| 53 | |
| 54 | while( data_pos < cas_size ) |
| 55 | { |
| 56 | UINT8 data = casdata[data_pos]; |
| 57 | int i; |
| 58 | |
| 59 | for ( i = 0; i < 8; i++ ) |
| 60 | { |
| 61 | /* Signal code */ |
| 62 | sample_count += trs80l2_cas_cycle( buffer, sample_count, 33, 6, 6 ); |
| 63 | |
| 64 | /* Bit code */ |
| 65 | if ( data & 0x80 ) |
| 66 | sample_count += trs80l2_cas_cycle( buffer, sample_count, 33, 6, 6 ); |
| 67 | else |
| 68 | sample_count += trs80l2_cas_cycle( buffer, sample_count, 33 + 6 + 6, 0, 0 ); |
| 69 | |
| 70 | data <<= 1; |
| 71 | } |
| 72 | |
| 73 | data_pos++; |
| 74 | } |
| 75 | return sample_count; |
| 76 | } |
| 77 | |
| 78 | |
| 79 | /******************************************************************* |
| 80 | Generate samples for the tape image |
| 81 | ********************************************************************/ |
| 82 | static int trs80l2_cas_fill_wave(INT16 *buffer, int sample_count, UINT8 *bytes) |
| 83 | { |
| 84 | return trs80l2_handle_cas( buffer, bytes ); |
| 85 | } |
| 86 | |
| 87 | |
| 88 | /******************************************************************* |
| 89 | Calculate the number of samples needed for this tape image |
| 90 | ********************************************************************/ |
| 91 | static int trs80l2_cas_to_wav_size(const UINT8 *casdata, int caslen) |
| 92 | { |
| 93 | cas_size = caslen; |
| 94 | |
| 95 | return trs80l2_handle_cas( NULL, casdata ); |
| 96 | } |
| 97 | |
| 98 | static const struct CassetteLegacyWaveFiller trs80l2_cas_legacy_fill_wave = |
| 99 | { |
| 100 | trs80l2_cas_fill_wave, /* fill_wave */ |
| 101 | -1, /* chunk_size */ |
| 102 | 0, /* chunk_samples */ |
| 103 | trs80l2_cas_to_wav_size, /* chunk_sample_calc */ |
| 104 | 44100, /* sample_frequency */ |
| 105 | 0, /* header_samples */ |
| 106 | 0 /* trailer_samples */ |
| 107 | }; |
| 108 | |
| 109 | |
| 110 | static casserr_t trs80l2_cas_identify(cassette_image *cassette, struct CassetteOptions *opts) |
| 111 | { |
| 112 | return cassette_legacy_identify(cassette, opts, &trs80l2_cas_legacy_fill_wave); |
| 113 | } |
| 114 | |
| 115 | |
| 116 | static casserr_t trs80l2_cas_load(cassette_image *cassette) |
| 117 | { |
| 118 | return cassette_legacy_construct(cassette, &trs80l2_cas_legacy_fill_wave); |
| 119 | } |
| 120 | |
| 121 | |
| 122 | static const struct CassetteFormat trs80l2_cas_format = |
| 123 | { |
| 124 | "cas", |
| 125 | trs80l2_cas_identify, |
| 126 | trs80l2_cas_load, |
| 127 | NULL |
| 128 | }; |
| 129 | |
| 130 | |
| 131 | CASSETTE_FORMATLIST_START(trs80l2_cassette_formats) |
| 132 | CASSETTE_FORMAT(trs80l2_cas_format) |
| 133 | CASSETTE_FORMATLIST_END |
| 134 | |
src/mess/drivers/trs80.c
| r3287 | r3288 | |
| 88 | 88 | /* Devices */ |
| 89 | 89 | #include "devices/basicdsk.h" |
| 90 | 90 | #include "devices/cassette.h" |
| 91 | #include "formats/trs_cas.h" |
| 91 | 92 | |
| 92 | 93 | |
| 93 | 94 | #define FW TRS80_FONT_W |
| r3287 | r3288 | |
| 369 | 370 | speaker_levels /* optional: level lookup table */ |
| 370 | 371 | }; |
| 371 | 372 | |
| 373 | static const cassette_config trs80l2_cassette_config = |
| 374 | { |
| 375 | trs80l2_cassette_formats, |
| 376 | NULL, |
| 377 | CASSETTE_PLAY |
| 378 | }; |
| 372 | 379 | |
| 373 | 380 | static MACHINE_DRIVER_START( level1 ) |
| 374 | 381 | /* basic machine hardware */ |
| r3287 | r3288 | |
| 413 | 420 | MDRV_CPU_MODIFY( "main" ) |
| 414 | 421 | MDRV_CPU_PROGRAM_MAP( mem_model1, 0 ) |
| 415 | 422 | MDRV_CPU_IO_MAP( io_model1, 0 ) |
| 423 | |
| 424 | MDRV_CASSETTE_MODIFY( "cassette", trs80l2_cassette_config ) |
| 416 | 425 | MACHINE_DRIVER_END |
| 417 | 426 | |
| 418 | 427 | |
| r3287 | r3288 | |
| 422 | 431 | MDRV_CPU_PROGRAM_MAP( mem_model3, 0 ) |
| 423 | 432 | MDRV_CPU_IO_MAP( io_model3, 0 ) |
| 424 | 433 | MDRV_CPU_VBLANK_INT_HACK(trs80_frame_interrupt, 2) |
| 434 | |
| 435 | MDRV_CASSETTE_MODIFY( "cassette", trs80l2_cassette_config ) |
| 425 | 436 | MACHINE_DRIVER_END |
| 426 | 437 | |
| 427 | 438 | static MACHINE_DRIVER_START( ht1080z ) |