#include <libqtools.h>

int main(int argc, char **agrv)
{
  char BSPmatch[] = "e1m1.bsp\0";
  char nameBSPold[] = "Quake:id1/maps/e1m1.bsp\0";
  char nameBSPnew[] = "Quake:id1/maps/e1m12.bsp\0";
  char nameVIS[] = "DH3:id1.vis\0";
  FILE *fileBSPold = fopen(nameBSPold, READ_BINARY);
  FILE *fileBSPnew = fopen(nameBSPnew, WRITE_BINARY_NEW);
  FILE *fileVIS = fopen(nameVIS, READ_BINARY);
  struct bspheader bspHeaderOld;
  struct bspheader bspHeaderNew;
  struct visdata visData;

  if ((!fileBSPold) || (!fileBSPnew) || (!fileVIS)) {
    printf("cannot open!\n");
    return 0;
  }
  EndianInit();

  fread(&bspHeaderOld, 1, sizeof(struct bspheader), fileBSPold);
  memcpy(&bspHeaderNew, &bspHeaderOld, sizeof(struct bspheader));
  fwrite(&bspHeaderNew, 1, sizeof(struct bspheader), fileBSPnew);

  while (fread(&visData, 1, sizeof(struct visdata), fileVIS)) {
    if (!strncmp(visData.procName, BSPmatch, 32)) {
      void *memory;

      printf("found %s ...\n", visData.procName);

      bspHeaderNew.entities.offset = LittleLong(ftell(fileBSPnew));
      bspHeaderNew.entities.size = bspHeaderOld.entities.size;
      if ((memory = malloc(LittleLong(bspHeaderOld.entities.size)))) {
	fseek(fileBSPold, LittleLong(bspHeaderOld.entities.offset), SEEK_SET);
	fread(memory, 1, LittleLong(bspHeaderOld.entities.size), fileBSPold);
	fwrite(memory, 1, LittleLong(bspHeaderNew.entities.size), fileBSPnew);
	free(memory);
      }

      bspHeaderNew.planes.offset = LittleLong(ftell(fileBSPnew));
      bspHeaderNew.planes.size = bspHeaderOld.planes.size;
      if ((memory = malloc(LittleLong(bspHeaderOld.planes.size)))) {
	fseek(fileBSPold, LittleLong(bspHeaderOld.planes.offset), SEEK_SET);
	fread(memory, 1, LittleLong(bspHeaderOld.planes.size), fileBSPold);
	fwrite(memory, 1, LittleLong(bspHeaderNew.planes.size), fileBSPnew);
	free(memory);
      }

      bspHeaderNew.miptex.offset = LittleLong(ftell(fileBSPnew));
      bspHeaderNew.miptex.size = bspHeaderOld.miptex.size;
      if ((memory = malloc(LittleLong(bspHeaderOld.miptex.size)))) {
	fseek(fileBSPold, LittleLong(bspHeaderOld.miptex.offset), SEEK_SET);
	fread(memory, 1, LittleLong(bspHeaderOld.miptex.size), fileBSPold);
	fwrite(memory, 1, LittleLong(bspHeaderNew.miptex.size), fileBSPnew);
	free(memory);
      }

      bspHeaderNew.vertices.offset = LittleLong(ftell(fileBSPnew));
      bspHeaderNew.vertices.size = bspHeaderOld.vertices.size;
      if ((memory = malloc(LittleLong(bspHeaderOld.vertices.size)))) {
	fseek(fileBSPold, LittleLong(bspHeaderOld.vertices.offset), SEEK_SET);
	fread(memory, 1, LittleLong(bspHeaderOld.vertices.size), fileBSPold);
	fwrite(memory, 1, LittleLong(bspHeaderNew.vertices.size), fileBSPnew);
	free(memory);
      }

      bspHeaderNew.visilist.offset = LittleLong(ftell(fileBSPnew));
      fread(&bspHeaderNew.visilist.size, 1, sizeof(int), fileVIS);

      if ((memory = malloc(LittleLong(bspHeaderNew.visilist.size)))) {
	fread(memory, 1, LittleLong(bspHeaderNew.visilist.size), fileVIS);
	fwrite(memory, 1, LittleLong(bspHeaderNew.visilist.size), fileBSPnew);
	free(memory);
      }

      bspHeaderNew.nodes.offset = LittleLong(ftell(fileBSPnew));
      bspHeaderNew.nodes.size = bspHeaderOld.nodes.size;
      if ((memory = malloc(LittleLong(bspHeaderOld.nodes.size)))) {
	fseek(fileBSPold, LittleLong(bspHeaderOld.nodes.offset), SEEK_SET);
	fread(memory, 1, LittleLong(bspHeaderOld.nodes.size), fileBSPold);
	fwrite(memory, 1, LittleLong(bspHeaderNew.nodes.size), fileBSPnew);
	free(memory);
      }

      bspHeaderNew.texinfo.offset = LittleLong(ftell(fileBSPnew));
      bspHeaderNew.texinfo.size = bspHeaderOld.texinfo.size;
      if ((memory = malloc(LittleLong(bspHeaderOld.texinfo.size)))) {
	fseek(fileBSPold, LittleLong(bspHeaderOld.texinfo.offset), SEEK_SET);
	fread(memory, 1, LittleLong(bspHeaderOld.texinfo.size), fileBSPold);
	fwrite(memory, 1, LittleLong(bspHeaderNew.texinfo.size), fileBSPnew);
	free(memory);
      }

      bspHeaderNew.faces.offset = LittleLong(ftell(fileBSPnew));
      bspHeaderNew.faces.size = bspHeaderOld.faces.size;
      if ((memory = malloc(LittleLong(bspHeaderOld.faces.size)))) {
	fseek(fileBSPold, LittleLong(bspHeaderOld.faces.offset), SEEK_SET);
	fread(memory, 1, LittleLong(bspHeaderOld.faces.size), fileBSPold);
	fwrite(memory, 1, LittleLong(bspHeaderNew.faces.size), fileBSPnew);
	free(memory);
      }

      bspHeaderNew.lightmaps.offset = LittleLong(ftell(fileBSPnew));
      bspHeaderNew.lightmaps.size = bspHeaderOld.lightmaps.size;
      if ((memory = malloc(LittleLong(bspHeaderOld.lightmaps.size)))) {
	fseek(fileBSPold, LittleLong(bspHeaderOld.lightmaps.offset), SEEK_SET);
	fread(memory, 1, LittleLong(bspHeaderOld.lightmaps.size), fileBSPold);
	fwrite(memory, 1, LittleLong(bspHeaderNew.lightmaps.size), fileBSPnew);
	free(memory);
      }

      bspHeaderNew.clipnodes.offset = LittleLong(ftell(fileBSPnew));
      bspHeaderNew.clipnodes.size = bspHeaderOld.clipnodes.size;
      if ((memory = malloc(LittleLong(bspHeaderOld.clipnodes.size)))) {
	fseek(fileBSPold, LittleLong(bspHeaderOld.clipnodes.offset), SEEK_SET);
	fread(memory, 1, LittleLong(bspHeaderOld.clipnodes.size), fileBSPold);
	fwrite(memory, 1, LittleLong(bspHeaderNew.clipnodes.size), fileBSPnew);
	free(memory);
      }

      bspHeaderNew.leaves.offset = LittleLong(ftell(fileBSPnew));
      fread(&bspHeaderNew.leaves.size, 1, sizeof(int), fileVIS);

      if ((memory = malloc(LittleLong(bspHeaderNew.leaves.size)))) {
	fread(memory, 1, LittleLong(bspHeaderNew.leaves.size), fileVIS);
	fwrite(memory, 1, LittleLong(bspHeaderNew.leaves.size), fileBSPnew);
	free(memory);
      }

      bspHeaderNew.lface.offset = LittleLong(ftell(fileBSPnew));
      bspHeaderNew.lface.size = bspHeaderOld.lface.size;
      if ((memory = malloc(LittleLong(bspHeaderOld.lface.size)))) {
	fseek(fileBSPold, LittleLong(bspHeaderOld.lface.offset), SEEK_SET);
	fread(memory, 1, LittleLong(bspHeaderOld.lface.size), fileBSPold);
	fwrite(memory, 1, LittleLong(bspHeaderNew.lface.size), fileBSPnew);
	free(memory);
      }

      bspHeaderNew.edges.offset = LittleLong(ftell(fileBSPnew));
      bspHeaderNew.edges.size = bspHeaderOld.edges.size;
      if ((memory = malloc(LittleLong(bspHeaderOld.edges.size)))) {
	fseek(fileBSPold, LittleLong(bspHeaderOld.edges.offset), SEEK_SET);
	fread(memory, 1, LittleLong(bspHeaderOld.edges.size), fileBSPold);
	fwrite(memory, 1, LittleLong(bspHeaderNew.edges.size), fileBSPnew);
	free(memory);
      }

      bspHeaderNew.ledges.offset = LittleLong(ftell(fileBSPnew));
      bspHeaderNew.ledges.size = bspHeaderOld.ledges.size;
      if ((memory = malloc(LittleLong(bspHeaderOld.ledges.size)))) {
	fseek(fileBSPold, LittleLong(bspHeaderOld.ledges.offset), SEEK_SET);
	fread(memory, 1, LittleLong(bspHeaderOld.ledges.size), fileBSPold);
	fwrite(memory, 1, LittleLong(bspHeaderNew.ledges.size), fileBSPnew);
	free(memory);
      }

      bspHeaderNew.models.offset = LittleLong(ftell(fileBSPnew));
      bspHeaderNew.models.size = bspHeaderOld.models.size;
      if ((memory = malloc(LittleLong(bspHeaderOld.models.size)))) {
	fseek(fileBSPold, LittleLong(bspHeaderOld.models.offset), SEEK_SET);
	fread(memory, 1, LittleLong(bspHeaderOld.models.size), fileBSPold);
	fwrite(memory, 1, LittleLong(bspHeaderNew.models.size), fileBSPnew);
	free(memory);
      }

      fseek(fileBSPnew, 0, SEEK_SET);
      fwrite(&bspHeaderNew, 1, sizeof(struct bspheader), fileBSPnew);

      break;
    }
    else {
      printf("skipping %s (%d bytes) ...\n", visData.procName, LittleLong(visData.size));
      fseek(fileVIS, LittleLong(visData.size), SEEK_CUR);
    }
  }

  fclose(fileBSPold);
  fclose(fileBSPnew);
  fclose(fileVIS);
}
