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