static void z80_to_snapshot( libspectrum_snap *snap ) { uint8 r_register; r_register = ( R7 & 0x80 ) | ( R & 0x7f ); libspectrum_snap_set_a ( snap, A ); libspectrum_snap_set_f ( snap, F ); libspectrum_snap_set_a_ ( snap, A_ ); libspectrum_snap_set_f_ ( snap, F_ ); libspectrum_snap_set_bc ( snap, BC ); libspectrum_snap_set_de ( snap, DE ); libspectrum_snap_set_hl ( snap, HL ); libspectrum_snap_set_bc_( snap, BC_ ); libspectrum_snap_set_de_( snap, DE_ ); libspectrum_snap_set_hl_( snap, HL_ ); libspectrum_snap_set_ix ( snap, IX ); libspectrum_snap_set_iy ( snap, IY ); libspectrum_snap_set_i ( snap, I ); libspectrum_snap_set_r ( snap, r_register ); libspectrum_snap_set_sp ( snap, SP ); libspectrum_snap_set_pc ( snap, PC ); libspectrum_snap_set_iff1( snap, IFF1 ); libspectrum_snap_set_iff2( snap, IFF2 ); libspectrum_snap_set_im( snap, IM ); libspectrum_snap_set_halted( snap, z80.halted ); libspectrum_snap_set_last_instruction_ei( snap, z80.interrupts_enabled_at == z80_tstates ); }
static int libspectrum_sna_read_128_header( const libspectrum_byte *buffer, size_t buffer_length, libspectrum_snap *snap ) { if( buffer_length < 4 ) { libspectrum_print_error( LIBSPECTRUM_ERROR_CORRUPT, "libspectrum_sna_read_128_header: not enough data in buffer" ); return LIBSPECTRUM_ERROR_CORRUPT; } libspectrum_snap_set_pc( snap, buffer[0] + 0x100 * buffer[1] ); libspectrum_snap_set_out_128_memoryport( snap, buffer[2] ); return LIBSPECTRUM_ERROR_NONE; }
static int libspectrum_sna_read_header( const libspectrum_byte *buffer, size_t buffer_length, libspectrum_snap *snap ) { int iff; if( buffer_length < LIBSPECTRUM_SNA_HEADER_LENGTH ) { libspectrum_print_error( LIBSPECTRUM_ERROR_CORRUPT, "libspectrum_sna_read_header: not enough data in buffer" ); return LIBSPECTRUM_ERROR_CORRUPT; } libspectrum_snap_set_a ( snap, buffer[22] ); libspectrum_snap_set_f ( snap, buffer[21] ); libspectrum_snap_set_bc ( snap, buffer[13] + buffer[14]*0x100 ); libspectrum_snap_set_de ( snap, buffer[11] + buffer[12]*0x100 ); libspectrum_snap_set_hl ( snap, buffer[ 9] + buffer[10]*0x100 ); libspectrum_snap_set_a_ ( snap, buffer[ 8] ); libspectrum_snap_set_f_ ( snap, buffer[ 7] ); libspectrum_snap_set_bc_( snap, buffer[ 5] + buffer[ 6]*0x100 ); libspectrum_snap_set_de_( snap, buffer[ 3] + buffer[ 4]*0x100 ); libspectrum_snap_set_hl_( snap, buffer[ 1] + buffer[ 2]*0x100 ); libspectrum_snap_set_ix ( snap, buffer[17] + buffer[18]*0x100 ); libspectrum_snap_set_iy ( snap, buffer[15] + buffer[16]*0x100 ); libspectrum_snap_set_i ( snap, buffer[ 0] ); libspectrum_snap_set_r ( snap, buffer[20] ); libspectrum_snap_set_pc ( snap, buffer[ 6] + buffer[ 7]*0x100 ); libspectrum_snap_set_sp ( snap, buffer[23] + buffer[24]*0x100 ); iff = ( buffer[19] & 0x04 ) ? 1 : 0; libspectrum_snap_set_iff1( snap, iff ); libspectrum_snap_set_iff2( snap, iff ); libspectrum_snap_set_im( snap, buffer[25] & 0x03 ); libspectrum_snap_set_out_ula( snap, buffer[26] & 0x07 ); return LIBSPECTRUM_ERROR_NONE; }
/* Initialise a libspectrum_snap structure */ libspectrum_snap* libspectrum_snap_alloc( void ) { libspectrum_snap *snap; size_t i; snap = libspectrum_snap_alloc_internal(); libspectrum_snap_set_a ( snap, 0x00 ); libspectrum_snap_set_f ( snap, 0x00 ); libspectrum_snap_set_bc ( snap, 0x0000 ); libspectrum_snap_set_de ( snap, 0x0000 ); libspectrum_snap_set_hl ( snap, 0x0000 ); libspectrum_snap_set_a_ ( snap, 0x00 ); libspectrum_snap_set_f_ ( snap, 0x00 ); libspectrum_snap_set_bc_ ( snap, 0x0000 ); libspectrum_snap_set_de_ ( snap, 0x0000 ); libspectrum_snap_set_hl_ ( snap, 0x0000 ); libspectrum_snap_set_ix ( snap, 0x0000 ); libspectrum_snap_set_iy ( snap, 0x0000 ); libspectrum_snap_set_i ( snap, 0x00 ); libspectrum_snap_set_r ( snap, 0x00 ); libspectrum_snap_set_sp ( snap, 0x0000 ); libspectrum_snap_set_pc ( snap, 0x0000 ); libspectrum_snap_set_memptr( snap, 0x0000 ); libspectrum_snap_set_iff1( snap, 1 ); libspectrum_snap_set_iff2( snap, 1 ); libspectrum_snap_set_im ( snap, 1 ); libspectrum_snap_set_halted( snap, 0 ); libspectrum_snap_set_last_instruction_ei( snap, 0 ); libspectrum_snap_set_last_instruction_set_f( snap, 0 ); libspectrum_snap_set_custom_rom( snap, 0 ); libspectrum_snap_set_custom_rom_pages( snap, 0 ); for( i = 0; i < 4; i++ ) { libspectrum_snap_set_roms( snap, i, NULL ); libspectrum_snap_set_rom_length( snap, i, 0 ); } for( i = 0; i < SNAPSHOT_RAM_PAGES; i++ ) libspectrum_snap_set_pages( snap, i, NULL ); for( i = 0; i < SNAPSHOT_SLT_PAGES; i++ ) { libspectrum_snap_set_slt( snap, i, NULL ); libspectrum_snap_set_slt_length( snap, i, 0 ); } libspectrum_snap_set_slt_screen( snap, NULL ); libspectrum_snap_set_slt_screen_level( snap, 0 ); libspectrum_snap_set_out_ula( snap, 0x00 ); libspectrum_snap_set_tstates( snap, 69664 ); libspectrum_snap_set_out_128_memoryport( snap, 0x07 ); libspectrum_snap_set_out_ay_registerport( snap, 0x0e ); for( i = 0; i < 16; i++ ) libspectrum_snap_set_ay_registers( snap, i, 0 ); libspectrum_snap_set_out_plus3_memoryport( snap, 0x08 ); libspectrum_snap_set_out_scld_hsr( snap, 0x00 ); libspectrum_snap_set_out_scld_dec( snap, 0x00 ); libspectrum_snap_set_interface1_active( snap, 0 ); libspectrum_snap_set_interface1_paged( snap, 0 ); libspectrum_snap_set_interface1_drive_count( snap, 0 ); libspectrum_snap_set_interface1_custom_rom( snap, 0 ); libspectrum_snap_set_interface1_rom( snap, 0, NULL ); libspectrum_snap_set_interface1_rom_length( snap, 0, 0 ); libspectrum_snap_set_beta_active( snap, 0 ); libspectrum_snap_set_beta_paged( snap, 0 ); libspectrum_snap_set_beta_autoboot( snap, 0 ); libspectrum_snap_set_beta_drive_count( snap, 0 ); libspectrum_snap_set_beta_custom_rom( snap, 0 ); libspectrum_snap_set_beta_direction( snap, 0 ); libspectrum_snap_set_beta_system( snap, 0 ); libspectrum_snap_set_beta_track ( snap, 0 ); libspectrum_snap_set_beta_sector( snap, 0 ); libspectrum_snap_set_beta_data ( snap, 0 ); libspectrum_snap_set_beta_status( snap, 0 ); libspectrum_snap_set_beta_rom( snap, 0, NULL ); libspectrum_snap_set_plusd_active( snap, 0 ); libspectrum_snap_set_plusd_paged( snap, 0 ); libspectrum_snap_set_plusd_drive_count( snap, 0 ); libspectrum_snap_set_plusd_custom_rom( snap, 0 ); libspectrum_snap_set_plusd_direction( snap, 0 ); libspectrum_snap_set_plusd_control( snap, 0 ); libspectrum_snap_set_plusd_track ( snap, 0 ); libspectrum_snap_set_plusd_sector( snap, 0 ); libspectrum_snap_set_plusd_data ( snap, 0 ); libspectrum_snap_set_plusd_status( snap, 0 ); libspectrum_snap_set_plusd_rom( snap, 0, NULL ); libspectrum_snap_set_plusd_ram( snap, 0, NULL ); libspectrum_snap_set_opus_active( snap, 0 ); libspectrum_snap_set_opus_paged ( snap, 0 ); libspectrum_snap_set_opus_drive_count( snap, 0 ); libspectrum_snap_set_opus_custom_rom( snap, 0 ); libspectrum_snap_set_opus_direction ( snap, 0 ); libspectrum_snap_set_opus_track ( snap, 0 ); libspectrum_snap_set_opus_sector( snap, 0 ); libspectrum_snap_set_opus_data ( snap, 0 ); libspectrum_snap_set_opus_status( snap, 0 ); libspectrum_snap_set_opus_data_reg_a( snap, 0 ); libspectrum_snap_set_opus_data_dir_a( snap, 0 ); libspectrum_snap_set_opus_control_a ( snap, 0 ); libspectrum_snap_set_opus_data_reg_b( snap, 0 ); libspectrum_snap_set_opus_data_dir_b( snap, 0 ); libspectrum_snap_set_opus_control_b ( snap, 0 ); libspectrum_snap_set_opus_rom( snap, 0, NULL ); libspectrum_snap_set_opus_ram( snap, 0, NULL ); libspectrum_snap_set_zxatasp_active( snap, 0 ); libspectrum_snap_set_zxatasp_upload( snap, 0 ); libspectrum_snap_set_zxatasp_writeprotect( snap, 0 ); libspectrum_snap_set_zxatasp_port_a( snap, 0 ); libspectrum_snap_set_zxatasp_port_b( snap, 0 ); libspectrum_snap_set_zxatasp_port_c( snap, 0 ); libspectrum_snap_set_zxatasp_control( snap, 0 ); libspectrum_snap_set_zxatasp_pages( snap, 0 ); libspectrum_snap_set_zxatasp_current_page( snap, 0 ); for( i = 0; i < SNAPSHOT_ZXATASP_PAGES; i++ ) libspectrum_snap_set_zxatasp_ram( snap, i, NULL ); libspectrum_snap_set_zxcf_active( snap, 0 ); libspectrum_snap_set_zxcf_upload( snap, 0 ); libspectrum_snap_set_zxcf_memctl( snap, 0x00 ); libspectrum_snap_set_zxcf_pages( snap, 0 ); for( i = 0; i < SNAPSHOT_ZXCF_PAGES; i++ ) libspectrum_snap_set_zxcf_ram( snap, i, NULL ); libspectrum_snap_set_interface2_active( snap, 0 ); libspectrum_snap_set_interface2_rom( snap, 0, NULL ); libspectrum_snap_set_dock_active( snap, 0 ); for( i = 0; i < SNAPSHOT_DOCK_EXROM_PAGES; i++ ) { libspectrum_snap_set_exrom_ram( snap, i, 0 ); libspectrum_snap_set_exrom_cart( snap, i, NULL ); libspectrum_snap_set_dock_ram( snap, i, 0 ); libspectrum_snap_set_dock_cart( snap, i, NULL ); } libspectrum_snap_set_issue2( snap, 0 ); libspectrum_snap_set_joystick_active_count( snap, 0 ); for( i = 0; i < SNAPSHOT_JOYSTICKS; i++ ) { libspectrum_snap_set_joystick_list( snap, i, LIBSPECTRUM_JOYSTICK_NONE ); libspectrum_snap_set_joystick_inputs( snap, i, 0 ); } libspectrum_snap_set_kempston_mouse_active( snap, 0 ); libspectrum_snap_set_simpleide_active( snap, 0 ); libspectrum_snap_set_specdrum_active( snap, 0 ); libspectrum_snap_set_specdrum_dac( snap, 0 ); libspectrum_snap_set_divide_active( snap, 0 ); libspectrum_snap_set_divide_eprom_writeprotect( snap, 0 ); libspectrum_snap_set_divide_paged( snap, 0 ); libspectrum_snap_set_divide_control( snap, 0 ); libspectrum_snap_set_divide_pages( snap, 0 ); libspectrum_snap_set_divide_eprom( snap, 0, NULL ); for( i = 0; i < SNAPSHOT_DIVIDE_PAGES; i++ ) { libspectrum_snap_set_divide_ram( snap, i, NULL ); } libspectrum_snap_set_fuller_box_active( snap, 0 ); libspectrum_snap_set_melodik_active( snap, 0 ); libspectrum_snap_set_spectranet_active( snap, 0 ); libspectrum_snap_set_spectranet_all_traps_disabled( snap, 0 ); libspectrum_snap_set_spectranet_rst8_trap_disabled( snap, 0 ); libspectrum_snap_set_spectranet_w5100( snap, 0, NULL ); libspectrum_snap_set_spectranet_flash( snap, 0, NULL ); libspectrum_snap_set_spectranet_ram( snap, 0, NULL ); libspectrum_snap_set_late_timings( snap, 0 ); libspectrum_snap_set_zx_printer_active( snap, 0 ); libspectrum_snap_set_usource_active( snap, 0 ); libspectrum_snap_set_usource_paged( snap, 0 ); libspectrum_snap_set_usource_custom_rom( snap, 0 ); libspectrum_snap_set_usource_rom( snap, 0, NULL ); libspectrum_snap_set_usource_rom_length( snap, 0, 0 ); libspectrum_snap_set_disciple_active( snap, 0 ); libspectrum_snap_set_disciple_paged( snap, 0 ); libspectrum_snap_set_disciple_inhibit_button( snap, 0 ); libspectrum_snap_set_disciple_drive_count( snap, 0 ); libspectrum_snap_set_disciple_custom_rom( snap, 0 ); libspectrum_snap_set_disciple_direction( snap, 0 ); libspectrum_snap_set_disciple_control( snap, 0 ); libspectrum_snap_set_disciple_track ( snap, 0 ); libspectrum_snap_set_disciple_sector( snap, 0 ); libspectrum_snap_set_disciple_data ( snap, 0 ); libspectrum_snap_set_disciple_status( snap, 0 ); libspectrum_snap_set_disciple_rom( snap, 0, NULL ); libspectrum_snap_set_disciple_rom_length( snap, 0, 0 ); libspectrum_snap_set_disciple_ram( snap, 0, NULL ); libspectrum_snap_set_didaktik80_active( snap, 0 ); libspectrum_snap_set_didaktik80_paged( snap, 0 ); libspectrum_snap_set_didaktik80_drive_count( snap, 0 ); libspectrum_snap_set_didaktik80_custom_rom( snap, 0 ); libspectrum_snap_set_didaktik80_direction( snap, 0 ); libspectrum_snap_set_didaktik80_aux( snap, 0 ); libspectrum_snap_set_didaktik80_track ( snap, 0 ); libspectrum_snap_set_didaktik80_sector( snap, 0 ); libspectrum_snap_set_didaktik80_data ( snap, 0 ); libspectrum_snap_set_didaktik80_status( snap, 0 ); libspectrum_snap_set_didaktik80_rom( snap, 0, NULL ); libspectrum_snap_set_didaktik80_rom_length( snap, 0, 0 ); libspectrum_snap_set_didaktik80_ram( snap, 0, NULL ); return snap; }
static int libspectrum_sna_read_data( const libspectrum_byte *buffer, size_t buffer_length, libspectrum_snap *snap ) { int error, page, i; libspectrum_word sp, offset; if( buffer_length < 0xc000 ) { libspectrum_print_error( LIBSPECTRUM_ERROR_CORRUPT, "libspectrum_sna_read_data: not enough data in buffer" ); return LIBSPECTRUM_ERROR_CORRUPT; } switch( libspectrum_snap_machine( snap ) ) { case LIBSPECTRUM_MACHINE_48: sp = libspectrum_snap_sp( snap ); if( sp < 0x4000 || sp == 0xffff ) { libspectrum_print_error( LIBSPECTRUM_ERROR_CORRUPT, "libspectrum_sna_read_data: SP invalid (0x%04x)", sp ); return LIBSPECTRUM_ERROR_CORRUPT; } /* Rescue PC from the stack */ offset = sp - 0x4000; libspectrum_snap_set_pc( snap, buffer[offset] + 0x100 * buffer[offset+1] ); /* Increase SP as PC has been unstacked */ libspectrum_snap_set_sp( snap, libspectrum_snap_sp( snap ) + 2 ); /* And split the pages up */ error = libspectrum_split_to_48k_pages( snap, buffer ); if( error != LIBSPECTRUM_ERROR_NONE ) return error; break; case LIBSPECTRUM_MACHINE_PENT: for( i=0; i<8; i++ ) { libspectrum_byte *ram = libspectrum_new( libspectrum_byte, 0x4000 ); libspectrum_snap_set_pages( snap, i, ram ); } memcpy( libspectrum_snap_pages( snap, 5 ), &buffer[0x0000], 0x4000 ); memcpy( libspectrum_snap_pages( snap, 2 ), &buffer[0x4000], 0x4000 ); error = libspectrum_sna_read_128_header( buffer + 0xc000, buffer_length - 0xc000, snap ); if( error != LIBSPECTRUM_ERROR_NONE ) return error; page = libspectrum_snap_out_128_memoryport( snap ) & 0x07; if( page == 5 || page == 2 ) { if( memcmp( libspectrum_snap_pages( snap, page ), &buffer[0x8000], 0x4000 ) ) { libspectrum_print_error( LIBSPECTRUM_ERROR_CORRUPT, "libspectrum_sna_read_data: duplicated page not identical" ); return LIBSPECTRUM_ERROR_CORRUPT; } } else { memcpy( libspectrum_snap_pages( snap, page ), &buffer[0x8000], 0x4000 ); } buffer += 0xc000 + LIBSPECTRUM_SNA_128_HEADER_LENGTH; buffer_length -= 0xc000 + LIBSPECTRUM_SNA_128_HEADER_LENGTH; error = libspectrum_sna_read_128_data( buffer, buffer_length, snap ); if( error != LIBSPECTRUM_ERROR_NONE ) return error; break; default: libspectrum_print_error( LIBSPECTRUM_ERROR_LOGIC, "libspectrum_sna_read_data: unknown machine" ); return LIBSPECTRUM_ERROR_LOGIC; } return LIBSPECTRUM_ERROR_NONE; }