p_checksum.c 2.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101
  1. #include <stdio.h>
  2. #include <string.h>
  3. #include <errno.h>
  4. #include <stdlib.h> /* exit(), atexit() */
  5. #include "p_checksum.h"
  6. #include "md5.h"
  7. #include "doomstat.h" /* players{,ingame} */
  8. #include "lprintf.h"
  9. /* forward decls */
  10. static void p_checksum_cleanup(void);
  11. void checksum_gamestate(int tic);
  12. /* vars */
  13. static void p_checksum_nop(int tic){} /* do nothing */
  14. void (*P_Checksum)(int) = p_checksum_nop;
  15. /*
  16. * P_RecordChecksum
  17. * sets up the file and function pointers to write out checksum data
  18. */
  19. static FILE *outfile = NULL;
  20. static struct MD5Context md5global;
  21. void P_RecordChecksum(const char *file) {
  22. size_t fnsize;
  23. fnsize = strlen(file);
  24. /* special case: write to stdout */
  25. if(0 == strncmp("-",file,MIN(1,fnsize)))
  26. outfile = stdout;
  27. else {
  28. outfile = fopen(file,"wb");
  29. if(NULL == outfile) {
  30. I_Error("cannot open %s for writing checksum:\n%s\n",
  31. file, strerror(errno));
  32. }
  33. atexit(p_checksum_cleanup);
  34. }
  35. MD5Init(&md5global);
  36. P_Checksum = checksum_gamestate;
  37. }
  38. void P_ChecksumFinal(void) {
  39. int i;
  40. unsigned char digest[16];
  41. if (!outfile)
  42. return;
  43. MD5Final(digest, &md5global);
  44. fprintf(outfile, "final: ");
  45. for (i=0; i<16; i++)
  46. fprintf(outfile,"%x", digest[i]);
  47. fprintf(outfile, "\n");
  48. MD5Init(&md5global);
  49. }
  50. static void p_checksum_cleanup(void) {
  51. if (outfile && (outfile != stdout))
  52. fclose(outfile);
  53. }
  54. /*
  55. * runs on each tic when recording checksums
  56. */
  57. void checksum_gamestate(int tic) {
  58. int i;
  59. struct MD5Context md5ctx;
  60. unsigned char digest[16];
  61. char buffer[2048];
  62. fprintf(outfile,"%6d, ", tic);
  63. /* based on "ArchivePlayers" */
  64. MD5Init(&md5ctx);
  65. for (i=0 ; i<MAXPLAYERS ; i++) {
  66. if (!playeringame[i]) continue;
  67. #ifdef HAVE_SNPRINTF
  68. snprintf (buffer, sizeof(buffer), "%d", players[i].health);
  69. #else
  70. sprintf (buffer, "%d", players[i].health);
  71. #endif
  72. buffer[sizeof(buffer)-1] = 0;
  73. MD5Update(&md5ctx, (md5byte const *)&buffer, strlen(buffer));
  74. }
  75. MD5Final(digest, &md5ctx);
  76. for (i=0; i<16; i++) {
  77. MD5Update(&md5global, (md5byte const *)&digest[i], sizeof(digest[i]));
  78. fprintf(outfile,"%x", digest[i]);
  79. }
  80. fprintf(outfile,"\n");
  81. }