int tape_toggle_play( int autoplay ) { if( tape_playing ) { return tape_stop(); } else { return tape_play( autoplay ); } }
int tape_next_edge( void ) { int error; libspectrum_error libspec_error; libspectrum_dword edge_tstates; int flags; /* If the tape's not playing, just return */ if( ! tape_playing ) return 0; /* Get the time until the next edge */ libspec_error = libspectrum_tape_get_next_edge( &tape, &edge_tstates, &flags ); if( libspec_error != LIBSPECTRUM_ERROR_NONE ) return libspec_error; /* Invert the microphone state */ if( edge_tstates || ( flags & LIBSPECTRUM_TAPE_FLAGS_STOP ) ) { tape_microphone = !tape_microphone; sound_beeper( 1, tape_microphone ); } /* If we've been requested to stop the tape, do so and then return without stacking another edge */ if( ( flags & LIBSPECTRUM_TAPE_FLAGS_STOP ) || ( ( flags & LIBSPECTRUM_TAPE_FLAGS_STOP48 ) && machine_current->machine == SPECTRUM_MACHINE_48 ) ) { error = tape_stop(); if( error ) return error; return 0; } /* If that was the end of a block, tape traps are active _and_ the new block is a ROM loader, return without putting another event into the queue */ if( ( flags & LIBSPECTRUM_TAPE_FLAGS_BLOCK ) && settings_current.tape_traps && ((libspectrum_tape_block*)(tape.current_block->data))->type == LIBSPECTRUM_TAPE_BLOCK_ROM ) { tape_playing = 0; return 0; } /* Otherwise, put this into the event queue which will cause the next block to become active when it occurs */ error = event_add( tstates + edge_tstates, EVENT_TYPE_EDGE ); if( error ) return error; return 0; }
int tape_close( void ) { int error; /* Stop the tape if it's currently playing */ if( tape_playing ) { error = tape_stop(); if( error ) return error; } /* And then remove it from memory */ error = libspectrum_tape_clear( tape ); if( error ) return error; //ui_tape_browser_update( UI_TAPE_BROWSER_NEW_TAPE, NULL ); return 0; }
void loader_detect_loader( void ) { libspectrum_dword tstates_diff = tstates - last_tstates_read; libspectrum_byte b_diff = z80.bc.b.h - last_b_read; last_tstates_read = tstates; last_b_read = z80.bc.b.h; if( settings_current.detect_loader ) { if( tape_is_playing() ) { if( tstates_diff > 1000 || ( b_diff != 1 && b_diff != 0 && b_diff != 0xff ) ) { successive_reads++; if( successive_reads >= 2 ) { tape_stop(); } } else { successive_reads = 0; } } else { if( tstates_diff <= 500 && ( b_diff == 1 || b_diff == 0xff ) ) { successive_reads++; if( successive_reads >= 10 ) { tape_do_play( 1 ); } } else { successive_reads = 0; } } } else { successive_reads = 0; } if( settings_current.accelerate_loader && tape_is_playing() ) check_for_acceleration(); }
int machine_reset( int hard_reset ) { size_t i; int error; /* Clear poke list (undoes effects of active pokes on Spectrum memory) */ pokemem_clear(); sound_ay_reset(); tape_stop(); memory_pool_free(); machine_current->ram.romcs = 0; machine_set_variable_timings( machine_current ); memory_reset(); /* Do the machine-specific bits, including loading the ROMs */ error = machine_current->reset(); if( error ) return error; module_reset( hard_reset ); error = machine_current->memory_map(); if( error ) return error; /* Set up the contention array */ for( i = 0; i < machine_current->timings.tstates_per_frame; i++ ) { ula_contention[ i ] = machine_current->ram.contend_delay( i ); ula_contention_no_mreq[ i ] = machine_current->ram.contend_delay_no_mreq( i ); } /* Update the disk menu items */ ui_menu_disk_update(); /* clear out old display image ready for new one */ display_refresh_all(); return 0; }
int machine_reset( int hard_reset ) { size_t i; int error; sound_ay_reset(); tape_stop(); memory_pool_free(); machine_current->ram.romcs = 0; machine_set_variable_timings( machine_current ); /* Do the machine-specific bits, including loading the ROMs */ error = machine_current->reset(); if( error ) return error; module_reset( hard_reset ); error = machine_current->memory_map(); if( error ) return error; /* Set up the contention array */ for( i = 0; i < machine_current->timings.tstates_per_frame; i++ ) { ula_contention[ i ] = machine_current->ram.contend_delay( i ); ula_contention_no_mreq[ i ] = machine_current->ram.contend_delay_no_mreq( i ); } /* Check for an Interface I ROM */ ui_statusbar_update( UI_STATUSBAR_ITEM_MICRODRIVE, UI_STATUSBAR_STATE_NOT_AVAILABLE ); /* Update the disk menu items */ ui_menu_disk_update(); /* clear out old display image ready for new one */ display_refresh_all(); return 0; }
/* Close the active tape file */ int tape_close( void ) { int error; ui_confirm_save_t confirm; /* If the tape has been modified, check if we want to do this */ if( tape_modified ) { confirm = ui_confirm_save( "Tape has been modified.\nDo you want to save it?" ); switch( confirm ) { case UI_CONFIRM_SAVE_SAVE: error = ui_tape_write(); if( error ) return error; break; case UI_CONFIRM_SAVE_DONTSAVE: break; case UI_CONFIRM_SAVE_CANCEL: return 1; } } /* Stop the tape if it's currently playing */ if( tape_playing ) { error = tape_stop(); if( error ) return error; } /* And then remove it from memory */ error = libspectrum_tape_clear( tape ); if( error ) return error; tape_modified = 0; ui_tape_browser_update( UI_TAPE_BROWSER_NEW_TAPE, NULL ); return 0; }
void tape_next_edge( libspectrum_dword last_tstates, int type, void *user_data ) { libspectrum_error libspec_error; libspectrum_tape_block *block; libspectrum_dword edge_tstates; int flags; /* If the tape's not playing, just return */ if( ! tape_playing ) return; /* Get the time until the next edge */ libspec_error = libspectrum_tape_get_next_edge( &edge_tstates, &flags, tape ); if( libspec_error != LIBSPECTRUM_ERROR_NONE ) return; /* Invert the microphone state */ if( edge_tstates || !( flags & LIBSPECTRUM_TAPE_FLAGS_NO_EDGE ) || ( flags & ( LIBSPECTRUM_TAPE_FLAGS_STOP | LIBSPECTRUM_TAPE_FLAGS_LEVEL_LOW | LIBSPECTRUM_TAPE_FLAGS_LEVEL_HIGH ) ) ) { if( flags & LIBSPECTRUM_TAPE_FLAGS_NO_EDGE ) { /* Do nothing */ } else if( flags & LIBSPECTRUM_TAPE_FLAGS_LEVEL_LOW ) { tape_microphone = 0; } else if( flags & LIBSPECTRUM_TAPE_FLAGS_LEVEL_HIGH ) { tape_microphone = 1; } else { tape_microphone = !tape_microphone; } } sound_beeper( last_tstates, tape_microphone ); /* If we've been requested to stop the tape, do so and then return without stacking another edge */ if( ( flags & LIBSPECTRUM_TAPE_FLAGS_STOP ) || ( ( flags & LIBSPECTRUM_TAPE_FLAGS_STOP48 ) && ( !( libspectrum_machine_capabilities( machine_current->machine ) & LIBSPECTRUM_MACHINE_CAPABILITY_128_MEMORY ) ) ) ) { tape_stop(); return; } /* If that was the end of a block, update the browser */ if( flags & LIBSPECTRUM_TAPE_FLAGS_BLOCK ) { ui_tape_browser_update( UI_TAPE_BROWSER_SELECT_BLOCK, NULL ); /* If the tape was started automatically, tape traps are active and the new block is a ROM loader, stop the tape and return without putting another event into the queue */ block = libspectrum_tape_current_block( tape ); if( tape_autoplay && settings_current.tape_traps && libspectrum_tape_block_type( block ) == LIBSPECTRUM_TAPE_BLOCK_ROM ) { tape_stop(); return; } } /* Otherwise, put this into the event queue; remember that this edge should occur 'edge_tstates' after the last edge, not after the current time (these will be slightly different as we only process events between instructions). */ event_add( last_tstates + edge_tstates, tape_edge_event ); /* Store length flags for acceleration purposes */ loader_set_acceleration_flags( flags ); }
int tape_next_edge(Z80Regs *regs, int *edge_tstates, int *bit) { int error; libspectrum_error libspec_error; libspectrum_tape_block *block; //libspectrum_dword edge_tstates; int flags; *edge_tstates = 0; *bit=-1; int one_value=0; /* If the tape's not playing, just return */ if( ! tape_playing ) return 0; block = libspectrum_tape_current_block( tape ); int type = libspectrum_tape_block_type( block ); if(type==LIBSPECTRUM_TAPE_BLOCK_ROM || type==LIBSPECTRUM_TAPE_BLOCK_TURBO || type==LIBSPECTRUM_TAPE_BLOCK_PURE_DATA /*|| type==LIBSPECTRUM_TAPE_BLOCK_RAW_DATA*/) { int state = libspectrum_tape_state( tape ); if(state==LIBSPECTRUM_TAPE_STATE_DATA1 || state==LIBSPECTRUM_TAPE_STATE_DATA2) { if(block->type==LIBSPECTRUM_TAPE_BLOCK_TURBO) { one_value = block->types.turbo.bit1_length; } else if(block->type==LIBSPECTRUM_TAPE_BLOCK_PURE_DATA) { one_value = block->types.pure_data.bit1_length; } else { one_value = 1710; } } } /* Get the time until the next edge */ libspectrum_dword tmp = 0; libspec_error = libspectrum_tape_get_next_edge(&tmp, &flags, tape); *edge_tstates = tmp; if(one_value!=0) *bit = *edge_tstates == one_value ? 1 : 0; //edge_tstates_target = edge_tstates_target+*edge_tstates; if( libspec_error != LIBSPECTRUM_ERROR_NONE ) return libspec_error; /* Invert the microphone state */ if( *edge_tstates || ( flags & LIBSPECTRUM_TAPE_FLAGS_STOP ) ) { if( flags & LIBSPECTRUM_TAPE_FLAGS_NO_EDGE ) { // Do nothing } else if( flags & LIBSPECTRUM_TAPE_FLAGS_LEVEL_LOW ) { tape_microphone = 0; } else if( flags & LIBSPECTRUM_TAPE_FLAGS_LEVEL_HIGH ) { tape_microphone = 1; } else { tape_microphone = !tape_microphone; } if(regs!=NULL) sound_beeper_1(tape_microphone,regs->IPeriod-regs->ICount);//TODO: poner pref } /* If we've been requested to stop the tape, do so and then return without stacking another edge */ int zx48=0; if(regs!=NULL) zx48=regs->IPeriod==69888; if((flags & LIBSPECTRUM_TAPE_FLAGS_STOP) || ( zx48 && (flags & LIBSPECTRUM_TAPE_FLAGS_STOP48) ) ) { error = tape_stop(); if( error ) return error; return 0; } /* If that was the end of a block, update the browser */ if( flags & LIBSPECTRUM_TAPE_FLAGS_BLOCK ) { //ui_tape_browser_update( UI_TAPE_BROWSER_SELECT_BLOCK, NULL ); /* If the tape was started automatically, tape traps are active and the new block is a ROM loader, stop the tape and return without putting another event into the queue */ block = libspectrum_tape_current_block( tape ); if( /*tape_autoplay &&*/ mconfig.flash_loading && libspectrum_tape_block_type( block ) == LIBSPECTRUM_TAPE_BLOCK_ROM ) { error = tape_stop(); if( error ) return error; return 0;//TODO: devolver valor que nos diga que nos diga que no hay que devolver otro edge? } } /* Otherwise, put this into the event queue; remember that this edge should occur 'edge_tstates' after the last edge, not after the current time (these will be slightly different as we only process events between instructions). */ return 0; }
int tape_open( const char *filename ) { struct stat file_info; int fd; unsigned char *buffer; int error; char error_message[ ERROR_MESSAGE_MAX_LENGTH ]; /* If we already have a tape file open, close it */ if( tape.blocks ) { error = tape_close(); if( error ) return error; } fd = open( filename, O_RDONLY ); if( fd == -1 ) { snprintf( error_message, ERROR_MESSAGE_MAX_LENGTH, "%s: couldn't open `%s'", fuse_progname, filename ); perror( error_message ); return 1; } if( fstat( fd, &file_info) ) { snprintf( error_message, ERROR_MESSAGE_MAX_LENGTH, "%s: Couldn't stat `%s'", fuse_progname, filename ); perror( error_message ); close(fd); return 1; } buffer = mmap( 0, file_info.st_size, PROT_READ, MAP_SHARED, fd, 0 ); if( buffer == (void*)-1 ) { snprintf( error_message, ERROR_MESSAGE_MAX_LENGTH, "%s: Couldn't mmap `%s'", fuse_progname, filename ); perror( error_message ); close(fd); return 1; } if( close(fd) ) { snprintf( error_message, ERROR_MESSAGE_MAX_LENGTH, "%s: Couldn't close `%s'", fuse_progname, filename ); perror( error_message ); munmap( buffer, file_info.st_size ); return 1; } /* First, try opening the file as a .tzx file; if we get back an error saying it didn't have the .tzx signature, then try opening it as a .tap file */ error = libspectrum_tzx_create( &tape, buffer, file_info.st_size ); if( error == LIBSPECTRUM_ERROR_SIGNATURE ) { error = libspectrum_tap_create( &tape, buffer, file_info.st_size ); } if( error != LIBSPECTRUM_ERROR_NONE ) { fprintf( stderr, "%s: error reading `%s': %s\n", fuse_progname, filename, libspectrum_error_message(error) ); munmap( buffer, file_info.st_size ); return error; } if( munmap( buffer, file_info.st_size ) == -1 ) { snprintf( error_message, ERROR_MESSAGE_MAX_LENGTH, "%s: Couldn't munmap `%s'", fuse_progname, filename ); perror( error_message ); return 1; } /* And the tape is stopped */ if( tape_playing ) tape_stop(); return 0; }