rd_output.c 2.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144
  1. // Copyright (c) 1993-2011 PrBoom developers (see AUTHORS)
  2. // Licence: GPLv2 or later (see COPYING)
  3. // Output wad construction - add lump data, build wad directory
  4. #include "config.h"
  5. #include <stdlib.h>
  6. #include <stdio.h>
  7. #include <string.h>
  8. #include <ctype.h>
  9. #include "rd_util.h"
  10. #include "rd_output.h"
  11. struct lump
  12. {
  13. const char *name;
  14. const void *data;
  15. size_t size;
  16. unsigned int offset;
  17. };
  18. static unsigned int numlumps, dirsize;
  19. static struct lump *dir;
  20. //
  21. // extract_lumpname
  22. //
  23. static char *extract_lumpname(const char *filename)
  24. {
  25. const char *base;
  26. char *lumpname, *suffix, *c;
  27. // strip off directory prefix
  28. base = strrchr(filename, '/');
  29. if (!base)
  30. base = filename;
  31. else
  32. base += 1;
  33. if (!*base)
  34. die("Empty lumpname: %s\n", filename);
  35. // copy the name
  36. lumpname = xstrdup(base);
  37. suffix = strrchr(lumpname, '.');
  38. if (suffix)
  39. *suffix = '\0';
  40. for (c = lumpname; *c; c++)
  41. *c = toupper(*c);
  42. return lumpname;
  43. }
  44. //
  45. // output_add - add lump to wad
  46. //
  47. void output_add(const char *filename, const void *data, size_t size)
  48. {
  49. struct lump *newlump;
  50. if (numlumps >= dirsize)
  51. {
  52. dirsize = dirsize ? 2*dirsize : 256;
  53. dir = xrealloc(dir, dirsize * sizeof(*dir));
  54. }
  55. newlump = &dir[numlumps++];
  56. newlump->name = extract_lumpname(filename);
  57. newlump->data = data;
  58. newlump->size = size;
  59. }
  60. //
  61. // write* - serialisation functions
  62. //
  63. // write a uint32_t, byteswapping if necessary
  64. static void write_u32(FILE *f, unsigned int n)
  65. {
  66. n = LONG(n);
  67. fwrite(&n, 4, 1, f);
  68. }
  69. // write a lump name (8 byte string)
  70. static void write_ch8(FILE *f, const char *s)
  71. {
  72. char buffer[9];
  73. memset(buffer, 0, sizeof(buffer));
  74. snprintf(buffer, sizeof(buffer), "%s", s);
  75. fwrite(buffer, 8, 1, f);
  76. }
  77. //
  78. // output_write - write wad to file
  79. //
  80. void output_write(const char *filename)
  81. {
  82. unsigned int i;
  83. struct lump *lump;
  84. unsigned int pos = 12;
  85. FILE *out;
  86. // calculate wad directory offsets
  87. for (i = numlumps, lump = dir; i; i--, lump++)
  88. {
  89. lump->offset = pos;
  90. pos += lump->size;
  91. }
  92. out = fopen(filename, "wb");
  93. if (!out)
  94. die("Cannot open %s\n", filename);
  95. // write wad header
  96. fwrite("PWAD", 4, 1, out);
  97. write_u32(out, numlumps);
  98. write_u32(out, pos);
  99. // write lumps
  100. for (i = numlumps, lump = dir; i; i--, lump++)
  101. fwrite(lump->data, lump->size, 1, out);
  102. // write wad directory
  103. for (i = numlumps, lump = dir; i; i--, lump++)
  104. {
  105. write_u32(out, lump->offset);
  106. write_u32(out, lump->size);
  107. write_ch8(out, lump->name);
  108. }
  109. fclose(out);
  110. }