Alright, guesses.
I'm going to guess that when the interrupt happens, it happens during the all-important collision function, and it wants to try that function back from the start. So, it retries the same bullet-target hitbox check and runs it again. Except the function was fully complete, had successfully spawned the object in its entirety, and the spawner code then looks for the next open slot as it didn't un-create the thing.
If that's the case, then I'm going to hate trying to find the magic combination of sprites to busy the hit detection function by exactly enough. I will leave that to someone else to work out.
I am willing, however, to generate a script that can tell you precisely when the important collision happened relative to the interrupt, but not willing to do the ground work to make it happen.
Regardless, I have my question. Let's see if it's the right question to ask.
Hah! Interrupt during handling the effect of the collision! But what is the consequence of this?
Well, when the double hit occurred, the first hit had enough time to read $00BA, use it as an index to stats in the $500s ($052D,Y, $0547,Y, $0561,Y, $057B,Y), and copy the X,Y position of the shot object into those spots, then store the value 20 into $0513,Y. It also increments $00BA.
Then it jumps to $8922 where it asks about $0374,X, with X still referencing the shot object, and it not being #$FF, it'll then go on to various management, which I haven't carefully looked at. The interrupt happens here, cutting off the management, and apparently never comes back to it. As a result, the bullet and shot object are still free to interact normally.
The stuff over in the 500s are things for the game to spawn later. We didn't stuff just one portal in there, but stuffed two there thanks to a well-timed interrupt. So that the game thinks that it should generate the two a few frames later.
Anyway, I still haven't cracked heavily into code analysis, but judging from the timing of the interrupt, and what the interrupt apparently does when it comes to the hit detection code, I'm around 80% certain it's based on the code being unstable around interrupts. Which is why the bullet spam is needed, I guess.
... Anyone need a script?
EDIT: If this is successful, we're starting planet 8 with the starter 1000 cash. We'll then warp to 13, then start pushing through 12.
The Sports Jetpod is really far out of reach with this route, so we'll no longer swing wormholes for fun and profit. No carrying them to items, no using them for breaking the 3.0 speed limit, none of that is possible. We can buy one Double-Strength Thruster or one Anti-Gravity for Planets 8 and 13, and we can buy two more after the singular challenge room prior to Planet 12.
From what I remember, we'll still want to self-destruct in Planet 12, as while I do cart a wormhole all the way to that last fuel unit (in the published run), there is another wormhole a short distance further ahead.
Due to menu time, we're highly discouraged from picking up a Double-Strength Thruster on Planet 8, then a second one on Planet 12. Anti-Gravity is very quick into the menu, so we can pick one up early and another later without loss. Therefore, we should only have one Double-Strength if we need it for Planet 13, but we can have one or two if we use Anti-Gravity instead.
So, two Anti-Gravities and one Double-Strength Thruster, or two Double-Strength Thrusters and one Anti-Gravity? And which one for Planet 13?
And when making the sacrifice at Planet 12, it looks likely we'll want both flavors for the first half, considering we're carting around a lot of fuel. We're doing a lot less carting around after the sacrifice, so one item should work fine. But it is possible to route in just one item on the first half so we'll have both for the final run, if that somehow saves more time.
So many potential routes with the Double-Strength Thrusters and Anti-Gravity...
P13 DST -> P12 DST+AG / AG
P13 DST -> P12 AG / DST+AG
P13 AG -> P12 DST+AG / DST
P13 AG -> P12 DST+AG / AG
P13 AG -> P12 DST / DST+AG
P13 AG -> P12 AG / DTS+AG