Exemplo n.º 1
0
static int load_mzm_common(struct world *mzx_world, const void *buffer, int file_length, int start_x,
 int start_y, int mode, int savegame, char *name)
{
  const unsigned char *bufferPtr = buffer;
  char magic_string[5];
  int storage_mode;
  int width, height;
  int savegame_mode;
  int num_robots;
  int robots_location;

  int data_start;
  int expected_data_size;

  // MegaZeux 2.83 is the last version that won't save the ver,
  // so if we don't have a ver, just act like it's 2.83
  int mzm_world_version = 0x0253;

  if (file_length < 4)
    goto err_invalid;

  memcpy(magic_string, bufferPtr, 4);
  bufferPtr += 4;

  magic_string[4] = 0;

  if(!strncmp(magic_string, "MZMX", 4))
  {
    // An MZM1 file is always storage mode 0
    storage_mode = 0;
    savegame_mode = 0;
    num_robots = 0;
    robots_location = 0;
    if (file_length < 16) goto err_invalid;
    width = mem_getc(&bufferPtr);
    height = mem_getc(&bufferPtr);
    bufferPtr += 10;
  }
  else

  if(!strncmp(magic_string, "MZM2", 4))
  {
    if (file_length < 16) goto err_invalid;
    width = mem_getw(&bufferPtr);
    height = mem_getw(&bufferPtr);
    robots_location = mem_getd(&bufferPtr);
    num_robots = mem_getc(&bufferPtr);
    storage_mode = mem_getc(&bufferPtr);
    savegame_mode = mem_getc(&bufferPtr);
    bufferPtr += 1;
  }
  else

  if(!strncmp(magic_string, "MZM3", 4))
  {
    if (file_length < 20) goto err_invalid;
    // MZM3 is like MZM2, except the robots are stored as source code if
    // savegame_mode is 0 and version >= VERSION_PROGRAM_SOURCE.
    width = mem_getw(&bufferPtr);
    height = mem_getw(&bufferPtr);
    robots_location = mem_getd(&bufferPtr);
    num_robots = mem_getc(&bufferPtr);
    storage_mode = mem_getc(&bufferPtr);
    savegame_mode = mem_getc(&bufferPtr);
    mzm_world_version = mem_getw(&bufferPtr);
    bufferPtr += 3;
  }

  else
    goto err_invalid;

  data_start = bufferPtr - (const unsigned char *)buffer;
  expected_data_size = (width * height) * (storage_mode ? 2 : 6);

  // Validate
  if(
    (savegame_mode > 1) || (savegame_mode < 0) // Invalid save mode
    || (storage_mode > 1) || (storage_mode < 0) // Invalid storage mode
    || (file_length - data_start < expected_data_size) // not enough space to store data
    || (file_length < robots_location) // The end of file is before the robot offset
    || (robots_location && (expected_data_size + data_start > robots_location)) // robots offset before data end
    )
    goto err_invalid;

  // If the mzm version is newer than the MZX version, show a message and continue.
  if(mzm_world_version > WORLD_VERSION)
  {
    error_message(E_MZM_FILE_VERSION_TOO_RECENT, mzm_world_version, name);
  }

  // If the MZM is a save MZM but we're not loading at runtime, show a message and continue.
  if(savegame_mode > savegame)
  {
    error_message(E_MZM_FILE_FROM_SAVEGAME, 0, name);
  }

  switch(mode)
  {
    // Write to board
    case 0:
    {
      struct board *src_board = mzx_world->current_board;
      int board_width = src_board->board_width;
      int board_height = src_board->board_height;
      int effective_width = width;
      int effective_height = height;
      int file_line_skip;
      int line_skip;
      int x, y;
      int offset = start_x + (start_y * board_width);
      char *level_id = src_board->level_id;
      char *level_param = src_board->level_param;
      char *level_color = src_board->level_color;
      char *level_under_id = src_board->level_under_id;
      char *level_under_param = src_board->level_under_param;
      char *level_under_color = src_board->level_under_color;
      enum thing src_id;

      // Clip

      if((effective_width + start_x) >= board_width)
        effective_width = board_width - start_x;

      if((effective_height + start_y) >= board_height)
        effective_height = board_height - start_y;

      line_skip = board_width - effective_width;

      switch(storage_mode)
      {
        case 0:
        {
          // Board style, write as is
          enum thing current_id;
          int current_robot_loaded = 0;
          int robot_x_locations[256];
          int robot_y_locations[256];
          int width_difference;
          int i;

          width_difference = width - effective_width;

          for(y = 0; y < effective_height; y++)
          {
            for(x = 0; x < effective_width; x++, offset++)
            {
              current_id = (enum thing)mem_getc(&bufferPtr);

              if(current_id >= SENSOR)
              {
                if(is_robot(current_id))
                {
                  robot_x_locations[current_robot_loaded] = x + start_x;
                  robot_y_locations[current_robot_loaded] = y + start_y;
                  current_robot_loaded++;
                }
                // Wipe a bunch of crap we don't want in MZMs with spaces
                else
                  current_id = 0;
              }

              src_id = (enum thing)level_id[offset];

              if(src_id >= SENSOR)
              {
                if(src_id == SENSOR)
                  clear_sensor_id(src_board, level_param[offset]);
                else

                if(is_signscroll(src_id))
                  clear_scroll_id(src_board, level_param[offset]);
                else

                if(is_robot(src_id))
                  clear_robot_id(src_board, level_param[offset]);
              }

              // Don't allow the player to be overwritten
              if(src_id != PLAYER)
              {
                level_id[offset] = current_id;
                level_param[offset] = mem_getc(&bufferPtr);
                level_color[offset] = mem_getc(&bufferPtr);
                level_under_id[offset] = mem_getc(&bufferPtr);
                level_under_param[offset] = mem_getc(&bufferPtr);
                level_under_color[offset] = mem_getc(&bufferPtr);

                // We don't want this on the under layer, thanks
                if(level_under_id[offset] >= SENSOR)
                {
                  level_under_id[offset] = 0;
                  level_under_param[offset] = 0;
                  level_under_color[offset] = 7;
                }
              }
              else
              {
                bufferPtr += 5;
              }
            }

            offset += line_skip;

            // Gotta run through and mark the next robots to be skipped
            for(i = 0; i < width_difference; i++)
            {
              current_id = (enum thing)mem_getc(&bufferPtr);
              bufferPtr += 5;

              if(is_robot(current_id))
              {
                robot_x_locations[current_robot_loaded] = -1;
                current_robot_loaded++;
              }
            }
          }

          for(i = current_robot_loaded; i < num_robots; i++)
          {
            robot_x_locations[i] = -1;
          }

          if(num_robots)
          {
            struct zip_archive *zp;
            unsigned int file_id;
            unsigned int robot_id;
            int result;

            struct robot *cur_robot;
            int current_x, current_y;
            int offset;
            int new_param;
            int robot_calculated_size = 0;
            int robot_partial_size = 0;
            int current_position;
            int dummy = 0;

            // We suppress the errors that will generally occur here and barely
            // error check the zip functions. Why? This needs to run all the way
            // through, regardless of whether it finds errors. Otherwise, we'll
            // get invalid robots with ID=0 littered around the board.

            set_error_suppression(E_WORLD_ROBOT_MISSING, 1);
            set_error_suppression(E_BOARD_ROBOT_CORRUPT, 1);

            // Reset the error count.
            get_and_reset_error_count();

            if(mzm_world_version <= WORLD_LEGACY_FORMAT_VERSION)
            {
              robot_partial_size =
               legacy_calculate_partial_robot_size(savegame_mode,
               mzm_world_version);

              bufferPtr = buffer;
              bufferPtr += robots_location;
              zp = NULL;
            }

            else
            {
              zp = zip_open_mem_read(buffer, file_length);
              zip_read_directory(zp);
              assign_fprops(zp, 1);
            }

            // If we're loading a "runtime MZM" then it means that we're loading
            // bytecode. And to do this we must both be in-game and must be
            // running the same version this was made in. But since loading
            // dynamically created MZMs in the editor is still useful, we'll just
            // dummy out the robots.

            if((savegame_mode > savegame) ||
              (WORLD_VERSION < mzm_world_version))
            {
              dummy = 1;
            }

            for(i = 0; i < num_robots; i++)
            {
              cur_robot = cmalloc(sizeof(struct robot));

              current_x = robot_x_locations[i];
              current_y = robot_y_locations[i];

              // TODO: Skipped legacy robots aren't checked for, so the loaded
              // chars for dummy robots on clipped MZMs might be off. This
              // shouldn't matter too often though.

              if(mzm_world_version <= WORLD_LEGACY_FORMAT_VERSION)
              {
                create_blank_robot(cur_robot);

                current_position = bufferPtr - (const unsigned char *)buffer;

                // If we fail, we have to continue, or robots won't be dummied
                // correctly. In this case, seek to the end.

                if(current_position + robot_partial_size <= file_length)
                {
                  robot_calculated_size =
                   legacy_load_robot_calculate_size(bufferPtr, savegame_mode,
                   mzm_world_version);

                  if(current_position + robot_calculated_size <= file_length)
                  {
                    legacy_load_robot_from_memory(mzx_world, cur_robot, bufferPtr,
                     savegame_mode, mzm_world_version, (int)current_position);
                  }
                  else
                  {
                    bufferPtr = (const unsigned char*)buffer + file_length;
                    dummy = 1;
                  }
                }
                else
                {
                  bufferPtr = (const unsigned char*)buffer + file_length;
                  dummy = 1;
                }

                bufferPtr += robot_calculated_size;
              }

              // Search the zip until a robot is found.
              else do
              {
                result = zip_get_next_prop(zp, &file_id, NULL, &robot_id);

                if(result != ZIP_SUCCESS)
                {
                  // We have to continue, or we'll get screwed up robots.
                  create_blank_robot(cur_robot);
                  create_blank_robot_program(cur_robot);
                  dummy = 1;
                  break;
                }
                else

                if(file_id != FPROP_ROBOT || (int)robot_id < i)
                {
                  // Not a robot or is a skipped robot
                  zip_skip_file(zp);
                }
                else

                if((int)robot_id > i)
                {
                  // There's a robot missing.
                  create_blank_robot(cur_robot);
                  create_blank_robot_program(cur_robot);
                  break;
                }

                else
                {
                  load_robot(mzx_world, cur_robot, zp, savegame_mode,
                   mzm_world_version);
                  break;
                }
              }
              while(1);

              if(dummy)
              {
                // Unfortunately, getting the actual character for the robot is
                // kind of a lot of work right now. We have to load it then
                // throw it away.

                // If this is from a futer version and the format changed, we'll
                // just end up with an 'R' char, but this shouldn't happen again
                if(current_x != -1)
                {
                  offset = current_x + (current_y * board_width);
                  level_id[offset] = CUSTOM_BLOCK;
                  level_param[offset] = cur_robot->robot_char;
                }
                clear_robot(cur_robot);
              }

              else
              {
                cur_robot->world_version = mzx_world->version;
                cur_robot->xpos = current_x;
                cur_robot->ypos = current_y;

#ifdef CONFIG_DEBYTECODE
                // If we're loading source code at runtime, we need to compile it
                if(savegame_mode < savegame)
                  prepare_robot_bytecode(mzx_world, cur_robot);
#endif

                if(current_x != -1)
                {
                  new_param = find_free_robot(src_board);
                  offset = current_x + (current_y * board_width);

                  if(new_param != -1)
                  {
                    if((enum thing)level_id[offset] != PLAYER)
                    {
                      add_robot_name_entry(src_board, cur_robot,
                        cur_robot->robot_name);
                      src_board->robot_list[new_param] = cur_robot;
                      cur_robot->xpos = current_x;
                      cur_robot->ypos = current_y;
                      level_param[offset] = new_param;
                    }
                    else
                    {
                      clear_robot(cur_robot);
                    }
                  }
                  else
                  {
                    clear_robot(cur_robot);
                    level_id[offset] = 0;
                    level_param[offset] = 0;
                    level_color[offset] = 7;
                  }
                }
                else
                {
                  clear_robot(cur_robot);
                }
              }
            }

            if(mzm_world_version > WORLD_LEGACY_FORMAT_VERSION)
            {
              zip_close(zp, NULL);
            }

            // If any errors were encountered, report
            if(get_and_reset_error_count())
              goto err_robots;
          }
          break;
        }

        case 1:
        {
          // Compact style; expand to customblocks
          // Board style, write as is

          file_line_skip = (width - effective_width) * 2;

          for(y = 0; y < effective_height; y++)
          {
            for(x = 0; x < effective_width; x++, offset++)
            {
              src_id = (enum thing)level_id[offset];

              if(src_id == SENSOR)
                clear_sensor_id(src_board, level_param[offset]);
              else

              if(is_signscroll(src_id))
                clear_scroll_id(src_board, level_param[offset]);
              else

              if(is_robot(src_id))
                clear_robot_id(src_board, level_param[offset]);

              // Don't allow the player to be overwritten
              if(src_id != PLAYER)
              {
                level_id[offset] = CUSTOM_BLOCK;
                level_param[offset] = mem_getc(&bufferPtr);
                level_color[offset] = mem_getc(&bufferPtr);
                level_under_id[offset] = 0;
                level_under_param[offset] = 0;
                level_under_color[offset] = 0;
              }
              else
              {
                bufferPtr += 2;
              }
            }

            offset += line_skip;
            bufferPtr += file_line_skip;
          }
          break;
        }
      }
      break;
    }

    // Overlay/vlayer
    case 1:
    case 2:
    {
      struct board *src_board = mzx_world->current_board;
      int dest_width = src_board->board_width;
      int dest_height = src_board->board_height;
      char *dest_chars;
      char *dest_colors;
      int effective_width = width;
      int effective_height = height;
      int file_line_skip;
      int line_skip;
      int x, y;
      int offset;

      if(mode == 1)
      {
        // Overlay
        if(!src_board->overlay_mode)
          setup_overlay(src_board, 3);

        dest_chars = src_board->overlay;
        dest_colors = src_board->overlay_color;
        dest_width = src_board->board_width;
        dest_height = src_board->board_height;
      }
      else
      {
        // Vlayer
        dest_chars = mzx_world->vlayer_chars;
        dest_colors = mzx_world->vlayer_colors;
        dest_width = mzx_world->vlayer_width;
        dest_height = mzx_world->vlayer_height;
      }

      offset = start_x + (start_y * dest_width);

      // Clip

      if((effective_width + start_x) >= dest_width)
        effective_width = dest_width - start_x;

      if((effective_height + start_y) >= dest_height)
        effective_height = dest_height - start_y;

      line_skip = dest_width - effective_width;

      switch(storage_mode)
      {
        case 0:
        {
          // Coming from board storage; for now use param as char

          file_line_skip = (width - effective_width) * 6;

          for(y = 0; y < effective_height; y++)
          {
            for(x = 0; x < effective_width; x++, offset++)
            {
              // Skip ID
              bufferPtr += 1;
              dest_chars[offset] = mem_getc(&bufferPtr);
              dest_colors[offset] = mem_getc(&bufferPtr);
              // Skip under parts
              bufferPtr += 3;
            }

            offset += line_skip;
            bufferPtr += file_line_skip;
          }
          break;
        }

        case 1:
        {
          // Coming from layer storage; transfer directly

          file_line_skip = (width - effective_width) * 2;

          for(y = 0; y < effective_height; y++)
          {
            for(x = 0; x < effective_width; x++, offset++)
            {
              dest_chars[offset] = mem_getc(&bufferPtr);
              dest_colors[offset] = mem_getc(&bufferPtr);
            }

            offset += line_skip;
            bufferPtr += file_line_skip;
          }
          break;
        }

      }
      break;
    }
  }

  // Clear none of the validation error suppressions:
  // 1) in combination with poor practice, they could lock MZX,
  // 2) they'll get reset after reloading the world.
  return 0;

err_robots:
  // The main file loaded fine, but there was a problem handling robots
  error_message(E_MZM_ROBOT_CORRUPT, 0, name);
  return 0;

err_invalid:
  error_message(E_MZM_FILE_INVALID, 0, name);
  return -1;
}
Exemplo n.º 2
0
int main(int ac, char *av[])
  {
   int errorn;
   long total_output_spks;
   double input_traject_vars[NUM_JOINTS*3]; // Desired trajectory position, velocity and acceletarion
   double robot_state_vars[NUM_JOINTS*3]; // Actual robot position, velocity and acceleration
   double cerebellar_output_vars[NUM_OUTPUT_VARS]={0.0}; // Corrective cerebellar output torque
   double robot_inv_dyn_torque[NUM_JOINTS]; // Robot's inverse dynamics torque
   double total_torque[NUM_JOINTS]; // Total torque applied to the robot
   double *delayed_error_vars;
   double robot_error_vars[NUM_JOINTS]; // Joint error (PD correction)
   double cerebellar_learning_vars[NUM_OUTPUT_VARS]; // Error-related learning signals
   // Robot's dynamics variables
   mxArray *robot_inv_dyn_object=NULL, *robot_dir_dyn_object=NULL;
   struct integrator_buffers num_integration_buffers; // Integration buffers used to simulate the robot
   Simulation *neural_sim;
   int n_robot_joints;
   // Time variables
   double sim_time,cur_traject_time;
   float slot_elapsed_time,sim_elapsed_time;
   int n_traj_exec;
   // Delay line
   struct delay error_delay;

   // Variable for logging the simulation state variables
   struct log var_log;

#if defined(REAL_TIME_WINNT)
	// Variables for consumed-CPU-time measurement
	LARGE_INTEGER startt,endt,freq;

#elif defined(REAL_TIME_OSX)
	uint64_t startt, endt, elapsed;
	static mach_timebase_info_data_t freq;
#elif defined(REAL_TIME_LINUX)
	// Calculate time taken by a request - Link with real-time library -lrt
	struct timespec startt, endt, freq;
#endif

#if defined(_DEBUG) && (defined(_WIN32) || defined(_WIN64))
//   _CrtMemState state0;
   _CrtSetReportMode(_CRT_WARN, _CRTDBG_MODE_FILE);
   _CrtSetReportFile(_CRT_WARN, _CRTDBG_FILE_STDERR);
#endif

#if defined(REAL_TIME_WINNT)
   if(!QueryPerformanceFrequency(&freq))
      puts("QueryPerformanceFrequency failed");
#elif defined (REAL_TIME_LINUX)
   if(clock_getres(CLOCK_REALTIME, &freq))
	   puts("clock_getres failed");
#elif defined (REAL_TIME_OSX)
   // If this is the first time we've run, get the timebase.
   // We can use denom == 0 to indicate that sTimebaseInfo is
   // uninitialised because it makes no sense to have a zero
   // denominator is a fraction.
   if (freq.denom == 0 ) {
	   (void) mach_timebase_info(&freq);
   }
#endif

   // Load Matlab robot objects from Matlab files
   if(!(errorn=load_robot(ROBOT_VAR_FILE_NAME,ROBOT_BASE_VAR_NAME,&n_robot_joints,&robot_inv_dyn_object)) && \
      !(errorn=load_robot(ROBOT_VAR_FILE_NAME,ROBOT_SIMUL_VAR_NAME,NULL,&robot_dir_dyn_object)))
     {
      if(!(errorn=allocate_integration_buffers(&num_integration_buffers,n_robot_joints))) // Initialize the buffers for numerical integration using the initial desired robot's state
        {
         // Initialize variable log
         if(!(errorn=create_log(&var_log, MAX_TRAJ_EXECUTIONS, TRAJECTORY_TIME)))
           {
            // Initialize EDLUT and load neural network files
            neural_sim=create_neural_simulation(NET_FILE, INPUT_WEIGHT_FILE, INPUT_ACTIVITY_FILE, OUTPUT_WEIGHT_FILE, OUTPUT_ACTIVITY_FILE, WEIGHT_SAVE_PERIOD, REAL_TIME_NEURAL_SIM);
            if(neural_sim)
              {
               double min_traj_amplitude[3], max_traj_amplitude[3]; // Position, velocity and acceleration
               calculate_input_trajectory_max_amplitude(TRAJECTORY_TIME,TRAJ_POS_AMP, min_traj_amplitude, max_traj_amplitude); // Calcula the maximum and minimum values of the desired trajectory

               total_output_spks=0L;
               puts("Simulating...");
               sim_elapsed_time=0.0;
               errorn=0;
//    _CrtMemCheckpoint(&state0);
               for(n_traj_exec=0;n_traj_exec<MAX_TRAJ_EXECUTIONS && !errorn;n_traj_exec++)
                 {
                  calculate_input_trajectory(robot_state_vars, TRAJ_POS_AMP, 0.0); // Initialize simulated robot's actual state from the desired state (input trajectory) (position, velocity and acceleration)
                  initialize_integration_buffers(robot_state_vars,&num_integration_buffers,n_robot_joints); // For the robot's direct 
                  reset_neural_simulation(neural_sim); // after each trajectory execution the network simulation state must be reset (pending activity events are discarded)
                  init_delay(&error_delay, ERROR_DELAY_TIME); // Clear the delay line
                  cur_traject_time=0.0;
                  do
                    {
                     int n_joint;

#if defined(REAL_TIME_WINNT)
        	QueryPerformanceCounter(&startt);
#elif defined(REAL_TIME_LINUX)
        	clock_gettime(CLOCK_REALTIME, &startt);
#elif defined(REAL_TIME_OSX)
        	startt = mach_absolute_time();
#endif

                     // control loop iteration starts
                     sim_time=(double)n_traj_exec*TRAJECTORY_TIME + cur_traject_time; // Calculate absolute simulation time
                     calculate_input_trajectory(input_traject_vars, TRAJ_POS_AMP, cur_traject_time); // Calculate desired input trajectory
                     //ECEA
                     generate_input_traj_activity(neural_sim, sim_time, input_traject_vars, min_traj_amplitude, max_traj_amplitude); // Translates desired trajectory (position and velocity) into spikes
                     generate_robot_state_activity(neural_sim, sim_time, input_traject_vars, min_traj_amplitude, max_traj_amplitude); // Translates desired trajectory into spikes again to improve the input codification (using the robot's state input neurons)
				     //ICEA
//                   generate_robot_state_activity(neural_sim, sim_time, robot_state_vars, min_traj_amplitude, max_traj_amplitude); // Translates robot's current state (position and velocity) into spikes

                     compute_robot_inv_dynamics(robot_inv_dyn_object,input_traject_vars,ROBOT_EXTERNAL_FORCE,ROBOT_GRAVITY,robot_inv_dyn_torque); // Calculate crude inverse dynamics of the base robot. They constitude the base robot's input torque
                     for(n_joint=0;n_joint<NUM_JOINTS;n_joint++) // Calculate total torque from forward controller (cerebellum) torque plus base controller torque
                        total_torque[n_joint]=robot_inv_dyn_torque[n_joint]+cerebellar_output_vars[n_joint*2]-cerebellar_output_vars[n_joint*2+1];
                     compute_robot_dir_dynamics(robot_dir_dyn_object,robot_state_vars,total_torque,robot_state_vars,&num_integration_buffers,ROBOT_EXTERNAL_FORCE,ROBOT_GRAVITY,SIM_SLOT_LENGTH); // Simulate the robot (direct dynamics).


                     calculate_error_signals(input_traject_vars, robot_state_vars, robot_error_vars); // Calculated robot's performed error
                     //delayed_error_vars=delay_line(&error_delay,robot_error_vars); // Delay in the error bars
                     delayed_error_vars=robot_error_vars; // No delay in the error bars
                     calculate_learning_signals(delayed_error_vars, cerebellar_output_vars, cerebellar_learning_vars); // Calculate learning signal from the calculated error
                     generate_learning_activity(neural_sim, sim_time, cerebellar_learning_vars); // Translates the learning activity into spikes and injects this activity in the network

                     errorn=run_neural_simulation_slot(neural_sim, sim_time+SIM_SLOT_LENGTH); // Simulation the neural network during a time slot
 
                     total_output_spks+=(long)compute_output_activity(neural_sim, cerebellar_output_vars); // Translates cerebellum output activity into analog output variables (corrective torques)
                     // control loop iteration ends

#if defined(REAL_TIME_WINNT)
                     QueryPerformanceCounter(&endt); // measures time
                     slot_elapsed_time=(endt.QuadPart-startt.QuadPart)/(float)freq.QuadPart; // to be logged
#elif defined(REAL_TIME_LINUX)
                     clock_gettime(CLOCK_REALTIME, &endt);
                     // Calculate time it took
                     slot_elapsed_time = (endt.tv_sec-startt.tv_sec ) + (endt.tv_nsec-endt.tv_nsec )/((float)(1e9));
#elif defined(REAL_TIME_OSX)
                     // Stop the clock.
                     endt = mach_absolute_time();
                     // Calculate the duration.
                     elapsed = endt - startt;
                     slot_elapsed_time = 1e-9 * elapsed * freq.numer / freq.denom;
#endif
                     sim_elapsed_time+=slot_elapsed_time;
                     log_vars(&var_log, sim_time, input_traject_vars, robot_state_vars, robot_inv_dyn_torque, cerebellar_output_vars, cerebellar_learning_vars, delayed_error_vars, slot_elapsed_time,get_neural_simulation_spike_counter(neural_sim)); // Store vars into RAM
                     cur_traject_time+=SIM_SLOT_LENGTH;
                    }
                  while(cur_traject_time<TRAJECTORY_TIME-(SIM_SLOT_LENGTH/2.0) && !errorn); // we add -(SIM_SLOT_LENGTH/2.0) because of floating-point-type codification problems
                 } 
//     reset_neural_simulation(neural_sim);
//     _CrtMemDumpAllObjectsSince(&state0);
               if(errorn)
                  printf("Error %i performing neural network simulation\n",errorn);
               printf("Total neural-network output spikes: %li\n",total_output_spks);
               printf("Total number of neural updates: %Ld\n",get_neural_simulation_event_counter(neural_sim));
               printf("Mean number of neural-network spikes in heap: %f\n",get_accumulated_heap_occupancy_counter(neural_sim)/(double)get_neural_simulation_event_counter(neural_sim));

#if defined(REAL_TIME_WINNT)
               printf("Total elapsed time: %fs (time resolution: %fus)\n",sim_elapsed_time,1.0e6/freq.QuadPart);
#elif defined(REAL_TIME_LINUX)
               printf("Total elapsed time: %fs (time resolution: %fus)\n",sim_elapsed_time,freq.tv_sec*1.0e6+freq.tv_nsec/((float)(1e3)));
#elif defined(REAL_TIME_OSX)
               printf("Total elapsed time: %fs (time resolution: %fus)\n",sim_elapsed_time,1e-3*freq.numer/freq.denom);
#endif

               save_neural_weights(neural_sim);
               finish_neural_simulation(neural_sim);
              }
            else
              {
               errorn=10000;
               printf("Error initializing neural network simulation\n");
              }              
            puts("Saving log file");
            errorn=save_and_finish_log(&var_log, LOG_FILE); // Store logged vars in disk
            if(errorn)
               printf("Error %i while saving log file\n",errorn);
           }
         else
           {
            errorn*=1000;
            printf("Error allocating memory for the log of the simulation variables\n");
           }         
         free_integration_buffers(&num_integration_buffers);
        }
      else
        {
         errorn*=100;
         printf("Error allocating memory for the numerical integration\n");
        }
      free_robot(robot_inv_dyn_object);
      free_robot(robot_dir_dyn_object);
     }
   else
     {
      errorn*=10;
      printf("Error loading the robot object from file: %s\n",ROBOT_VAR_FILE_NAME);
     } 
   if(!errorn)
      puts("OK");
   else
      printf("Error: %i\n",errorn);
#if defined(_DEBUG) && (defined(_WIN32) || defined(_WIN64))
   _CrtDumpMemoryLeaks();
#endif
   return(errorn);
  }