scripts

misc scripts and tools
git clone git://git.2f30.org/scripts.git
Log | Files | Refs

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 }