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; }
void Tape::NextEdge (DWORD dwTime_) { libspectrum_error error; if (fEar) keyboard |= BORD_EAR_MASK; else keyboard &= ~BORD_EAR_MASK; if (!g_nTurbo) pDAC->Output(fEar ? 0xa0 : 0x80); libspectrum_dword tstates; int nFlags; // Fetch details of the next edge, and the time until it's due error = libspectrum_tape_get_next_edge(&tstates, &nFlags, pTape); if (error) { Stop(); return; } if (nFlags & LIBSPECTRUM_TAPE_FLAGS_LEVEL_LOW) fEar = false; else if (nFlags & LIBSPECTRUM_TAPE_FLAGS_LEVEL_HIGH) fEar = true; else if (!(nFlags & LIBSPECTRUM_TAPE_FLAGS_NO_EDGE)) fEar = !fEar; // End of tape block? if ((nFlags & LIBSPECTRUM_TAPE_FLAGS_BLOCK)) { // Stop the tape as it'll restart when required Stop(); } else { // Timings are in 3.5MHz t-states, so convert to SAM t-states tstates = tstates*(REAL_TSTATES_PER_SECOND/1000) + tremain; libspectrum_dword tadd = tstates/(SPECTRUM_TSTATES_PER_SECOND/1000); tremain = tstates % (SPECTRUM_TSTATES_PER_SECOND/1000); // Schedule an event to activate the edge AddCpuEvent(evtTapeEdge, dwTime_+tadd); } }
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; }