mirror of
https://git.code.sf.net/p/fuse-emulator/fuse
synced 2026-01-27 01:41:34 +03:00
349 lines
11 KiB
C
349 lines
11 KiB
C
/* binary.c: Win32 routines to load/save chunks of binary data
|
|
Copyright (c) 2003-2008 Philip Kendall, Marek Januszewski
|
|
|
|
This program is free software; you can redistribute it and/or modify
|
|
it under the terms of the GNU General Public License as published by
|
|
the Free Software Foundation; either version 2 of the License, or
|
|
(at your option) any later version.
|
|
|
|
This program is distributed in the hope that it will be useful,
|
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
GNU General Public License for more details.
|
|
|
|
You should have received a copy of the GNU General Public License along
|
|
with this program; if not, write to the Free Software Foundation, Inc.,
|
|
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
|
|
|
Author contact information:
|
|
|
|
E-mail: philip-fuse@shadowmagic.org.uk
|
|
|
|
*/
|
|
|
|
#include <config.h>
|
|
|
|
#include <libspectrum.h>
|
|
#include <tchar.h>
|
|
#include <windows.h>
|
|
|
|
#include "fuse.h"
|
|
#include "ui/ui.h"
|
|
#include "utils.h"
|
|
#include "win32internals.h"
|
|
|
|
#include "binary.h"
|
|
|
|
struct binary_info {
|
|
|
|
TCHAR *filename;
|
|
utils_file file;
|
|
|
|
TCHAR *dialog_title;
|
|
|
|
void (*on_change_filename)( HWND hwndDlg, LONG_PTR user_data );
|
|
void (*on_execute)( HWND hwndDlg, LONG_PTR user_data );
|
|
};
|
|
|
|
static void change_load_filename( HWND hwndDlg, LONG_PTR user_data );
|
|
static void load_data( HWND hwndDlg, LONG_PTR user_data );
|
|
|
|
static void change_save_filename( HWND hwndDlg, LONG_PTR user_data );
|
|
static void save_data( HWND hwndDlg, LONG_PTR user_data );
|
|
|
|
static INT_PTR CALLBACK
|
|
binarydata_proc( HWND hwndDlg, UINT uMsg, WPARAM wParam, LPARAM lParam );
|
|
|
|
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 = (TCHAR *) 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();
|
|
}
|
|
|
|
static INT_PTR CALLBACK
|
|
binarydata_proc( HWND hwndDlg, UINT uMsg, WPARAM wParam, LPARAM lParam )
|
|
{
|
|
struct binary_info *info = NULL;
|
|
|
|
switch( uMsg ) {
|
|
case WM_INITDIALOG: {
|
|
TCHAR buffer[80];
|
|
info = ( struct binary_info * ) lParam;
|
|
|
|
/* save the pointer to info with this dialog window */
|
|
SetWindowLongPtr( hwndDlg, GWLP_USERDATA, ( LONG_PTR ) info );
|
|
|
|
SendMessage( hwndDlg, WM_SETTEXT, 0, ( LPARAM ) info->dialog_title );
|
|
|
|
SendDlgItemMessage( hwndDlg, IDC_BINARY_STATIC_PATH, WM_SETTEXT,
|
|
0, ( LPARAM ) info->filename );
|
|
|
|
if( info->file.length != -1 ) {
|
|
_sntprintf( buffer, 80, "%lu", (unsigned long) info->file.length );
|
|
SendDlgItemMessage( hwndDlg, IDC_BINARY_EDIT_LENGTH, WM_SETTEXT,
|
|
0, ( LPARAM ) buffer );
|
|
}
|
|
return FALSE;
|
|
}
|
|
case WM_COMMAND:
|
|
switch( LOWORD( wParam ) ) {
|
|
case IDC_BINARY_BUTTON_BROWSE:
|
|
info = ( struct binary_info * ) GetWindowLongPtr( hwndDlg, GWLP_USERDATA );
|
|
info->on_change_filename( hwndDlg, ( LONG_PTR ) info ) ;
|
|
return 0;
|
|
|
|
case IDOK:
|
|
info = ( struct binary_info * ) GetWindowLongPtr( hwndDlg, GWLP_USERDATA );
|
|
info->on_execute( hwndDlg, ( LONG_PTR ) info ) ;
|
|
return 0;
|
|
|
|
case IDCANCEL:
|
|
EndDialog( hwndDlg, 0 );
|
|
return 0;
|
|
}
|
|
break;
|
|
|
|
case WM_CLOSE:
|
|
EndDialog( hwndDlg, 0 );
|
|
return 0;
|
|
}
|
|
return FALSE;
|
|
}
|
|
|
|
static void
|
|
change_load_filename( HWND hwndDlg, LONG_PTR 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 */
|
|
utils_close_file( &info->file );
|
|
|
|
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 );
|
|
}
|
|
|
|
static void
|
|
load_data( HWND hwndDlg, LONG_PTR user_data )
|
|
{
|
|
struct binary_info *info = ( struct binary_info * )user_data;
|
|
HWND hwnd_control;
|
|
|
|
long start, length; size_t i;
|
|
|
|
TCHAR *temp_buffer, *endptr;
|
|
size_t temp_buffer_len;
|
|
int base;
|
|
|
|
errno = 0;
|
|
temp_buffer_len = SendDlgItemMessage( hwndDlg, IDC_BINARY_EDIT_LENGTH,
|
|
WM_GETTEXTLENGTH, 0, 0 );
|
|
temp_buffer = malloc( sizeof( TCHAR ) * ( temp_buffer_len + 1 ) );
|
|
SendDlgItemMessage( hwndDlg, IDC_BINARY_EDIT_LENGTH, WM_GETTEXT,
|
|
temp_buffer_len + 1, ( LPARAM ) temp_buffer );
|
|
|
|
errno = 0;
|
|
base = ( !_tcsncmp( _T("0x"), temp_buffer, strlen( _T("0x") ) ) )? 16 : 10;
|
|
length = _tcstol( temp_buffer, &endptr, base );
|
|
if( errno || length < 1 || length > 0x10000 || endptr == temp_buffer ) {
|
|
free( temp_buffer );
|
|
ui_error( UI_ERROR_ERROR, "Length must be between 1 and 65536" );
|
|
hwnd_control = GetDlgItem( hwndDlg, IDC_BINARY_EDIT_LENGTH );
|
|
SendMessage( hwndDlg, WM_NEXTDLGCTL, (WPARAM) hwnd_control, TRUE );
|
|
return;
|
|
}
|
|
free( temp_buffer );
|
|
|
|
if( length > info->file.length ) {
|
|
ui_error( UI_ERROR_ERROR,
|
|
"'%s' contains only %lu bytes",
|
|
info->filename, (unsigned long)info->file.length );
|
|
return;
|
|
}
|
|
|
|
errno = 0;
|
|
temp_buffer_len = SendDlgItemMessage( hwndDlg, IDC_BINARY_EDIT_START,
|
|
WM_GETTEXTLENGTH, 0, 0 );
|
|
temp_buffer = malloc( sizeof( TCHAR ) * ( temp_buffer_len + 1 ) );
|
|
SendDlgItemMessage( hwndDlg, IDC_BINARY_EDIT_START, WM_GETTEXT,
|
|
temp_buffer_len + 1, ( LPARAM ) temp_buffer );
|
|
|
|
errno = 0;
|
|
base = ( !_tcsncmp( _T("0x"), temp_buffer, strlen( _T("0x") ) ) )? 16 : 10;
|
|
start = _tcstol( temp_buffer, &endptr, base );
|
|
if( errno || start < 0 || start > 0xffff || endptr == temp_buffer ) {
|
|
free( temp_buffer );
|
|
ui_error( UI_ERROR_ERROR, "Start must be between 0 and 65535" );
|
|
hwnd_control = GetDlgItem( hwndDlg, IDC_BINARY_EDIT_START );
|
|
SendMessage( hwndDlg, WM_NEXTDLGCTL, (WPARAM) hwnd_control, TRUE );
|
|
return;
|
|
}
|
|
free( temp_buffer );
|
|
|
|
if( start + length > 0x10000 ) {
|
|
ui_error( UI_ERROR_ERROR, "Block ends after address 65535" );
|
|
hwnd_control = GetDlgItem( hwndDlg, IDC_BINARY_EDIT_LENGTH );
|
|
SendMessage( hwndDlg, WM_NEXTDLGCTL, (WPARAM) hwnd_control, TRUE );
|
|
return;
|
|
}
|
|
|
|
for( i = 0; i < length; i++ )
|
|
writebyte_internal( start + i, info->file.buffer[ i ] );
|
|
|
|
EndDialog( hwndDlg, 0 );
|
|
}
|
|
|
|
void
|
|
menu_file_savebinarydata( int action )
|
|
{
|
|
struct binary_info info;
|
|
|
|
fuse_emulation_pause();
|
|
|
|
info.dialog_title = (TCHAR *) TEXT( "Fuse - Save Binary Data" );
|
|
|
|
info.filename = ui_get_save_filename( info.dialog_title );
|
|
if( !info.filename ) { fuse_emulation_unpause(); return; }
|
|
|
|
info.file.length = -1; /* let the dialog know to leave length box blank */
|
|
info.on_change_filename = &change_save_filename;
|
|
info.on_execute = &save_data;
|
|
|
|
/* Information display */
|
|
DialogBoxParam( fuse_hInstance, MAKEINTRESOURCE( IDD_BINARY ), fuse_hWnd,
|
|
binarydata_proc, ( LPARAM ) &info );
|
|
|
|
free( info.filename );
|
|
|
|
fuse_emulation_unpause();
|
|
}
|
|
|
|
static void
|
|
change_save_filename( HWND hwndDlg, LONG_PTR user_data )
|
|
{
|
|
struct binary_info *info = ( struct binary_info * ) user_data;
|
|
TCHAR *new_filename;
|
|
|
|
new_filename = ui_get_save_filename( "Fuse - Save Binary Data" );
|
|
if( !new_filename ) return;
|
|
|
|
free( info->filename );
|
|
|
|
info->filename = new_filename;
|
|
|
|
SendDlgItemMessage( hwndDlg, IDC_BINARY_STATIC_PATH, WM_SETTEXT,
|
|
0, ( LPARAM ) new_filename );
|
|
}
|
|
|
|
static void
|
|
save_data( HWND hwndDlg, LONG_PTR user_data )
|
|
{
|
|
struct binary_info *info = ( struct binary_info * ) user_data;
|
|
long start, length;
|
|
HWND hwnd_control;
|
|
|
|
TCHAR *temp_buffer, *endptr;
|
|
size_t temp_buffer_len;
|
|
int base;
|
|
|
|
int error;
|
|
|
|
errno = 0;
|
|
temp_buffer_len = SendDlgItemMessage( hwndDlg, IDC_BINARY_EDIT_LENGTH,
|
|
WM_GETTEXTLENGTH, 0, 0 );
|
|
temp_buffer = malloc( sizeof( TCHAR ) * ( temp_buffer_len + 1 ) );
|
|
SendDlgItemMessage( hwndDlg, IDC_BINARY_EDIT_LENGTH, WM_GETTEXT,
|
|
temp_buffer_len + 1, ( LPARAM ) temp_buffer );
|
|
|
|
errno = 0;
|
|
base = ( !_tcsncmp( _T("0x"), temp_buffer, strlen( _T("0x") ) ) )? 16 : 10;
|
|
length = _tcstol( temp_buffer, &endptr, base );
|
|
if( errno || length < 1 || length > 0x10000 || endptr == temp_buffer ) {
|
|
free( temp_buffer );
|
|
ui_error( UI_ERROR_ERROR, "Length must be between 1 and 65536" );
|
|
hwnd_control = GetDlgItem( hwndDlg, IDC_BINARY_EDIT_LENGTH );
|
|
SendMessage( hwndDlg, WM_NEXTDLGCTL, (WPARAM) hwnd_control, TRUE );
|
|
return;
|
|
}
|
|
free( temp_buffer );
|
|
|
|
errno = 0;
|
|
temp_buffer_len = SendDlgItemMessage( hwndDlg, IDC_BINARY_EDIT_START,
|
|
WM_GETTEXTLENGTH, 0, 0 );
|
|
temp_buffer = malloc( sizeof( TCHAR ) * ( temp_buffer_len + 1 ) );
|
|
SendDlgItemMessage( hwndDlg, IDC_BINARY_EDIT_START, WM_GETTEXT,
|
|
temp_buffer_len + 1, ( LPARAM ) temp_buffer );
|
|
|
|
errno = 0;
|
|
base = ( !_tcsncmp( _T("0x"), temp_buffer, strlen( _T("0x") ) ) )? 16 : 10;
|
|
start = _tcstol( temp_buffer, &endptr, base );
|
|
if( errno || start < 0 || start > 0xffff || endptr == temp_buffer ) {
|
|
free( temp_buffer );
|
|
ui_error( UI_ERROR_ERROR, "Start must be between 0 and 65535" );
|
|
hwnd_control = GetDlgItem( hwndDlg, IDC_BINARY_EDIT_START );
|
|
SendMessage( hwndDlg, WM_NEXTDLGCTL, (WPARAM) hwnd_control, TRUE );
|
|
return;
|
|
}
|
|
free( temp_buffer );
|
|
|
|
if( start + length > 0x10000 ) {
|
|
ui_error( UI_ERROR_ERROR, "Block ends after address 65535" );
|
|
hwnd_control = GetDlgItem( hwndDlg, IDC_BINARY_EDIT_LENGTH );
|
|
SendMessage( hwndDlg, WM_NEXTDLGCTL, (WPARAM) hwnd_control, TRUE );
|
|
return;
|
|
}
|
|
|
|
error = utils_save_binary( start, length, info->filename );
|
|
if( error ) return;
|
|
|
|
EndDialog( hwndDlg, 0 );
|
|
}
|