static int machine_load_rom_bank_from_file( memory_page* bank_map, size_t which, int page_num, const char *filename, size_t expected_length, int custom ) { compat_fd fd; int error; utils_file rom; fd = utils_find_auxiliary_file( filename, UTILS_AUXILIARY_ROM ); if( fd == COMPAT_FILE_OPEN_FAILED ) { ui_error( UI_ERROR_ERROR, "couldn't find ROM '%s'", filename ); return 1; } error = utils_read_fd( fd, filename, &rom ); if( error ) return error; if( rom.length != expected_length ) { ui_error( UI_ERROR_ERROR, "ROM '%s' is %ld bytes long; expected %ld bytes", filename, (unsigned long)rom.length, (unsigned long)expected_length ); utils_close_file( &rom ); return 1; } error = machine_load_rom_bank_from_buffer( bank_map, which, page_num, rom.buffer, rom.length, custom ); error |= utils_close_file( &rom ); return error; }
static int machine_load_rom_bank_from_file( memory_page* bank_map, int page_num, const char *filename, size_t expected_length, int custom ) { int error; utils_file rom; error = utils_read_auxiliary_file( filename, &rom, UTILS_AUXILIARY_ROM ); if( error == -1 ) { ui_error( UI_ERROR_ERROR, "couldn't find ROM '%s'", filename ); return 1; } if( error ) return error; if( rom.length != expected_length ) { ui_error( UI_ERROR_ERROR, "ROM '%s' is %ld bytes long; expected %ld bytes", filename, (unsigned long)rom.length, (unsigned long)expected_length ); utils_close_file( &rom ); return 1; } error = machine_load_rom_bank_from_buffer( bank_map, page_num, rom.buffer, rom.length, custom ); utils_close_file( &rom ); return error; }
int snapshot_read( const char *filename ) { utils_file file; libspectrum_snap *snap = libspectrum_snap_alloc(); int error; error = utils_read_file( filename, &file ); if( error ) { libspectrum_snap_free( snap ); return error; } error = libspectrum_snap_read( snap, file.buffer, file.length, LIBSPECTRUM_ID_UNKNOWN, filename ); if( error ) { utils_close_file( &file ); libspectrum_snap_free( snap ); return error; } utils_close_file( &file ); error = snapshot_copy_from( snap ); if( error ) { libspectrum_snap_free( snap ); return error; } error = libspectrum_snap_free( snap ); if( error ) return error; return 0; }
void menu_help_keyboard( int action ) { int error, fd; utils_file file; widget_picture_data info; static const char *filename = "keyboard.scr"; fd = utils_find_auxiliary_file( filename, UTILS_AUXILIARY_LIB ); if( fd == -1 ) { ui_error( UI_ERROR_ERROR, "couldn't find keyboard picture ('%s')", filename ); return; } error = utils_read_fd( fd, filename, &file ); if( error ) return; if( file.length != 6912 ) { ui_error( UI_ERROR_ERROR, "keyboard picture ('%s') is not 6912 bytes long", filename ); utils_close_file( &file ); return; } info.filename = filename; info.screen = file.buffer; info.border = 0; widget_do( WIDGET_TYPE_PICTURE, &info ); if( utils_close_file( &file ) ) return; }
int rzx_finalise_recording( const char *filename ) { libspectrum_byte *buffer; size_t length; libspectrum_error libspec_error; int error; utils_file file; if( rzx_recording || rzx_playback ) return 1; error = utils_read_file( filename, &file ); if( error ) return error; rzx = libspectrum_rzx_alloc(); libspec_error = libspectrum_rzx_read( rzx, file.buffer, file.length ); if( libspec_error != LIBSPECTRUM_ERROR_NONE ) { utils_close_file( &file ); libspectrum_rzx_free( rzx ); return libspec_error; } utils_close_file( &file ); libspec_error = libspectrum_rzx_finalise( rzx ); if( libspec_error != LIBSPECTRUM_ERROR_NONE ) { libspectrum_rzx_free( rzx ); return libspec_error; } /* Write the file */ length = 0; buffer = NULL; libspec_error = libspectrum_rzx_write( &buffer, &length, rzx, LIBSPECTRUM_ID_UNKNOWN, fuse_creator, settings_current.rzx_compression, rzx_competition_mode ? &rzx_key : NULL ); if( libspec_error != LIBSPECTRUM_ERROR_NONE ) { libspectrum_rzx_free( rzx ); return libspec_error; } error = utils_write_file( filename, buffer, length ); if( error ) { libspectrum_free( buffer ); libspectrum_rzx_free( rzx ); return error; } libspectrum_free( buffer ); libspectrum_rzx_free( rzx ); return 0; }
int tape_open( const char *filename, int autoload ) { utils_file file; int error; error = utils_read_file( filename, &file ); if( error ) return error; error = tape_read_buffer( file.buffer, file.length, LIBSPECTRUM_ID_UNKNOWN, filename, autoload ); if( error ) { utils_close_file( &file ); return error; } utils_close_file( &file ); return 0; }
static void change_load_filename( HWND hwndDlg, LONG user_data ) { struct binary_info *info = ( struct binary_info * ) user_data; TCHAR *new_filename; utils_file new_file; TCHAR buffer[80]; int error; new_filename = ui_get_open_filename( "Fuse - Load Binary Data" ); if( !new_filename ) return; error = utils_read_file( new_filename, &new_file ); if( error ) { free( new_filename ); return; } /* Remove the data for the old file */ error = utils_close_file( &info->file ); if( error ) { free( new_filename ); return; } free( info->filename ); /* Put the new data in */ info->filename = new_filename; info->file = new_file; /* And update the displayed information */ SendDlgItemMessage( hwndDlg, IDC_BINARY_STATIC_PATH, WM_SETTEXT, 0, ( LPARAM ) new_filename ); _sntprintf( buffer, 80, "%lu", (unsigned long) info->file.length ); SendDlgItemMessage( hwndDlg, IDC_BINARY_EDIT_LENGTH, WM_SETTEXT, 0, ( LPARAM ) buffer ); }
void menu_file_loadbinarydata( int action ) { /* FIXME: a way to associate a long type with a window is via SetWindowLong with GWL_USERDATA parameter - review past code and implement */ struct binary_info info; int error; fuse_emulation_pause(); info.dialog_title = TEXT( "Fuse - Load Binary Data" ); info.filename = ui_get_open_filename( info.dialog_title ); if( !info.filename ) { fuse_emulation_unpause(); return; } error = utils_read_file( info.filename, &info.file ); if( error ) { free( info.filename ); fuse_emulation_unpause(); return; } info.on_change_filename = &change_load_filename; info.on_execute = &load_data; /* Information display */ DialogBoxParam( fuse_hInstance, MAKEINTRESOURCE( IDD_BINARY ), fuse_hWnd, binarydata_proc, ( LPARAM ) &info ); free( info.filename ); utils_close_file( &info.file ); fuse_emulation_unpause(); }
/* Load a snap to start the current tape autoloading */ static int tape_autoload( libspectrum_machine hardware ) { int error; const char *id; compat_fd fd; char filename[80]; utils_file snap; libspectrum_id_t type; id = machine_get_id( hardware ); if( !id ) { ui_error( UI_ERROR_ERROR, "Unknown machine type %d!", hardware ); return 1; } /* Look for an autoload snap. Try .szx first, then .z80 */ type = LIBSPECTRUM_ID_SNAPSHOT_SZX; snprintf( filename, sizeof(filename), "tape_%s.szx", id ); fd = utils_find_auxiliary_file( filename, UTILS_AUXILIARY_LIB ); if( fd == COMPAT_FILE_OPEN_FAILED ) { type = LIBSPECTRUM_ID_SNAPSHOT_Z80; snprintf( filename, sizeof(filename), "tape_%s.z80", id ); fd = utils_find_auxiliary_file( filename, UTILS_AUXILIARY_LIB ); } /* If we couldn't find either, give up */ if( fd == COMPAT_FILE_OPEN_FAILED ) { ui_error( UI_ERROR_ERROR, "Couldn't find autoload snap for machine type '%s'", id ); return 1; } error = utils_read_fd( fd, filename, &snap ); if( error ) return error; error = snapshot_read_buffer( snap.buffer, snap.length, type ); if( error ) { utils_close_file( &snap ); return error; } if( utils_close_file( &snap ) ) { ui_error( UI_ERROR_ERROR, "Couldn't close '%s': %s", filename, strerror( errno ) ); return 1; } return 0; }
int rzx_continue_recording( const char *filename ) { utils_file file; libspectrum_error libspec_error; int error; libspectrum_snap* snap = NULL; libspectrum_rzx_iterator last_it = NULL; if( rzx_recording || rzx_playback ) return 1; /* Store the filename */ rzx_filename = utils_safe_strdup( filename ); error = utils_read_file( filename, &file ); if( error ) return error; rzx = libspectrum_rzx_alloc(); libspec_error = libspectrum_rzx_read( rzx, file.buffer, file.length ); if( libspec_error != LIBSPECTRUM_ERROR_NONE ) { utils_close_file( &file ); return libspec_error; } utils_close_file( &file ); /* Get final snapshot */ last_it = libspectrum_rzx_iterator_last( rzx ); if( last_it ) snap = libspectrum_rzx_iterator_get_snap( last_it ); if( snap ) { error = snapshot_copy_from( snap ); if( error ) return error; } else { ui_error( UI_ERROR_WARNING, "RZX file cannot be continued" ); libspectrum_free( rzx_filename ); libspectrum_rzx_free( rzx ); return 1; } start_recording( rzx, 0 ); return 0; }
int rzx_start_playback( const char *filename, int check_snapshot ) { utils_file file; libspectrum_error libspec_error; int error; libspectrum_snap* snap; if( rzx_recording ) return 1; rzx = libspectrum_rzx_alloc(); error = utils_read_file( filename, &file ); if( error ) return error; libspec_error = libspectrum_rzx_read( rzx, file.buffer, file.length ); if( libspec_error != LIBSPECTRUM_ERROR_NONE ) { utils_close_file( &file ); return libspec_error; } utils_close_file( &file ); snap = rzx_get_initial_snapshot(); if( !snap && check_snapshot ) { /* We need to load an external snapshot. Could be skipped if the snapshot is preloaded from command line */ error = utils_open_snap(); if( error ) return error; } error = start_playback( rzx ); if( error ) { libspectrum_rzx_free( rzx ); return error; } return 0; }
void ml_logger_close_files(ml_logger_t* mll) { int i = 0; int count = sizeof(mll->files)/sizeof(utils_file_t); utils_file_t* uf; for(i=0; i<count; i++) { uf = &mll->files.file[i]; utils_close_file(uf); } }
void menu_help_keyboard( int action ) { utils_file screen; widget_picture_data info; static const char *filename = "keyboard.scr"; if( utils_read_screen( filename, &screen ) ) { return; } info.filename = filename; info.screen = screen.buffer; info.border = 0; widget_do( WIDGET_TYPE_PICTURE, &info ); utils_close_file( &screen ); }
int dck_reset( void ) { utils_file file; size_t num_block = 0; libspectrum_dck *dck; int error; dck_active = 0; if( !settings_current.dck_file ) { ui_menu_activate( UI_MENU_ITEM_MEDIA_CARTRIDGE_DOCK_EJECT, 0 ); return 0; } dck = libspectrum_dck_alloc(); error = utils_read_file( settings_current.dck_file, &file ); if( error ) { libspectrum_dck_free( dck, 0 ); return error; } error = libspectrum_dck_read2( dck, file.buffer, file.length, settings_current.dck_file ); if( error ) { utils_close_file( &file ); libspectrum_dck_free( dck, 0 ); return error; } if( utils_close_file( &file ) ) { libspectrum_dck_free( dck, 0 ); return 1; } while( dck->dck[num_block] != NULL ) { memory_page **mem; int i; switch( dck->dck[num_block]->bank ) { case LIBSPECTRUM_DCK_BANK_HOME: mem = memory_map_home; break; case LIBSPECTRUM_DCK_BANK_DOCK: mem = memory_map_dock; break; case LIBSPECTRUM_DCK_BANK_EXROM: mem = memory_map_exrom; break; default: ui_error( UI_ERROR_INFO, "Sorry, bank ID %i is unsupported", dck->dck[num_block]->bank ); libspectrum_dck_free( dck, 0 ); return 1; } for( i = 0; i < 8; i++ ) { switch( dck->dck[num_block]->access[i] ) { case LIBSPECTRUM_DCK_PAGE_NULL: break; case LIBSPECTRUM_DCK_PAGE_ROM: mem[i]->page = memory_pool_allocate( MEMORY_PAGE_SIZE ); if( !mem[i]->page ) return 1; memcpy( mem[i]->page, dck->dck[num_block]->pages[i], MEMORY_PAGE_SIZE ); mem[i]->writable = 0; mem[i]->source = MEMORY_SOURCE_CARTRIDGE; break; case LIBSPECTRUM_DCK_PAGE_RAM_EMPTY: case LIBSPECTRUM_DCK_PAGE_RAM: /* Because the scr and snapshot code depends on the standard memory map being in the RAM[] array, we just copy RAM blocks from the HOME bank into the appropriate page; in other cases, we allocate ourselves a new page to store the contents in */ if( !(dck->dck[num_block]->bank == LIBSPECTRUM_DCK_BANK_HOME && i>1) ) { mem[i]->page = memory_pool_allocate( MEMORY_PAGE_SIZE ); if( !mem[i]->page ) return 1; mem[i]->writable = 1; } mem[i]->source = MEMORY_SOURCE_CARTRIDGE; memcpy( mem[i]->page, dck->dck[num_block]->pages[i], MEMORY_PAGE_SIZE ); break; } } num_block++; } dck_active = 1; /* Make the menu item to eject the cartridge active */ ui_menu_activate( UI_MENU_ITEM_MEDIA_CARTRIDGE_DOCK_EJECT, 1 ); return libspectrum_dck_free( dck, 0 ); }
/* Open `filename' and do something sensible with it; autoload tapes if `autoload' is true and return the type of file found in `type' */ int utils_open_file( const char *filename, int autoload, libspectrum_id_t *type_ptr) { utils_file file; libspectrum_id_t type; libspectrum_class_t class; int error; error = 0; if( rzx_recording ) error = rzx_stop_recording(); if( rzx_playback ) error = rzx_stop_playback( 1 ); if( error ) return error; /* Read the file into a buffer */ if( utils_read_file( filename, &file ) ) return 1; /* See if we can work out what it is */ if( libspectrum_identify_file_with_class( &type, &class, filename, file.buffer, file.length ) ) { utils_close_file( &file ); return 1; } switch( class ) { case LIBSPECTRUM_CLASS_UNKNOWN: ui_error( UI_ERROR_ERROR, "utils_open_file: couldn't identify `%s'", filename ); utils_close_file( &file ); return 1; case LIBSPECTRUM_CLASS_RECORDING: error = rzx_start_playback_from_buffer( file.buffer, file.length ); break; case LIBSPECTRUM_CLASS_SNAPSHOT: error = snapshot_read_buffer( file.buffer, file.length, type ); pokemem_find_pokfile( filename ); break; case LIBSPECTRUM_CLASS_TAPE: error = tape_read_buffer( file.buffer, file.length, type, filename, autoload ); pokemem_find_pokfile( filename ); break; case LIBSPECTRUM_CLASS_DISK_PLUS3: if( !( machine_current->capabilities & LIBSPECTRUM_MACHINE_CAPABILITY_PLUS3_DISK ) ) { error = machine_select( LIBSPECTRUM_MACHINE_PLUS3 ); if( error ) break; } error = specplus3_disk_insert( SPECPLUS3_DRIVE_A, filename, autoload ); break; case LIBSPECTRUM_CLASS_DISK_DIDAKTIK: error = didaktik80_disk_insert( DIDAKTIK80_DRIVE_A, filename, autoload ); break; case LIBSPECTRUM_CLASS_DISK_PLUSD: if( periph_is_active( PERIPH_TYPE_DISCIPLE ) ) error = disciple_disk_insert( DISCIPLE_DRIVE_1, filename, autoload ); else error = plusd_disk_insert( PLUSD_DRIVE_1, filename, autoload ); break; case LIBSPECTRUM_CLASS_DISK_OPUS: error = opus_disk_insert( OPUS_DRIVE_1, filename, autoload ); break; case LIBSPECTRUM_CLASS_DISK_TRDOS: if( !( machine_current->capabilities & LIBSPECTRUM_MACHINE_CAPABILITY_TRDOS_DISK ) && !periph_is_active( PERIPH_TYPE_BETA128 ) ) { error = machine_select( LIBSPECTRUM_MACHINE_PENT ); if( error ) break; } /* Check that we actually got a Beta capable machine to insert the disk */ if( ( machine_current->capabilities & LIBSPECTRUM_MACHINE_CAPABILITY_TRDOS_DISK ) || periph_is_active( PERIPH_TYPE_BETA128 ) ) { error = beta_disk_insert( BETA_DRIVE_A, filename, autoload ); } break; case LIBSPECTRUM_CLASS_DISK_GENERIC: if( machine_current->machine == LIBSPECTRUM_MACHINE_PLUS3 || machine_current->machine == LIBSPECTRUM_MACHINE_PLUS2A ) error = specplus3_disk_insert( SPECPLUS3_DRIVE_A, filename, autoload ); else if( machine_current->machine == LIBSPECTRUM_MACHINE_PENT || machine_current->machine == LIBSPECTRUM_MACHINE_PENT512 || machine_current->machine == LIBSPECTRUM_MACHINE_PENT1024 || machine_current->machine == LIBSPECTRUM_MACHINE_SCORP ) error = beta_disk_insert( BETA_DRIVE_A, filename, autoload ); else if( periph_is_active( PERIPH_TYPE_BETA128 ) ) error = beta_disk_insert( BETA_DRIVE_A, filename, autoload ); else if( periph_is_active( PERIPH_TYPE_DISCIPLE ) ) error = disciple_disk_insert( DISCIPLE_DRIVE_1, filename, autoload ); else if( periph_is_active( PERIPH_TYPE_PLUSD ) ) error = plusd_disk_insert( PLUSD_DRIVE_1, filename, autoload ); break; case LIBSPECTRUM_CLASS_CARTRIDGE_IF2: error = if2_insert( filename ); break; case LIBSPECTRUM_CLASS_MICRODRIVE: error = if1_mdr_insert( -1, filename ); break; case LIBSPECTRUM_CLASS_CARTRIDGE_TIMEX: if( !( machine_current->capabilities & LIBSPECTRUM_MACHINE_CAPABILITY_TIMEX_DOCK ) ) { error = machine_select( LIBSPECTRUM_MACHINE_TC2068 ); if( error ) break; } /* Check that we actually got a Dock capable machine to insert the cart */ if( machine_current->capabilities & LIBSPECTRUM_MACHINE_CAPABILITY_TIMEX_DOCK ) { error = dck_insert( filename ); } break; case LIBSPECTRUM_CLASS_HARDDISK: if( !settings_current.simpleide_active && !settings_current.zxatasp_active && !settings_current.divide_enabled && !settings_current.zxcf_active ) { settings_current.zxcf_active = 1; periph_update(); } if( settings_current.zxcf_active ) { error = zxcf_insert( filename ); } else if( settings_current.zxatasp_active ) { error = zxatasp_insert( filename, LIBSPECTRUM_IDE_MASTER ); } else if( settings_current.simpleide_active ) { error = simpleide_insert( filename, LIBSPECTRUM_IDE_MASTER ); } else { error = divide_insert( filename, LIBSPECTRUM_IDE_MASTER ); } if( error ) return error; break; case LIBSPECTRUM_CLASS_AUXILIARY: if( type == LIBSPECTRUM_ID_AUX_POK ) { ui_pokemem_selector( filename ); } break; default: ui_error( UI_ERROR_ERROR, "utils_open_file: unknown class %d", type ); error = 1; break; } if( error ) { utils_close_file( &file ); return error; } utils_close_file( &file ); if( type_ptr ) *type_ptr = type; return 0; }
int screenshot_scr_read( const char *filename ) { int error = 0; int i; utils_file screen; error = utils_read_file( filename, &screen ); if( error ) return error; switch( screen.length ) { case STANDARD_SCR_SIZE: memcpy( &RAM[ memory_current_screen ][display_get_addr(0,0)], screen.buffer, screen.length ); /* If it is a Timex and it is in hi colour or hires mode, switch out of hires or hicolour mode */ if( scld_last_dec.name.b1 || scld_last_dec.name.hires ) scld_dec_write( 0xff, scld_last_dec.byte & ~HIRES ); break; case HICOLOUR_SCR_SIZE: /* If it is a Timex and it is not in hi colour mode, copy screen and switch mode if neccesary */ /* If it is not a Timex copy the mono bitmap and raise an error */ if( machine_current->timex ) { if( !scld_last_dec.name.b1 ) scld_dec_write( 0xff, ( scld_last_dec.byte & ~HIRESATTR ) | EXTCOLOUR ); memcpy( &RAM[ memory_current_screen ][display_get_addr(0,0) + ALTDFILE_OFFSET], screen.buffer + MONO_BITMAP_SIZE, MONO_BITMAP_SIZE ); } else ui_error( UI_ERROR_INFO, "The file contained a TC2048 high-colour screen, loaded as mono"); memcpy( &RAM[ memory_current_screen ][display_get_addr(0,0)], screen.buffer, MONO_BITMAP_SIZE ); break; case HIRES_SCR_SIZE: /* If it is a Timex and it is not in hi res mode, copy screen and switch mode if neccesary */ /* If it is not a Timex scale the bitmap and raise an error */ if( machine_current->timex ) { memcpy( &RAM[ memory_current_screen ][display_get_addr(0,0)], screen.buffer, MONO_BITMAP_SIZE ); memcpy( &RAM[ memory_current_screen ][display_get_addr(0,0)] + ALTDFILE_OFFSET, screen.buffer + MONO_BITMAP_SIZE, MONO_BITMAP_SIZE ); if( !scld_last_dec.name.hires ) scld_dec_write( 0xff, ( scld_last_dec.byte & ~( HIRESCOLMASK | HIRES ) ) | ( *(screen.buffer + HIRES_ATTR) & ( HIRESCOLMASK | HIRES ) ) ); } else { libspectrum_byte attr = hires_convert_dec( *(screen.buffer + HIRES_ATTR) ); for( i = 0; i < MONO_BITMAP_SIZE; i++ ) RAM[ memory_current_screen ][display_get_addr(0,0) + i] = convert_hires_to_lores( *(screen.buffer + MONO_BITMAP_SIZE + i), *(screen.buffer + i) ); /* set attributes based on hires attribute byte */ for( i = 0; i < 768; i++ ) RAM[ memory_current_screen ][display_get_addr(0,0) + MONO_BITMAP_SIZE + i] = attr; ui_error( UI_ERROR_INFO, "The file contained a TC2048 high-res screen, converted to lores"); } break; default: ui_error( UI_ERROR_ERROR, "'%s' is not a valid scr file", filename ); error = 1; } utils_close_file( &screen ); display_refresh_all(); return error; }
int dck_reset( void ) { utils_file file; size_t num_block = 0; libspectrum_dck *dck; int error; dck_active = 0; if( !settings_current.dck_file ) { ui_menu_activate( UI_MENU_ITEM_MEDIA_CARTRIDGE_DOCK_EJECT, 0 ); return 0; } dck = libspectrum_dck_alloc(); error = utils_read_file( settings_current.dck_file, &file ); if( error ) { libspectrum_dck_free( dck, 0 ); return error; } error = libspectrum_dck_read2( dck, file.buffer, file.length, settings_current.dck_file ); if( error ) { utils_close_file( &file ); libspectrum_dck_free( dck, 0 ); return error; } utils_close_file( &file ); while( dck->dck[num_block] != NULL ) { memory_page *page; int i; libspectrum_dck_bank dck_bank = dck->dck[num_block]->bank; if( dck_bank != LIBSPECTRUM_DCK_BANK_HOME && dck_bank != LIBSPECTRUM_DCK_BANK_DOCK && dck_bank != LIBSPECTRUM_DCK_BANK_EXROM ) { ui_error( UI_ERROR_INFO, "Sorry, bank ID %i is unsupported", dck->dck[num_block]->bank ); libspectrum_dck_free( dck, 0 ); return 1; } for( i = 0; i < 8; i++ ) { libspectrum_byte *data; int j; switch( dck->dck[num_block]->access[i] ) { case LIBSPECTRUM_DCK_PAGE_NULL: break; case LIBSPECTRUM_DCK_PAGE_ROM: data = memory_pool_allocate( 0x2000 ); memcpy( data, dck->dck[num_block]->pages[i], 0x2000 ); for( j = 0; j < MEMORY_PAGES_IN_8K; j++ ) { page = dck_get_memory_page( dck_bank, i * MEMORY_PAGES_IN_8K + j); page->offset = j * MEMORY_PAGE_SIZE; page->writable = 0; page->save_to_snapshot = 1; page->page = data + page->offset; } break; case LIBSPECTRUM_DCK_PAGE_RAM_EMPTY: case LIBSPECTRUM_DCK_PAGE_RAM: /* Because the scr and snapshot code depends on the standard memory map being in the RAM[] array, we just copy RAM blocks from the HOME bank into the appropriate page; in other cases, we allocate ourselves a new page to store the contents in */ if( dck_bank == LIBSPECTRUM_DCK_BANK_HOME && i>1 ) { for( j = 0; j < MEMORY_PAGES_IN_8K; j++ ) { page = dck_get_memory_page( dck_bank, i * MEMORY_PAGES_IN_8K + j); if( dck->dck[num_block]->access[i] == LIBSPECTRUM_DCK_PAGE_RAM ) { memcpy( page->page, dck->dck[num_block]->pages[i] + j * MEMORY_PAGE_SIZE, MEMORY_PAGE_SIZE ); } else { memset( page->page, 0, MEMORY_PAGE_SIZE ); } } } else { data = memory_pool_allocate( 0x2000 ); if( dck->dck[num_block]->access[i] == LIBSPECTRUM_DCK_PAGE_RAM ) { memcpy( data, dck->dck[num_block]->pages[i], 0x2000 ); } else { memset( data, 0, 0x2000 ); } for( j = 0; j < MEMORY_PAGES_IN_8K; j++ ) { page = dck_get_memory_page( dck_bank, i * MEMORY_PAGES_IN_8K + j); page->offset = j * MEMORY_PAGE_SIZE; page->writable = 1; page->save_to_snapshot = 1; page->page = data + page->offset; } } break; } } num_block++; } dck_active = 1; /* Reset contention for pages */ scld_set_exrom_dock_contention(); /* Make the menu item to eject the cartridge active */ ui_menu_activate( UI_MENU_ITEM_MEDIA_CARTRIDGE_DOCK_EJECT, 1 ); return libspectrum_dck_free( dck, 0 ); }