src/mess/formats/kim1_cas.c
| r0 | r3322 | |
| 1 | #include "kim1_cas.h" |
| 2 | |
| 3 | #define SMPLO -32768 |
| 4 | #define SMPHI 32767 |
| 5 | |
| 6 | |
| 7 | static int cas_size; |
| 8 | |
| 9 | |
| 10 | INLINE int kim1_output_signal( INT16 *buffer, int sample_pos, int high ) |
| 11 | { |
| 12 | int sample_count, i, j; |
| 13 | |
| 14 | sample_count = 0; |
| 15 | |
| 16 | if ( high ) |
| 17 | { |
| 18 | /* high frequency (~3600Hz) */ |
| 19 | for ( i = 0; i < 9; i++ ) |
| 20 | { |
| 21 | if ( buffer ) |
| 22 | { |
| 23 | for ( j = 0; j < 6; j++ ) |
| 24 | buffer[ sample_pos + sample_count + j ] = SMPHI; |
| 25 | } |
| 26 | sample_count += 6; |
| 27 | |
| 28 | if ( buffer ) |
| 29 | { |
| 30 | for ( j = 0; j < 6; j++ ) |
| 31 | buffer[ sample_pos + sample_count + j ] = SMPLO; |
| 32 | } |
| 33 | sample_count += 6; |
| 34 | } |
| 35 | } |
| 36 | else |
| 37 | { |
| 38 | /* low frequency (~2400Hz) */ |
| 39 | for ( i = 0; i < 6; i++ ) |
| 40 | { |
| 41 | if ( buffer ) |
| 42 | { |
| 43 | for ( j = 0; j < 9; j++ ) |
| 44 | buffer[ sample_pos + sample_count + j ] = SMPHI; |
| 45 | } |
| 46 | sample_count += 9; |
| 47 | |
| 48 | if ( buffer ) |
| 49 | { |
| 50 | for ( j = 0; j < 9; j++ ) |
| 51 | buffer[ sample_pos + sample_count + j ] = SMPLO; |
| 52 | } |
| 53 | sample_count += 9; |
| 54 | } |
| 55 | } |
| 56 | |
| 57 | return sample_count; |
| 58 | } |
| 59 | |
| 60 | |
| 61 | INLINE int kim1_output_byte( INT16 *buffer, int sample_pos, UINT8 byte ) |
| 62 | { |
| 63 | int i; |
| 64 | int sample_count = 0; |
| 65 | |
| 66 | for ( i = 0; i < 8; i++ ) |
| 67 | { |
| 68 | sample_count += kim1_output_signal( buffer, sample_pos + sample_count, 1 ); |
| 69 | sample_count += kim1_output_signal( buffer, sample_pos + sample_count, byte & 0x01 ? 0 : 1 ); |
| 70 | sample_count += kim1_output_signal( buffer, sample_pos + sample_count, 0 ); |
| 71 | byte >>= 1; |
| 72 | } |
| 73 | return sample_count; |
| 74 | } |
| 75 | |
| 76 | |
| 77 | static int kim1_handle_kim(INT16 *buffer, const UINT8 *casdata) |
| 78 | { |
| 79 | static const UINT8 encoding[16] = { 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46 }; |
| 80 | int i, data_pos, sample_count; |
| 81 | UINT16 size, address, file_id, checksum; |
| 82 | |
| 83 | if ( cas_size < 9 ) return -1; |
| 84 | if ( memcmp( casdata, "KIM1", 4 ) ) return -1; |
| 85 | |
| 86 | address = casdata[4] | ( casdata[5] << 8 ); |
| 87 | size = casdata[6] | ( casdata[7] << 8 ); |
| 88 | file_id = casdata[8]; |
| 89 | |
| 90 | data_pos = 9; |
| 91 | sample_count = 0; |
| 92 | checksum = casdata[4] + casdata[5]; |
| 93 | |
| 94 | /* First output a sync header: 100 x 16h */ |
| 95 | for ( i = 0; i < 100; i++ ) |
| 96 | sample_count += kim1_output_byte( buffer, sample_count, 0x16 ); |
| 97 | |
| 98 | /* Output end of sync: 2Ah */ |
| 99 | sample_count += kim1_output_byte( buffer, sample_count, 0x2A ); |
| 100 | |
| 101 | /* Output ID */ |
| 102 | sample_count += kim1_output_byte( buffer, sample_count, encoding[ file_id >> 4 ] ); |
| 103 | sample_count += kim1_output_byte( buffer, sample_count, encoding[ file_id & 0x0f ] ); |
| 104 | |
| 105 | /* Output starting address */ |
| 106 | sample_count += kim1_output_byte( buffer, sample_count, encoding[ ( address & 0xff ) >> 4 ] ); |
| 107 | sample_count += kim1_output_byte( buffer, sample_count, encoding[ address & 0x0f ] ); |
| 108 | sample_count += kim1_output_byte( buffer, sample_count, encoding[ address >> 12 ] ); |
| 109 | sample_count += kim1_output_byte( buffer, sample_count, encoding[ ( address >> 8 ) & 0x0f ] ); |
| 110 | |
| 111 | /* Output the data */ |
| 112 | while( data_pos < cas_size && data_pos < ( size + 9 ) ) |
| 113 | { |
| 114 | UINT8 data = casdata[data_pos]; |
| 115 | |
| 116 | sample_count += kim1_output_byte( buffer, sample_count, encoding[ data >> 4 ] ); |
| 117 | sample_count += kim1_output_byte( buffer, sample_count, encoding[ data & 0x0f ] ); |
| 118 | checksum += data; |
| 119 | data_pos++; |
| 120 | } |
| 121 | |
| 122 | /* Output end of data marker: 2Fh */ |
| 123 | sample_count += kim1_output_byte( buffer, sample_count, 0x2F ); |
| 124 | |
| 125 | /* Output checksum */ |
| 126 | sample_count += kim1_output_byte( buffer, sample_count, encoding[ ( checksum & 0xff ) >> 4 ] ); |
| 127 | sample_count += kim1_output_byte( buffer, sample_count, encoding[ checksum & 0x0f ] ); |
| 128 | sample_count += kim1_output_byte( buffer, sample_count, encoding[ checksum >> 12 ] ); |
| 129 | sample_count += kim1_output_byte( buffer, sample_count, encoding[ ( checksum >> 8 ) & 0x0f ] ); |
| 130 | |
| 131 | /* Output end of transmission marker: 2 x 04h */ |
| 132 | sample_count += kim1_output_byte( buffer, sample_count, 0x04 ); |
| 133 | sample_count += kim1_output_byte( buffer, sample_count, 0x04 ); |
| 134 | |
| 135 | return sample_count; |
| 136 | } |
| 137 | |
| 138 | |
| 139 | /******************************************************************* |
| 140 | Generate samples for the tape image |
| 141 | ********************************************************************/ |
| 142 | static int kim1_kim_fill_wave(INT16 *buffer, int sample_count, UINT8 *bytes) |
| 143 | { |
| 144 | return kim1_handle_kim( buffer, bytes ); |
| 145 | } |
| 146 | |
| 147 | |
| 148 | /******************************************************************* |
| 149 | Calculate the number of samples needed for this tape image |
| 150 | ********************************************************************/ |
| 151 | static int kim1_kim_to_wav_size(const UINT8 *casdata, int caslen) |
| 152 | { |
| 153 | cas_size = caslen; |
| 154 | |
| 155 | return kim1_handle_kim( NULL, casdata ); |
| 156 | } |
| 157 | |
| 158 | static const struct CassetteLegacyWaveFiller kim1_kim_legacy_fill_wave = |
| 159 | { |
| 160 | kim1_kim_fill_wave, /* fill_wave */ |
| 161 | -1, /* chunk_size */ |
| 162 | 0, /* chunk_samples */ |
| 163 | kim1_kim_to_wav_size, /* chunk_sample_calc */ |
| 164 | 44100, /* sample_frequency */ |
| 165 | 0, /* header_samples */ |
| 166 | 0 /* trailer_samples */ |
| 167 | }; |
| 168 | |
| 169 | |
| 170 | static casserr_t kim1_kim_identify(cassette_image *cassette, struct CassetteOptions *opts) |
| 171 | { |
| 172 | return cassette_legacy_identify(cassette, opts, &kim1_kim_legacy_fill_wave); |
| 173 | } |
| 174 | |
| 175 | |
| 176 | static casserr_t kim1_kim_load(cassette_image *cassette) |
| 177 | { |
| 178 | return cassette_legacy_construct(cassette, &kim1_kim_legacy_fill_wave); |
| 179 | } |
| 180 | |
| 181 | |
| 182 | static const struct CassetteFormat kim1_kim_format = |
| 183 | { |
| 184 | "kim,kim1", |
| 185 | kim1_kim_identify, |
| 186 | kim1_kim_load, |
| 187 | NULL |
| 188 | }; |
| 189 | |
| 190 | |
| 191 | CASSETTE_FORMATLIST_START(kim1_cassette_formats) |
| 192 | CASSETTE_FORMAT(kim1_kim_format) |
| 193 | CASSETTE_FORMATLIST_END |
| 194 | |
src/mess/drivers/kim1.c
| r3321 | r3322 | |
| 82 | 82 | #include "driver.h" |
| 83 | 83 | #include "machine/6530miot.h" |
| 84 | 84 | #include "devices/cassette.h" |
| 85 | #include "formats/kim1_cas.h" |
| 85 | 86 | #include "kim1.lh" |
| 86 | 87 | |
| 87 | 88 | |
| r3321 | r3322 | |
| 311 | 312 | } |
| 312 | 313 | |
| 313 | 314 | |
| 315 | static const cassette_config kim1_cassette_config = |
| 316 | { |
| 317 | kim1_cassette_formats, |
| 318 | NULL, |
| 319 | CASSETTE_STOPPED |
| 320 | }; |
| 321 | |
| 322 | |
| 314 | 323 | static MACHINE_DRIVER_START( kim1 ) |
| 315 | 324 | /* basic machine hardware */ |
| 316 | 325 | MDRV_CPU_ADD("main", M6502, 1000000) /* 1 MHz */ |
| r3321 | r3322 | |
| 329 | 338 | MDRV_SOUND_ADD("dac", DAC, 0) |
| 330 | 339 | MDRV_SOUND_ROUTE(ALL_OUTPUTS, "mono", 1.00) |
| 331 | 340 | |
| 332 | | MDRV_CASSETTE_ADD( "cassette", default_cassette_config ) |
| 341 | MDRV_CASSETTE_ADD( "cassette", kim1_cassette_config ) |
| 333 | 342 | |
| 334 | 343 | /* video */ |
| 335 | 344 | MDRV_DEFAULT_LAYOUT( layout_kim1 ) |
| r3321 | r3322 | |
| 343 | 352 | ROM_END |
| 344 | 353 | |
| 345 | 354 | |
| 346 | | #ifdef UNUSED_FUNCTION |
| 347 | | static DEVICE_IMAGE_LOAD( kim1_cassette ) |
| 348 | | { |
| 349 | | const char magic[] = "KIM1"; |
| 350 | | char buff[4]; |
| 351 | | UINT16 addr, size; |
| 352 | | UINT8 ident, *RAM = memory_region(image->machine, "main"); |
| 353 | | |
| 354 | | image_fread(image, buff, sizeof (buff)); |
| 355 | | if (memcmp(buff, magic, sizeof (buff))) |
| 356 | | { |
| 357 | | logerror("kim1_rom_load: magic '%s' not found\n", magic); |
| 358 | | return INIT_FAIL; |
| 359 | | } |
| 360 | | image_fread(image, &addr, 2); |
| 361 | | addr = LITTLE_ENDIANIZE_INT16(addr); |
| 362 | | image_fread(image, &size, 2); |
| 363 | | size = LITTLE_ENDIANIZE_INT16(size); |
| 364 | | image_fread(image, &ident, 1); |
| 365 | | logerror("kim1_rom_load: $%04X $%04X $%02X\n", addr, size, ident); |
| 366 | | while (size-- > 0) |
| 367 | | image_fread(image, &RAM[addr++], 1); |
| 368 | | return INIT_PASS; |
| 369 | | } |
| 370 | | |
| 371 | | |
| 372 | | static void kim1_cassette_getinfo(const mess_device_class *devclass, UINT32 state, union devinfo *info) |
| 373 | | { |
| 374 | | switch(state) |
| 375 | | { |
| 376 | | /* --- the following bits of info are returned as 64-bit signed integers --- */ |
| 377 | | case MESS_DEVINFO_INT_TYPE: info->i = IO_CASSETTE; break; |
| 378 | | case MESS_DEVINFO_INT_READABLE: info->i = 1; break; |
| 379 | | case MESS_DEVINFO_INT_WRITEABLE: info->i = 0; break; |
| 380 | | case MESS_DEVINFO_INT_CREATABLE: info->i = 0; break; |
| 381 | | case MESS_DEVINFO_INT_COUNT: info->i = 1; break; |
| 382 | | case MESS_DEVINFO_INT_RESET_ON_LOAD: info->i = 1; break; |
| 383 | | |
| 384 | | /* --- the following bits of info are returned as pointers to data or functions --- */ |
| 385 | | case MESS_DEVINFO_PTR_LOAD: info->load = DEVICE_IMAGE_LOAD_NAME(kim1_cassette); break; |
| 386 | | |
| 387 | | /* --- the following bits of info are returned as NULL-terminated strings --- */ |
| 388 | | case MESS_DEVINFO_STR_FILE_EXTENSIONS: strcpy(info->s = device_temp_str(), "kim1"); break; |
| 389 | | } |
| 390 | | } |
| 391 | | |
| 392 | | |
| 393 | | static SYSTEM_CONFIG_START(kim1) |
| 394 | | CONFIG_DEVICE(kim1_cassette_getinfo) |
| 395 | | SYSTEM_CONFIG_END |
| 396 | | #endif |
| 397 | | |
| 398 | 355 | /* YEAR NAME PARENT COMPAT MACHINE INPUT INIT CONFIG COMPANY FULLNAME */ |
| 399 | 356 | COMP( 1975, kim1, 0, 0, kim1, kim1, 0, 0, "MOS Technologies", "KIM-1" , GAME_SUPPORTS_SAVE) |