Here is Lua script for parsing level scripts.
https://gist.github.com/realmonster/9c4325aa0d2fa825549abe7675e3e0c2
It was tested in Gens. For bizhawk you need only change shortcuts. Run it once in any level.
Description of output:
There are following two types of lines within the output. Camera-related trigger.
enemy x=12E y=B5 hb=0 code=20504
this tells us that when Camera in position "good" for x = 12E and y = B5, then it will spawn enemy with those parameters, and its "code" is 20504. Code defines what enemy is spawned, and its behavior. What means Camera in "good" position? It depends on "direction" of level. If you walk or fly to the right, then it checks x position, if you move or fly to up, then it check y position. It triggers when the coordinate falls within certain range. Range width is fixed both for horizontal and vertical levels. And coordinate of trigger gives offset of this range.
action x=1E0 y=0 code=1693A
Similarly, when Camera is in "good" position, then action is started. I call it at this moment "action" because it's similar to an "act" in theater, a part of a play in the theater.
unknown offs=16118 x=801 y=112 hb=0 code=1FF78
This means that my script unable identify what trigger does, but its real code is at offset 1FF78. You can disassemble it and look what it is. Similarly with other Camera-related triggers, it's only triggered when Camera in "good" position.
Other part of output is disassemble of actions code. It starts with:
======= action 1693A =======
it tells entry point of action.
Then code of action is listed until line
===========
Each line is in format: offset command
For example:
16946: set_timer F00
It means that at offset 16946 (hex) there is command set_timer with operand F00.
A little note about commands names. It's my naming, of course I have no idea about original naming.
Basic commands:
lock_screen - locks screen
unlock_screen - unlocks screen
set_enemy_limits - sets enemy limits which required to make this action active
set c1 - sets action own variable c1 to the value. it's used to make simple loops in conjunction with dbf.
set c2 - sets action own variable c2 to the value. it's used to make simple loops in conjunction with dbf.
exec - its single argument is offset of raw m68k code. you can disassemble it.
Control flow:
set_timer - set timer and postpone execution.
set_timer rand[ ) - set timer to a random value within range in the brackets. Brackets means low is inclusive, and high is not inclusive.
spawn - spawns something and postpone execution. Most of occurrences it's enemy. But I'm not sure if it's always enemy. See format of enemy description below.
spawn_multiple - spawns multiple enemies simultaneously, and postpone execution.
spawn_random - spawns one enemy from the list, and postpone execution.
wait_enemies - postpone execution until enemies less than or equal the number.
jmp - jump action execution to the offset
jmprnd - jump action execution to one from the list
dbf - two operands: counter and offset. Decrease counter and jump to the offset, but only if it was positive before. So if set c1 = 5, and then dbf c1, it means the number of repetition is 5.
die - terminate action, no mater when
jsr - jump to subroutine
rts - return back from subroutine
There is also several unknown commands. All of their names starts from "unknown".
Spawn description. there are four numbers in square brackets. First two is X and Y position. If brackets are round, then it's position relative to camera. If brackets are square, then it's global position. Third number is some parameter of enemy. I don't know at this moment. And the last number is offset to enemy code. Its code is not m68k raw code. It's in similar fashion as scripts of actions, but with some differences.
Important note about action execution. It is inactive if its timer value > 0, and if enemies count >= numbers in its parameters. In feos script in the video above. those 5, 5 numbers or 7FFF and 7FFF it's restriction for script being active. If enemies count (2 bytes value at offset FFDFAA) is high enough, script doesn't do anything. Literally. First of those two numbers is limit if one player alive, and second if two players alive. So, for example, action has numbers 3, 4 and one character alive, then it's require 2 or less enemies to be alive to even reduce timer of action. If other player press start to revive character, then it require 3 or less enemies to be alive. So, if 3 enemies were alive and timer was 0 at the moment when other player pressed start to revive character, then action will continue execution on the next frame, but it won't continue if other player won't press start.