/* Check whether we're actually in the right ROM when a tape trap hit */ static int trap_check_rom( void ) { if( plusd_available && plusd_active ) return 0; /* +D must not be active */ if( opus_available && opus_active ) return 0; /* Opus must not be active */ if( memory_custom_rom() ) return 0; /* and we can't be using a custom ROM */ switch( machine_current->machine ) { case LIBSPECTRUM_MACHINE_16: case LIBSPECTRUM_MACHINE_48: case LIBSPECTRUM_MACHINE_48_NTSC: case LIBSPECTRUM_MACHINE_TC2048: return 1; /* Always OK here */ case LIBSPECTRUM_MACHINE_TC2068: case LIBSPECTRUM_MACHINE_TS2068: /* OK if we're in the EXROM (location of the tape routines) */ return( memory_map_read[0].bank == MEMORY_BANK_EXROM ); case LIBSPECTRUM_MACHINE_128: case LIBSPECTRUM_MACHINE_PLUS2: case LIBSPECTRUM_MACHINE_SE: /* OK if we're in ROM 1 */ return( machine_current->ram.current_rom == 1 ); case LIBSPECTRUM_MACHINE_PLUS2A: case LIBSPECTRUM_MACHINE_PLUS3: case LIBSPECTRUM_MACHINE_PLUS3E: /* OK if we're not in a 64Kb RAM configuration and we're in ROM 3 */ return( ! machine_current->ram.special && machine_current->ram.current_rom == 3 ); case LIBSPECTRUM_MACHINE_PENT: case LIBSPECTRUM_MACHINE_PENT512: case LIBSPECTRUM_MACHINE_PENT1024: case LIBSPECTRUM_MACHINE_SCORP: /* OK if we're in ROM 1 and the Beta disk interface is not active */ return( machine_current->ram.current_rom == 1 && !beta_active ); case LIBSPECTRUM_MACHINE_UNKNOWN: /* should never happen */ ui_error( UI_ERROR_ERROR, "trap_check_rom: machine type is LIBSPECTRUM_MACHINE_UNKNOWN" ); fuse_abort(); } ui_error( UI_ERROR_ERROR, "trap_check_rom: unknown machine type %d", machine_current->machine ); fuse_abort(); }
int debugger_breakpoint_add_event( debugger_breakpoint_type type, const char *type_string, const char *detail, size_t ignore, debugger_breakpoint_life life, debugger_expression *condition ) { debugger_breakpoint_value value; switch( type ) { case DEBUGGER_BREAKPOINT_TYPE_EVENT: break; default: ui_error( UI_ERROR_ERROR, "%s given type %d", __func__, type ); fuse_abort(); } if( !debugger_event_is_registered( type_string, detail ) ) { ui_error( UI_ERROR_WARNING, "Event type %s:%s not known", type_string, detail ); return 1; } value.event.detail = NULL; value.event.type = strdup( type_string ); value.event.detail = strdup( detail ); if( !value.event.type || !value.event.detail ) { free( value.event.type ); free( value.event.detail ); return 1; } return breakpoint_add( type, value, ignore, life, condition ); }
scaler_type menu_get_scaler( scaler_available_fn selector ) { size_t count, i; const char *options[ SCALER_NUM ]; widget_select_t info; int error; count = 0; info.current = 0; for( i = 0; i < SCALER_NUM; i++ ) if( selector( i ) ) { if( current_scaler == i ) info.current = count; options[ count++ ] = scaler_name( i ); } info.title = "Select scaler"; info.options = options; info.count = count; error = widget_do( WIDGET_TYPE_SELECT, &info ); if( error ) return SCALER_NUM; if( info.result == -1 ) return SCALER_NUM; for( i = 0; i < SCALER_NUM; i++ ) if( selector( i ) && !info.result-- ) return i; ui_error( UI_ERROR_ERROR, "widget_select_scaler: ran out of scalers" ); fuse_abort(); }
static int sdldisplay_load_gfx_mode( void ) { Uint16 *tmp_screen_pixels; sdldisplay_force_full_refresh = 1; tmp_screen = NULL; tmp_screen_width = (image_width + 3); sdldisplay_current_size = scaler_get_scaling_factor( current_scaler ); sdldisplay_find_best_fullscreen_scaler(); /* Create the surface that contains the scaled graphics in 16 bit mode */ sdldisplay_gc = SDL_SetVideoMode( image_width * sdldisplay_current_size, image_height * sdldisplay_current_size, 16, settings_current.full_screen ? (SDL_FULLSCREEN|SDL_SWSURFACE) : SDL_SWSURFACE ); if( !sdldisplay_gc ) { fprintf( stderr, "%s: couldn't create SDL graphics context\n", fuse_progname ); fuse_abort(); } sdldisplay_is_full_screen = settings_current.full_screen = !!(sdldisplay_gc->flags & SDL_FULLSCREEN); /* Distinguish 555 and 565 mode */ if( sdldisplay_gc->format->Gmask >> sdldisplay_gc->format->Gshift == 0x1f ) scaler_select_bitformat( 555 ); else
/* Is a binary operator non-associative? */ static int is_non_associative( int operation ) { switch( operation ) { /* Simple cases */ case '+': case '*': return 0; case '-': case '/': return 1; /* None of the comparison operators are associative due to them returning truth values */ case DEBUGGER_TOKEN_EQUAL_TO: case DEBUGGER_TOKEN_NOT_EQUAL_TO: case '<': case '>': case DEBUGGER_TOKEN_LESS_THAN_OR_EQUAL_TO: case DEBUGGER_TOKEN_GREATER_THAN_OR_EQUAL_TO: return 1; /* The logical operators are associative */ case DEBUGGER_TOKEN_LOGICAL_AND: return 0; case DEBUGGER_TOKEN_LOGICAL_OR: return 0; /* The bitwise operators are also associative (consider them as vectorised logical operators) */ case '&': return 0; case '^': return 0; case '|': return 0; } /* Should never get here */ ui_error( UI_ERROR_ERROR, "unknown binary operation %d", operation ); fuse_abort(); }
nic_w5100_t* nic_w5100_alloc( void ) { int error; int i; nic_w5100_t *self; compat_socket_networking_init(); self = libspectrum_new( nic_w5100_t, 1 ); self->selfpipe = compat_socket_selfpipe_alloc(); for( i = 0; i < 4; i++ ) nic_w5100_socket_init( &self->socket[i], i ); nic_w5100_reset( self ); self->stop_io_thread = 0; error = pthread_create( &self->thread, NULL, w5100_io_thread, self ); if( error ) { ui_error( UI_ERROR_ERROR, "w5100: error %d creating thread", error ); fuse_abort(); } return self; }
void debugger_event( int event_code ) { debugger_event_t event; GSList *ptr; if( event_code >= registered_events->len ) { ui_error( UI_ERROR_ERROR, "internal error: invalid debugger event %d", event_code ); fuse_abort(); } event = g_array_index( registered_events, debugger_event_t, event_code ); for( ptr = debugger_breakpoints; ptr; ptr = ptr->next ) { debugger_breakpoint *bp = ptr->data; if( bp->type != DEBUGGER_BREAKPOINT_TYPE_EVENT ) continue; if( event_matches( &bp->value.event, event.type, event.detail ) && debugger_breakpoint_trigger( bp ) ) { debugger_mode = DEBUGGER_MODE_HALTED; debugger_command_evaluate( bp->commands ); } } }
/* Add a breakpoint */ int debugger_breakpoint_add_address( debugger_breakpoint_type type, int page, libspectrum_word offset, size_t ignore, debugger_breakpoint_life life, debugger_expression *condition ) { debugger_breakpoint_value value; switch( type ) { case DEBUGGER_BREAKPOINT_TYPE_EXECUTE: case DEBUGGER_BREAKPOINT_TYPE_READ: case DEBUGGER_BREAKPOINT_TYPE_WRITE: break; default: ui_error( UI_ERROR_ERROR, "debugger_breakpoint_add_address given type %d", type ); fuse_abort(); } value.address.page = page; value.address.offset = offset; return breakpoint_add( type, value, ignore, life, condition ); }
static enum precedence_t binaryop_precedence( int operation ) { switch( operation ) { case DEBUGGER_TOKEN_LOGICAL_OR: return PRECEDENCE_LOGICAL_OR; case DEBUGGER_TOKEN_LOGICAL_AND: return PRECEDENCE_LOGICAL_AND; case '|': return PRECEDENCE_BITWISE_OR; case '^': return PRECEDENCE_BITWISE_XOR; case '&': return PRECEDENCE_BITWISE_AND; case '+': case '-': return PRECEDENCE_ADDITION; case '*': case '/': return PRECEDENCE_MULTIPLICATION; case DEBUGGER_TOKEN_EQUAL_TO: case DEBUGGER_TOKEN_NOT_EQUAL_TO: return PRECEDENCE_EQUALITY; case '<': case '>': case DEBUGGER_TOKEN_LESS_THAN_OR_EQUAL_TO: case DEBUGGER_TOKEN_GREATER_THAN_OR_EQUAL_TO: return PRECEDENCE_COMPARISON; default: ui_error( UI_ERROR_ERROR, "unknown binary operator %d", operation ); fuse_abort(); } }
int machine_select( libspectrum_machine type ) { int i; int error; for( i=0; i < machine_count; i++ ) { if( machine_types[i]->machine == type ) { machine_location = i; error = machine_select_machine( machine_types[i] ); if( !error ) return 0; /* If we couldn't select the new machine type, try falling back to plain old 48K */ if( type != LIBSPECTRUM_MACHINE_48 ) error = machine_select( LIBSPECTRUM_MACHINE_48 ); /* If that still didn't work, give up */ if( error ) { ui_error( UI_ERROR_ERROR, "can't select 48K machine. Giving up." ); fuse_abort(); } else { ui_error( UI_ERROR_INFO, "selecting 48K machine" ); return 0; } return 0; } } ui_error( UI_ERROR_ERROR, "machine type %d unknown", type ); return 1; }
libspectrum_dword debugger_expression_evaluate( debugger_expression *exp ) { switch( exp->type ) { case DEBUGGER_EXPRESSION_TYPE_INTEGER: return exp->types.integer; case DEBUGGER_EXPRESSION_TYPE_REGISTER: return debugger_register_get( exp->types.reg ); case DEBUGGER_EXPRESSION_TYPE_UNARYOP: return evaluate_unaryop( &( exp->types.unaryop ) ); case DEBUGGER_EXPRESSION_TYPE_BINARYOP: return evaluate_binaryop( &( exp->types.binaryop ) ); case DEBUGGER_EXPRESSION_TYPE_VARIABLE: return debugger_variable_get( exp->types.variable ); } ui_error( UI_ERROR_ERROR, "unknown expression type %d", exp->type ); fuse_abort(); }
int debugger_expression_deparse( char *buffer, size_t length, const debugger_expression *exp ) { switch( exp->type ) { case DEBUGGER_EXPRESSION_TYPE_INTEGER: if( debugger_output_base == 10 ) { snprintf( buffer, length, "%d", exp->types.integer ); } else { snprintf( buffer, length, "0x%x", exp->types.integer ); } return 0; case DEBUGGER_EXPRESSION_TYPE_REGISTER: snprintf( buffer, length, "%s", debugger_register_text( exp->types.reg ) ); return 0; case DEBUGGER_EXPRESSION_TYPE_UNARYOP: return deparse_unaryop( buffer, length, &( exp->types.unaryop ) ); case DEBUGGER_EXPRESSION_TYPE_BINARYOP: return deparse_binaryop( buffer, length, &( exp->types.binaryop ) ); case DEBUGGER_EXPRESSION_TYPE_VARIABLE: snprintf( buffer, length, "$%s", exp->types.variable ); return 0; } ui_error( UI_ERROR_ERROR, "unknown expression type %d", exp->type ); fuse_abort(); }
int compat_get_next_path( path_context *ctx ) { char buffer[ PATH_MAX ]; const char *path_segment, *path2; switch( (ctx->state)++ ) { /* First look relative to the current directory */ case 0: strncpy( ctx->path, ".", PATH_MAX ); return 1; /* Then relative to the Fuse executable */ case 1: switch( ctx->type ) { case UTILS_AUXILIARY_LIB: path_segment = "lib"; break; case UTILS_AUXILIARY_ROM: path_segment = "roms"; break; case UTILS_AUXILIARY_WIDGET: path_segment = "ui/widget"; break; case UTILS_AUXILIARY_GTK: path_segment = "ui/gtk"; break; default: ui_error( UI_ERROR_ERROR, "unknown auxiliary file type %d", ctx->type ); return 0; } if( compat_is_absolute_path( fuse_progname ) ) { strncpy( buffer, fuse_progname, PATH_MAX ); buffer[ PATH_MAX - 1 ] = '\0'; } else { size_t len; len = PATH_MAX - strlen( fuse_progname ) - strlen( FUSE_DIR_SEP_STR ); if( !getcwd( buffer, len ) ) { ui_error( UI_ERROR_ERROR, "error getting current working directory: %s", strerror( errno ) ); return 0; } strcat( buffer, FUSE_DIR_SEP_STR ); strcat( buffer, fuse_progname ); } path2 = dirname( buffer ); snprintf( ctx->path, PATH_MAX, "%s" FUSE_DIR_SEP_STR "%s", path2, path_segment ); return 1; /* Then where we may have installed the data files */ case 2: path2 = "sd:/apps/fuse"; strncpy( ctx->path, path2, PATH_MAX ); buffer[ PATH_MAX - 1 ] = '\0'; return 1; case 3: return 0; } ui_error( UI_ERROR_ERROR, "unknown path_context state %d", ctx->state ); fuse_abort(); }
void profile_map( libspectrum_word pc ) { if( tstates - profile_last_tstates > 256 ) fuse_abort(); total_tstates[ profile_last_pc ] += tstates - profile_last_tstates; profile_last_pc = z80.pc.w; profile_last_tstates = tstates; }
int compat_get_next_path( path_context *ctx ) { char buffer[ PATH_MAX ]; const char *path_segment, *path2; switch( ctx->type ) { case UTILS_AUXILIARY_LIB: path_segment = "lib"; break; case UTILS_AUXILIARY_ROM: path_segment = "roms"; break; case UTILS_AUXILIARY_WIDGET: path_segment = "ui/widget"; break; case UTILS_AUXILIARY_GTK: path_segment = "ui/gtk"; break; default: ui_error( UI_ERROR_ERROR, "unknown auxiliary file type %d", ctx->type ); return 0; } switch( (ctx->state)++ ) { /* First look relative to the Fuse executable */ case 0: if( compat_is_absolute_path( fuse_progname ) ) { strncpy( buffer, fuse_progname, PATH_MAX ); buffer[ PATH_MAX - 1 ] = '\0'; } else { DWORD retval; retval = GetModuleFileName( NULL, buffer, PATH_MAX ); if( !retval ) return 0; } path2 = dirname( buffer ); snprintf( ctx->path, PATH_MAX, "%s" FUSE_DIR_SEP_STR "%s", path2, path_segment ); return 1; /* Then relative to %APPDATA%/Fuse directory */ case 1: path2 = getenv( "APPDATA" ); if( !path2 ) return 0; snprintf( ctx->path, PATH_MAX, "%s" FUSE_DIR_SEP_STR "Fuse" FUSE_DIR_SEP_STR "%s", path2, path_segment ); return 1; /* Then relative to the current directory */ case 2: snprintf( ctx->path, PATH_MAX, "." FUSE_DIR_SEP_STR "%s", path_segment ); return 1; case 3: return 0; } ui_error( UI_ERROR_ERROR, "unknown path_context state %d", ctx->state ); fuse_abort(); }
static enum precedence_t unaryop_precedence( int operation ) { switch( operation ) { case '!': case '~': case '-': return PRECEDENCE_NEGATE; default: ui_error( UI_ERROR_ERROR, "unknown unary operator %d", operation ); fuse_abort(); } }
static keyboard_key_name get_fire_button_key( int which, input_key button ) { switch( which ) { case 0: switch( button ) { case INPUT_JOYSTICK_FIRE_1 : return settings_current.joystick_1_fire_1; case INPUT_JOYSTICK_FIRE_2 : return settings_current.joystick_1_fire_2; case INPUT_JOYSTICK_FIRE_3 : return settings_current.joystick_1_fire_3; case INPUT_JOYSTICK_FIRE_4 : return settings_current.joystick_1_fire_4; case INPUT_JOYSTICK_FIRE_5 : return settings_current.joystick_1_fire_5; case INPUT_JOYSTICK_FIRE_6 : return settings_current.joystick_1_fire_6; case INPUT_JOYSTICK_FIRE_7 : return settings_current.joystick_1_fire_7; case INPUT_JOYSTICK_FIRE_8 : return settings_current.joystick_1_fire_8; case INPUT_JOYSTICK_FIRE_9 : return settings_current.joystick_1_fire_9; case INPUT_JOYSTICK_FIRE_10: return settings_current.joystick_1_fire_10; case INPUT_JOYSTICK_FIRE_11: return settings_current.joystick_1_fire_11; case INPUT_JOYSTICK_FIRE_12: return settings_current.joystick_1_fire_12; case INPUT_JOYSTICK_FIRE_13: return settings_current.joystick_1_fire_13; case INPUT_JOYSTICK_FIRE_14: return settings_current.joystick_1_fire_14; case INPUT_JOYSTICK_FIRE_15: return settings_current.joystick_1_fire_15; default: break; } break; case 1: switch( button ) { case INPUT_JOYSTICK_FIRE_1 : return settings_current.joystick_2_fire_1; case INPUT_JOYSTICK_FIRE_2 : return settings_current.joystick_2_fire_2; case INPUT_JOYSTICK_FIRE_3 : return settings_current.joystick_2_fire_3; case INPUT_JOYSTICK_FIRE_4 : return settings_current.joystick_2_fire_4; case INPUT_JOYSTICK_FIRE_5 : return settings_current.joystick_2_fire_5; case INPUT_JOYSTICK_FIRE_6 : return settings_current.joystick_2_fire_6; case INPUT_JOYSTICK_FIRE_7 : return settings_current.joystick_2_fire_7; case INPUT_JOYSTICK_FIRE_8 : return settings_current.joystick_2_fire_8; case INPUT_JOYSTICK_FIRE_9 : return settings_current.joystick_2_fire_9; case INPUT_JOYSTICK_FIRE_10: return settings_current.joystick_2_fire_10; case INPUT_JOYSTICK_FIRE_11: return settings_current.joystick_2_fire_11; case INPUT_JOYSTICK_FIRE_12: return settings_current.joystick_2_fire_12; case INPUT_JOYSTICK_FIRE_13: return settings_current.joystick_2_fire_13; case INPUT_JOYSTICK_FIRE_14: return settings_current.joystick_2_fire_14; case INPUT_JOYSTICK_FIRE_15: return settings_current.joystick_2_fire_15; default: break; } break; } ui_error( UI_ERROR_ERROR, "get_fire_button_key: which = %d, button = %d", which, button ); fuse_abort(); }
int didaktik80_disk_insert( didaktik80_drive_number which, const char *filename, int autoload ) { if( which >= DIDAKTIK80_NUM_DRIVES ) { ui_error( UI_ERROR_ERROR, "didaktik80_insert: unknown drive %d", which ); fuse_abort(); } return ui_media_drive_insert( &didaktik_ui_drives[ which ], filename, autoload ); }
/* Move all rectangles not updated on this line to the inactive list */ void rectangle_end_line( int y ) { size_t i; struct rectangle *ptr; for( i = 0; i < rectangle_active_count; i++ ) { /* Skip if this rectangle was updated this line */ if( rectangle_active[i].y + rectangle_active[i].h == y + 1 ) continue; if ( settings_current.frame_rate > 1 && compare_and_merge_rectangles( &rectangle_active[i] ) ) { /* Mark the active rectangle as done */ rectangle_active[i].h = 0; continue; } /* We couldn't find a rectangle to extend, so create a new one */ if( ++rectangle_inactive_count > rectangle_inactive_allocated ) { size_t new_alloc; new_alloc = rectangle_inactive_allocated ? 2 * rectangle_inactive_allocated : 8; ptr = realloc( rectangle_inactive, new_alloc * sizeof( struct rectangle ) ); if( !ptr ) { ui_error( UI_ERROR_ERROR, "Out of memory at %s:%d", __FILE__, __LINE__ ); fuse_abort(); } rectangle_inactive_allocated = new_alloc; rectangle_inactive = ptr; } rectangle_inactive[ rectangle_inactive_count - 1 ] = rectangle_active[i]; /* Mark the active rectangle as done */ rectangle_active[i].h = 0; } /* Compress the list of active rectangles */ for( i = 0, ptr = rectangle_active; i < rectangle_active_count; i++ ) { if( rectangle_active[i].h == 0 ) continue; *ptr = rectangle_active[i]; ptr++; } rectangle_active_count = ptr - rectangle_active; }
void compat_socket_networking_init( void ) { WORD wVersionRequested; WSADATA wsaData; int error; wVersionRequested = MAKEWORD( 2, 2 ); error = WSAStartup( wVersionRequested, &wsaData ); if( error ) { ui_error( UI_ERROR_ERROR, "%s:%d: error %d from WSAStartup()", __FILE__, __LINE__, error ); fuse_abort(); } if( LOBYTE( wsaData.wVersion ) != 2 || HIBYTE( wsaData.wVersion ) != 2 ) { ui_error( UI_ERROR_ERROR, "%s:%d: unexpected version 0x%02x from WSAStartup()", __FILE__, __LINE__, wsaData.wVersion ); fuse_abort(); } }
static libspectrum_dword evaluate_unaryop( struct unaryop_type *unary ) { switch( unary->operation ) { case '!': return !debugger_expression_evaluate( unary->op ); case '~': return ~debugger_expression_evaluate( unary->op ); case '-': return -debugger_expression_evaluate( unary->op ); } ui_error( UI_ERROR_ERROR, "unknown unary operator %d", unary->operation ); fuse_abort(); }
/* Process a z80 maskable interrupt */ int z80_interrupt( void ) { /* An interrupt will occur if IFF1 is set and the /INT line hasn't gone high again. On a Timex machine, we also need the SCLD's INTDISABLE to be clear */ if( IFF1 && tstates < machine_current->timings.interrupt_length && !scld_last_dec.name.intdisable ) { /* If interrupts have just been enabled, don't accept the interrupt now, but check after the next instruction has been executed */ if( tstates == z80.interrupts_enabled_at ) { event_add( tstates + 1, z80_interrupt_event ); return 0; } if( z80.halted ) { PC++; z80.halted = 0; } IFF1=IFF2=0; writebyte( --SP, PCH ); writebyte( --SP, PCL ); R++; rzx_instructions_offset--; switch(IM) { case 0: PC = 0x0038; tstates += 7; break; case 1: PC = 0x0038; tstates += 7; break; case 2: { libspectrum_word inttemp=(0x100*I)+0xff; PCL = readbyte(inttemp++); PCH = readbyte(inttemp); tstates += 7; break; } default: ui_error( UI_ERROR_ERROR, "Unknown interrupt mode %d", IM ); fuse_abort(); } return 1; /* Accepted an interrupt */ } else { return 0; /* Did not accept an interrupt */ } }
/* Called by the menu when Machine/Reset selected */ void menu_machine_reset( int action ) { int hard_reset = action; const char *message = "Reset?"; if( hard_reset ) message = "Hard reset?"; if( win32ui_confirm( message ) && machine_reset( hard_reset ) ) { ui_error( UI_ERROR_ERROR, "couldn't reset machine: giving up!" ); /* FIXME: abort() seems a bit extreme here, but it'll do for now */ fuse_abort(); } }
/* Check whether 'bp' should trigger if we're looking for a breakpoint of 'type' with parameter 'value'. Returns non-zero if we should trigger */ static int breakpoint_check( debugger_breakpoint *bp, debugger_breakpoint_type type, libspectrum_dword value ) { int page; if( bp->type != type ) return 0; switch( type ) { case DEBUGGER_BREAKPOINT_TYPE_EXECUTE: case DEBUGGER_BREAKPOINT_TYPE_READ: case DEBUGGER_BREAKPOINT_TYPE_WRITE: page = bp->value.address.page; /* If page == -1, value must match exactly; otherwise, the page and the offset must match */ if( page == -1 ) { if( bp->value.address.offset != value ) return 0; } else { if( page != encode_bank_and_page( type, value ) ) return 0; if( bp->value.address.offset != ( value & 0x3fff ) ) return 0; } break; /* Port values must match after masking */ case DEBUGGER_BREAKPOINT_TYPE_PORT_READ: case DEBUGGER_BREAKPOINT_TYPE_PORT_WRITE: if( ( value & bp->value.port.mask ) != bp->value.port.port ) return 0; break; /* Timed breakpoints trigger if we're past the relevant time */ case DEBUGGER_BREAKPOINT_TYPE_TIME: if( bp->value.time.triggered || bp->value.time.tstates > tstates ) return 0; break; default: ui_error( UI_ERROR_ERROR, "Unknown breakpoint type %d", bp->type ); fuse_abort(); } return debugger_breakpoint_trigger( bp ); }
compat_socket_selfpipe_t* compat_socket_selfpipe_alloc( void ) { int error; int pipefd[2]; compat_socket_selfpipe_t *self = libspectrum_new( compat_socket_selfpipe_t, 1 ); error = pipe( pipefd ); if( error ) { ui_error( UI_ERROR_ERROR, "%s: %d: error %d creating pipe", __FILE__, __LINE__, error ); fuse_abort(); } self->read_fd = pipefd[0]; self->write_fd = pipefd[1]; return self; }
/* When deparsing, do we need to put brackets around `operand' when being used as an operand of the binary operation `top_operation'? */ static int brackets_necessary( int top_operation, debugger_expression *operand ) { enum precedence_t top_precedence, bottom_precedence; top_precedence = binaryop_precedence( top_operation ); bottom_precedence = operand->precedence; /* If the top level operation has a higher precedence than the bottom level operation, we always need brackets */ if( top_precedence > bottom_precedence ) return 1; /* If the two operations are of equal precedence, we need brackets i) if the top level operation is non-associative, or ii) if the operand is a non-associative operation Note the assumption here that all things with a precedence equal to a binary operator are also binary operators Strictly, we don't need brackets in either of these cases, but otherwise the user is going to have to remember operator left-right associativity; I think things are clearer with brackets in. */ if( top_precedence == bottom_precedence ) { if( is_non_associative( top_operation ) ) return 1; /* Sanity check */ if( operand->type != DEBUGGER_EXPRESSION_TYPE_BINARYOP ) { ui_error( UI_ERROR_ERROR, "binary operator has same precedence as non-binary operator" ); fuse_abort(); } return is_non_associative( operand->types.binaryop.operation ); } /* Otherwise (ie if the top level operation is of lower precedence than the bottom, or both operators have equal precedence and everything is associative) we don't need brackets */ return 0; }
/* Add the rectangle { x, line, w, 1 } to the list of rectangles to be redrawn, either by extending an existing rectangle or creating a new one */ void rectangle_add( int y, int x, int w ) { size_t i; struct rectangle *ptr; /* Check through all 'active' rectangles (those which were modified on the previous line) and see if we can use this new rectangle to extend them */ for( i = 0; i < rectangle_active_count; i++ ) { if( rectangle_active[i].x == x && rectangle_active[i].w == w ) { rectangle_active[i].h++; return; } } /* We couldn't find a rectangle to extend, so create a new one */ if( ++rectangle_active_count > rectangle_active_allocated ) { size_t new_alloc; new_alloc = rectangle_active_allocated ? 2 * rectangle_active_allocated : 8; ptr = realloc( rectangle_active, new_alloc * sizeof( struct rectangle ) ); if( !ptr ) { ui_error( UI_ERROR_ERROR, "Out of memory at %s:%d", __FILE__, __LINE__ ); fuse_abort(); } rectangle_active_allocated = new_alloc; rectangle_active = ptr; } ptr = &rectangle_active[ rectangle_active_count - 1 ]; ptr->x = x; ptr->y = y; ptr->w = w; ptr->h = 1; }
static int deparse_unaryop( char *buffer, size_t length, const struct unaryop_type *unaryop ) { char *operand_buffer; const char *operation_string = NULL; int brackets; int error; operand_buffer = malloc( length ); if( !operand_buffer ) { ui_error( UI_ERROR_ERROR, "out of memory at %s:%d", __FILE__, __LINE__ ); return 1; } error = debugger_expression_deparse( operand_buffer, length, unaryop->op ); if( error ) { free( operand_buffer ); return error; } switch( unaryop->operation ) { case '!': operation_string = "!"; break; case '~': operation_string = "~"; break; case '-': operation_string = "-"; break; default: ui_error( UI_ERROR_ERROR, "unknown unary operation %d", unaryop->operation ); fuse_abort(); } brackets = ( unaryop->op->precedence < unaryop_precedence( unaryop->operation ) ); snprintf( buffer, length, "%s%s%s%s", operation_string, brackets ? "( " : "", operand_buffer, brackets ? " )" : "" ); free( operand_buffer ); return 0; }
int debugger_breakpoint_add_time( debugger_breakpoint_type type, libspectrum_dword tstates, size_t ignore, debugger_breakpoint_life life, debugger_expression *condition ) { debugger_breakpoint_value value; switch( type ) { case DEBUGGER_BREAKPOINT_TYPE_TIME: break; default: ui_error( UI_ERROR_ERROR, "debugger_breakpoint_add_time given type %d", type ); fuse_abort(); } value.time.tstates = tstates; return breakpoint_add( type, value, ignore, life, condition ); }
int machine_select( libspectrum_machine type ) { int i; int error; /* We don't want to have to deal with screen size changes in the movie code and recording movies where we change machines seems pretty obscure */ movie_stop(); for( i=0; i < machine_count; i++ ) { if( machine_types[i]->machine == type ) { machine_location = i; error = machine_select_machine( machine_types[i] ); if( !error ) return 0; /* If we couldn't select the new machine type, try falling back to plain old 48K */ if( type != LIBSPECTRUM_MACHINE_48 ) error = machine_select( LIBSPECTRUM_MACHINE_48 ); /* If that still didn't work, give up */ if( error ) { ui_error( UI_ERROR_ERROR, "can't select 48K machine. Giving up." ); fuse_abort(); } else { ui_error( UI_ERROR_INFO, "selecting 48K machine" ); return 0; } return 0; } } ui_error( UI_ERROR_ERROR, "machine type %d unknown", type ); return 1; }