commit
						d8fbf80a4b
					
				 15 changed files with 1889 additions and 0 deletions
			
			
		| @ -0,0 +1,2 @@ | |||
| My resources used to beat https://zzazzdzz.github.io/fools2019/   | |||
| No writeups or explanations provided. | |||
| @ -0,0 +1,98 @@ | |||
| #include <stdlib.h> | |||
| #include <stdio.h> | |||
| #include <time.h> | |||
| #include <glib.h> | |||
| 
 | |||
| 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; | |||
| } | |||
| @ -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) | |||
| @ -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 | |||
								
									Binary file not shown.
								
							
						
					| @ -0,0 +1,86 @@ | |||
| // Written by luckytyphlosion
 | |||
| 
 | |||
| #include <stdio.h> | |||
| #include <time.h> | |||
| #include <string.h> | |||
| 
 | |||
| 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]); | |||
|     } | |||
| } | |||
| @ -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("<H", mem[addr:addr+2])[0] | |||
|     if gadget in gadgets: | |||
|         print("   ", gadgets[gadget]) | |||
|     else: | |||
|         print("    dw $%04X" % gadget) | |||
|     if gadget == 0x1708: | |||
|         break | |||
|     addr += 2 | |||
| @ -0,0 +1,78 @@ | |||
| #!/usr/bin/env python3 | |||
| 
 | |||
| from sys import argv | |||
| from struct import unpack | |||
| 
 | |||
| mem = open("fools.dump", "rb").read() | |||
| 
 | |||
| addr = int(argv[1], 0) | |||
| 
 | |||
| while True: | |||
|     gadget = unpack("<B", mem[addr:addr+1])[0] | |||
| 
 | |||
|     if gadget == 0x01: | |||
|         param = unpack("<H", mem[addr+1:addr+3])[0] | |||
|         print("    ; sSaveSource = $%04X" % param) | |||
|         print("    dbw $01, $%04X  ; ROP_s02_AEF3" % param) | |||
|         print() | |||
|         addr += 3 | |||
|     elif gadget == 0x02: | |||
|         param = unpack("<B", mem[addr+1:addr+2])[0] | |||
|         print("    ; sSaveBlockChecksum = $%02X" % param) | |||
|         print("    dbb $02, $%02X  ; ROP_s02_AF09" % param) | |||
|         print() | |||
|         addr += 2 | |||
|     elif gadget == 0x03: | |||
|         print("    ; w00_C800 = *(sSaveSource++)") | |||
|         print("    db $03  ; ROP_s02_AF19") | |||
|         print() | |||
|         addr += 1 | |||
|     elif gadget == 0x05: | |||
|         print("    ; w00_C800 ^= func(s02_ADB1)") | |||
|         print("    db $05  ; ROP_s02_AF3B") | |||
|         print() | |||
|         addr += 1 | |||
|     elif gadget == 0x06: | |||
|         print("    ; rotatebuffer(w00_C800)") | |||
|         print("    db $06  ; ROP_s02_AF85") | |||
|         print() | |||
|         addr += 1 | |||
|     elif gadget == 0x07: | |||
|         param = unpack("<I", mem[addr+1:addr+5])[0] | |||
|         print("    ; s02_ADB1 = $%08X" % param) | |||
|         print("    dbl $07, $%08X  ; ROP_s02_AFE3" % param) | |||
|         print() | |||
|         addr += 5 | |||
|     elif gadget == 0x08: | |||
|         print("    ; sSaveBlockChecksum += w00_C800") | |||
|         print("    db $08  ; ROP_s02_B005") | |||
|         print() | |||
|         addr += 1 | |||
|     elif gadget == 0x09: | |||
|         print("    ; sSaveBlockChecksum ^= w00_C800") | |||
|         print("    db $09  ; ROP_s02_B013") | |||
|         print() | |||
|         addr += 1 | |||
|     elif gadget == 0x0B: | |||
|         print("    ; w00_C800 = sSaveBlockChecksum") | |||
|         print("    db $0B  ; ROP_s02_B033") | |||
|         print() | |||
|         addr += 1 | |||
|     elif gadget == 0x0C: | |||
|         param1 = unpack("<H", mem[addr+1:addr+3])[0] | |||
|         param2 = unpack("<B", mem[addr+3:addr+4])[0] | |||
|         print("    dbwb $0C, $%03X, $%02X  ; ROP_rept" % (param1, param2)) | |||
|         print() | |||
|         addr += 4 | |||
|     elif gadget == 0x0D: | |||
|         print("    ; *(sSaveSource++) = sSaveBlockChecksum") | |||
|         print("    db $0D  ; ROP_s02_B045") | |||
|         print() | |||
|         addr += 1 | |||
|     elif gadget == 0x0E: | |||
|         print("    ; sSaveBlockChecksum = *sSaveSource") | |||
|         print("    db $0E  ; ROP_s02_B069") | |||
|         print() | |||
|         addr += 1 | |||
|     else: | |||
|         break | |||
| @ -0,0 +1,997 @@ | |||
| Text_WouldYouLikeToSaveTheGame EQU $5283 | |||
| Text_SavingDontTurnOffThePower EQU $5288 | |||
| SaveTheGame_yesorno EQU $4BAF | |||
| SaveMenu.refused EQU $4A4A | |||
| Text_WaitBGMap EQU $13B6 | |||
| SpeechTextBox EQU $103E | |||
| FarCall EQU $08 | |||
| FadeOutPalettes EQU $23:$4084 | |||
| LoadMapPalettes EQU $41:$47EB | |||
| ClearScreen EQU $0FDB | |||
| UpdateSprites EQU $1AD2 | |||
| GetSGBLayout EQU $3340 | |||
| SetPalettes EQU $32F9 | |||
| DelayFrame EQU $045A | |||
| DelayFrames EQU $0468 | |||
| PrintText EQU $1057 | |||
| Request1bpp EQU $0F1E | |||
| DoubleSpeed EQU $2FEF | |||
| hTransferVirtualOAM EQU $FFEC | |||
| rSTAT EQU $FF41 | |||
| CopyBytes EQU $3026 | |||
| 
 | |||
| s02_9A12: db  ; s02_9A12 | |||
| 
 | |||
| SaveGame:  ; s02_AD44 | |||
|     push af | |||
|     push bc | |||
|     push de | |||
|     push hl | |||
|     ei    | |||
|     call Text_WaitBGMap | |||
| 
 | |||
|     ld   a,[wSavingAllowed] | |||
|     and  a | |||
|     jr   z,.cantsave | |||
| 
 | |||
|     ; Ask the player to save or some dumb shit idfk | |||
|     ld   hl,$B1E8 | |||
|     ld   a,$02 | |||
|     ld   [w01_DF34],a | |||
|     call $A2A3 | |||
|     ld   bc,$0204 | |||
|     ld   hl,$A41A | |||
|     ld   de,Start | |||
|     call $AB1F  ; Get player input? | |||
|     and  a | |||
|     jr   z,.declined | |||
| 
 | |||
|     ; Confirmed save | |||
|     ld   a,[wPartyCount] | |||
|     cp   a,$04 | |||
|     jr   c,.actuallysave | |||
| 
 | |||
|     ; Too many party members yadda yadda | |||
|     ld   hl,$B323 | |||
|     ld   a,$02 | |||
|     ld   [w01_DF34],a | |||
|     call $A2A3 | |||
|     ld   bc,$0204 | |||
|     ld   hl,$A41A | |||
|     ld   de,Start | |||
|     call $AB1F | |||
|     and  a | |||
|     jr   z,$ADA7 | |||
| 
 | |||
| .actuallysave  ; s02_AD8F | |||
|     ld   a,BANK(FadeOutPalettes) | |||
|     ld   hl,FadeOutPalettes | |||
|     rst  FarCall | |||
|     ld   a,BANK(LoadMapPalettes) | |||
|     ld   hl,LoadMapPalettes | |||
|     rst  FarCall | |||
|     jp   SavingTheGame | |||
| 
 | |||
| .cantsave  ; s02_A9DC | |||
|     ld   hl,$B1A6 | |||
|     ld   a,$02 | |||
|     ld   [$DF34],a | |||
|     call $A2A3 | |||
| 
 | |||
| .declined  ; s02_ADA7 | |||
|     pop  hl | |||
|     pop  de | |||
|     pop  bc | |||
|     pop  af | |||
|     jp   $0460 | |||
| 
 | |||
| sSaveSource: dw  ; s02_ADAE | |||
| sSaveBlockChecksum: db  ; s02_ADB0 | |||
| s02_ADB1: dl  ; s02_ADB1 | |||
| sBufferCarry:     ; s02_ADB5 | |||
| sROPScriptBackup: dw  ; s02_ADB6 | |||
| s02_ADB8: db  ; s02_ADB8 | |||
| s02_ADB9: db  ; s02_ADB9 | |||
| 
 | |||
| ROPGadget_ldi_a_hl:  ; s02_ADBA | |||
|     ld a, [hl+] | |||
|     ret | |||
| 
 | |||
| ROPGadget_ldd_a_hl:  ; s02_ADBC | |||
|     ld a, [hl-] | |||
|     ret | |||
| 
 | |||
| ROPGadget_ld_hl_c:  ; s02_ADBE | |||
|     ld [hl], c | |||
|     ret | |||
| 
 | |||
| ROPGadget_ld_b_hl:  ; s02_ADC0 | |||
|     ld b, [hl] | |||
|     ret | |||
| 
 | |||
| ROPGadget_add_b:  ; s02_ADC2 | |||
|     add b | |||
|     ret | |||
| 
 | |||
| ROPGadget_srl_a:  ; s02_ADC4 | |||
|     srl a | |||
|     ret | |||
| 
 | |||
| ROPGadget_xor_hl:  ; s02_ADC7 | |||
|     xor [hl] | |||
|     ret | |||
| 
 | |||
| ROPGadget_call_z:  ; s02_ADC9 | |||
|     ret z | |||
|     pop hl | |||
|     ret | |||
| 
 | |||
| ROPGadget_variable:  ; s02_ADCC | |||
|     add [hl] | |||
|     ret | |||
| 
 | |||
| SavingTheGame:  ; s02_ADCE | |||
|     ; Cleanup shit because well fuck nobody cares | |||
|     call ClearScreen | |||
|     call UpdateSprites | |||
|     call UninstallVBlankHook  ; Only interesting line in this entire blob of fuzz | |||
|     ld   b,$08 | |||
|     call GetSGBLayout | |||
|     call SetPalettes | |||
|     ld   hl,wMusicFadeID | |||
|     ld   [hl],$00 | |||
|     dec  hl | |||
|     dec  hl | |||
|     ld   [hl],$08 | |||
|     ld   c,$32 | |||
|     call DelayFrames | |||
|     ld   a,$03 | |||
|     ld   [wOptions],a | |||
|     ld   a,$05 | |||
|     rst  $10 | |||
|     ld   hl,Text_SavingDontTurnOffThePower | |||
|     call PrintText | |||
|     ld   de,$B400 | |||
|     ld   hl,$8C00  ; This graphic is probably a picture of a cucumber | |||
|     ld   bc,$0104 | |||
|     call Request1bpp | |||
|     call DelayFrame | |||
| 
 | |||
|     ; Now THAT's more like it | |||
|     ld   de,ROPScript_SaveMain | |||
|     di    | |||
|     call DoubleSpeed | |||
|     call UpdateSaveSpinner | |||
|     ld   sp,SaveROPMain | |||
|     ret   | |||
| 
 | |||
| ROP_SaveMain:  ; s02_AE18 | |||
|     ld a, [de] | |||
|     inc de | |||
|     add a | |||
| 
 | |||
|     ld bc, 0 | |||
|     ld c, a | |||
|     ld hl, .jmptable | |||
|     add hl, bc | |||
|     ldw hl, [hl] | |||
| .jmptable  ; s02_AE2C | |||
|     jp hl | |||
|     dw ROP_SetAddr  ; $01 | |||
|     dw ROP_InitChecksum  ; $02 | |||
|     dw ROP_FetchByte  ; $03 | |||
|     dw ROP_end  ; $04 | |||
|     dw ROP_ApplyCrypto  ; $05 | |||
|     dw ROP_RotateBuffer  ; $06 | |||
|     dw ROP_InitCrypto  ; $07 | |||
|     dw ROP_AddChecksum  ; $08 | |||
|     dw ROP_XorChecksum  ; $09 | |||
|     dw $0000  ; $0A | |||
|     dw ROP_WriteChecksumByte  ; $0B | |||
|     dw ROP_rept  ; $0C | |||
|     dw ROP_StoreByte  ; $0D | |||
|     dw ROP_LoadByte  ; $0E | |||
| 
 | |||
| ROP_end:  ; s02_AE4A | |||
|     ld bc, $0100 | |||
|     ld de, $CB00 | |||
|     ld hl, $AE58 | |||
|     ld af, $FF00 | |||
|     call CopyBytes | |||
|     ; Here's the destination of the copied code, | |||
|     ;   it does some shit to copy the buffer back to the SRAM. | |||
|     ; I don't really care what it does. | |||
| 
 | |||
| UpdateSaveSpinner:  ; s02_AEDB | |||
|     ld   hl,s02_9A12 | |||
|     ld   b,$C0 | |||
|     ld   a,[s02_ADB9] | |||
|     inc  a | |||
|     and  a,%11 | |||
|     ld   [s02_ADB9],a | |||
|     add  b | |||
|     ld   b,a | |||
| 
 | |||
|     ; Wait for HBlank | |||
| .loop  ; s02_AEEB | |||
|     ldh  a,[rSTAT] | |||
|     and  a,%11 | |||
|     jr   nz,.loop | |||
| 
 | |||
|     ld   [hl],b | |||
|     ret   | |||
| 
 | |||
| ROP_SetAddr:  ; s02_AEF3 | |||
| ; sSaveSource = param | |||
| 
 | |||
|     ld hl, sSaveSource | |||
|     ld a, [de] | |||
|     ld [hl+], a | |||
|     inc de | |||
|     ld a, [de] | |||
|     ld [hl+], a | |||
|     inc de | |||
|     ld hl, ROP_SaveMain | |||
|     jp hl | |||
| 
 | |||
| ROP_InitChecksum:  ; s02_AF09 | |||
| ; sSaveBlockChecksum = param | |||
| 
 | |||
|     ld hl, sSaveBlockChecksum | |||
|     ld a, [de] | |||
|     inc de | |||
|     ld [hl+], a | |||
|     ld hl, ROP_SaveMain | |||
|     jp hl | |||
| 
 | |||
| ROP_FetchByte:  ; s02_AF19 | |||
| ; w00_C800 = *(sSaveSource++) | |||
| 
 | |||
|     ; Fetch byte from pointer stored at sSaveSource | |||
|     ld hl, sSaveSource | |||
|     ldw hl, [hl] | |||
|     ld a, [hl+] | |||
| 
 | |||
|     ; Save incremented pointer back into sSaveSource | |||
|     ld b, h | |||
|     ld c, l | |||
|     ld hl, sSaveSource | |||
|     ld [hl], c | |||
|     inc hl | |||
|     ld [hl], b | |||
| 
 | |||
|     ; Save byte into w00_C800 | |||
|     ld hl, w00_C800 | |||
|     ld [hl+], a | |||
| 
 | |||
|     ld hl, ROP_SaveMain | |||
|     jp hl | |||
| 
 | |||
| ROP_ApplyCrypto:  ; s02_AF3B | |||
| ; w00_C800 ^= func(s02_ADB1) | |||
| 
 | |||
|     ; s02_ADB2 ^= (s02_ADB1 + 1) ^ s02_ADB4 | |||
|     ld hl, s02_ADB1 | |||
|     inc [hl] | |||
|     ld b, [hl]  ; s02_ADB1 | |||
|     ld a, [hl+] | |||
|     ld a, [hl+] | |||
|     ld a, [hl+] | |||
|     ld a, [hl-]  ; s02_ADB4 | |||
|     xor b | |||
|     ld b, a | |||
|     ld a, [hl-] | |||
|     ld a, [hl-]  ; s02_ADB2 | |||
|     inc hl | |||
|     xor b | |||
|     ld [hl+], a  ; s02_ADB2 | |||
| 
 | |||
|     ; s02_ADB3 += s02_ADB2 | |||
|     ld b, a | |||
|     ld a, [hl-]  ; s02_ADB3 | |||
|     inc hl | |||
|     add b | |||
|     ld [hl+], a  ; s02_ADB3 | |||
| 
 | |||
|     ; s02_ADB4 = s02_ADB2 ^ (s02_ADB4 + (s02_ADB3 / 2)) | |||
|     srl a | |||
|     ld b, a | |||
|     ld a, [hl-]  ; s02_ADB4 | |||
|     add b | |||
|     ld b, a | |||
|     ld a, [hl-] | |||
|     ld a, [hl+]  ; s02_ADB2 | |||
|     xor b | |||
|     inc hl | |||
|     ld [hl+], a  ; s02_ADB4 | |||
| 
 | |||
|     ; w00_C800 ^= s02_ADB4 | |||
|     ld hl, w00_C800 | |||
|     xor [hl] | |||
|     ld [hl+], a | |||
| 
 | |||
|     ld hl, ROP_SaveMain | |||
|     jp hl | |||
| 
 | |||
| ROP_RotateBuffer:  ; s02_AF85 | |||
|     ; s02_ADB8 = ((s02_ADB8 + 1) | $C0) ^ $C0 | |||
|     ; s02_ADB8 = (s02_ADB8 + 1) & 0x3F | |||
|     ld hl, s02_ADB8 | |||
|     ld a, [hl-] | |||
|     inc a | |||
|     ld hl, $07FC | |||
|     or [hl] | |||
|     ld bc, $C000 | |||
|     xor b | |||
|     ld hl, s02_ADB8 | |||
|     ld [hl+], a | |||
| 
 | |||
|     ; Called every 64 times this function is ran | |||
|     and a | |||
|     call z, UpdateSaveSpinner | |||
| 
 | |||
|     ; Save ROPScript pointer | |||
|     ld hl, sROPScriptBackup | |||
|     ld a, e | |||
|     ld [hl+], a | |||
|     ld [hl], d | |||
| 
 | |||
|     ; Rotate the entire buffer, using sBufferCarry as carry | |||
|     ld hl, w00_C800 | |||
|     ld a, [hl+] | |||
|     ld hl, sBufferCarry | |||
|     ld [hl+], a | |||
|     ld bc, $01B0 | |||
|     ld de, w00_C800 | |||
|     ld hl, w00_C800 + 1 | |||
|     ld af, $FF00 | |||
|     call CopyBytes  ; bc bytes from hl to de | |||
|     ld hl, sBufferCarry | |||
|     ld a, [hl+] | |||
|     ld hl, w00_C9AF | |||
|     ld [hl+], a | |||
| 
 | |||
|     ; Restore ROPScript pointer | |||
|     ld hl, sROPScriptBackup | |||
|     ld a, [hl+] | |||
|     ld d, [hl] | |||
|     ld e, a | |||
| 
 | |||
|     ld hl, ROP_SaveMain | |||
|     jp hl | |||
| 
 | |||
| ROP_InitCrypto:  ; s02_AFE3 | |||
| ; s02_ADB1 = param | |||
| 
 | |||
|     ld hl, s02_ADB1 | |||
|     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 | |||
|     inc de | |||
|     ld hl, ROP_SaveMain | |||
|     jp hl | |||
| 
 | |||
| ROP_AddChecksum:  ; s02_B005 | |||
| ; sSaveBlockChecksum += w00_C800 | |||
| 
 | |||
|     ld hl, ROPGadget_variable | |||
|     ld af, $8600  ; add [hl] | |||
|     ld [hl+], a | |||
|     ld hl, ROP_s02_B01B | |||
|     jp hl | |||
| 
 | |||
| ROP_XorChecksum:  ; s02_B013 | |||
| ; sSaveBlockChecksum ^= w00_C800 | |||
| 
 | |||
|     ld hl, ROPGadget_variable | |||
|     ld af, $AE00  ; xor [hl] | |||
|     ld [hl+], a | |||
| 
 | |||
|     ; fallthrough | |||
| 
 | |||
| ROP_s02_B01B:  ; s02_B01B | |||
|     ld hl, sSaveBlockChecksum | |||
|     ld a, [hl+] | |||
|     ld hl, w00_C800 | |||
|     add [hl]/xor [hl]  ; Modified by caller | |||
|     ld hl, sSaveBlockChecksum | |||
|     ld [hl+], a | |||
|     ld hl, ROP_SaveMain | |||
|     jp hl | |||
| 
 | |||
| ROP_WriteChecksumByte:  ; s02_B033 | |||
| ; w00_C800 = sSaveBlockChecksum | |||
| 
 | |||
|     ld hl, sSaveBlockChecksum | |||
|     ld a, [hl+] | |||
|     ld hl, w00_C800 | |||
|     ld [hl+], a | |||
|     ld hl, ROP_SaveMain | |||
|     jp hl | |||
| 
 | |||
| ROP_StoreByte:  ; s02_B045 | |||
| ; *(sSaveSource++) = sSaveBlockChecksum | |||
| 
 | |||
|     ; *sSaveSource = sSaveBlockChecksum | |||
|     ld hl, sSaveBlockChecksum | |||
|     ld b, [hl] | |||
|     ld hl, sSaveSource | |||
|     ldw hl, [hl] | |||
|     ld [hl], b | |||
|     inc hl | |||
| 
 | |||
|     ; sSaveSource = sSaveSource + 1 | |||
|     ld b, h | |||
|     ld c, l | |||
|     ld hl, sSaveSource | |||
|     ld [hl], c | |||
|     inc hl | |||
|     ld [hl], b | |||
| 
 | |||
|     ld hl, ROP_SaveMain | |||
|     jp hl | |||
| 
 | |||
| ROP_LoadByte:  ; s02_B069 | |||
| ; sSaveBlockChecksum = *sSaveSource | |||
| 
 | |||
|     ld hl, sSaveSource | |||
|     ldw hl, [hl] | |||
|     ld a, [hl+] | |||
|     ld hl, sSaveBlockChecksum | |||
|     ld [hl+], a | |||
| 
 | |||
|     ld hl, ROP_SaveMain | |||
|     jp hl | |||
| 
 | |||
| ROP_rept:  ; s02_B07D | |||
| ; do {} while(param[2]--); | |||
| 
 | |||
|     ; Fetch jump pointer to bc | |||
|     ld a, [de] | |||
|     ld c, a | |||
|     inc de | |||
|     ld a, [de] | |||
|     ld b, a | |||
|     inc de | |||
| 
 | |||
|     ; If param == 0, return | |||
|     ld a, [de] | |||
|     inc de | |||
|     ld hl, ROP_SaveMain | |||
|     and a | |||
|     call z, (jp hl) | |||
| 
 | |||
|     ; Decrement parameter, if 0, return | |||
|     dec a | |||
|     dec de | |||
|     ld [de], a | |||
|     inc de | |||
|     ld hl, ROP_SaveMain | |||
|     call z, (jp hl) | |||
| 
 | |||
|     ; Jump to the script at bc | |||
|     ld d, b | |||
|     ld a, c | |||
|     ld e, a | |||
|     ld hl, ROP_SaveMain | |||
|     jp hl | |||
| 
 | |||
| ROPScript_SaveMain:  ; s02_B0B3 | |||
|     ; ========================================================================== | |||
|     ;     Start compiling data into save blob, and applying first crypto layer. | |||
|     ;     Each "section" of the save blob has its own, fixed crypto seed and checksum. | |||
|     ; ========================================================================== | |||
| 
 | |||
|     ; sSaveSource = $FCDF | |||
|     dbw $01, $FCDF  ; ROP_SetAddr | |||
| 
 | |||
|     ; sSaveBlockChecksum = $7F | |||
|     dbb $02, $7F  ; ROP_InitChecksum | |||
| 
 | |||
|     ; s02_ADB1 = $8C10E62F | |||
|     dbl $07, $8C10E62F  ; ROP_InitCrypto | |||
| 
 | |||
| .s02_B0BD | |||
|     ; rept ($48) { | |||
|         ; w00_C800 = *(sSaveSource++) | |||
|         db $03  ; ROP_FetchByte | |||
| 
 | |||
|         ; w00_C800 ^= func(s02_ADB1) | |||
|         db $05  ; ROP_ApplyCrypto | |||
| 
 | |||
|         ; sSaveBlockChecksum += w00_C800 | |||
|         db $08  ; ROP_AddChecksum | |||
| 
 | |||
|         ; rotatebuffer(w00_C800) | |||
|         db $06  ; ROP_RotateBuffer | |||
| 
 | |||
|         ; w00_C800 = *(sSaveSource++) | |||
|         db $03  ; ROP_FetchByte | |||
| 
 | |||
|         ; sSaveBlockChecksum ^= w00_C800 | |||
|         db $09  ; ROP_XorChecksum | |||
| 
 | |||
|         ; w00_C800 ^= func(s02_ADB1) | |||
|         db $05  ; ROP_ApplyCrypto | |||
| 
 | |||
|         ; rotatebuffer(w00_C800) | |||
|         db $06  ; ROP_RotateBuffer | |||
|     ; } | |||
|     dbwb $0C, .s02_B0BD, $48  ; ROP_rept | |||
| 
 | |||
|     ; w00_C800 = sSaveBlockChecksum | |||
|     db $0B  ; ROP_WriteChecksumByte | |||
| 
 | |||
|     ; rotatebuffer(w00_C800) | |||
|     db $06  ; ROP_RotateBuffer | |||
| 
 | |||
|     ; sSaveSource = $FA7A | |||
|     dbw $01, $FA7A  ; ROP_SetAddr | |||
| 
 | |||
|     ; sSaveBlockChecksum = $C2 | |||
|     dbb $02, $C2  ; ROP_InitChecksum | |||
| 
 | |||
|     ; s02_ADB1 = $6AF528C2 | |||
|     dbl $07, $6AF528C2  ; ROP_InitCrypto | |||
| 
 | |||
| .s02_B0D5 | |||
|     ; rept ($14) { | |||
|         ; w00_C800 = *(sSaveSource++) | |||
|         db $03  ; ROP_FetchByte | |||
| 
 | |||
|         ; w00_C800 ^= func(s02_ADB1) | |||
|         db $05  ; ROP_ApplyCrypto | |||
| 
 | |||
|         ; sSaveBlockChecksum ^= w00_C800 | |||
|         db $09  ; ROP_XorChecksum | |||
| 
 | |||
|         ; rotatebuffer(w00_C800) | |||
|         db $06  ; ROP_RotateBuffer | |||
|     ; } | |||
|     dbwb $0C, .s02_B0D5, $14  ; ROP_rept | |||
| 
 | |||
|     ; w00_C800 = sSaveBlockChecksum | |||
|     db $0B  ; ROP_WriteChecksumByte | |||
| 
 | |||
|     ; rotatebuffer(w00_C800) | |||
|     db $06  ; ROP_RotateBuffer | |||
| 
 | |||
|     ; sSaveSource = $F84E | |||
|     dbw $01, $F84E  ; ROP_SetAddr | |||
| 
 | |||
| .s02_B0E2 | |||
|     ; rept ($03) { | |||
|         ; w00_C800 = *(sSaveSource++) | |||
|         db $03  ; ROP_FetchByte | |||
| 
 | |||
|         ; rotatebuffer(w00_C800) | |||
|         db $06  ; ROP_RotateBuffer | |||
|     ; } | |||
|     dbwb $0C, .s02_B0E2, $03  ; ROP_rept | |||
| 
 | |||
|     ; sSaveSource = $F859 | |||
|     dbw $01, $F859  ; ROP_SetAddr | |||
| 
 | |||
|     ; sSaveBlockChecksum = $06 | |||
|     dbb $02, $06  ; ROP_InitChecksum | |||
| 
 | |||
|     ; s02_ADB1 = $EF7305A6 | |||
|     dbl $07, $EF7305A6  ; ROP_InitCrypto | |||
| 
 | |||
| .s02_B0F2 | |||
|     ; rept ($4C) { | |||
|         ; w00_C800 = *(sSaveSource++) | |||
|         db $03  ; ROP_FetchByte | |||
| 
 | |||
|         ; w00_C800 ^= func(s02_ADB1) | |||
|         db $05  ; ROP_ApplyCrypto | |||
| 
 | |||
|         ; sSaveBlockChecksum ^= w00_C800 | |||
|         db $09  ; ROP_XorChecksum | |||
| 
 | |||
|         ; rotatebuffer(w00_C800) | |||
|         db $06  ; ROP_RotateBuffer | |||
| 
 | |||
|         ; w00_C800 = *(sSaveSource++) | |||
|         db $03  ; ROP_FetchByte | |||
| 
 | |||
|         ; w00_C800 ^= func(s02_ADB1) | |||
|         db $05  ; ROP_ApplyCrypto | |||
| 
 | |||
|         ; sSaveBlockChecksum += w00_C800 | |||
|         db $08  ; ROP_AddChecksum | |||
| 
 | |||
|         ; rotatebuffer(w00_C800) | |||
|         db $06  ; ROP_RotateBuffer | |||
|     ; } | |||
|     dbwb $0C, .s02_B0F2, $4C  ; ROP_rept | |||
| 
 | |||
|     ; w00_C800 = sSaveBlockChecksum | |||
|     db $0B  ; ROP_WriteChecksumByte | |||
| 
 | |||
|     ; rotatebuffer(w00_C800) | |||
|     db $06  ; ROP_RotateBuffer | |||
| 
 | |||
|     ; sSaveSource = $DE41 | |||
|     dbw $01, $DE41  ; ROP_SetAddr | |||
| 
 | |||
|     ; s02_ADB1 = $2A7FEC38 | |||
|     dbl $07, $2A7FEC38  ; ROP_InitCrypto | |||
| 
 | |||
|     ; sSaveBlockChecksum = $3C | |||
|     dbb $02, $3C  ; ROP_InitChecksum | |||
| 
 | |||
| .s02_B10A | |||
|     ; rept ($21) { | |||
|         ; w00_C800 = *(sSaveSource++) | |||
|         db $03  ; ROP_FetchByte | |||
| 
 | |||
|         ; sSaveBlockChecksum += w00_C800 | |||
|         db $08  ; ROP_AddChecksum | |||
| 
 | |||
|         ; w00_C800 ^= func(s02_ADB1) | |||
|         db $05  ; ROP_ApplyCrypto | |||
| 
 | |||
|         ; rotatebuffer(w00_C800) | |||
|         db $06  ; ROP_RotateBuffer | |||
|     ; } | |||
|     dbwb $0C, .s02_B10A, $21  ; ROP_rept | |||
| 
 | |||
|     ; w00_C800 = sSaveBlockChecksum | |||
|     db $0B  ; ROP_WriteChecksumByte | |||
| 
 | |||
|     ; rotatebuffer(w00_C800) | |||
|     db $06  ; ROP_RotateBuffer | |||
| 
 | |||
|     ; sSaveSource = $DE99 | |||
|     dbw $01, $DE99  ; ROP_SetAddr | |||
| 
 | |||
|     ; sSaveBlockChecksum = $E2 | |||
|     dbb $02, $E2  ; ROP_InitChecksum | |||
| 
 | |||
|     ; s02_ADB1 = $4BFC1115 | |||
|     dbl $07, $4BFC1115  ; ROP_InitCrypto | |||
| 
 | |||
| .s02_B11E | |||
|     ; rept ($40) { | |||
|         ; w00_C800 = *(sSaveSource++) | |||
|         db $03  ; ROP_FetchByte | |||
| 
 | |||
|         ; w00_C800 ^= func(s02_ADB1) | |||
|         db $05  ; ROP_ApplyCrypto | |||
| 
 | |||
|         ; sSaveBlockChecksum += w00_C800 | |||
|         db $08  ; ROP_AddChecksum | |||
| 
 | |||
|         ; rotatebuffer(w00_C800) | |||
|         db $06  ; ROP_RotateBuffer | |||
|     ; } | |||
|     dbwb $0C, .s02_B11E, $40  ; ROP_rept | |||
| 
 | |||
|     ; w00_C800 = sSaveBlockChecksum | |||
|     db $0B  ; ROP_WriteChecksumByte | |||
| 
 | |||
|     ; rotatebuffer(w00_C800) | |||
|     db $06  ; ROP_RotateBuffer | |||
| 
 | |||
|     ; s02_ADB1 = $A23F387C | |||
|     dbl $07, $A23F387C  ; ROP_InitCrypto | |||
| 
 | |||
|     ; sSaveBlockChecksum = $16 | |||
|     dbb $02, $16  ; ROP_InitChecksum | |||
| 
 | |||
|     ; sSaveSource = $A003 | |||
|     dbw $01, $A003  ; ROP_SetAddr | |||
| 
 | |||
| .s02_B132 | |||
|     ; rept ($04) { | |||
|         ; w00_C800 = *(sSaveSource++) | |||
|         db $03  ; ROP_FetchByte | |||
| 
 | |||
|         ; w00_C800 ^= func(s02_ADB1) | |||
|         db $05  ; ROP_ApplyCrypto | |||
| 
 | |||
|         ; sSaveBlockChecksum ^= w00_C800 | |||
|         db $09  ; ROP_XorChecksum | |||
| 
 | |||
|         ; sSaveBlockChecksum += w00_C800 | |||
|         db $08  ; ROP_AddChecksum | |||
| 
 | |||
|         ; rotatebuffer(w00_C800) | |||
|         db $06  ; ROP_RotateBuffer | |||
|     ; } | |||
|     dbwb $0C, .s02_B132, $04  ; ROP_rept | |||
| 
 | |||
|     ; w00_C800 = sSaveBlockChecksum | |||
|     db $0B  ; ROP_WriteChecksumByte | |||
| 
 | |||
|     ; rotatebuffer(w00_C800) | |||
|     db $06  ; ROP_RotateBuffer | |||
| 
 | |||
|     ; ========================================================================== | |||
|     ;     End compiling data into save blob. | |||
|     ; ========================================================================== | |||
| 
 | |||
| 
 | |||
|     ; ========================================================================== | |||
|     ;     Apply second layer of crypto onto the save file as a whole. | |||
|     ;     The seed for this crypto is based on random bytes, | |||
|     ;       which are stored in the final blob as well. | |||
|     ; ========================================================================== | |||
| 
 | |||
|     ; sSaveBlockChecksum = $00 | |||
|     dbb $02, $00  ; ROP_InitChecksum | |||
| 
 | |||
|     ; sSaveSource = $FFE1 | |||
|     dbw $01, $FFE1  ; ROP_SetAddr | |||
| 
 | |||
|     ; w00_C800 = *(sSaveSource++) | |||
|     db $03  ; ROP_FetchByte | |||
| 
 | |||
|     ; sSaveBlockChecksum += w00_C800 | |||
|     db $08  ; ROP_AddChecksum | |||
| 
 | |||
|     ; sSaveSource = $B16B | |||
|     dbw $01, $B16B  ; ROP_SetAddr | |||
| 
 | |||
|     ; *(sSaveSource++) = sSaveBlockChecksum | |||
|     db $0D  ; ROP_StoreByte | |||
| 
 | |||
|     ; rotatebuffer(w00_C800) | |||
|     db $06  ; ROP_RotateBuffer | |||
| 
 | |||
|     ; sSaveSource = $FFE2 | |||
|     dbw $01, $FFE2  ; ROP_SetAddr | |||
| 
 | |||
|     ; w00_C800 = *(sSaveSource++) | |||
|     db $03  ; ROP_FetchByte | |||
| 
 | |||
|     ; sSaveBlockChecksum ^= w00_C800 | |||
|     db $09  ; ROP_XorChecksum | |||
| 
 | |||
|     ; w00_C800 = sSaveBlockChecksum | |||
|     db $0B  ; ROP_WriteChecksumByte | |||
| 
 | |||
|     ; sSaveSource = $B16C | |||
|     dbw $01, $B16C  ; ROP_SetAddr | |||
| 
 | |||
|     ; *(sSaveSource++) = sSaveBlockChecksum | |||
|     db $0D  ; ROP_StoreByte | |||
| 
 | |||
|     ; rotatebuffer(w00_C800) | |||
|     db $06  ; ROP_RotateBuffer | |||
| 
 | |||
|     ; sSaveSource = $FF04 | |||
|     dbw $01, $FF04  ; ROP_SetAddr | |||
| 
 | |||
|     ; w00_C800 = *(sSaveSource++) | |||
|     db $03  ; ROP_FetchByte | |||
| 
 | |||
|     ; sSaveBlockChecksum += w00_C800 | |||
|     db $08  ; ROP_AddChecksum | |||
| 
 | |||
|     ; w00_C800 = sSaveBlockChecksum | |||
|     db $0B  ; ROP_WriteChecksumByte | |||
| 
 | |||
|     ; sSaveSource = $B16D | |||
|     dbw $01, $B16D  ; ROP_SetAddr | |||
| 
 | |||
|     ; *(sSaveSource++) = sSaveBlockChecksum | |||
|     db $0D  ; ROP_StoreByte | |||
| 
 | |||
|     ; rotatebuffer(w00_C800) | |||
|     db $06  ; ROP_RotateBuffer | |||
| 
 | |||
|     ; sSaveSource = $FF05 | |||
|     dbw $01, $FF05  ; ROP_SetAddr | |||
| 
 | |||
|     ; w00_C800 = *(sSaveSource++) | |||
|     db $03  ; ROP_FetchByte | |||
| 
 | |||
|     ; sSaveBlockChecksum ^= w00_C800 | |||
|     db $09  ; ROP_XorChecksum | |||
| 
 | |||
|     ; w00_C800 = sSaveBlockChecksum | |||
|     db $0B  ; ROP_WriteChecksumByte | |||
| 
 | |||
|     ; sSaveSource = $B16E | |||
|     dbw $01, $B16E  ; ROP_SetAddr | |||
| 
 | |||
|     ; *(sSaveSource++) = sSaveBlockChecksum | |||
|     db $0D  ; ROP_StoreByte | |||
| 
 | |||
|     ; rotatebuffer(w00_C800) | |||
|     db $06  ; ROP_RotateBuffer | |||
| 
 | |||
|     ; NOTE: The parameter of this command is modified by the commands above. | |||
|     ; s02_ADB1 = $EFBEADDE | |||
|     dbl $07, $EFBEADDE  ; ROP_InitCrypto | |||
| 
 | |||
|     ; rotatebuffer(w00_C800) | |||
|     db $06  ; ROP_RotateBuffer | |||
| 
 | |||
|     ; rotatebuffer(w00_C800) | |||
|     db $06  ; ROP_RotateBuffer | |||
| 
 | |||
|     ; sSaveBlockChecksum = $55 | |||
|     dbb $02, $55  ; ROP_InitChecksum | |||
| 
 | |||
|     ; sSaveSource = $F350 | |||
|     dbw $01, $F350  ; ROP_SetAddr | |||
| 
 | |||
|     ; *(sSaveSource++) = sSaveBlockChecksum | |||
|     db $0D  ; ROP_StoreByte | |||
| 
 | |||
|     ; *(sSaveSource++) = sSaveBlockChecksum | |||
|     db $0D  ; ROP_StoreByte | |||
| 
 | |||
| .s02_B178 | |||
|     ; rept ($1AB) { | |||
|         ; sSaveSource = $F350 | |||
|         dbw $01, $F350  ; ROP_SetAddr | |||
| 
 | |||
|         ; sSaveBlockChecksum = *sSaveSource | |||
|         db $0E  ; ROP_LoadByte | |||
| 
 | |||
|         ; sSaveBlockChecksum += w00_C800 | |||
|         db $08  ; ROP_AddChecksum | |||
| 
 | |||
|         ; *(sSaveSource++) = sSaveBlockChecksum | |||
|         db $0D  ; ROP_StoreByte | |||
| 
 | |||
|         ; sSaveBlockChecksum = *sSaveSource | |||
|         db $0E  ; ROP_LoadByte | |||
| 
 | |||
|         ; sSaveBlockChecksum ^= w00_C800 | |||
|         db $09  ; ROP_XorChecksum | |||
| 
 | |||
|         ; *(sSaveSource++) = sSaveBlockChecksum | |||
|         db $0D  ; ROP_StoreByte | |||
| 
 | |||
|         ; w00_C800 ^= func(s02_ADB1) | |||
|         db $05  ; ROP_ApplyCrypto | |||
| 
 | |||
|         ; rotatebuffer(w00_C800) | |||
|         db $06  ; ROP_RotateBuffer | |||
|     ; } | |||
|     dbwb $0C, .s02_B178, $D5  ; ROP_rept | |||
|     dbwb $0C, .s02_B178, $D6  ; ROP_rept | |||
| 
 | |||
|     ; sSaveBlockChecksum = $CC | |||
|     dbb $02, $CC  ; ROP_InitChecksum | |||
| 
 | |||
|     ; sSaveSource = $ADB1 | |||
|     dbw $01, $ADB1  ; ROP_SetAddr | |||
| 
 | |||
|     ; sSaveBlockChecksum ^= w00_C800 | |||
|     db $09  ; ROP_XorChecksum | |||
| 
 | |||
|     ; *(sSaveSource++) = sSaveBlockChecksum | |||
|     db $0D  ; ROP_StoreByte | |||
| 
 | |||
|     ; rotatebuffer(w00_C800) | |||
|     db $06  ; ROP_RotateBuffer | |||
| 
 | |||
|     ; sSaveBlockChecksum ^= w00_C800 | |||
|     db $09  ; ROP_XorChecksum | |||
| 
 | |||
|     ; *(sSaveSource++) = sSaveBlockChecksum | |||
|     db $0D  ; ROP_StoreByte | |||
| 
 | |||
|     ; rotatebuffer(w00_C800) | |||
|     db $06  ; ROP_RotateBuffer | |||
| 
 | |||
|     ; sSaveBlockChecksum ^= w00_C800 | |||
|     db $09  ; ROP_XorChecksum | |||
| 
 | |||
|     ; *(sSaveSource++) = sSaveBlockChecksum | |||
|     db $0D  ; ROP_StoreByte | |||
| 
 | |||
|     ; rotatebuffer(w00_C800) | |||
|     db $06  ; ROP_RotateBuffer | |||
| 
 | |||
|     ; sSaveBlockChecksum ^= w00_C800 | |||
|     db $09  ; ROP_XorChecksum | |||
| 
 | |||
|     ; *(sSaveSource++) = sSaveBlockChecksum | |||
|     db $0D  ; ROP_StoreByte | |||
| 
 | |||
|     ; rotatebuffer(w00_C800) | |||
|     db $06  ; ROP_RotateBuffer | |||
| 
 | |||
|     ; sSaveSource = $F350 | |||
|     dbw $01, $F350  ; ROP_SetAddr | |||
| 
 | |||
|     ; w00_C800 = *(sSaveSource++) | |||
|     db $03  ; ROP_FetchByte | |||
| 
 | |||
|     ; w00_C800 ^= func(s02_ADB1) | |||
|     db $05  ; ROP_ApplyCrypto | |||
| 
 | |||
|     ; rotatebuffer(w00_C800) | |||
|     db $06  ; ROP_RotateBuffer | |||
| 
 | |||
|     ; w00_C800 = *(sSaveSource++) | |||
|     db $03  ; ROP_FetchByte | |||
| 
 | |||
|     ; w00_C800 ^= func(s02_ADB1) | |||
|     db $05  ; ROP_ApplyCrypto | |||
| 
 | |||
|     ; rotatebuffer(w00_C800) | |||
|     db $06  ; ROP_RotateBuffer | |||
| 
 | |||
| 
 | |||
|     ; Copy save blob from the buffer to final location in SRAM, and end. | |||
|     db $04  ; ROP_end | |||
| 
 | |||
| 
 | |||
| ; Temporary save location for the DelayFrame return pointer | |||
| sVBlankReturnPointer: dw  ; s02_B4E6 | |||
| 
 | |||
| VBlankHook_Save:  ; s02_B673 | |||
| ; Saving hook code | |||
| 
 | |||
|     ; Check if the "P" tile is on the screen (part of "PLAYER") | |||
|     ld   a,[$C4CD]  ; wTileMap + ??? | |||
|     cp   a,"P"  ; $8F | |||
|     ret  nz | |||
| 
 | |||
|     ; Check that we're trying to make a textbox for saving the game | |||
|     ld   hl,[sp+$12] | |||
|     ldi  a,[hl] | |||
|     cp   a,LOW(Text_WouldYouLikeToSaveTheGame) | |||
|     ret  nz | |||
|     ldd  a,[hl] | |||
|     cp   a,HIGH(Text_WouldYouLikeToSaveTheGame) | |||
|     ret  nz | |||
| 
 | |||
|     ; Change that text pointer to an empty text box (only include the TX_END command) | |||
|     ld   [hl],LOW($0134) | |||
|     inc  hl | |||
|     ld   [hl],HIGH($0134) | |||
| 
 | |||
|     ; Change the MapTextbox return address to skip to the end of SaveTheGame_yesorno | |||
|     ld   hl,sp+$16 | |||
|     ld   [hl],LOW(SaveTheGame_yesorno + 27)  ; $4BCA | |||
| 
 | |||
|     ; Change the SaveTheGame_yesorno return address to skip to SaveMenu.refused | |||
|     inc  hl | |||
|     inc  hl | |||
|     ld   [hl],LOW(SaveMenu.refused) | |||
|     inc  hl | |||
|     ld   [hl],HIGH(SaveMenu.refused) | |||
| 
 | |||
|     ; Overwrite return pointer for the vblank hook | |||
|     ld   hl,SaveGame | |||
|     ld   a,l | |||
|     ld   [sVBlankReturnPointer],a | |||
|     ld   a,h | |||
|     ld   [sVBlankReturnPointer + 1],a | |||
|     ld   a,BANK(SaveGame) | |||
|     ld   [wVBlankReturnBank],a  ; Overwrite return bank? | |||
|     ret   | |||
| 
 | |||
| UninstallVBlankHook:  ; s02_B711 | |||
|     ld hl, hTransferVirtualOAM | |||
|     ld [hl], $3E  ; ld a, n8 | |||
|     inc hl | |||
|     ld [hl], $C4 | |||
|     ret | |||
| 
 | |||
| w00_C800: ds $1b0  ; w00_C800 | |||
| w00_C9AF:  ; w00_C9AF | |||
| 
 | |||
| wOptions: db  ; w01_CFCC | |||
| wPartyCount: db  ; w01_DCD7 | |||
| 
 | |||
| w01_DF34: db | |||
| wVBlankReturnBank: db  ; w01_DF35 | |||
| wSavingAllowed: db  ; w01_DF3A | |||
								
									Binary file not shown.
								
							
						
					| @ -0,0 +1,30 @@ | |||
| 
 | |||
| ; Break for: | |||
| ; BC=1A5 | |||
| ; BC=1A6 | |||
| ; BC=1A7 | |||
| ; BC=1A8 | |||
| 
 | |||
| ; Hook this at 02:AF1F | |||
| ; Unhook when 02:B13D is read (original: ADBA) | |||
|     ld a, [$AD42] | |||
|     ld c, a | |||
|     ld a, [$AD43] | |||
|     ld b, a | |||
|     nop | |||
|     ld a, c | |||
|     ret | |||
| 
 | |||
| ; Hook this at the end of 02:AFDD | |||
|     ld a, [$AD42] | |||
|     ld c, a | |||
|     ld a, [$AD43] | |||
|     ld b, a | |||
|     inc bc | |||
|     ld a, c | |||
|     ld [$AD42], a | |||
|     ld a, b | |||
|     ld [$AD43], a | |||
| 
 | |||
|     ld sp, $AE18 | |||
|     ret | |||
								
									Binary file not shown.
								
							
						
					| @ -0,0 +1,41 @@ | |||
| $0394 - and a | |||
| $0831 - ld hl, n16 | |||
| $08F1 - ld bc, n16 | |||
| $0933 - xor b | |||
| $09A2 - ld bc, de, hl, af, n16 | |||
| $09A4 - ld hl, af, n16 | |||
| $0D8E - ld c, a | |||
| $106A - inc de | |||
| $106A - inc de | |||
| $1380 - dec de | |||
| $1447 - inc hl | |||
| $1489 - ld b, a | |||
| $1708 - jp hl | |||
| $1898 - ld a, [de] | |||
| $18D0 - ld a, e | |||
| $18DC - ld c, l | |||
| $1C85 - ldw hl, [hl] | |||
| $1D17 - add hl, bc | |||
| $1FA5 - ld e, a | |||
| $1FEE - ld [hl], b | |||
| $2250 - ld [hl+], a | |||
| $2CAD - ld a, c | |||
| $2DE0 - or [hl] | |||
| $2EC9 - dec a | |||
| $3351 - ld [hl], d | |||
| $37C2 - inc a | |||
| $3E3D - add a | |||
| $4128 - ld [de], a | |||
| $4404 - ld b, h | |||
| $4D6A - ld d, b | |||
| $50EC - ld d, [hl] | |||
| $65E1 - inc [hl] | |||
| $ADBA - ld a, [hl+] | |||
| $ADBC - ld a, [hl-] | |||
| $ADBE - ld [hl], c | |||
| $ADC0 - ld b, [hl] | |||
| $ADC2 - add b | |||
| $ADC4 - srl a | |||
| $ADC7 - xor [hl] | |||
| $ADC9 - call z, n16 | |||
| $ADCC - add [hl]/xor [hl] | |||
| @ -0,0 +1,196 @@ | |||
| #include <stdio.h> | |||
| 
 | |||
| // 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++;
 | |||
| } | |||
| @ -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 | |||
					Loading…
					
					
				
		Reference in new issue