static libspectrum_error generalised_data_init( libspectrum_tape_generalised_data_block *block, libspectrum_tape_generalised_data_block_state *state ) { state->run = 0; state->symbols_through_run = 0; state->edges_through_symbol = 0; state->current_symbol = 0; state->symbols_through_stream = 0; state->current_byte = 0; state->bits_through_byte = 0; state->bytes_through_stream = 0; if( block->pilot_table.symbols_in_block ) { state->state = LIBSPECTRUM_TAPE_STATE_PILOT; } else if( block->data_table.symbols_in_block ) { state->state = LIBSPECTRUM_TAPE_STATE_DATA1; state->current_byte = block->data[ 0 ]; state->current_symbol = get_generalised_data_symbol( block, state ); } else { state->state = LIBSPECTRUM_TAPE_STATE_PAUSE; } return LIBSPECTRUM_ERROR_NONE; }
static libspectrum_error generalised_data_edge( libspectrum_tape_generalised_data_block *block, libspectrum_tape_generalised_data_block_state *state, libspectrum_dword *tstates, int *end_of_block, int *flags ) { libspectrum_tape_generalised_data_symbol_table *table; libspectrum_tape_generalised_data_symbol *symbol; size_t current_symbol; switch( state->state ) { case LIBSPECTRUM_TAPE_STATE_PILOT: table = &( block->pilot_table ); current_symbol = block->pilot_symbols[ state->run ]; symbol = &( table->symbols[ current_symbol ] ); set_tstates_and_flags( symbol, state->edges_through_symbol, tstates, flags ); state->edges_through_symbol++; if( state->edges_through_symbol == table->max_pulses || symbol->lengths[ state->edges_through_symbol ] == 0 ) { state->edges_through_symbol = 0; if( ++state->symbols_through_run == block->pilot_repeats[ state->run ] ) { state->symbols_through_run = 0; if( ++state->run == table->symbols_in_block ) { state->state = LIBSPECTRUM_TAPE_STATE_DATA1; state->bits_through_byte = 0; state->bytes_through_stream = 0; state->symbols_through_stream = 0; state->current_byte = block->data[ 0 ]; state->current_symbol = get_generalised_data_symbol( block, state ); } } } break; case LIBSPECTRUM_TAPE_STATE_DATA1: table = &( block->data_table ); symbol = &( table->symbols[ state->current_symbol ] ); set_tstates_and_flags( symbol, state->edges_through_symbol, tstates, flags ); state->edges_through_symbol++; if( state->edges_through_symbol == table->max_pulses || symbol->lengths[ state->edges_through_symbol ] == 0 ) { if( ++state->symbols_through_stream == table->symbols_in_block ) { state->state = LIBSPECTRUM_TAPE_STATE_PAUSE; } else { state->edges_through_symbol = 0; state->current_symbol = get_generalised_data_symbol( block, state ); } } break; case LIBSPECTRUM_TAPE_STATE_PAUSE: /* The pause at the end of the block */ *tstates = ( block->pause * 69888 )/20; /* FIXME: should vary with tstates per frame */ *end_of_block = 1; break; default: libspectrum_print_error( LIBSPECTRUM_ERROR_LOGIC, "%s: unknown state %d", __func__, state->state ); return LIBSPECTRUM_ERROR_LOGIC; } return LIBSPECTRUM_ERROR_NONE; }