d2-resurrect.c (2336B)
1 /* Resurrect hardcore characters in Diablo 2 */ 2 3 #include <unistd.h> 4 #include <sys/stat.h> 5 #include <stdio.h> 6 #include <stdlib.h> 7 #include <stdbool.h> 8 #include <stdint.h> 9 #include <fcntl.h> 10 #include <getopt.h> 11 #include <err.h> 12 13 static uint32_t 14 rotl(const uint32_t value, int shift) 15 { 16 if ((shift &= sizeof(value) * 8 - 1) == 0) 17 return value; 18 return (value << shift) | (value >> (sizeof(value) * 8 - shift)); 19 } 20 21 static void 22 usage(const char *prog) 23 { 24 fprintf(stderr, "usage: %s [-h] <d2s>\n", prog); 25 fprintf(stderr, " -h\tMake player hardcore\n"); 26 } 27 28 static int hflag; 29 30 int 31 main(int argc, char *argv[]) 32 { 33 struct stat sbuf; 34 const char *prog; 35 unsigned char *buf; 36 unsigned char tmp; 37 int ret, fd, i, c; 38 uint32_t chksum; 39 uint32_t status; 40 41 prog = *argv; 42 43 for (c = 0; c >= 0; c = getopt(argc, argv, "h")) { 44 switch (c) { 45 case 'h': 46 hflag = true; 47 break; 48 case '?': 49 usage(prog); 50 return 1; 51 } 52 } 53 54 argc -= optind; 55 argv += optind; 56 57 if (argc != 1) { 58 usage(prog); 59 return 1; 60 } 61 62 fd = open(*argv, O_RDWR); 63 if (fd < 0) 64 err(1, "open"); 65 66 ret = fstat(fd, &sbuf); 67 if (ret < 0) 68 err(1, "fstat"); 69 70 buf = malloc(sbuf.st_size); 71 if (!buf) 72 err(1, "malloc"); 73 74 ret = read(fd, buf, sbuf.st_size); 75 if (ret != sbuf.st_size) 76 err(1, "read"); 77 78 status = buf[0x24]; 79 printf("old character status: %#hhx, bitmap: [", status); 80 for (i = 7; i >= 0; i--) { 81 if (status & (1 << i)) 82 putchar('1'); 83 else 84 putchar('0'); 85 } 86 printf("]\n"); 87 if (status & (1 << 3)) { 88 printf("resurrecting character...\n"); 89 status &= ~(1 << 3); 90 buf[0x24] = status; 91 printf("new character status: %#hhx, bitmap: [", status); 92 for (i = 7; i >= 0; i--) { 93 if (status & (1 << i)) 94 putchar('1'); 95 else 96 putchar('0'); 97 } 98 printf("]\n"); 99 } 100 if (hflag) { 101 printf("making character hardcore\n"); 102 status |= (1 << 2); 103 buf[0x24] = status; 104 } 105 106 printf("checksum before: %#x\n", *(uint32_t *)&buf[12]); 107 *(uint32_t *)&buf[12] = 0; 108 for (chksum = 0, i = 0; i < sbuf.st_size; i++) { 109 tmp = buf[i]; 110 chksum = rotl(chksum, 1); 111 chksum += tmp; 112 } 113 printf("checksum after: %#x\n", chksum); 114 *(uint32_t *)&buf[12] = chksum; 115 116 ret = lseek(fd, 0, SEEK_SET); 117 if (ret < 0) 118 err(1, "lseek"); 119 120 printf("writing changes..."); 121 if (write(fd, buf, sbuf.st_size) != sbuf.st_size) 122 err(1, "write"); 123 printf("OK!\n"); 124 125 close(fd); 126 return 0; 127 }