432 lines
		
	
	
		
			20 KiB
		
	
	
	
		
			Python
		
	
	
	
	
	
		
		
			
		
	
	
			432 lines
		
	
	
		
			20 KiB
		
	
	
	
		
			Python
		
	
	
	
	
	
|   | remote_textbox_shower = [ | ||
|  |     # Pops up the textbox(s) of whatever textbox IDs is written at 0x02025300 and 0x02025302 and increments the current | ||
|  |     # received item index at 0x020253D0 if a number to increment it by is written at 0x02025304. Also plays the sound | ||
|  |     # effect of the ID written at 0x02025306, if one is written there. This will NOT give any items on its own; the item | ||
|  |     # has to be written by the client into the inventory alongside writing the above-mentioned things. | ||
|  | 
 | ||
|  |     # Make sure we didn't hit the lucky one frame before room transitioning wherein Nathan is on top of the room | ||
|  |     # transition tile. | ||
|  |     0x0C, 0x88,  # ldrh r4, [r1] | ||
|  |     0x80, 0x20,  # movs r0, #0x80 | ||
|  |     0x20, 0x40,  # ands r0, r4 | ||
|  |     0x00, 0x28,  # cmp  r0, #0 | ||
|  |     0x2F, 0xD1,  # bne  0x87FFF8A | ||
|  |     0x11, 0xB4,  # push r0, r4 | ||
|  |     # Check the cutscene value to make sure we are not in a cutscene; forcing a textbox while there's already another | ||
|  |     # textbox on-screen messes things up. | ||
|  |     0x1E, 0x4A,  # ldr  r2, =0x2026000 | ||
|  |     0x13, 0x78,  # ldrb r3, [r2] | ||
|  |     0x00, 0x2B,  # cmp  r0, #0 | ||
|  |     0x29, 0xD1,  # bne  0x87FFF88 | ||
|  |     # Check our "delay" timer buffer for a non-zero. If it is, decrement it by one and skip straight to the return part | ||
|  |     # of this code, as we may have received an item on a frame wherein it's "unsafe" to pop the item textbox. | ||
|  |     0x16, 0x4A,  # ldr  r2, =0x2025300 | ||
|  |     0x13, 0x89,  # ldrh r3, [r2, #8] | ||
|  |     0x00, 0x2B,  # cmp  r0, #0 | ||
|  |     0x02, 0xD0,  # beq  0x87FFF42 | ||
|  |     0x01, 0x3B,  # subs r3, #1 | ||
|  |     0x13, 0x81,  # strh r3, [r2, #8] | ||
|  |     0x22, 0xE0,  # beq  0x87FFF88 | ||
|  |     # Check our first custom "textbox ID" buffers for a non-zero number. | ||
|  |     0x10, 0x88,  # ldrh r0, [r2] | ||
|  |     0x00, 0x28,  # cmp  r0, #0 | ||
|  |     0x12, 0xD0,  # beq  0x87FFF6E | ||
|  |     # Increase the "received item index" by the specified number in our "item index amount to increase" buffer. | ||
|  |     0x93, 0x88,  # ldrh r3, [r2, #4] | ||
|  |     0xD0, 0x32,  # adds r2, #0xD0 | ||
|  |     0x11, 0x88,  # ldrh r1, [r2] | ||
|  |     0xC9, 0x18,  # adds r1, r1, r3 | ||
|  |     0x11, 0x80,  # strh r1, [r2] | ||
|  |     # Check our second custom "textbox ID" buffers for a non-zero number. | ||
|  |     0xD0, 0x3A,  # subs r2, #0xD0 | ||
|  |     0x51, 0x88,  # ldrh r1, [r2, #2] | ||
|  |     0x00, 0x29,  # cmp  r1, #0 | ||
|  |     0x01, 0xD0,  # beq  0x87FFF5E | ||
|  |     # If we have a second textbox ID, run the "display two textboxes" function. | ||
|  |     # Otherwise, run the "display one textbox" function. | ||
|  |     0x0E, 0x4A,  # ldr  r2, =0x805F104 | ||
|  |     0x00, 0xE0,  # b    0x87FFF60 | ||
|  |     0x0E, 0x4A,  # ldr  r2, =0x805F0C8 | ||
|  |     0x7B, 0x46,  # mov  r3, r15 | ||
|  |     0x05, 0x33,  # adds r3, #5 | ||
|  |     0x9E, 0x46,  # mov  r14, r3 | ||
|  |     0x97, 0x46,  # mov  r15, r2 | ||
|  |     0x09, 0x48,  # ldr  r0, =0x2025300 | ||
|  |     0x02, 0x21,  # movs r1, #2 | ||
|  |     0x01, 0x81,  # strh r1, [r0, #8] | ||
|  |     # Check our "sound effect ID" buffer and run the "play sound" function if it's a non-zero number. | ||
|  |     0x08, 0x48,  # ldr  r0, =0x2025300 | ||
|  |     0xC0, 0x88,  # ldrh r0, [r0, #6] | ||
|  |     0x00, 0x28,  # cmp  r0, #0 | ||
|  |     0x04, 0xD0,  # beq  0x87FFF7E | ||
|  |     0x0B, 0x4A,  # ldr  r2, =0x8005E80 | ||
|  |     0x7B, 0x46,  # mov  r3, r15 | ||
|  |     0x05, 0x33,  # adds r3, #5 | ||
|  |     0x9E, 0x46,  # mov  r14, r3 | ||
|  |     0x97, 0x46,  # mov  r15, r2 | ||
|  |     # Clear all our buffers and return to the "check for Nathan being in a room transition" function we've hooked into. | ||
|  |     0x03, 0x48,  # ldr  r0, =0x2025300 | ||
|  |     0x00, 0x21,  # movs r1, #0 | ||
|  |     0x01, 0x60,  # str  r1, [r0] | ||
|  |     0x41, 0x60,  # str  r1, [r0, #4] | ||
|  |     0x11, 0xBC,  # pop  r0, r4 | ||
|  |     0x04, 0x4A,  # ldr  r2, =0x8007D68 | ||
|  |     0x00, 0x28,  # cmp  r0, #0 | ||
|  |     0x97, 0x46,  # mov  r15, r2 | ||
|  |     # LDR number pool | ||
|  |     0x00, 0x53, 0x02, 0x02, | ||
|  |     0x04, 0xF1, 0x05, 0x08, | ||
|  |     0xC8, 0xF0, 0x05, 0x08, | ||
|  |     0x68, 0x7D, 0x00, 0x08, | ||
|  |     0x90, 0x1E, 0x02, 0x02, | ||
|  |     0x80, 0x5E, 0x00, 0x08, | ||
|  |     0x00, 0x60, 0x02, 0x02 | ||
|  | ] | ||
|  | 
 | ||
|  | transition_textbox_delayer = [ | ||
|  |     # Sets the remote item textbox delay timer whenever the player screen transitions to ensure the item textbox won't | ||
|  |     # pop during said transition. | ||
|  |     0x40, 0x78,  # ldrb r0, [r0, #1] | ||
|  |     0x28, 0x70,  # strb r0, [r5] | ||
|  |     0xF8, 0x6D,  # ldr  r0, [r7, #0x5C] | ||
|  |     0x20, 0x18,  # adds r0, r4, r0 | ||
|  |     0x02, 0x4A,  # ldr  r2, =0x2025300 | ||
|  |     0x10, 0x23,  # movs r3, #0x10 | ||
|  |     0x13, 0x80,  # strh r3, [r2] | ||
|  |     0x02, 0x4A,  # ldr  r2, =0x806CE1C | ||
|  |     0x97, 0x46,  # mov  r15, r2 | ||
|  |     0x00, 0x00, | ||
|  |     # LDR number pool | ||
|  |     0x08, 0x53, 0x02, 0x02, | ||
|  |     0x1C, 0xCE, 0x06, 0x08, | ||
|  | ] | ||
|  | 
 | ||
|  | magic_item_sfx_customizer = [ | ||
|  |     # Enables a different sound to be played depending on which Magic Item was picked up. The array starting at 086797C0 | ||
|  |     # contains each 2-byte sound ID for each Magic Item. Putting 0000 for a sound will cause no sound to play; this is | ||
|  |     # currently used for the dummy AP Items as their sound is played by the "sent" textbox instead. | ||
|  |     0x70, 0x68,  # ldr  r0, [r6, #4] | ||
|  |     0x80, 0x79,  # ldrb r0, [r0, #6] | ||
|  |     0x40, 0x00,  # lsl  r0, r0, 1 | ||
|  |     0x07, 0x49,  # ldr  r1, =0x86797C0 | ||
|  |     0x08, 0x5A,  # ldrh r0, [r1, r0] | ||
|  |     0x00, 0x28,  # cmp  r0, 0 | ||
|  |     0x04, 0xD0,  # beq  0x8679818 | ||
|  |     0x03, 0x4A,  # ldr  r2, =0x8005E80 | ||
|  |     0x7B, 0x46,  # mov  r3, r15 | ||
|  |     0x05, 0x33,  # adds r3, #5 | ||
|  |     0x9E, 0x46,  # mov  r14, r3 | ||
|  |     0x97, 0x46,  # mov  r15, r2 | ||
|  |     0x01, 0x48,  # ldr  r0, =0x8095BEC | ||
|  |     0x87, 0x46,  # mov  r15, r0 | ||
|  |     # LDR number pool | ||
|  |     0x80, 0x5E, 0x00, 0x08, | ||
|  |     0xEC, 0x5B, 0x09, 0x08, | ||
|  |     0xC0, 0x97, 0x67, 0x08, | ||
|  | ] | ||
|  | 
 | ||
|  | start_inventory_giver = [ | ||
|  |     # This replaces AutoDashBoots.ips from standalone CotMR by allowing the player to start with any set of items, not | ||
|  |     # just the Dash Boots. If playing Magician Mode, they will be given all cards that were not put into the starting | ||
|  |     # inventory right after this code runs. | ||
|  | 
 | ||
|  |     # Magic Items | ||
|  |     0x13, 0x48,  # ldr  r0, =0x202572F | ||
|  |     0x14, 0x49,  # ldr  r1, =0x8680080 | ||
|  |     0x00, 0x22,  # mov  r2, #0 | ||
|  |     0x8B, 0x5C,  # ldrb r3, [r1, r2] | ||
|  |     0x83, 0x54,  # strb r3, [r0, r2] | ||
|  |     0x01, 0x32,  # adds r2, #1 | ||
|  |     0x08, 0x2A,  # cmp  r2, #8 | ||
|  |     0xFA, 0xDB,  # blt  0x8680006 | ||
|  |     # Max Ups | ||
|  |     0x11, 0x48,  # ldr  r0, =0x202572C | ||
|  |     0x12, 0x49,  # ldr  r1, =0x8680090 | ||
|  |     0x00, 0x22,  # mov  r2, #0 | ||
|  |     0x8B, 0x5C,  # ldrb r3, [r1, r2] | ||
|  |     0x83, 0x54,  # strb r3, [r0, r2] | ||
|  |     0x01, 0x32,  # adds r2, #1 | ||
|  |     0x03, 0x2A,  # cmp  r2, #3 | ||
|  |     0xFA, 0xDB,  # blt  0x8680016 | ||
|  |     # Cards | ||
|  |     0x0F, 0x48,  # ldr  r0, =0x2025674 | ||
|  |     0x10, 0x49,  # ldr  r1, =0x86800A0 | ||
|  |     0x00, 0x22,  # mov  r2, #0 | ||
|  |     0x8B, 0x5C,  # ldrb r3, [r1, r2] | ||
|  |     0x83, 0x54,  # strb r3, [r0, r2] | ||
|  |     0x01, 0x32,  # adds r2, #1 | ||
|  |     0x14, 0x2A,  # cmp  r2, #0x14 | ||
|  |     0xFA, 0xDB,  # blt  0x8680026 | ||
|  |     # Inventory Items (not currently supported) | ||
|  |     0x0D, 0x48,  # ldr  r0, =0x20256ED | ||
|  |     0x0E, 0x49,  # ldr  r1, =0x86800C0 | ||
|  |     0x00, 0x22,  # mov  r2, #0 | ||
|  |     0x8B, 0x5C,  # ldrb r3, [r1, r2] | ||
|  |     0x83, 0x54,  # strb r3, [r0, r2] | ||
|  |     0x01, 0x32,  # adds r2, #1 | ||
|  |     0x36, 0x2A,  # cmp  r2, #36 | ||
|  |     0xFA, 0xDB,  # blt  0x8680036 | ||
|  |     # Return to the function that checks for Magician Mode. | ||
|  |     0xBA, 0x21,  # movs r1, #0xBA | ||
|  |     0x89, 0x00,  # lsls r1, r1, #2 | ||
|  |     0x70, 0x18,  # adds r0, r6, r1 | ||
|  |     0x04, 0x70,  # strb r4, [r0] | ||
|  |     0x00, 0x4A,  # ldr  r2, =0x8007F78 | ||
|  |     0x97, 0x46,  # mov  r15, r2 | ||
|  |     # LDR number pool | ||
|  |     0x78, 0x7F, 0x00, 0x08, | ||
|  |     0x2F, 0x57, 0x02, 0x02, | ||
|  |     0x80, 0x00, 0x68, 0x08, | ||
|  |     0x2C, 0x57, 0x02, 0x02, | ||
|  |     0x90, 0x00, 0x68, 0x08, | ||
|  |     0x74, 0x56, 0x02, 0x02, | ||
|  |     0xA0, 0x00, 0x68, 0x08, | ||
|  |     0xED, 0x56, 0x02, 0x02, | ||
|  |     0xC0, 0x00, 0x68, 0x08, | ||
|  | ] | ||
|  | 
 | ||
|  | max_max_up_checker = [ | ||
|  |     # Whenever the player picks up a Max Up, this will check to see if they currently have 255 of that particular Max Up | ||
|  |     # and only increment the number further if they don't. This is necessary for extreme Item Link seeds, as going over | ||
|  |     # 255 of any Max Up will reset the counter to 0. | ||
|  |     0x08, 0x78,  # ldrb r0, [r1] | ||
|  |     0xFF, 0x28,  # cmp  r0, 0xFF | ||
|  |     0x17, 0xD1,  # bne  0x86A0036 | ||
|  |     # If it's an HP Max, refill our HP. | ||
|  |     0xFF, 0x23,  # mov  r3, #0xFF | ||
|  |     0x0B, 0x40,  # and  r3, r1 | ||
|  |     0x2D, 0x2B,  # cmp  r3, 0x2D | ||
|  |     0x03, 0xD1,  # bne  0x86A0016 | ||
|  |     0x0D, 0x4A,  # ldr  r2, =0x202562E | ||
|  |     0x93, 0x88,  # ldrh r3, [r2, #4] | ||
|  |     0x13, 0x80,  # strh r3, [r2] | ||
|  |     0x11, 0xE0,  # b    0x86A003A | ||
|  |     # If it's an MP Max, refill our MP. | ||
|  |     0x2E, 0x2B,  # cmp  r3, 0x2E | ||
|  |     0x03, 0xD1,  # bne  0x86A0022 | ||
|  |     0x0B, 0x4A,  # ldr  r2, =0x2025636 | ||
|  |     0x93, 0x88,  # ldrh r3, [r2, #4] | ||
|  |     0x13, 0x80,  # strh r3, [r2] | ||
|  |     0x0B, 0xE0,  # b    0x86A003A | ||
|  |     # Else, meaning it's a Hearts Max, add +6 Hearts. If adding +6 Hearts would put us over our current max, set our | ||
|  |     # current amount to said current max instead. | ||
|  |     0x0A, 0x4A,  # ldr  r2, =0x202563C | ||
|  |     0x13, 0x88,  # ldrh r3, [r2] | ||
|  |     0x06, 0x33,  # add  r3, #6 | ||
|  |     0x51, 0x88,  # ldrh r1, [r2, #2] | ||
|  |     0x8B, 0x42,  # cmp  r3, r1 | ||
|  |     0x00, 0xDB,  # blt  0x86A0030 | ||
|  |     0x0B, 0x1C,  # add  r3, r1, #0 | ||
|  |     0x13, 0x80,  # strh r3, [r2] | ||
|  |     0x02, 0xE0,  # b 0x86A003A | ||
|  |     0x00, 0x00, | ||
|  |     # Increment the Max Up count like normal. Should only get here if the Max Up count was determined to be less than | ||
|  |     # 255, branching past if not the case. | ||
|  |     0x01, 0x30,  # adds r0, #1 | ||
|  |     0x08, 0x70,  # strb r0, [r1] | ||
|  |     # Return to the function that gives Max Ups normally. | ||
|  |     0x05, 0x48,  # ldr  r0, =0x1B3 | ||
|  |     0x00, 0x4A,  # ldr  r2, =0x805E170 | ||
|  |     0x97, 0x46,  # mov  r15, r2 | ||
|  |     # LDR number pool | ||
|  |     0x78, 0xE1, 0x05, 0x08, | ||
|  |     0x2E, 0x56, 0x02, 0x02, | ||
|  |     0x36, 0x56, 0x02, 0x02, | ||
|  |     0x3C, 0x56, 0x02, 0x02, | ||
|  |     0xB3, 0x01, 0x00, 0x00, | ||
|  | ] | ||
|  | 
 | ||
|  | maiden_detonator = [ | ||
|  |     # Detonates the iron maidens upon picking up the Maiden Detonator item by setting the "broke iron maidens" flag. | ||
|  |     0x2A, 0x20,  # mov  r0, #0x2A | ||
|  |     0x03, 0x4A,  # ldr  r2, =0x8007E24 | ||
|  |     0x7B, 0x46,  # mov  r3, r15 | ||
|  |     0x05, 0x33,  # adds r3, #5 | ||
|  |     0x9E, 0x46,  # mov  r14, r3 | ||
|  |     0x97, 0x46,  # mov  r15, r2 | ||
|  |     0x01, 0x4A,  # ldr  r2, =0x8095BE4 | ||
|  |     0x97, 0x46,  # mov  r15, r2 | ||
|  |     # LDR number pool | ||
|  |     0x24, 0x7E, 0x00, 0x08, | ||
|  |     0xE4, 0x5B, 0x09, 0x08, | ||
|  | ] | ||
|  | 
 | ||
|  | doubleless_roc_midairs_preventer = [ | ||
|  |     # Prevents being able to Roc jump in midair without the Double. Will pass if the jump counter is 0 or if Double is | ||
|  |     # in the inventory. | ||
|  |     # Check for Roc Wing in the inventory normally. | ||
|  |     0x58, 0x18,  # add  r0, r3, r1 | ||
|  |     0x00, 0x78,  # ldrb r0, [r0] | ||
|  |     0x00, 0x28,  # cmp  r0, 0 | ||
|  |     0x11, 0xD0,  # beq  0x8679A2C | ||
|  |     # Check the "jumps since last on the ground" counter. Is it 0? | ||
|  |     # If so, then we are on the ground and can advance to the Kick Boots question. If not, advance to the Double check. | ||
|  |     0x0B, 0x48,  # ldr  r0, =0x2000080 | ||
|  |     0x01, 0x78,  # ldrb r1, [r0] | ||
|  |     0x00, 0x29,  # cmp  r1, 0 | ||
|  |     0x03, 0xD0,  # beq  0x8679A18 | ||
|  |     # Check for Double in the inventory. Is it there? | ||
|  |     # If not, then it's not time to Roc! Otherwise, advance to the next check. | ||
|  |     0x0A, 0x4A,  # ldr  r2, =0x202572F | ||
|  |     0x52, 0x78,  # ldrb r2, [r2, 1] | ||
|  |     0x00, 0x2A,  # cmp  r2, 0 | ||
|  |     0x09, 0xD0,  # beq  0x8679A2C | ||
|  |     # Check for Kick Boots in the inventory. Are they there? | ||
|  |     # If they are, then we can definitely Roc! If they aren't, however, then on to the next question... | ||
|  |     0x08, 0x4A,  # ldr  r2, =0x202572F | ||
|  |     0xD2, 0x78,  # ldrb r2, [r2, 3] | ||
|  |     0x00, 0x2A,  # cmp  r2, 0 | ||
|  |     0x03, 0xD1,  # bne  0x8679A28 | ||
|  |     # Is our "jumps since last on the ground" counter 2? | ||
|  |     # If it is, then we already Double jumped and should not Roc jump as well. | ||
|  |     # Should always pass if we came here from the "on the ground" 0 check. | ||
|  |     0x02, 0x29,  # cmp  r1, 2 | ||
|  |     0x03, 0xD0,  # beq  0x8679A2C | ||
|  |     # If we did not Double jump yet, then set the above-mentioned counter to 2, and now we can finally Roc on! | ||
|  |     0x02, 0x21,  # mov  r1, 2 | ||
|  |     0x01, 0x70,  # strb r1, [r0] | ||
|  |     # Go to the "Roc jump" code. | ||
|  |     0x01, 0x4A,  # ldr  r2, =0x806B8A8 | ||
|  |     0x97, 0x46,  # mov  r15, r2 | ||
|  |     # Go to the "don't Roc jump" code. | ||
|  |     0x01, 0x4A,  # ldr  r2, =0x806B93C | ||
|  |     0x97, 0x46,  # mov  r15, r2 | ||
|  |     # LDR number pool | ||
|  |     0xA8, 0xB8, 0x06, 0x08, | ||
|  |     0x3C, 0xB9, 0x06, 0x08, | ||
|  |     0x80, 0x00, 0x00, 0x02, | ||
|  |     0x2F, 0x57, 0x02, 0x02, | ||
|  | ] | ||
|  | 
 | ||
|  | kickless_roc_height_shortener = [ | ||
|  |     # Shortens the amount of time spent rising with Roc Wing if the player doesn't have Kick Boots. | ||
|  |     0x06, 0x49,  # ldr  r1, =0x202572F | ||
|  |     0xC9, 0x78,  # ldrb r1, [r1, 3] | ||
|  |     0x00, 0x29,  # cmp  r1, 0 | ||
|  |     0x00, 0xD1,  # bne  0x8679A6A | ||
|  |     0x10, 0x20,  # mov  r0, 0x12 | ||
|  |     0xA8, 0x65,  # str  r0, [r5, 0x58] | ||
|  |     # Go back to the Roc jump code. | ||
|  |     0x00, 0x24,  # mov  r4, 0 | ||
|  |     0x2C, 0x64,  # str  r4, [r5, 0x40] | ||
|  |     0x03, 0x49,  # ldr  r1, =0x80E03A0 | ||
|  |     0x01, 0x4A,  # ldr  r2, =0x806B8BC | ||
|  |     0x97, 0x46,  # mov  r15, r2 | ||
|  |     0x00, 0x00, | ||
|  |     # LDR number pool | ||
|  |     0xBC, 0xB8, 0x06, 0x08, | ||
|  |     0x2F, 0x57, 0x02, 0x02, | ||
|  |     0xA0, 0x03, 0x0E, 0x08 | ||
|  | ] | ||
|  | 
 | ||
|  | missing_char_data = { | ||
|  |     # The pixel data for all ASCII characters missing from the game's dialogue textbox font. | ||
|  | 
 | ||
|  |     # Each character consists of 8 bytes, with each byte representing one row of pixels in the character. The bytes are | ||
|  |     # arranged from top to bottom row going from left to right. | ||
|  | 
 | ||
|  |     # Each bit within each byte represents the following pixels within that row: | ||
|  |     # 8- = -+------ | ||
|  |     # 4- = +------- | ||
|  |     # 2- = ---+---- | ||
|  |     # 1- = --+----- | ||
|  |     # -8 = -----+-- | ||
|  |     # -4 = ----+--- | ||
|  |     # -2 = -------+ | ||
|  |     # -1 = ------+- | ||
|  |     0x396C54: [0x00, 0x9C, 0x9C, 0x18, 0x84, 0x00, 0x00, 0x00],  # " | ||
|  |     0x396C5C: [0x00, 0x18, 0xBD, 0x18, 0x18, 0x18, 0xBD, 0x18],  # # | ||
|  |     0x396C64: [0x00, 0x0C, 0x2D, 0x0C, 0x21, 0x00, 0x00, 0x00],  # * | ||
|  |     0x396C6C: [0x00, 0x20, 0x3C, 0xA0, 0x34, 0x28, 0xB4, 0x20],  # $ | ||
|  |     0x396C74: [0x00, 0x34, 0x88, 0x80, 0xB4, 0x88, 0x88, 0x34],  # 6 | ||
|  |     0x396C7C: [0x00, 0xBC, 0x88, 0x04, 0x04, 0x20, 0x20, 0x20],  # 7 | ||
|  |     0x396CBC: [0x00, 0x34, 0x88, 0x88, 0x3C, 0x08, 0x88, 0x34],  # 9 | ||
|  |     0x396CC4: [0x00, 0xC0, 0xC0, 0x00, 0x00, 0x00, 0xC0, 0xC0],  # : | ||
|  |     0x396CCC: [0x00, 0xC0, 0xC0, 0x00, 0xC0, 0xC0, 0x80, 0x40],  # ; | ||
|  |     0x396D0C: [0x00, 0x00, 0x09, 0x24, 0x90, 0x24, 0x09, 0x00],  # < | ||
|  |     0x396D14: [0x00, 0x00, 0xFD, 0x00, 0x00, 0x00, 0xFD, 0x00],  # = | ||
|  |     0x396D1C: [0x00, 0x00, 0xC0, 0x30, 0x0C, 0x30, 0xC0, 0x00],  # > | ||
|  |     0x396D54: [0x00, 0x34, 0x88, 0xAC, 0xA8, 0xAC, 0x80, 0x34],  # @ | ||
|  |     0x396D5C: [0x00, 0x34, 0x88, 0x88, 0xA8, 0x8C, 0x88, 0x35],  # Q | ||
|  |     0x396D64: [0x00, 0x40, 0x80, 0x10, 0x20, 0x04, 0x08, 0x01],  # \ | ||
|  |     0x396D6C: [0x00, 0x20, 0x14, 0x88, 0x00, 0x00, 0x00, 0x00],  # ^ | ||
|  |     0x396D9C: [0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFD],  # _ | ||
|  |     0x396DA4: [0x00, 0x90, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00],  # ` | ||
|  |     0x396DAC: [0x00, 0x08, 0x04, 0x04, 0x20, 0x04, 0x04, 0x08],  # { | ||
|  |     0x396DB4: [0x00, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20],  # | | ||
|  |     0x396DBC: [0x00, 0x80, 0x10, 0x10, 0x20, 0x10, 0x10, 0x80],  # } | ||
|  |     0x396DF4: [0x00, 0x00, 0x00, 0x90, 0x61, 0x0C, 0x00, 0x00],  # ~ | ||
|  | } | ||
|  | 
 | ||
|  | extra_item_sprites = [ | ||
|  |     # The VRAM data for all the extra item sprites, including the Archipelago Items. | ||
|  | 
 | ||
|  |     # NOTE: The Archipelago logo is © 2022 by Krista Corkos and Christopher Wilson | ||
|  |     # and licensed under Attribution-NonCommercial 4.0 International. | ||
|  |     # See LICENSES.txt at the root of this apworld's directory for more licensing information. | ||
|  | 
 | ||
|  |     # Maiden Detonator | ||
|  |     0x00, 0x00, 0x00, 0x11, 0x00, 0x00, 0x10, 0xCC, 0x00, 0x00, 0xC1, 0xBB, 0x00, 0x10, 0x1C, 0xB8, | ||
|  |     0x00, 0x10, 0x1C, 0xB1, 0x00, 0x10, 0xBC, 0xBB, 0x00, 0x00, 0x11, 0x11, 0x00, 0x10, 0xCC, 0xBB, | ||
|  |     0x11, 0x00, 0x00, 0x00, 0xCC, 0x01, 0x00, 0x00, 0xBB, 0x1C, 0x00, 0x00, 0x8B, 0xC1, 0x01, 0x00, | ||
|  |     0x1B, 0xC1, 0x01, 0x00, 0xBB, 0xCB, 0x01, 0x00, 0x11, 0x11, 0x00, 0x00, 0xBB, 0xCC, 0x01, 0x00, | ||
|  |     0x00, 0x10, 0x11, 0x11, 0x00, 0xC1, 0xBC, 0x1B, 0x00, 0x10, 0x11, 0x11, 0x00, 0xC1, 0xBC, 0x1B, | ||
|  |     0x00, 0x10, 0x11, 0x11, 0x00, 0xC1, 0xBC, 0x1B, 0x00, 0xC1, 0xBC, 0x1B, 0x00, 0x10, 0x11, 0x01, | ||
|  |     0x11, 0x11, 0x01, 0x00, 0xB1, 0xCB, 0x1C, 0x00, 0x11, 0x11, 0x01, 0x00, 0xB1, 0xCB, 0x1C, 0x00, | ||
|  |     0x11, 0x11, 0x01, 0x00, 0xB1, 0xCB, 0x1C, 0x00, 0xB1, 0xCB, 0x1C, 0x00, 0x10, 0x11, 0x01, 0x00, | ||
|  |     # Archipelago Filler | ||
|  |     0x00, 0x00, 0x00, 0x22, 0x00, 0x00, 0x20, 0x88, 0x00, 0x22, 0x82, 0x88, 0x20, 0x66, 0x26, 0x88, | ||
|  |     0x62, 0x66, 0x62, 0x82, 0x62, 0x66, 0x66, 0x82, 0x62, 0x22, 0x62, 0x22, 0x20, 0xAA, 0x2A, 0x00, | ||
|  |     0x02, 0x00, 0x00, 0x00, 0x28, 0x00, 0x00, 0x00, 0x82, 0x22, 0x02, 0x00, 0x28, 0xCC, 0x2C, 0x00, | ||
|  |     0xC2, 0xCC, 0xC2, 0x02, 0xC2, 0xCC, 0xCC, 0x02, 0xC2, 0x22, 0xC2, 0x02, 0x20, 0xFF, 0x2F, 0x00, | ||
|  |     0xA2, 0xAA, 0xA2, 0x02, 0xA2, 0xAA, 0xAA, 0x22, 0xA2, 0xAA, 0x2A, 0x77, 0x20, 0xAA, 0x72, 0x77, | ||
|  |     0x00, 0x22, 0x72, 0x77, 0x00, 0x00, 0x72, 0x77, 0x00, 0x00, 0x20, 0x77, 0x00, 0x00, 0x00, 0x22, | ||
|  |     0xF2, 0xFF, 0xF2, 0x02, 0xF2, 0xFF, 0xFF, 0x02, 0x27, 0xFF, 0xFF, 0x02, 0x72, 0xF2, 0x2F, 0x00, | ||
|  |     0x77, 0x22, 0x02, 0x00, 0x77, 0x02, 0x00, 0x00, 0x27, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, | ||
|  |     # Archipelago Useful | ||
|  |     0x00, 0x00, 0x00, 0x22, 0x00, 0x00, 0x20, 0x88, 0x00, 0x22, 0x82, 0x88, 0x20, 0x66, 0x26, 0x88, | ||
|  |     0x62, 0x66, 0x62, 0x82, 0x62, 0x66, 0x66, 0x82, 0x62, 0x22, 0x62, 0x22, 0x20, 0xAA, 0x2A, 0x00, | ||
|  |     0x02, 0xAA, 0x0A, 0x00, 0x28, 0x9A, 0x0A, 0x00, 0xAA, 0x9A, 0xAA, 0x0A, 0x9A, 0x99, 0x99, 0x0A, | ||
|  |     0xAA, 0x9A, 0xAA, 0x0A, 0xC2, 0x9A, 0xCA, 0x02, 0xC2, 0xAA, 0xCA, 0x02, 0x20, 0xFF, 0x2F, 0x00, | ||
|  |     0xA2, 0xAA, 0xA2, 0x02, 0xA2, 0xAA, 0xAA, 0x22, 0xA2, 0xAA, 0x2A, 0x77, 0x20, 0xAA, 0x72, 0x77, | ||
|  |     0x00, 0x22, 0x72, 0x77, 0x00, 0x00, 0x72, 0x77, 0x00, 0x00, 0x20, 0x77, 0x00, 0x00, 0x00, 0x22, | ||
|  |     0xF2, 0xFF, 0xF2, 0x02, 0xF2, 0xFF, 0xFF, 0x02, 0x27, 0xFF, 0xFF, 0x02, 0x72, 0xF2, 0x2F, 0x00, | ||
|  |     0x77, 0x22, 0x02, 0x00, 0x77, 0x02, 0x00, 0x00, 0x27, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, | ||
|  |     # Archipelago Progression | ||
|  |     0x00, 0x00, 0x00, 0x22, 0x00, 0x00, 0x20, 0x88, 0x00, 0x22, 0x82, 0x88, 0x20, 0x66, 0x26, 0x88, | ||
|  |     0x62, 0x66, 0x62, 0x82, 0x62, 0x66, 0x66, 0x82, 0x62, 0x22, 0x62, 0x22, 0x20, 0xAA, 0x2A, 0x00, | ||
|  |     0x02, 0x10, 0x00, 0x00, 0x28, 0x71, 0x01, 0x00, 0x12, 0x77, 0x17, 0x00, 0x71, 0x77, 0x77, 0x01, | ||
|  |     0x11, 0x77, 0x17, 0x01, 0x12, 0x77, 0x17, 0x02, 0x12, 0x11, 0x11, 0x02, 0x20, 0xFF, 0x2F, 0x00, | ||
|  |     0xA2, 0xAA, 0xA2, 0x02, 0xA2, 0xAA, 0xAA, 0x22, 0xA2, 0xAA, 0x2A, 0x77, 0x20, 0xAA, 0x72, 0x77, | ||
|  |     0x00, 0x22, 0x72, 0x77, 0x00, 0x00, 0x72, 0x77, 0x00, 0x00, 0x20, 0x77, 0x00, 0x00, 0x00, 0x22, | ||
|  |     0xF2, 0xFF, 0xF2, 0x02, 0xF2, 0xFF, 0xFF, 0x02, 0x27, 0xFF, 0xFF, 0x02, 0x72, 0xF2, 0x2F, 0x00, | ||
|  |     0x77, 0x22, 0x02, 0x00, 0x77, 0x02, 0x00, 0x00, 0x27, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, | ||
|  |     # Archipelago Trap | ||
|  |     0x00, 0x00, 0x00, 0x22, 0x00, 0x00, 0x20, 0x88, 0x00, 0x22, 0x82, 0x82, 0x20, 0x66, 0x26, 0x88, | ||
|  |     0x62, 0x62, 0x66, 0x82, 0x62, 0x66, 0x66, 0x82, 0x62, 0x22, 0x62, 0x22, 0x20, 0xAA, 0x2A, 0x00, | ||
|  |     0x02, 0x10, 0x00, 0x00, 0x28, 0x71, 0x01, 0x00, 0x18, 0x77, 0x17, 0x00, 0x71, 0x77, 0x77, 0x01, | ||
|  |     0x11, 0x77, 0x17, 0x01, 0x12, 0x77, 0x17, 0x02, 0x12, 0x11, 0x11, 0x02, 0x20, 0xFF, 0x2F, 0x00, | ||
|  |     0xA2, 0xA2, 0xAA, 0x02, 0xA2, 0xAA, 0xAA, 0x22, 0xA2, 0xAA, 0x2A, 0x77, 0x20, 0xAA, 0x72, 0x72, | ||
|  |     0x00, 0x22, 0x72, 0x77, 0x00, 0x00, 0x72, 0x77, 0x00, 0x00, 0x20, 0x77, 0x00, 0x00, 0x00, 0x22, | ||
|  |     0xF2, 0xF2, 0xFF, 0x02, 0xF2, 0xFF, 0xFF, 0x02, 0x27, 0xFF, 0xFF, 0x02, 0x77, 0xF2, 0x2F, 0x00, | ||
|  |     0x77, 0x22, 0x02, 0x00, 0x77, 0x02, 0x00, 0x00, 0x27, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, | ||
|  |     # Archipelago Progression + Useful | ||
|  |     0x00, 0x00, 0x00, 0x22, 0x00, 0x00, 0x20, 0x88, 0x00, 0x22, 0x82, 0x88, 0x20, 0x66, 0x26, 0x88, | ||
|  |     0x62, 0x66, 0x62, 0x82, 0x62, 0x66, 0x66, 0x82, 0x62, 0x22, 0x62, 0x22, 0x20, 0xAA, 0x2A, 0x00, | ||
|  |     0x02, 0x10, 0x00, 0x00, 0x28, 0x71, 0x01, 0x00, 0x12, 0x77, 0x17, 0x00, 0x71, 0x77, 0x77, 0x01, | ||
|  |     0x11, 0x77, 0x17, 0x01, 0x12, 0x77, 0x17, 0x02, 0x12, 0x11, 0x11, 0x02, 0x20, 0xFF, 0x2F, 0x00, | ||
|  |     0xA2, 0xAA, 0xA2, 0x02, 0xA2, 0xAA, 0xAA, 0x22, 0xA2, 0xAA, 0x2A, 0x77, 0x20, 0xAA, 0x72, 0x77, | ||
|  |     0x00, 0x22, 0x72, 0x77, 0x00, 0x00, 0x72, 0x77, 0x00, 0x00, 0x20, 0x77, 0x00, 0x00, 0x00, 0x22, | ||
|  |     0xF2, 0xFF, 0xF2, 0x02, 0xF2, 0xAA, 0xFA, 0x02, 0x27, 0x9A, 0xFA, 0x02, 0xAA, 0x9A, 0xAA, 0x0A, | ||
|  |     0x9A, 0x99, 0x99, 0x0A, 0xAA, 0x9A, 0xAA, 0x0A, 0x27, 0x9A, 0x0A, 0x00, 0x02, 0xAA, 0x0A, 0x00, | ||
|  |     # Hourglass (Specifically used to represent Max Sand from Timespinner) | ||
|  |     0x00, 0x00, 0xFF, 0xFF, 0x00, 0xF0, 0xEE, 0xCC, 0x00, 0xF0, 0x43, 0x42, 0x00, 0xF0, 0x12, 0x11, | ||
|  |     0x00, 0x00, 0x1F, 0x11, 0x00, 0x00, 0x2F, 0x88, 0x00, 0x00, 0xF0, 0x82, 0x00, 0x00, 0x00, 0x1F, | ||
|  |     0xFF, 0xFF, 0x00, 0x00, 0xCC, 0xEE, 0x0F, 0x00, 0x42, 0x34, 0x0F, 0x00, 0x11, 0x21, 0x0F, 0x00, | ||
|  |     0x11, 0xF1, 0x00, 0x00, 0x98, 0xF2, 0x00, 0x00, 0x29, 0x0F, 0x00, 0x00, 0xF9, 0x00, 0x00, 0x00, | ||
|  |     0x00, 0x00, 0x00, 0x1F, 0x00, 0x00, 0xF0, 0x81, 0x00, 0x00, 0x2F, 0x81, 0x00, 0x00, 0x1F, 0x88, | ||
|  |     0x00, 0xF0, 0x12, 0xA9, 0x00, 0xF0, 0x43, 0x24, 0x00, 0xF0, 0xEE, 0xCC, 0x00, 0x00, 0xFF, 0xFF, | ||
|  |     0xF9, 0x00, 0x00, 0x00, 0x19, 0x0F, 0x00, 0x00, 0x99, 0xF2, 0x00, 0x00, 0xA9, 0xF1, 0x00, 0x00, | ||
|  |     0xAA, 0x21, 0x0F, 0x00, 0x42, 0x34, 0x0F, 0x00, 0xCC, 0xEE, 0x0F, 0x00, 0xFF, 0xFF, 0x00, 0x00, | ||
|  | ] |