commit d8fbf80a4bfd5f9c1ab6f93a4d2dc839339b6908 Author: mid-kid Date: Sun Apr 7 22:38:51 2019 +0200 Initial commit diff --git a/README.md b/README.md new file mode 100644 index 0000000..c6b6226 --- /dev/null +++ b/README.md @@ -0,0 +1,2 @@ +My resources used to beat https://zzazzdzz.github.io/fools2019/ +No writeups or explanations provided. diff --git a/pk3/calc.c b/pk3/calc.c new file mode 100644 index 0000000..49b5c0c --- /dev/null +++ b/pk3/calc.c @@ -0,0 +1,98 @@ +#include +#include +#include +#include + +int s03_A0F3 = 0x5D0B1C11; +int s03_A0F7 = 0x35E79125; +int s03_A0FB = 0x56596b10; +int s03_A0FF = 0x7FFFFB0A; +int s03_A103 = 0x1B080733; + +int s03_A107; +int s03_A10B; +int s03_A10D; +int s03_A10E; + +char buffer[0x200]; + +int main() +{ + FILE *f = fopen("fools.sav", "r"); + if (!f) { + perror("fopen"); + exit(1); + } + fseek(f, 0x6567, SEEK_SET); + fread(buffer, 1, 0x200, f); + fclose(f); + + GHashTable *hashtable = g_hash_table_new(g_direct_hash, g_direct_equal); + + double start = clock(); + do { + gint lcg = s03_A0F3 & 0xFFFFFE00; + gint cur_lcg = GPOINTER_TO_INT(g_hash_table_lookup(hashtable, GINT_TO_POINTER(lcg))); + cur_lcg += 1; + g_hash_table_replace(hashtable, GINT_TO_POINTER(lcg), GINT_TO_POINTER(cur_lcg)); + + s03_A0F3 = (s03_A0F3 * s03_A0F7 + s03_A0FB) & 0xFFFFFFFF; + + if (s03_A0FF % 0x100000 == 0) { + double framespers = 0x100000 / ((double)(clock() - start) / CLOCKS_PER_SEC); + unsigned eta = (double)(s03_A0FF) / framespers; + fprintf(stderr, "Progress: %d (speed: %.2f iter/s, ETA: %02u:%02u:%02u)\n", + s03_A0FF, framespers, + eta / 60 / 60, (eta / 60) % 60, eta % 60); + start = clock(); + } + } while (--s03_A0FF); + + int count = 0; + + GHashTableIter iter; + gpointer key, value; + g_hash_table_iter_init(&iter, hashtable); + while (g_hash_table_iter_next(&iter, &key, &value)) { + count += GPOINTER_TO_INT(value) % 2; + } + + int i = 0; + start = clock(); + g_hash_table_iter_init(&iter, hashtable); + while (g_hash_table_iter_next(&iter, &key, &value)) { + if (GPOINTER_TO_INT(value) % 2 == 0) { + continue; + } + + double framespers = 1 / ((double)(clock() - start) / CLOCKS_PER_SEC); + unsigned eta = (double)(count - i) / framespers; + fprintf(stderr, "Progress: %d/%d %.2f%% (speed: %.2f iter/s, ETA: %02u:%02u:%02u)\n", + i, count, (double)i / count * 100, framespers, + eta / 60 / 60, (eta / 60) % 60, eta % 60); + start = clock(); + i += 1; + + s03_A107 = s03_A103; + + s03_A10B = (GPOINTER_TO_INT(key) & 0xFF00) >> 8; + s03_A10D = (GPOINTER_TO_INT(key) & 0xFF0000) >> 16; + s03_A10E = (GPOINTER_TO_INT(key) & 0xFF000000) >> 24; + + int bufi = 0; + do { + s03_A10B = ((s03_A10B / 2) * s03_A10D + s03_A10E) & 0xFFFF; + buffer[bufi] ^= s03_A10B & 0xFF; + + if (++bufi >= 0x200) bufi = 0; + } while (--s03_A107); + } + + g_hash_table_destroy(hashtable); + + f = fopen("output.buf", "w"); + fwrite(buffer, 1, 0x200, f); + fclose(f); + + return 0; +} diff --git a/pk3/calc.py b/pk3/calc.py new file mode 100644 index 0000000..f884f43 --- /dev/null +++ b/pk3/calc.py @@ -0,0 +1,38 @@ +# Seed values (break at s03_A13A to fetch them) +s03_A0F3 = 0x5D0B1C11 # Match +s03_A0F7 = 0x35E79125 # Match +s03_A0FB = 0x56596b10 # Match +s03_A0FF = 0x7FFFFB0A # Match +s03_A103 = 0x1b080733 # Match + +file = open("fools.sav", "rb") +file.seek(0x6567) +buf = bytearray(file.read(0x200)) +file.close() + +while s03_A0FF != 0: + s03_A107 = s03_A103 + + s03_A10B = (s03_A0F3 & 0xFF00) >> 8 + s03_A10D = (s03_A0F3 & 0xFF0000) >> 16 + s03_A10E = (s03_A0F3 & 0xFF000000) >> 24 + + print(s03_A0FF - i_out) + + bufi = 0 + i = 0 + while s03_A107 != 0: + s03_A10B = ((s03_A10B // 2) * s03_A10D + s03_A10E) & 0xFFFF + buf[bufi] ^= (s03_A10B) & 0xFF + + bufi += 1 + if bufi >= 0x200: + bufi = 0 + + s03_A107 -= 1 + + s03_A0F3 = (s03_A0F3 * s03_A0F7 + s03_A0FB) & 0xFFFFFFFF + + s03_A0FF -= 1 + +file = open("output.buffer", "wb").write(buf) diff --git a/pk3/fools.asm b/pk3/fools.asm new file mode 100644 index 0000000..a89f9d1 --- /dev/null +++ b/pk3/fools.asm @@ -0,0 +1,222 @@ +CopyDEtoHL_32bit: ; s03_A084 +; Copies value pointed to by de to hl + + ld a, [de] + ld [hl+], a + inc de + ld a, [de] + ld [hl+], a + inc de + ld a, [de] + ld [hl+], a + inc de + ld a, [de] + ld [hl+], a + ret + +AddDEToHL_32bit: ; s03_A090 +; Adds value pointed to by de to value pointed to by hl + + ld a, [de] + add [hl] + ld [hl+], a + inc de + + ld a, [de] + adc [hl] + ld [hl+], a + inc de + + ld a, [de] + adc [hl] + ld [hl+], a + inc de + + ld a, [de] + adc [hl] + ld [hl], a + ret + +s03_A0A0: dl $FFFFFFFF + +DecHL_32bit: ; s03_A0A4 +; Decrements 32-bit value at hl, checks if result is 0 + + push hl + ld de, s03_A0A0 + call AddDEToHL_32bit + pop hl + + ; Checks 4-byte value at hl is 0 + ld a, [hl+] + and a + ret nz + ld a, [hl+] + and a + ret nz + ld a, [hl+] + and a + ret nz + ld a, [hl+] + and a + ret + +Multiplier: ds 4 ; s03_A0B8 +CalcResult: ds 4 ; s03_A0BC +Clean32bit: dl $00000000 ; s03_A0C0 + +MulDEToHL_32bit: ; s03_A0C4 +; Multiplies value at de with value at hl, stores in hl + + push hl + + ; Copy DE to the Multiplier + push hl + push de + ld hl, Multiplier + call CopyDEtoHL_32bit + pop de + pop hl + + ; Clear the result value + push hl + ld hl, CalcResult + ld de, Clean32bit + call CopyDEtoHL_32bit + pop de + + ; Add HL (now DE) Multiplier times to CalcResult +.loop + push de + ld hl, CalcResult + call AddDEToHL_32bit + pop de + push de + ld hl, Multiplier + call DecHL_32bit + pop de + jr nz, .loop + + ; Copy the result back to HL + pop hl + ld de, CalcResult + jp CopyDEtoHL_32bit + + +s03_A0F3: ds 4 ; Initial value: $5D0B1C11 +s03_A0F7: dl $35E79125 +s03_A0FB: dl $56596b10 +s03_A0FF: ds 4 ; Initial value: $7FFFFB0A + +s03_A103: dl $1b080733 +s03_A107: ds 4 ; Initialized with A103 + +s03_A10B: dw +s03_A10D: db +s03_A10E: db + +s03_A10F: +; (u16)s03_A10B = ((u16)s03_A10B / 2) * s03_A10D + s03_A10E + + ld hl, s03_A10B + ld a, [hl+] + ld h, [hl] + ld l, a + + and a + srl h + rr l + + ld d, h + ld e, l + ld hl, 0 + ld a, [s03_A10D] + ld c, a + and a + jr z, .end +.loop + add hl, de + dec c + jr nz, .loop +.end + + ld a, [s03_A10E] + ld c, a + ld b, 0 + add hl, bc + + ld a, h + ld [s03_A10B + 1], a + ld a, l + ld [s03_A10B], a + ret + +s03_A13A: +; Main decryption routine + +.outer_loop + ld hl, s03_A107 + ld de, s03_A103 + call CopyDEtoHL_32bit + + ; Initialize values + ld hl, s03_A0F3 + 1 + ld de, s03_A10B + ld a, [hl+] + ld [de], a + inc de ; s03_A10B + 1 + xor a + ld [de], a + inc de ; s03_A10D + ld a, [hl+] + ld [de], a + inc de ; s03_A10E + ld a, [hl] + ld [de], a + + ld hl, Buffer + ld bc, 0 + +; Problem with this routine: Writing to SRAM!!! +; This means that whatever is in hl's buffer is useless on next bootup, so we +; need to make sure to start from a clean save file. + +.loop ; s03_A15A + push hl + push bc + call s03_A10F ; (u16)s03_A10B = ((u16)s03_A10B / 2) * s03_A10D + s03_A10E + pop bc + pop hl + + ; Exor the buffer + xor [hl] + ld [hl+], a + + ; Reset HL to Buffer every $200 bytes + inc bc + ld a, b + cp $2 + jr nz, .s03_A16F + ld bc, 0 + ld hl, Buffer +.s03_A16F + + push hl + ld hl, s03_A107 + call DecHL_32bit + pop hl + jr nz, .loop + + ld hl, s03_A0F3 + ld de, s03_A0F7 + call MulDEToHL_32bit + ld hl, s03_A0F3 + ld de, s03_A0FB + call AddDEToHL_32bit + + ld hl, s03_A0FF + call DecHL_32bit + jr nz, .outer_loop + ret + +Buffer: ds $200 ; s03_A567 diff --git a/pk3/output.buf b/pk3/output.buf new file mode 100644 index 0000000..96c9c1a Binary files /dev/null and b/pk3/output.buf differ diff --git a/pk3/pk3_5seconds.c b/pk3/pk3_5seconds.c new file mode 100644 index 0000000..190899f --- /dev/null +++ b/pk3/pk3_5seconds.c @@ -0,0 +1,86 @@ +// Written by luckytyphlosion + +#include +#include +#include + +typedef unsigned int uint; +typedef unsigned short u16; +typedef unsigned char u8; + +#define _A0F4 (_A0F3 >> 8) & 0xff +#define _A0F5 (_A0F3 >> 16) & 0xff +#define _A0F6 (_A0F3 >> 24) & 0xff +#define TRUE 1 +#define FALSE 0 + +u8 sA567[] = {0x15, 0xc8, 0x7b, 0x6b, 0x7f, 0xa1, 0xa3, 0x29, 0xe8, 0x81, 0x1, 0x99, 0x9f, 0xeb, 0xf2, 0x80, 0x5f, 0xa3, 0x96, 0x7c, 0x17, 0xdb, 0xd2, 0x41, 0xa1, 0xbc, 0xbb, 0x13, 0xbc, 0xd8, 0xc3, 0x9, 0xf4, 0x2, 0x1b, 0x95, 0xf3, 0x72, 0x65, 0xdb, 0x6f, 0x82, 0x9e, 0x52, 0xd9, 0x89, 0xd8, 0xdf, 0x5a, 0xb0, 0x3, 0xf2, 0x9a, 0xe6, 0xef, 0x81, 0x32, 0xa5, 0x57, 0x60, 0xe0, 0xc8, 0x2d, 0x8c, 0x52, 0x63, 0x5d, 0xd8, 0xf, 0x72, 0xdf, 0xa1, 0x36, 0x1c, 0x3e, 0xc8, 0xc2, 0x4f, 0x1e, 0xfd, 0x1d, 0x11, 0xc, 0x74, 0x13, 0x21, 0x49, 0xad, 0xc0, 0xd9, 0xba, 0xda, 0xd, 0xe4, 0x6, 0x8e, 0x94, 0xe6, 0x25, 0x8b, 0xba, 0xc2, 0x2b, 0x92, 0xa, 0x90, 0xa1, 0x4a, 0x6, 0x53, 0x84, 0x79, 0xe5, 0xe7, 0xcf, 0x60, 0x74, 0xd2, 0x3b, 0x2a, 0xe0, 0x56, 0x32, 0xa6, 0x10, 0x69, 0x52, 0xf, 0xd3, 0x3d, 0x7f, 0xf3, 0x12, 0x6d, 0x0, 0x57, 0x41, 0x3f, 0x96, 0x3b, 0x8, 0xb7, 0x48, 0x72, 0xb2, 0x1e, 0x12, 0x57, 0x60, 0x95, 0x23, 0xc8, 0xab, 0x52, 0xc8, 0x3f, 0xc4, 0xc0, 0x50, 0xc1, 0xd3, 0x38, 0x28, 0x6e, 0x96, 0x6d, 0xdf, 0x8f, 0x41, 0x24, 0x21, 0x91, 0xf4, 0x64, 0x3e, 0xc9, 0xe6, 0xc7, 0x45, 0x26, 0xa1, 0x4c, 0xa, 0xd3, 0x2f, 0x8f, 0x77, 0x7d, 0x68, 0x86, 0x23, 0x43, 0xcf, 0xbf, 0xe1, 0xf4, 0xc8, 0x9e, 0x35, 0x5a, 0x11, 0x26, 0xb7, 0x9f, 0x23, 0xcd, 0x68, 0xa2, 0xb5, 0xca, 0xd3, 0x53, 0x95, 0xda, 0xb, 0x87, 0x15, 0xca, 0xe7, 0x73, 0xbd, 0x66, 0x39, 0x90, 0xc0, 0xa4, 0x94, 0x94, 0x3e, 0x61, 0x9e, 0xef, 0x89, 0x1e, 0x93, 0x13, 0xc1, 0xfa, 0xd9, 0xee, 0x5b, 0x27, 0x71, 0x16, 0xcd, 0xa2, 0xef, 0x49, 0xcc, 0xd6, 0x1d, 0x24, 0xa6, 0x3b, 0x89, 0x94, 0x58, 0x28, 0xd2, 0x83, 0x5b, 0x25, 0x8a, 0x5f, 0x25, 0xfe, 0xe3, 0x2d, 0xe8, 0x58, 0x5e, 0xbb, 0x9b, 0xd5, 0xe8, 0x46, 0xa5, 0xdc, 0xde, 0x8f, 0x97, 0x3, 0xf1, 0x16, 0x1, 0xfc, 0x2e, 0x3f, 0x47, 0x5b, 0xaf, 0x71, 0x2e, 0x7f, 0x19, 0xce, 0xe3, 0x7d, 0xe2, 0x49, 0x5e, 0x71, 0xa, 0x57, 0xe1, 0x98, 0xac, 0xdd, 0x7f, 0xfd, 0x5d, 0xae, 0xdc, 0x24, 0xc5, 0x30, 0x3b, 0x65, 0xc1, 0xd6, 0xf4, 0x62, 0xa0, 0xee, 0xbc, 0x86, 0x68, 0xb4, 0x5, 0x68, 0x1b, 0xdb, 0x5c, 0xa8, 0x25, 0x92, 0x70, 0xc8, 0xa5, 0xf6, 0x1a, 0x55, 0xad, 0xae, 0x44, 0x2a, 0x4a, 0x77, 0xca, 0x2d, 0x6b, 0xdd, 0x47, 0x51, 0x95, 0x58, 0xff, 0x75, 0xdd, 0x30, 0x81, 0x80, 0x1b, 0xdb, 0xc2, 0xa9, 0x29, 0xce, 0xa8, 0xd6, 0xd8, 0x8, 0xc1, 0x86, 0x1c, 0xec, 0xf, 0x63, 0x48, 0x38, 0x1b, 0xeb, 0x32, 0xe3, 0xa0, 0xe6, 0x28, 0x5e, 0xf4, 0xa, 0xa2, 0x2d, 0xf1, 0xb0, 0x61, 0xfc, 0xdd, 0x4c, 0x6b, 0x43, 0xe8, 0x82, 0x4, 0xe8, 0xf3, 0x3d, 0x43, 0xf5, 0x6d, 0x4e, 0x8a, 0x45, 0xc9, 0x6a, 0x96, 0x1d, 0x37, 0x93, 0x76, 0x53, 0x9e, 0x33, 0xa, 0xaf, 0x8, 0x3e, 0x80, 0xfc, 0xe7, 0xc5, 0x17, 0x69, 0xe7, 0x91, 0x55, 0x52, 0x4a, 0xa5, 0x51, 0x6, 0xa8, 0x3e, 0x82, 0x1d, 0xff, 0x27, 0x14, 0xee, 0x26, 0x39, 0x55, 0xc0, 0x8f, 0xd7, 0xf2, 0x47, 0x14, 0x9a, 0x54, 0x5e, 0xac, 0x9a, 0xc2, 0x93, 0xc0, 0x96, 0x60, 0x44, 0x11, 0x8, 0xed, 0x22, 0x20, 0x44, 0x77, 0xb3, 0xfc, 0x78, 0xe5, 0xda, 0xa, 0xc5, 0xa1, 0xbe, 0x64, 0x80, 0x25, 0x20, 0xa7, 0xfb, 0x3e, 0xdb, 0x26, 0x39, 0x99, 0x2a, 0xee, 0xa3, 0x36, 0x7b, 0xb6, 0x63, 0x24, 0xf6, 0xf6, 0x13, 0xe, 0x83, 0x86, 0x1f, 0x3a, 0xf}; + +u16 values[65536] = {0}; +u16 values_set[65536] = {0}; +int values_size = 0; + +int main(void) { + uint _A0F3 = 0x5d0b1c11; + const uint _A0F7 = 0x35e79125; + const uint _A0FB = 0x56596b10; + struct timespec start_time; + + for (int i = 0; i < 0x3ffffb0a; i++) { + _A0F3 = _A0F3 * _A0F7 + _A0FB; + } + + for (int i = 0; i < 0x4f6; i++) { + u16 _A10B = _A0F4; + int _A10D = _A0F5; + int _A10E = _A0F6; + int data_count = 0; + int start_index = -1; + values_size = 0; + int sublcg_count = 0; + memset(values_set, 0xff, sizeof(values_set)); + while (TRUE) { + values[values_size++] = _A10B; + _A10B = (_A10B >> 1) * _A10D + _A10E; + if (values_set[_A10B] != 0xffff) { + start_index = values_set[_A10B]; + break; + } + values_set[_A10B] = values_size; + sA567[data_count++] ^= (_A10B & 0xff); + data_count = data_count & 0x1ff; + sublcg_count++; + } + int sublcg_index = start_index; + + int period = values_size - start_index; + while ((period & 1) == 0) { + period >>= 1; + } + + int num_xors_until_repeat = period * 512; + int num_repeat_iterations = (0x1b080733 - sublcg_count) / num_xors_until_repeat; + int remaining_sublcg_iterations = (0x1b080733 - sublcg_count) % num_xors_until_repeat; + if (num_repeat_iterations & 1 == 1) { + remaining_sublcg_iterations += num_xors_until_repeat; + } + + for (int j = 0; j < remaining_sublcg_iterations; j++) { + sA567[data_count++] ^= (values[sublcg_index++] & 0xff); + data_count = data_count & 0x1ff; + if (sublcg_index >= values_size) { + sublcg_index = start_index; + } + } + _A0F3 = _A0F3 * _A0F7 + _A0FB; + if (i % 10000 == 9999) { + struct timespec end_time; + clock_gettime(CLOCK_MONOTONIC, &end_time); + fprintf(stderr, "difftime: %f, iter: %u\n", 1000.0*end_time.tv_sec + 1e-6*end_time.tv_nsec - (1000.0*start_time.tv_sec + 1e-6*start_time.tv_nsec), i); + } + } + + for (int i = 0; i < 0x200; i++) { + printf("0x%02x, ", sA567[i]); + } +} diff --git a/pk4/dumprop.py b/pk4/dumprop.py new file mode 100755 index 0000000..eee9bb0 --- /dev/null +++ b/pk4/dumprop.py @@ -0,0 +1,29 @@ +#!/usr/bin/env python3 + +from sys import argv +from struct import unpack + +gadgets = {} + +for line in open("ropgadgets.txt"): + split = line.split("-") + if len(split) < 2: + continue + + addr = int(split[0][1:], 16) + cmd = "-".join(split[1:]).strip() + gadgets[addr] = cmd + +mem = open("fools.dump", "rb").read() + +addr = int(argv[1], 0) + +while True: + gadget = unpack(" + +// Final buffer goes at 3:A100 of the save file + +char buf[0x1b0]; + +int s02_ADB1; + +char s02_ADB1_b; +char s02_ADB2; +char s02_ADB3; +char s02_ADB4; + +char sSaveBlockChecksum; + +char func() +{ + s02_ADB1_b = (s02_ADB1 >> 0) & 0xFF; + s02_ADB2 = (s02_ADB1 >> 8) & 0xFF; + s02_ADB3 = (s02_ADB1 >> 16) & 0xFF; + s02_ADB4 = (s02_ADB1 >> 24) & 0xFF; + + s02_ADB2 ^= (s02_ADB1_b + 1) ^ s02_ADB4; + s02_ADB3 += s02_ADB2; + s02_ADB4 = s02_ADB2 ^ (s02_ADB4 + (s02_ADB3 / 2)); + + s02_ADB1 = (s02_ADB4 << 24) | (s02_ADB3 << 16) | (s02_ADB2 << 8) | s02_ADB1_b; + + return s02_ADB4; +} + +int main() +{ + int bufi = 0; + + // sSaveSource = $FCDF; + sSaveBlockChecksum = 0x7F; + s02_ADB1 = 0x8C10E62F; + for (int i = 0; i < 0x48; i++) { + buf[bufi] = (char)(bufi & 0xFF); + buf[bufi] ^= func(); + sSaveBlockChecksum += buf[bufi]; + bufi++; + + buf[bufi] = (char)(bufi & 0xFF); + sSaveBlockChecksum ^= buf[bufi]; + buf[bufi] ^= func(); + bufi++; + } + buf[bufi] = sSaveBlockChecksum; + bufi++; + + // sSaveSource = $FA7A; + sSaveBlockChecksum = 0xC2; + s02_ADB1 = 0x6AF528C2; + for (int i = 0; i < 0x14; i++) { + buf[bufi] = (char)(bufi & 0xFF); + buf[bufi] ^= func(); + sSaveBlockChecksum ^= buf[bufi]; + bufi++; + } + buf[bufi] = sSaveBlockChecksum; + bufi++; + + // sSaveSource = $F84E; + for (int i = 0; i < 0x03; i++) { + buf[bufi] = (char)(bufi & 0xFF); + bufi++; + } + + // sSaveSource = $F859; + sSaveBlockChecksum = 0x06; + s02_ADB1 = 0xEF7305A6; + for (int i = 0; i < 0x4C; i++) { + buf[bufi] = (char)(bufi & 0xFF); + buf[bufi] ^= func(); + sSaveBlockChecksum ^= buf[bufi]; + bufi++; + + buf[bufi] = (char)(bufi & 0xFF); + buf[bufi] ^= func(); + sSaveBlockChecksum += buf[bufi]; + bufi++; + } + buf[bufi] = sSaveBlockChecksum; + bufi++; + + // sSaveSource = $DE41; + s02_ADB1 = 0x2A7FEC38; + sSaveBlockChecksum = 0x3C; + for (int i = 0; i < 0x21; i++) { + buf[bufi] = (char)(bufi & 0xFF); + sSaveBlockChecksum += buf[bufi]; + buf[bufi] ^= func(); + bufi++; + } + buf[bufi] = sSaveBlockChecksum; + bufi++; + + // sSaveSource = $DE99; + sSaveBlockChecksum = 0xE2; + s02_ADB1 = 0x4BFC1115; + for (int i = 0 ; i < 0x40; i++) { + buf[bufi] = (char)(bufi & 0xFF); + buf[bufi] ^= func(); + sSaveBlockChecksum += buf[bufi]; + bufi++; + } + buf[bufi] = sSaveBlockChecksum; + bufi++; + + s02_ADB1 = 0xA23F387C; + sSaveBlockChecksum = 0x16; + // sSaveSource = $A003; + for (int i = 0; i < 0x04; i++) { + buf[bufi] = (char)(bufi & 0xFF); + buf[bufi] ^= func(); + sSaveBlockChecksum ^= buf[bufi]; + sSaveBlockChecksum += buf[bufi]; + bufi++; + } + buf[bufi] = sSaveBlockChecksum; + bufi++; + + sSaveBlockChecksum = 0x00; + + // sSaveSource = $FFE1; + buf[bufi] = (char)(bufi & 0xFF); + sSaveBlockChecksum += buf[bufi]; + sSaveSource = 0xB16B; + *(sSaveSource++) = sSaveBlockChecksum; + bufi++; + + // sSaveSource = $FFE2; + // buf[bufi] = *(sSaveSource++); + // sSaveBlockChecksum ^= buf[bufi]; + // buf[bufi] = sSaveBlockChecksum; + // sSaveSource = $B16C; + // *(sSaveSource++) = sSaveBlockChecksum; + // bufi++; + + // sSaveSource = $FF04; + // buf[bufi] = *(sSaveSource++); + // sSaveBlockChecksum += buf[bufi]; + // buf[bufi] = sSaveBlockChecksum; + // sSaveSource = $B16D; + // *(sSaveSource++) = sSaveBlockChecksum; + // bufi++; + // sSaveSource = $FF05; + // buf[bufi] = *(sSaveSource++); + // sSaveBlockChecksum ^= buf[bufi]; + // buf[bufi] = sSaveBlockChecksum; + // sSaveSource = $B16E; + // *(sSaveSource++) = sSaveBlockChecksum; + // bufi++; + // s02_ADB1 = $EFBEADDE; + // bufi++; + // bufi++; + // sSaveBlockChecksum = $55; + // sSaveSource = $F350; + // *(sSaveSource++) = sSaveBlockChecksum; + // *(sSaveSource++) = sSaveBlockChecksum; + // rept ($1AB) {; + // sSaveSource = $F350; + // sSaveBlockChecksum = *sSaveSource; + // sSaveBlockChecksum += buf[bufi]; + // *(sSaveSource++) = sSaveBlockChecksum; + // sSaveBlockChecksum = *sSaveSource; + // sSaveBlockChecksum ^= buf[bufi]; + // *(sSaveSource++) = sSaveBlockChecksum; + // buf[bufi] ^= func(s02_ADB1); + // bufi++; + // }; + + // sSaveBlockChecksum = $CC; + // sSaveSource = $ADB1; + // sSaveBlockChecksum ^= buf[bufi]; + // *(sSaveSource++) = sSaveBlockChecksum; + // bufi++; + // sSaveBlockChecksum ^= buf[bufi]; + // *(sSaveSource++) = sSaveBlockChecksum; + // bufi++; + // sSaveBlockChecksum ^= buf[bufi]; + // *(sSaveSource++) = sSaveBlockChecksum; + // bufi++; + // sSaveBlockChecksum ^= buf[bufi]; + // *(sSaveSource++) = sSaveBlockChecksum; + // bufi++; + // sSaveSource = $F350; + // buf[bufi] = *(sSaveSource++); + // buf[bufi] ^= func(s02_ADB1); + // bufi++; + // buf[bufi] = *(sSaveSource++); + // buf[bufi] ^= func(s02_ADB1); + // bufi++; +} diff --git a/pokecrystal.diff b/pokecrystal.diff new file mode 100644 index 0000000..09c4a63 --- /dev/null +++ b/pokecrystal.diff @@ -0,0 +1,72 @@ +# These are the patches I used to speed through the game. +# They include: +# - All pokemon's stats and HP are max when sent into battle +# - HP bars deplete instantly (to avoid destiny bond softlocking the game...) +# - No trainers can spot you (used to solve PK1 mostly) + +diff --git a/Makefile b/Makefile +index e213bf63c..812cb9799 100644 +--- a/Makefile ++++ b/Makefile +@@ -89,6 +89,7 @@ endif + pokecrystal.gbc: $(crystal_obj) pokecrystal.link + $(RGBLINK) -n pokecrystal.sym -m pokecrystal.map -l pokecrystal.link -o $@ $(crystal_obj) + $(RGBFIX) -Cjv -i BYTE -k 01 -l 0x33 -m 0x10 -p 0 -r 3 -t PM_CRYSTAL $@ ++ dd bs=1 if=baserom.gbc of=pokecrystal.gbc count=2 conv=notrunc skip=334 seek=334 + tools/sort_symfile.sh pokecrystal.sym + + pokecrystal11.gbc: $(crystal11_obj) pokecrystal.link +diff --git a/engine/battle/core.asm b/engine/battle/core.asm +index 38abbb51f..f752e4d46 100644 +--- a/engine/battle/core.asm ++++ b/engine/battle/core.asm +@@ -3884,11 +3884,13 @@ InitBattleMon: + ld bc, MON_NAME_LENGTH + call CopyBytes + ld hl, wBattleMonAttack +- ld de, wPlayerStats ++ ld a, $ff + ld bc, PARTYMON_STRUCT_LENGTH - MON_ATK +- call CopyBytes +- call ApplyStatusEffectOnPlayerStats +- call BadgeStatBoosts ++ call ByteFill ++ ld a, $ff ++ ld [wBattleMonHP], a ++ nop ++ nop + ret + + BattleCheckPlayerShininess: +diff --git a/engine/overworld/events.asm b/engine/overworld/events.asm +index a84d72db4..9d1dd8d44 100644 +--- a/engine/overworld/events.asm ++++ b/engine/overworld/events.asm +@@ -294,8 +294,10 @@ PlayerEvents: + CheckTrainerBattle_GetPlayerEvent: + nop + nop +- call CheckTrainerBattle +- jr nc, .nope ++ nop ++ nop ++ nop ++ jr .nope + + ld a, PLAYEREVENT_SEENBYTRAINER + scf +diff --git a/engine/pokemon/health.asm b/engine/pokemon/health.asm +index d11a073b5..0cd97d237 100644 +--- a/engine/pokemon/health.asm ++++ b/engine/pokemon/health.asm +@@ -104,7 +104,9 @@ ComputeHPBarPixels: + ret + + AnimateHPBar: +- call WaitBGMap ++ ret ++ ret ++ ret + call _AnimateHPBar + call WaitBGMap + ret