.version GC_V3 .quest_num 88530 .language 1 .episode Episode1 .name "GC v1.2 USA patch enabler" .short_desc "" .long_desc "" start: // Create quest opcode handlers for F9FE to call flush_code and F9FF to call // the copied code. Fortunately, quest_call_l leaves the byteswapped value of // the opcode argument in r4, so as long as the address ends with 00, it will // be valid as the size argument to flush_code. We'll end up flushing many // more bytes than needed, but this isn't a problem. leti r3, 0x80004000 // dest addr write4 0x804C81C8, 0x801F2A14 // quest_call_l write4 0x804C81CC, 0x8000C274 // flush_code write4 0x804C81D0, r3 // written code ptr read4 r0, 0x805D5E70 // quest_script_base leto r4, code read4 r4, r4 add r4, r0 // r4 = address of code label leto r5, code_end read4 r5, r5 add r5, r0 // r5 = address of code_end label // Copy all data from [code, code_end) to 80004000 copy_byte: jmp_eq r4, r5, copy_done read1 r0, r4 write1 r3, r0 addi r3, 1 addi r4, 1 jmp copy_byte copy_done: // Call flush_code(0x80004000, 0x00400080) to commit it to memory .data F9FE00400080 // Call the copied native code .data F9FF // This script runs on the first frame during the quest loading procedure, // but this procedure is started from the lobby overview, not from a game! // To make the result of loading a quest sane, we need to set some extra // state that will take effect when loading is done. ba_initial_floor 17 // Make player spawn in lobby (for one frame) write2 0x805D5CE8, 1 // Leave "game" immediately (sends 98) // Clean up quest handler table write4 0x804C81C8, 0 write4 0x804C81CC, 0 write4 0x804C81D0, 0 ret code: .include_native q8853x-gc.s code_end: