static void write_header( libspectrum_byte **buffer, libspectrum_byte **ptr, size_t *length, libspectrum_snap *snap ) { libspectrum_make_room( buffer, LIBSPECTRUM_SNA_HEADER_LENGTH, ptr, length ); *(*ptr)++ = libspectrum_snap_i ( snap ); libspectrum_write_word( ptr, libspectrum_snap_hl_( snap ) ); libspectrum_write_word( ptr, libspectrum_snap_de_( snap ) ); libspectrum_write_word( ptr, libspectrum_snap_bc_( snap ) ); *(*ptr)++ = libspectrum_snap_f_( snap ); *(*ptr)++ = libspectrum_snap_a_( snap ); libspectrum_write_word( ptr, libspectrum_snap_hl ( snap ) ); libspectrum_write_word( ptr, libspectrum_snap_de ( snap ) ); libspectrum_write_word( ptr, libspectrum_snap_bc ( snap ) ); libspectrum_write_word( ptr, libspectrum_snap_iy ( snap ) ); libspectrum_write_word( ptr, libspectrum_snap_ix ( snap ) ); *(*ptr)++ = libspectrum_snap_iff2( snap ) ? 0x04 : 0x00; *(*ptr)++ = libspectrum_snap_r ( snap ); *(*ptr)++ = libspectrum_snap_f ( snap ); *(*ptr)++ = libspectrum_snap_a ( snap ); libspectrum_write_word( ptr, libspectrum_snap_sp ( snap ) ); *(*ptr)++ = libspectrum_snap_im( snap ); *(*ptr)++ = libspectrum_snap_out_ula( snap ) & 0x07; }
static libspectrum_error write_48k_sna( libspectrum_byte **buffer, libspectrum_byte **ptr, size_t *length, libspectrum_snap *snap ) { libspectrum_error error; libspectrum_byte *stack, *sp; /* Must have somewhere in RAM to store PC */ if( libspectrum_snap_sp( snap ) < 0x4002 ) { libspectrum_print_error( LIBSPECTRUM_ERROR_INVALID, "SP is too low (0x%04x) to stack PC", libspectrum_snap_sp( snap ) ); return LIBSPECTRUM_ERROR_INVALID; } libspectrum_make_room( buffer, 0xc000, ptr, length ); error = write_page( &( (*ptr)[ 0x0000 ] ), snap, 5 ); if( error ) return error; error = write_page( &( (*ptr)[ 0x4000 ] ), snap, 2 ); if( error ) return error; error = write_page( &( (*ptr)[ 0x8000 ] ), snap, 0 ); if( error ) return error; /* Place PC on the stack */ stack = &( (*ptr)[ libspectrum_snap_sp( snap ) - 0x4000 - 2 ] ); libspectrum_write_word( &stack, libspectrum_snap_pc( snap ) ); *ptr += 0xc000; /* Store the new value of SP */ sp = *buffer + SNA_OFFSET_SP; libspectrum_write_word( &sp, libspectrum_snap_sp( snap ) - 2 ); return LIBSPECTRUM_ERROR_NONE; }
/* Routines for transferring the Z80 contents to and from snapshots */ static void z80_from_snapshot( libspectrum_snap *snap ) { A = libspectrum_snap_a ( snap ); F = libspectrum_snap_f ( snap ); A_ = libspectrum_snap_a_( snap ); F_ = libspectrum_snap_f_( snap ); BC = libspectrum_snap_bc ( snap ); DE = libspectrum_snap_de ( snap ); HL = libspectrum_snap_hl ( snap ); BC_ = libspectrum_snap_bc_( snap ); DE_ = libspectrum_snap_de_( snap ); HL_ = libspectrum_snap_hl_( snap ); IX = libspectrum_snap_ix( snap ); IY = libspectrum_snap_iy( snap ); I = libspectrum_snap_i ( snap ); R = R7 = libspectrum_snap_r( snap ); SP = libspectrum_snap_sp( snap ); PC = libspectrum_snap_pc( snap ); IFF1 = libspectrum_snap_iff1( snap ); IFF2 = libspectrum_snap_iff2( snap ); IM = libspectrum_snap_im( snap ); z80.halted = libspectrum_snap_halted( snap ); z80.interrupts_enabled_at = libspectrum_snap_last_instruction_ei( snap ) ? z80_tstates : -1; }
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; }