I gave an initial attempt at looking into this, it's certainly more complicated then I initially thought.
So far what I have is 2 savestates on the same frame in slightly different position (0x05B0). One savstate leads to a fuel drop if you go forward, the other doesn't. So far I haven't found any other variable that relates to this drop.
I also have a savestate a little further back, and it seems the order in which you kill enemies also plays some role.
Looks like a more complete RAM map of this game will be needed to sort this out. I'll have some more time later in the week to dive into it a little deeper.
X is the index in the object list, and $0674[X] is a drop-related value of the object. As you can see, this routine sets $0674[X] based on the index of objects. If the object index is 2, a tank will be dropped. If the object index is 4, a fuel will be dropped. You can confirm this with mymovies, by freezing the value of $0674- or deleting objects (set $04FE- to 0).
Since $0674- are modified also in other places, other item drops might be determined by other routines. But at least this will be a clue.
# RAM
# ---
$3D U8 $2000 mirror
$3E U8 $2001 mirror
$3F U8 $2005 x mirror
$40 U8 $2005 y mirror
$41 U8 tmp variable for input reading
$42 U8 tmp variable for input reading
$43 U8 P1 input # ABSTUDLR
$44 U8 P1 input modified # suppress continuous A
$45 U8 P2 input
$46 U8 P2 input modified
$6A U8 current sprite buffer page # 2..3
$E4 U8 P1 life
$E5 U8 P2 life
$0200-$02FF Sprite[64] sprite buffer 1
$0300-$03FF Sprite[64] sprite buffer 2
# In object list, index 0 means player1, index 1 means player2.
# Object position seems to be signed 24-bit (lower 8-bit is subpixel).
# Calculation of y-position is weird a bit (see $DD02).
$04FE- U8[] object type etc? # 0:not-exist
$0576- U8[] object position x mid
$0594- U8[] object position y lo # subpx
$05B0- U8[] object position y mid
$05CC- U8[] object position y hi
$05E8- U8[] object position x lo # subpx
$0604- U8[] object position x hi
$063C- U8[] object direction # 0..15
$0674- U8[] object drop-related value
$067F U8 P1 ammo of gun
$0680 U8 P2 ammo of gun
$0681 U8 P1 ammo of grenade
$0682 U8 P2 ammo of grenade
# ROM
# ---
$C271 code read inputs
$D97E code check if object list is full?
$DC9E code calculate object velocity?
$DD02 code move object
$DDF9 code multiplication (S24 * U8 -> S24)
And, I uploaded a CDL file (Unknown ratio: 8.45%).
i'm not sure I'm reading your reply correctly. It sounds interesting with addresses that somehow follow the type of item drop, but $0674 stays 0 for me in both your movies. What am I supposed to see by looking at that address?
Well, I am so bad at English that I am also not sure I told my thoughts correctly :P
In short, the item drops of tanks in the beginning of area2 are determined by the object index of the tanks. If the tank has object index 2, it will drop a tank. And if the tank has object index 4, it will drop a fuel.
I uploaded a movie. Let's see an example with it.
While playing the movie, please look at $04FE-$0502. These addresses store the property of objects, and if its value is zero, the object does not exist. As I said, object 0 is always player1, and object 1 is always player2. This movie is in 1-player mode, so $04FF is always zero.
On frame 2144, $0500 and $0501 becomes 0x42. These are the doors on sides. And on frame 2176, $0502 becomes 0xC0. This is the first enemy tank, and note that it has object index 4 ($04FE + 4 = $0502). So, it drops a fuel when I destroy it.
And, on frame 2492, $0500 becomes 0, because I destroyed the left door. By this, object index 2 becomes empty and the next enemy tank will have object index 2. In fact, on frame 2536, $0500 becomes 0xC0. And it drops a tank when I destroy it.
I also checked with your area3 movie. On frame 1550, $0502 becomes 0xC0 (enemy tank), and it drops a fuel. I confirmed that the routine $04:90B0 is executed here.
By the way, $0674- is the array of drop-related value.
$0674 corresponds to $04FE (object 0)
$0675 corresponds to $04FF (object 1)
$0676 corresponds to $0500 (object 2)
...etc.
When a enemy tank drop a tank, you will see that $0676 becomes 0x20 for a while.
TaoTao, thanks for your patience with me and for explaining it step-by-step. The first level of understanding of the enemy drops is perfectly clear to me now.
I've started studying the drop in area 3. I have a fairly good understanding of what it takes to get the fuel now. The good thing is that it doesn't rely on some frame-dependent counter (at least not at the level I'm looking at), but can sort of be predicted by visual cues. I'm still far from having a reliable method of manipulating the fuel though, because it depends on the order the object addresses are populated, which is subject to quite a bit of randomness (= it's beyond the level of detail I'm looking at). I'm not sure it's going to be possible to come up with a fool-proof way to get the drop in real-time. However, there are plenty of things I still need to try out, so I expect that at the very least I'll be able to eliminate some bad methods and thereby somewhat improve the odds compared to just blindly playing and hoping for the best. In the best case, I'll be able to out from the different possible enemy movement patterns be able to come up with case-specific actions for getting the fuel drop. But that might just be wishful thinking...
Thanks a lot again, these findings are huge for me.
Thanks to the help with the fuel drops, I've managed to complete my console speedrun. I'm now looking into a TAS. It's the first time I'm attempting a TAS and it's something I plan to have on the side, so progress might be a bit slow and irregular, but I have at least completed the first area:
http://tasvideos.org/userfiles/info/38672276706293120
It's three seconds faster than on console, which is roughly what I expected. Two of them come from frame-perfect inputs and one second is due to a diagonal movement method that isn't feasible in real-time. My only regret is the helicopter section. It's possible to fly until the fuel almost runs out before going into the flying state. The flying state is interesting for a few seconds, but quickly gets old, so it would have been nice to stay in the helicopter for a bit longer. However, for unknown reasons, that doesn't seem to work with the movie I have (the jump at the end gets messed up) and I had to leave the helicopter almost immediately.
Before continuing, I will have to find out if it saves time overall to skip the B-upgrade. Grenades are tossed at a lower rate with the B-upgrade, so you can save ~3 seconds on the bosses in area 3 and 4. However, proceeding without the upgrade will also cost a bit of time in several places, so I have to test if it pays off in the end.
I've accidentally self-exploded several times in the helicopter in area 1. However, I've been so focused on getting a deathless run (I have a bit of an old-school mindset when it comes to death abuse vs deathless) that I never reflected on how that mechanics could be useful in area 3 and 4. I did a quick test right now. In a real-time attempt, you should save a couple of seconds in area 3 and probably in average 10+ seconds in area 4 (mostly due to how you usually need to make a detour for the fuel drop) if you go for death abuse. Not to mention that the run gets quite a lot easier. I'm not sure it's going to be beneficial in a TAS though since you'll anyways be moving more or less in a straight line and can manipulate the fuel drop with only a minimal detour. But I'll of course test that when I get there.
I haven't done much progress on the TAS since my last post, which wasn't long ago, but I have at least found out that it will be faster to skip the B-upgrade.