| |
ros:expert_guides:disasm04 [2025/03/01 00:18] – created mariofan2468 | ros:expert_guides:disasm04 [2025/08/31 18:38] (current) – enemyDataSlotSize mariofan2468 |
---|
| |
Here is my interpretation of how the computer runs ''deactivateAllEnemies'' after shooting the block. Step through the code yourself and cross-reference with my interpretation to find where things go wrong. | Here is my interpretation of how the computer runs ''deactivateAllEnemies'' after shooting the block. Step through the code yourself and cross-reference with my interpretation to find where things go wrong. |
''a'' is initialized to $FF, the status value for an enemy slot that is empty, as explained in "docs/Enemy Headers.md". ''hl'' is initialized to the first element in the ''enemyDataSlots'' table. ''c'' is initialized to ''ENEMY_SLOT_SIZE'', the size of an element in ''enemyDataSlots''. ''d'' is initialized to $10, the quantity of elements in ''enemyDataSlots''. | ''a'' is initialized to $FF, the status value for an enemy slot that is empty, as explained in "docs/Enemy Headers.md". ''hl'' is initialized to the first element in the ''enemyDataSlots'' table. ''c'' is initialized to ''enemyDataSlotSize'', the size of an element in ''enemyDataSlots''. ''d'' is initialized to $10, the quantity of elements in ''enemyDataSlots''. |
Now we reach the ''deactivateAllEnemies.loop_A''. $FF is written to the status of the first enemy slot in ''enemyDataSlots''. ''bc'' is added to ''hl'' so that ''hl'' now points to the second enemy slot in ''enemyDataSlots''. ''d'' is decremented by one to update the number of elements left. Then since ''d'' was not zero, we jump back to the start of ''.loop_A''. | Now we reach the ''deactivateAllEnemies.loop_A''. $FF is written to the status of the first enemy slot in ''enemyDataSlots''. ''bc'' is added to ''hl'' so that ''hl'' now points to the second enemy slot in ''enemyDataSlots''. ''d'' is decremented by one to update the number of elements left. Then since ''d'' was not zero, we jump back to the start of ''.loop_A''. |
| |
This bug is untriggerable in vanilla Metroid II, because the only routine that calls ''deactivateAllEnemies'' coincidentally happens to have a value of $00 for ''b'' before the call. | This bug is untriggerable in vanilla Metroid II, because the only routine that calls ''deactivateAllEnemies'' coincidentally happens to have a value of $00 for ''b'' before the call. |
| |
This is quite easy to fix. Simply replacing the line ''ld c, ENEMY_SLOT_SIZE'' with ''ld bc, ENEMY_SLOT_SIZE'' will initialize ''b'' properly. Compile and test. It crashes again, but in a different way. If you approach the missile block from the right side of the ship and shoot a missile from under it, the game resets to the title screen. However, if you roll under the ship and approach the missile block from the left side before shooting a missile from under it, the game will not crash. We're making progress. Let's use the debugger again to find out the cause of this latest crash. | This is quite easy to fix. Simply replacing the line ''ld c, enemyDataSlotSize'' with ''ld bc, enemyDataSlotSize'' will initialize ''b'' properly. Compile and test. It crashes again, but in a different way. If you approach the missile block from the right side of the ship and shoot a missile from under it, the game resets to the title screen. However, if you roll under the ship and approach the missile block from the left side before shooting a missile from under it, the game will not crash. We're making progress. Let's use the debugger again to find out the cause of this latest crash. |
| |
Using the same breakpoint as last time, shoot the missile block in such a way that it will crash the game. | Using the same breakpoint as last time, shoot the missile block in such a way that it will crash the game. |