// File: /workspace/github_cpp_makefile_star2_O3/Thilotilo[P]DoaERando/Randomizer.cpp
// Function: DoaERando::Randomizer::ReturnToEntryDirectionOnFlagClear()
void Randomizer::ReturnToEntryDirectionOnFlagClear()
{
    // Intro: There are a few locations in the game that we can enter, then
    // exit, but whether we can move past that location is entirely dependent
    // on a trigger (either a story flag or a battle-completed flag)
    // In vanilla, this exit location is hardcoded (so for example, Bo Hai always
    // returns us below Bo Hai if we haven't talked to the lady at the bridge
    // with Xu Zhe in our party.  With the open map in the randomizer, we instead
    // want to return us to the direction from which we came.  So if we enter Bo
    // Hai from the East, we'll return to the east side of the castle when we
    // exit.  There is no mechanism for this, so what we do is store the direction
    // that we entered from into $94, which seems to be unused as far as I can tell.
    // Then when we exit, we use the value in $94 to determine how to alter our
    // position.  In rewriting the location-exit code, we have eliminated a few
    // requirements.  First, Si Shui only worries about if the battle is clear, not
    // what chapter we're on.  Zhang Song's hut, Chang An, and Gui Yang no longer
    // have any special code.

    // PART 1: Store the entry location to $94 only if we are entering a first-level
    //         location.
    std::vector<BYTE> entryLocStoreCode {
        0x48,               // PHA
        0xAD, 0x11, 0x60,   // LDA $6011
        0xC9, 0x01,         // CMP #$01 (Only write direction if we've entered from the world map)
        0xD0, 0x04,         // BNE (PLA instruction)
        0xA5, 0x87,         // LDA $87
        0x85, 0x94,         // STA $94
        0x68,               // PLA
        // These 3 bytes are needed because they are what we are overriding with the
        // upcoming JSR instruction
        0x29, 0xC0,         // AND #$C0
        0x18,               // CLC
        0x60,               // RTS
    };

    for (int i = 0; i < entryLocStoreCode.size(); ++i)
    {
        myRom->WriteByte(0x1DAF9 + i, entryLocStoreCode[i]);
    }

    // PART 2: Actually do the jump to this code on the location-enter code
    // (JSR $9AE9)
    myRom->WriteByte(0x3BD3C, 0x20);
    myRom->WriteByte(0x3BD3D, 0xE9);
    myRom->WriteByte(0x3BD3E, 0x9A);

    // PART 3: Update the location-exit code to use this new value at $94
    //         to determine any coordinate adjustments, and to use the new
    //         location triggers
    std::vector<BYTE> locationTriggerCode {
        // Start with Si Shui courtyard
        0xC0, 0x20,         // CPY #$20
        0xD0, 0x06,         // BNE (Luo Yang check)
        0xAD, 0x06, 0x65,   // LDA $6506 (Fortress battle completed)
        0x4C, 0x8A, 0xBE,   // JMP $BE8A (location to update coordinates)
        // Next, check Luo Yang courtyard
        0xC0, 0x21,         // CPY #$21
        0xD0, 0x06,         // BNE (Guang Zong check)
        0xAD, 0x0A, 0x65,   // LDA $650A (Luo Yang battle completed)
        0x4C, 0x8A, 0xBE,   // JMP $BE8A
        // Next, check Guang Zong outskirts
        0xC0, 0x28,         // CPY #$28
        0xD0, 0x06,         // BNE (Luo check)
        0xAD, 0x16, 0x65,   // LDA $6516 (Castle battle completed)
        0x4C, 0x8A, 0xBE,   // JMP $BE8A
        // Next, check Luo
        0xC0, 0x5F,         // CPY #$5F
        0xD0, 0x08,         // BNE (Bo Hai check)
        0xAD, 0x52, 0x65,   // LDA $6552
        0x29, 0x04,         // AND #$04 (6552b2 indicates we've unlocked the Liu Zheng gate)
        0x4C, 0x8A, 0xBE,   // JMP $BE8A
        // Finally, check Bo Hai
        0xC0, 0x69,         // CPY #$69
        0xD0, 0x4F,         // BNE (Standard exit code)
        0xAD, 0x51, 0x65,   // LDA $6551
        0x29, 0x80,         // AND #$80 (6551b7 indicates the lady has moved from the bridge)
        // This is the location to update coordinates.  If we are here, then that means we are
        // at one of the key locations.  If A is 0, then we need to do an adjustment.  Otherwise,
        // we simply go to the exit code
        0xD0, 0x48,         // BNE (Standard exit code)
        0xA5, 0x94,         // LDA $94 (location we entered from)
        // Check Up
        0xC9, 0x00,         // CMP #$00 (Up)
        0xD0, 0x05,         // BNE (Check Down)
        0xE6, 0x60,         // INC $60 (Move Y coordinate down 1)
        0x4C, 0xD4, 0xBE,   // JMP (standard exit code)
        // Check Down
        0xC9, 0x01,         // CMP #$01 (Down)
        0xD0, 0x05,         // BNE (Check Left)
        0xC6, 0x60,         // DEC $60 (Move Y coordinate up 1)
        0x4C, 0xD4, 0xBE,   // JMP (standard exit code)
        // Check Left
        0xC9, 0x02,         // CMP #$02 (Left)
        0xD0, 0x05,         // BNE (Use right)
        0xE6, 0x62,         // INC $62 (Move X coordinate right 1)
        0x4C, 0xD4, 0xBE,   // JMP (standard exit code)
        // Use Right (Up/Down/Left are all false)
        0xC6, 0x62,         // DEC $62 (Move X coordinate left 1)
        0x4C, 0xD4, 0xBE,   // JMP (standard exit code)
    };

    for (int i = 0; i < locationTriggerCode.size(); ++i)
    {
        myRom->WriteByte(0x3BE67 + i, locationTriggerCode[i]);
    }

    // Finally, zero out the remaining unused bytes in this section
    const int NUM_BYTES_TO_CLEAR = 0x3BED4 - 0x3BE67 - locationTriggerCode.size();
    for (int i = 0; i < NUM_BYTES_TO_CLEAR; ++i)
    {
        myRom->WriteByte(0x3BE67 + locationTriggerCode.size() + i, 0x00);
    }
}

// Assembly:
pushq %rbp
movq %rsp, %rbp
pushq %r15
pushq %r14
pushq %rbx
subq $0x98, %rsp
movq %rdi, %rbx
movups 0x184c7c(%rip), %xmm0   # 0x58c4ce
leaq -0xb0(%rbp), %rsi
movaps %xmm0, (%rsi)
movb $0x60, 0x10(%rsi)
leaq -0x50(%rbp), %r14
leaq -0x38(%rbp), %rcx
movl $0x11, %edx
movq %r14, %rdi
callq 0x40a9ca
movq (%r14), %rax
cmpq %rax, 0x8(%r14)
je 0x4078a8
xorl %r14d, %r14d
movq (%rbx), %rdi
movzbl (%rax,%r14), %edx
leal 0x1daf9(%r14), %esi
callq 0x404a24
incq %r14
movq -0x50(%rbp), %rax
movq -0x48(%rbp), %rcx
subq %rax, %rcx
cmpq %r14, %rcx
ja 0x407881
movq (%rbx), %rdi
movl $0x3bd3c, %esi          # imm = 0x3BD3C
movl $0x20, %edx
callq 0x404a24
movq (%rbx), %rdi
movl $0x3bd3d, %esi          # imm = 0x3BD3D
movl $0xe9, %edx
callq 0x404a24
movq (%rbx), %rdi
movl $0x3bd3e, %esi          # imm = 0x3BD3E
movl $0x9a, %edx
callq 0x404a24
leaq 0x184bfa(%rip), %rsi    # 0x58c4df
leaq -0xb0(%rbp), %r14
movl $0x57, %edx
movq %r14, %rdi
callq 0x401070
leaq -0x38(%rbp), %rdi
leaq -0x19(%rbp), %rcx
movl $0x57, %edx
movq %r14, %rsi
callq 0x40a9ca
movq -0x38(%rbp), %rdi
cmpq %rdi, -0x30(%rbp)
je 0x407955
xorl %r14d, %r14d
movq (%rbx), %rax
movzbl (%rdi,%r14), %edx
leal 0x3be67(%r14), %esi
movq %rax, %rdi
callq 0x404a24
incq %r14
movq -0x38(%rbp), %rdi
movq -0x30(%rbp), %rax
subq %rdi, %rax
cmpq %r14, %rax
ja 0x40791b
movl $0x6d, %r14d
subl %eax, %r14d
testl %r14d, %r14d
jg 0x40795b
jmp 0x407990
movl $0x6d, %r14d
negl %r14d
movl $0x3be67, %r15d         # imm = 0x3BE67
movq (%rbx), %rdi
movl -0x30(%rbp), %esi
subl -0x38(%rbp), %esi
addl %r15d, %esi
xorl %edx, %edx
callq 0x404a24
leal (%r14,%r15), %eax
incl %eax
movl %r15d, %ecx
incl %ecx
movl %ecx, %r15d
cmpl $0x3be67, %eax          # imm = 0x3BE67
jne 0x407964
movq -0x38(%rbp), %rdi
testq %rdi, %rdi
je 0x40799a
callq 0x410b90
movq -0x50(%rbp), %rdi
testq %rdi, %rdi
je 0x4079a8
callq 0x410b90
addq $0x98, %rsp
popq %rbx
popq %r14
popq %r15
popq %rbp
retq
jmp 0x4079bc
jmp 0x4079bc
jmp 0x4079c1
movq %rax, %rbx
jmp 0x4079d2
movq %rax, %rbx
movq -0x38(%rbp), %rdi
testq %rdi, %rdi
je 0x4079d2
callq 0x410b90
movq -0x50(%rbp), %rdi
testq %rdi, %rdi
je 0x4079e0
callq 0x410b90
movq %rbx, %rdi
callq 0x4bb660