I believe I have the answer to this question.
BattleScript 0xef is the pokeball catch routine. It is used whenever a ball is thrown, and depending on several checks, jumps to the script best equiped to handle the situation. Near the beginning, it makes three checks to check for situations where the outcome is always the same.
Starting at at 0802D452, we have:
- the ghost battle check; continues to the script at 0x081D9Ad1
- the trainer battle check; contiu 0x081D9AC1
- the fake battle check; continues to the script at 0x081D9A88
With a small bypass near that area, we can use the ghost script (that has nothing related to the ghost battle in it) to prevent capture of a pokemon when a certain flag, variable or another address in the RAM has the desired value. The code is presented below:
Code:
Catch_me_not: ldr r0, num_to_check /*can be anything you want, like flags, variables or addresses. Here, we'll use addresses*/
ldrb r0, [r0]
cmp r0, #0x1 /*or any other value you want*/
bne return_to_normal
ldr r1, battleFlags
ldr r1, [r1]
ldr r0, afterGhostAddr
bx r0
return_to_normal: ldr r1, battleFlags
ldr r1, [r1]
ldr r0, ghostCheckAddr
bx r0
num_to_check: .word 0x020370c0 /*var 8004 address, in this examle*/
battleFlags: .word 0x02022b4c
afterGhostAddr: .word 0x0802d461
ghostCheckAddr: .word 0x0802d457
In the attachment, you have the compiled version of this code, as well as the source that contains a variable access and a flag access code, commented. For those versions, replace num_to_check with the number of the flag/variable you want.