The operations from 06F8 to 0734 (the second
(...) in your post) appear to be a table lookup. They're comparing A (i.e. the old value of (FFE5)) to a range of different values, and setting the value of BC accordingly. (This took me a while to understand because there's a triple negative, e.g. the first test is saying "if subtracting 7 from the value does not borrow, do not continue", but with "borrow" expressed as "not carry"; no wonder it's confusing.)
If A is less than or equal to 7h (7 decimal), BC is set to 030Ch (780 decimal).
If A is less than or equal to Bh (11 decimal), BC is set to 0734h (1844 decimal).
If A is less than or equal to Fh (15 decimal), BC is set to 0B5Ch (2908 decimal).
If A is less than or equal to 15h (19 decimal), BC is set to 0F84h (3972 decimal).
This table probably continues, but the rest of the table doesn't show in the trace because that's the case that was taken in the trace in question.
At that point, the B half of BC is saved back in FFE5, and the code moves on to FFE6, which is zeroed (like in your trace). The C half is saved into C0AB, and the code moves onto a subroutine at 21B1 (which appears to be very long and complex and start with several block copy / block clear routines; this would suggest to me that it's a major loading routine, which wouldn't be surprising if it's called during the player respawning). C0AB doesn't seem to be used immediately, although several values near it
are used, so it wouldn't surprise me if it's part of some sort of "this is where the player is" state. I'd strongly recommend at least putting a memory watch on C0AA and C0AB because they seem to be relevant here.
21BC is the first point at which the code gets back to FFE4/FFE5/FFE6 rather than large block copies, and is still inside the long and complex subroutine mentioned earlier. FFE6 is compared to zero; if it actually is zero (as it is in this case), then something fairly small/simple gets skipped (which doesn't show up in the trace because it was skipped). As such, I'd expect FFE6 to be related to "the reason the player respawned".
It starts by looking at the memory address (4000 +
twice the value in FFE4); 16 bits gets loaded from that memory address into DE (in a painfully indirect way because the Z80 doesn't have any instructions for doing that efficiently, e.g. it has to use all of A/D/E/H/L as temporaries, because addresses like A are useful for doubling a value by adding it to itself). So I assume there's some sort of array starting at 4000. The code then does something very similar again, adding twice the value in FFE5 to the value that was previously in DE (again, in a very indirect way with a bunch of register-shuffling); several consecutive values get read from the resulting address.
In C-like pseudocode, we'd write that code something like this:
extern byte*** a4000; // * = 16-bit pointer to an address
byte *base = a4000[ffe4][ffe5];
That is, we're taking a hardcoded array that points to another set of arrays, and indexing into it twice to get a base pointer. That pointer's then used to read several values from memory which determine how the game loads from there.
Given that we already know that FFE5 is set to 3, 7, B, or F, (and probably other values but the pattern likely continues, it's going up by 4 each time), my guess is that there's an 8-byte structure that contains values describing how a level checkpoint behaves, and several of these structures exist for any given level; presumably, the first structure describes the level spawn point. I'd also guess that ffe4 somehow specifies which level the player is currently playing (that's just a guess but you can probably confirm it with memory watch).
The code logged here seems to make sense: there seem to be checkpoints at FFE5 = 7, B, F, etc., and if the player has gone sufficiently past them (i.e. to 8, A, 10 respectively), they'll respawn at that checkpoint. There's no immediate bug there that I can spot. There is something that's bothering me, though: with the part of the code seen in the trace, respawning at say, checkpoint 2 would subsequently put you back at checkpoint 1 if you died without moving from then on, something which the developers are moderately likely to have tested and which is probably undesirable. I have a suspicion, therefore, that the setting of FFE5 in the part of the trace you posted is used
only to determine which checkpoint to respawn at, and some other part of the code sets the new value of FFE5. I further have a hunch that the respawn bug you saw is a consequence of the value in FFE5 somehow getting out of sync with the player's/camera's actual x coordinate. You might want to try to work out the relationship between those to see if there's anything unexpected there.