Allow drag&drop of state files
This commit is contained in:
parent
c1509b6339
commit
8a84a5897e
@ -44,5 +44,6 @@
|
||||
-(void) writeMemory:(uint16_t) addr value:(uint8_t)value;
|
||||
-(void) performAtomicBlock: (void (^)())block;
|
||||
-(void) connectLinkCable:(NSMenuItem *)sender;
|
||||
- (bool)loadStateFile:(const char *)path;
|
||||
@end
|
||||
|
||||
|
@ -1172,12 +1172,12 @@ static unsigned *multiplication_table_for_frequency(unsigned frequency)
|
||||
}
|
||||
}
|
||||
|
||||
- (IBAction)loadState:(id)sender
|
||||
- (bool)loadStateFile:(const char *)path
|
||||
{
|
||||
bool __block success = false;
|
||||
NSString *error =
|
||||
[self captureOutputForBlock:^{
|
||||
success = GB_load_state(&gb, [[self.fileURL URLByDeletingPathExtension] URLByAppendingPathExtension:[NSString stringWithFormat:@"s%ld", (long)[sender tag] ]].path.UTF8String) == 0;
|
||||
success = GB_load_state(&gb, path) == 0;
|
||||
}];
|
||||
|
||||
if (!success) {
|
||||
@ -1186,6 +1186,12 @@ static unsigned *multiplication_table_for_frequency(unsigned frequency)
|
||||
if (error) {
|
||||
[GBWarningPopover popoverWithContents:error onWindow:self.mainWindow];
|
||||
}
|
||||
return success;
|
||||
}
|
||||
|
||||
- (IBAction)loadState:(id)sender
|
||||
{
|
||||
[self loadStateFile:[[self.fileURL URLByDeletingPathExtension] URLByAppendingPathExtension:[NSString stringWithFormat:@"s%ld", (long)[sender tag] ]].path.UTF8String];
|
||||
}
|
||||
|
||||
- (IBAction)clearConsole:(id)sender
|
||||
|
@ -142,6 +142,8 @@ static const uint8_t workboy_vk_to_key[] = {
|
||||
|
||||
- (void) _init
|
||||
{
|
||||
[self registerForDraggedTypes:[NSArray arrayWithObjects: NSPasteboardTypeFileURL, nil]];
|
||||
|
||||
[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(ratioKeepingChanged) name:@"GBAspectChanged" object:nil];
|
||||
tracking_area = [ [NSTrackingArea alloc] initWithRect:(NSRect){}
|
||||
options:NSTrackingMouseEnteredAndExited | NSTrackingActiveAlways | NSTrackingInVisibleRect
|
||||
@ -626,4 +628,29 @@ static const uint8_t workboy_vk_to_key[] = {
|
||||
return image_buffers[(current_buffer + 2) % self.numberOfBuffers];
|
||||
}
|
||||
|
||||
-(NSDragOperation)draggingEntered:(id<NSDraggingInfo>)sender
|
||||
{
|
||||
NSPasteboard *pboard = [sender draggingPasteboard];
|
||||
|
||||
if ( [[pboard types] containsObject:NSURLPboardType] ) {
|
||||
NSURL *fileURL = [NSURL URLFromPasteboard:pboard];
|
||||
if (GB_is_stave_state(fileURL.fileSystemRepresentation)) {
|
||||
return NSDragOperationGeneric;
|
||||
}
|
||||
}
|
||||
return NSDragOperationNone;
|
||||
}
|
||||
|
||||
-(BOOL)performDragOperation:(id<NSDraggingInfo>)sender
|
||||
{
|
||||
NSPasteboard *pboard = [sender draggingPasteboard];
|
||||
|
||||
if ( [[pboard types] containsObject:NSURLPboardType] ) {
|
||||
NSURL *fileURL = [NSURL URLFromPasteboard:pboard];
|
||||
return [_document loadStateFile:fileURL.fileSystemRepresentation];
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
@end
|
||||
|
@ -19,12 +19,6 @@
|
||||
#endif
|
||||
|
||||
|
||||
static inline uint32_t state_magic(void)
|
||||
{
|
||||
if (sizeof(bool) == 1) return 'SAME';
|
||||
return 'S4ME';
|
||||
}
|
||||
|
||||
void GB_attributed_logv(GB_gameboy_t *gb, GB_log_attributes attributes, const char *fmt, va_list args)
|
||||
{
|
||||
char *string = NULL;
|
||||
|
@ -1170,3 +1170,36 @@ int GB_load_state_from_buffer(GB_gameboy_t *gb, const uint8_t *buffer, size_t le
|
||||
|
||||
return load_state_internal(gb, &file);
|
||||
}
|
||||
|
||||
|
||||
bool GB_is_stave_state(const char *path)
|
||||
{
|
||||
bool ret = false;
|
||||
FILE *f = fopen(path, "rb");
|
||||
if (!f) return false;
|
||||
uint32_t magic = 0;
|
||||
fread(&magic, sizeof(magic), 1, f);
|
||||
if (magic == state_magic()) {
|
||||
ret = true;
|
||||
goto exit;
|
||||
}
|
||||
|
||||
// Legacy corrupted Windows save state
|
||||
if (magic == 0) {
|
||||
fread(&magic, sizeof(magic), 1, f);
|
||||
if (magic == state_magic()) {
|
||||
ret = true;
|
||||
goto exit;
|
||||
}
|
||||
}
|
||||
|
||||
fseek(f, -sizeof(magic), SEEK_END);
|
||||
fread(&magic, sizeof(magic), 1, f);
|
||||
if (magic == BE32('BESS')) {
|
||||
ret = true;
|
||||
}
|
||||
|
||||
exit:
|
||||
fclose(f);
|
||||
return ret;
|
||||
}
|
||||
|
@ -27,8 +27,14 @@ void GB_save_state_to_buffer(GB_gameboy_t *gb, uint8_t *buffer);
|
||||
|
||||
int GB_load_state(GB_gameboy_t *gb, const char *path);
|
||||
int GB_load_state_from_buffer(GB_gameboy_t *gb, const uint8_t *buffer, size_t length);
|
||||
|
||||
bool GB_is_stave_state(const char *path);
|
||||
#ifdef GB_INTERNAL
|
||||
static inline uint32_t state_magic(void)
|
||||
{
|
||||
if (sizeof(bool) == 1) return 'SAME';
|
||||
return 'S4ME';
|
||||
}
|
||||
|
||||
/* For internal in-memory save states (rewind, debugger) that do not need BESS */
|
||||
size_t GB_get_save_state_size_no_bess(GB_gameboy_t *gb);
|
||||
void GB_save_state_to_buffer_no_bess(GB_gameboy_t *gb, uint8_t *buffer);
|
||||
|
13
SDL/gui.c
13
SDL/gui.c
@ -18,6 +18,7 @@ SDL_Texture *texture = NULL;
|
||||
SDL_PixelFormat *pixel_format = NULL;
|
||||
enum pending_command pending_command;
|
||||
unsigned command_parameter;
|
||||
char *dropped_state_file = NULL;
|
||||
|
||||
#ifdef __APPLE__
|
||||
#define MODIFIER_NAME " " CMD_STRING
|
||||
@ -1300,9 +1301,15 @@ void run_gui(bool is_running)
|
||||
break;
|
||||
}
|
||||
case SDL_DROPFILE: {
|
||||
set_filename(event.drop.file, SDL_free);
|
||||
pending_command = GB_SDL_NEW_FILE_COMMAND;
|
||||
return;
|
||||
if (GB_is_stave_state(event.drop.file)) {
|
||||
dropped_state_file = event.drop.file;
|
||||
pending_command = GB_SDL_LOAD_STATE_FROM_FILE_COMMAND;
|
||||
}
|
||||
else {
|
||||
set_filename(event.drop.file, SDL_free);
|
||||
pending_command = GB_SDL_NEW_FILE_COMMAND;
|
||||
return;
|
||||
}
|
||||
}
|
||||
case SDL_JOYBUTTONDOWN:
|
||||
{
|
||||
|
@ -39,12 +39,14 @@ enum pending_command {
|
||||
GB_SDL_RESET_COMMAND,
|
||||
GB_SDL_NEW_FILE_COMMAND,
|
||||
GB_SDL_QUIT_COMMAND,
|
||||
GB_SDL_LOAD_STATE_FROM_FILE_COMMAND,
|
||||
};
|
||||
|
||||
#define GB_SDL_DEFAULT_SCALE_MAX 8
|
||||
|
||||
extern enum pending_command pending_command;
|
||||
extern unsigned command_parameter;
|
||||
extern char *dropped_state_file;
|
||||
|
||||
typedef enum {
|
||||
JOYPAD_BUTTON_LEFT,
|
||||
|
17
SDL/main.c
17
SDL/main.c
@ -142,8 +142,14 @@ static void handle_events(GB_gameboy_t *gb)
|
||||
break;
|
||||
|
||||
case SDL_DROPFILE: {
|
||||
set_filename(event.drop.file, SDL_free);
|
||||
pending_command = GB_SDL_NEW_FILE_COMMAND;
|
||||
if (GB_is_stave_state(event.drop.file)) {
|
||||
dropped_state_file = event.drop.file;
|
||||
pending_command = GB_SDL_LOAD_STATE_FROM_FILE_COMMAND;
|
||||
}
|
||||
else {
|
||||
set_filename(event.drop.file, SDL_free);
|
||||
pending_command = GB_SDL_NEW_FILE_COMMAND;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
@ -433,6 +439,13 @@ static bool handle_pending_command(void)
|
||||
end_capturing_logs(true, false);
|
||||
return false;
|
||||
}
|
||||
|
||||
case GB_SDL_LOAD_STATE_FROM_FILE_COMMAND:
|
||||
start_capturing_logs();
|
||||
GB_load_state(&gb, dropped_state_file);
|
||||
end_capturing_logs(true, false);
|
||||
SDL_free(dropped_state_file);
|
||||
return false;
|
||||
|
||||
case GB_SDL_NO_COMMAND:
|
||||
return false;
|
||||
|
Loading…
Reference in New Issue
Block a user