예제 #1
0
파일: board.c 프로젝트: mzxrules/megazeux
int save_board(struct board *cur_board, FILE *fp, int savegame, int version)
{
  int num_robots, num_scrolls, num_sensors;
  int start_location = ftell(fp);
  int board_width = cur_board->board_width;
  int board_height = cur_board->board_height;
  int board_size = board_width * board_height;
  int i;

  // Board mode is now ignored, put 0
  fputc(0, fp);
  // Put overlay mode

  if(cur_board->overlay_mode)
  {
    fputc(0, fp);
    fputc(cur_board->overlay_mode, fp);
    fputw(cur_board->board_width, fp);
    fputw(cur_board->board_height, fp);
    save_RLE2_plane(cur_board->overlay, fp, board_size);
    fputw(cur_board->board_width, fp);
    fputw(cur_board->board_height, fp);
    save_RLE2_plane(cur_board->overlay_color, fp, board_size);
  }

  fputw(board_width, fp);
  fputw(board_height, fp);
  save_RLE2_plane(cur_board->level_id, fp, board_size);
  fputw(board_width, fp);
  fputw(board_height, fp);
  save_RLE2_plane(cur_board->level_color, fp, board_size);
  fputw(board_width, fp);
  fputw(board_height, fp);
  save_RLE2_plane(cur_board->level_param, fp, board_size);
  fputw(board_width, fp);
  fputw(board_height, fp);
  save_RLE2_plane(cur_board->level_under_id, fp, board_size);
  fputw(board_width, fp);
  fputw(board_height, fp);
  save_RLE2_plane(cur_board->level_under_color, fp, board_size);
  fputw(board_width, fp);
  fputw(board_height, fp);
  save_RLE2_plane(cur_board->level_under_param, fp, board_size);

  // Save board parameters

  {
    size_t len = strlen(cur_board->mod_playing);
    fputw((int)len, fp);
    if(len)
      fwrite(cur_board->mod_playing, len, 1, fp);
  }

  fputc(cur_board->viewport_x, fp);
  fputc(cur_board->viewport_y, fp);
  fputc(cur_board->viewport_width, fp);
  fputc(cur_board->viewport_height, fp);
  fputc(cur_board->can_shoot, fp);
  fputc(cur_board->can_bomb, fp);
  fputc(cur_board->fire_burn_brown, fp);
  fputc(cur_board->fire_burn_space, fp);
  fputc(cur_board->fire_burn_fakes, fp);
  fputc(cur_board->fire_burn_trees, fp);
  fputc(cur_board->explosions_leave, fp);
  fputc(cur_board->save_mode, fp);
  fputc(cur_board->forest_becomes, fp);
  fputc(cur_board->collect_bombs, fp);
  fputc(cur_board->fire_burns, fp);

  for(i = 0; i < 4; i++)
  {
    fputc(cur_board->board_dir[i], fp);
  }

  fputc(cur_board->restart_if_zapped, fp);
  fputw(cur_board->time_limit, fp);

  if(savegame)
  {
    size_t len;

    fputc(cur_board->last_key, fp);
    fputw(cur_board->num_input, fp);
    fputw((int)cur_board->input_size, fp);

    len = strlen(cur_board->input_string);
    fputw((int)len, fp);
    if(len)
      fwrite(cur_board->input_string, len, 1, fp);

    fputc(cur_board->player_last_dir, fp);

    len = strlen(cur_board->bottom_mesg);
    fputw((int)len, fp);
    if(len)
      fwrite(cur_board->bottom_mesg, len, 1, fp);

    fputc(cur_board->b_mesg_timer, fp);
    fputc(cur_board->lazwall_start, fp);
    fputc(cur_board->b_mesg_row, fp);
    fputc(cur_board->b_mesg_col, fp);
    fputw(cur_board->scroll_x, fp);
    fputw(cur_board->scroll_y, fp);
    fputw(cur_board->locked_x, fp);
    fputw(cur_board->locked_y, fp);
  }

  fputc(cur_board->player_ns_locked, fp);
  fputc(cur_board->player_ew_locked, fp);
  fputc(cur_board->player_attack_locked, fp);

  if(savegame)
  {
    fputc(cur_board->volume, fp);
    fputc(cur_board->volume_inc, fp);
    fputc(cur_board->volume_target, fp);
  }

  // Save robots
  num_robots = cur_board->num_robots;
  fputc(num_robots, fp);

  if(num_robots)
  {
    struct robot *cur_robot;

    for(i = 1; i <= num_robots; i++)
    {
      cur_robot = cur_board->robot_list[i];
      save_robot(cur_robot, fp, savegame, version);
    }
  }

  // Save scrolls
  num_scrolls = cur_board->num_scrolls;
  putc(num_scrolls, fp);

  if(num_scrolls)
  {
    struct scroll *cur_scroll;

    for(i = 1; i <= num_scrolls; i++)
    {
      cur_scroll = cur_board->scroll_list[i];
      save_scroll(cur_scroll, fp, savegame);
    }
  }

  // Save sensors
  num_sensors = cur_board->num_sensors;
  fputc(num_sensors, fp);

  if(num_sensors)
  {
    struct sensor *cur_sensor;

    for(i = 1; i <= num_sensors; i++)
    {
      cur_sensor = cur_board->sensor_list[i];
      save_sensor(cur_sensor, fp, savegame);
    }
  }

  return (ftell(fp) - start_location);
}
예제 #2
0
파일: mzm.c 프로젝트: colin-branch/megazeux
static void save_mzm_common(struct world *mzx_world, int start_x, int start_y, int width,
 int height, int mode, int savegame, void *(*alloc)(size_t, void **), void **storage)
{
    int storage_mode = 0;
    void *buffer;
    unsigned char *bufferPtr;

    size_t mzm_size;
    int num_robots_alloc = 0;

    if(mode)
      storage_mode = 1;

    if(savegame)
      savegame = 1;

    // Before saving the MZM, we first calculate its file size
    // Then we allocate the memory needed to store the MZM
    mzm_size = 20;
    
    // Add on the storage space required to store all tiles
    if (storage_mode == 0) {
      mzm_size += width * height * 6;
    } else {
      mzm_size += width * height * 2;
    }

    if (mode == 0)
    {
      // Allocate memory for robots
      struct board *src_board = mzx_world->current_board;
      struct robot **robot_list = src_board->robot_list_name_sorted;
      int num_robots_active = src_board->num_robots_active;
      int i;

      for (i = 0; i < num_robots_active; i++)
      {
        struct robot *cur_robot = robot_list[i];
        if (cur_robot)
        {
          if (cur_robot->xpos >= start_x && cur_robot->ypos >= start_y &&
              cur_robot->xpos < start_x + width && cur_robot->ypos < start_y + height)
          {
            mzm_size += save_robot_calculate_size(mzx_world, cur_robot,
             savegame, WORLD_VERSION);
            num_robots_alloc++;
          }
        }
      }
    }

    // Now, we need to add the total overhead of the zip file.
    // File names are all "r##", so the max name length is 3.
    mzm_size += zip_bound_total_header_usage(num_robots_alloc, 3);

    buffer = alloc(mzm_size, storage);
    bufferPtr = buffer;
    memcpy(bufferPtr, "MZM3", 4);
    bufferPtr += 4;

    mem_putw(width, &bufferPtr);
    mem_putw(height, &bufferPtr);
    // Come back here later if there's robot information
    mem_putd(0, &bufferPtr);
    mem_putc(0, &bufferPtr);
    mem_putc(storage_mode, &bufferPtr);
    mem_putc(0, &bufferPtr);

    mem_putw(WORLD_VERSION, &bufferPtr);
    bufferPtr += 3;

    switch(mode)
    {
      // Board, raw
      case 0:
      {
        struct zip_archive *zp;

        struct board *src_board = mzx_world->current_board;
        int board_width = src_board->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;
        int x, y;
        int offset = start_x + (start_y * board_width);
        int line_skip = board_width - width;
        int num_robots = 0;
        int robot_numbers[256];
        int robot_table_position;
        enum thing current_id;
        int i;

        for(y = 0; y < height; y++)
        {
          for(x = 0; x < width; x++, offset++)
          {
            current_id = (enum thing)level_id[offset];

            if(is_robot(current_id))
            {
              // Robot
              robot_numbers[num_robots] = level_param[offset];
              num_robots++;

              mem_putc(current_id, &bufferPtr);
              mem_putc(0, &bufferPtr);
              mem_putc(level_color[offset], &bufferPtr);
              mem_putc(level_under_id[offset], &bufferPtr);
              mem_putc(level_under_param[offset], &bufferPtr);
              mem_putc(level_under_color[offset], &bufferPtr);
            }
            else

            if((current_id == SENSOR) || is_signscroll(current_id) ||
             (current_id == PLAYER))
            {
              // Sensor, scroll, sign, or player
              // Put customblock fake
              mem_putc((int)CUSTOM_BLOCK, &bufferPtr);
              mem_putc(get_id_char(src_board, offset), &bufferPtr);
              mem_putc(get_id_color(src_board, offset), &bufferPtr);
              mem_putc(level_under_id[offset], &bufferPtr);
              mem_putc(level_under_param[offset], &bufferPtr);
              mem_putc(level_under_color[offset], &bufferPtr);
            }
            else
            {
              mem_putc(current_id, &bufferPtr);
              mem_putc(level_param[offset], &bufferPtr);
              mem_putc(level_color[offset], &bufferPtr);
              mem_putc(level_under_id[offset], &bufferPtr);
              mem_putc(level_under_param[offset], &bufferPtr);
              mem_putc(level_under_color[offset], &bufferPtr);
            }
          }
          offset += line_skip;
        }

        // Get the zip redy 2 go
        zp = zip_open_mem_write(buffer, mzm_size);
        robot_table_position = bufferPtr - (unsigned char *)buffer;

        // Get the zip in position. Won't alter the bufferPtr
        zseek(zp, robot_table_position, SEEK_SET);

        // Go back to header to put robot table information
        if(num_robots)
        {
          struct robot **robot_list = src_board->robot_list;
          char name[4];

          bufferPtr = buffer;
          bufferPtr += 8;
          // Where the robots will be stored
          // (not actually necessary anymore)
          mem_putd(robot_table_position, &bufferPtr);
          // Number of robots
          mem_putc(num_robots, &bufferPtr);
          // Skip board storage mode
          bufferPtr += 1;
          // Savegame mode for robots
          mem_putc(savegame, &bufferPtr);

          // Write robots into the zip
          for(i = 0; i < num_robots; i++)
          {
            sprintf(name, "r%2.2X", i);

            // Save each robot
            save_robot(mzx_world, robot_list[robot_numbers[i]], zp,
             savegame, WORLD_VERSION, name, FPROP_ROBOT, 0, i);
          }
        }

        zip_close(zp, NULL);

        break;
      }

      // Overlay/Vlayer
      case 1:
      case 2:
      {
        struct board *src_board = mzx_world->current_board;
        int board_width;
        int x, y;
        int offset;
        int line_skip;
        char *chars;
        char *colors;

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

          chars = src_board->overlay;
          colors = src_board->overlay_color;
          board_width = src_board->board_width;
        }
        else
        {
          // Vlayer
          chars = mzx_world->vlayer_chars;
          colors = mzx_world->vlayer_colors;
          board_width = mzx_world->vlayer_width;
        }

        offset = start_x + (start_y * board_width);
        line_skip = board_width - width;

        for(y = 0; y < height; y++)
        {
          for(x = 0; x < width; x++, offset++)
          {
            mem_putc(chars[offset], &bufferPtr);
            mem_putc(colors[offset], &bufferPtr);
          }
          offset += line_skip;
        }

        break;
      }

      // Board, char based
      case 3:
      {
        struct board *src_board = mzx_world->current_board;
        int board_width = src_board->board_width;
        int x, y;
        int offset = start_x + (start_y * board_width);
        int line_skip = board_width - width;

        for(y = 0; y < height; y++)
        {
          for(x = 0; x < width; x++, offset++)
          {
            mem_putc(get_id_char(src_board, offset), &bufferPtr);
            mem_putc(get_id_color(src_board, offset), &bufferPtr);
          }
          offset += line_skip;
        }


        break;
      }
    }

}