News:

Don't forget to visit the main site! There's lots of helpful docs, patches, and more!

Main Menu

Manipulating the Intro Cutscenes

Started by interdpth, February 05, 2018, 08:49:25 PM

Previous topic - Next topic

interdpth

Hey there

Quick guide on how to manipulate the cutscenes for your pleasure!
Main intro function is at 0x8087708, I call it PlayIntroCutScenes and it's a rather large switch statement,
The cases are as follow,

Setup = 0
WaitTimer  = 1
PlayerUniverseCutscene = 2
PlaySR388CutScene = 3
PlaySamusAlmostDies = 4
PlaySamusInvaded = 5
PlaySamusFloat = 6
PlayScientistHelpSamus = 7
PlayMetroidCutscene = 8
PlaySamusUp = 9
StartNewFile = 0xA
FinishIntro = 0xB
LoadGame = 0xC

So these are all the states for the cutscene function, this state is stored in 0x03000BE0 the EventController(unsigned short/16 bit/2 bytes). The second important variable here is 0300148C the MiniEventCounter(unsigned short/16 bit/2 bytes).

The minievent controller determines what part of the cutscene runs, so you must manipulate both variables to get to your desired cutscene. Such as generally, you'd want to load the event controller number, and set the mini event counter to 0.


The sprites on screen are handled through 0x8098D4C which I called ProcessProperIntroScreen, this runs each frame I believe, the sprites are loaded each frame. It seems each sprite you see in the intro also has init ai for the most part. So it uses the in game OAM system, instead of just writing directly to OAM. I believe these also have hitboxes and collision....

So, using this info you can skip parts of the cutscenes. If you wish to load right into a cutscene, you'll need code like this. Example is lacking initing new game variables.

PUSH            {R7,LR}
ADD             R7, SP, #0
initvars()//pseudo-code below
LDR             R3, =word_3000BDE //Game Mode
MOVS            R2, #7
STRH            R2, [R3]
LDR             R3, =byte_3000BE0//Event Controller
MOVS            R2, #0xA
STRB            R2, [R3]
LDR             R3, =byte_3000BE2//SubGameMode01
MOVS            R2, #1
STRB            R2, [R3]
LDR             R3, =byte_300002C//CurrentArea
MOVS            R2, #0
STRB            R2, [R3]
LDR             R3, =byte_300002D//CurrentRoom
MOVS            R2, #0
STRB            R2, [R3]
LDR             R3, =byte_300134A///SamusisInvisible
MOVS            R2, #0
STRB            R2, [R3]
LDR             R3, =word_300148C//FrameEventcounter
MOVS            R2, #0
STRH            R2, [R3]
LDR             R3, =byte_3000B84//subgamemodeb84
MOVS            R2, #0
STRB            R2, [R3]
LDR             R3, =byte_3000B87//event counter
MOVS            R2, #0
STRB            R2, [R3]
LDR             R3, =loc_80003AC
MOV             PC, R3  //hijack PC register!

Example: https://youtu.be/oxteaj5jUP0?t=11



InitVars pseudo code:


   memfill(3, 0, MapExplored, 896,0);//8002FEC
   memfill(3, 0xFFFF, NoRespawn1, 4608,0);
   memfill(3, 0xFFFF, NoRespawn2, 2304,0);

   for (v0 = 0; v0 <= 7  ; v0++)
   {
      byte_3000033[v0] = 0;
      0x300003B[v0] = 0;
   }
   *&In_game_timer = 0;
   SamusIsInvisible = 0;
   UpdateSamusByEvent(0);//0x08074890
   byte_3000B88 = -1;
   word_3000062 = 255;
   SecurityDoorStatus = -1;
   DoorFlash = -1;
   LastSecurityDoorStatus = -1;
   DownloadedMapStatus = 0;
   LastAbilityEventWise = 0;
   CurrentArea = 7;
   currentRoom = 1;
   CurrentLastDoorProperties = 0;
   AreaBackupMan = 0;
   Curroom = 0;
   CurrentLastDoor =9;
   byte_300004C = 0;
   byte_300004D = 0;
   SamusXPosition = 0xE << 6;
   Previous_SamusX_position = SamusXPosition;
   SamusYPosition = 0x19 << 6;
   Previous_SamusY_position = SamusYPosition;
   LoadMinimapMaybe();
   Type_of_save_room = 0;
   BeamStatus = 1 & 2;//Charge and Wide Beam. Update to ENUM
   MissileBombsStatus = 0x10 | 0x1 | 0x2;//morphball, Missiles, Super Missiles
   SamusSuitStatus = 0x1 | 0x2 | 0x10 | 0x40; // Hi-Jump, Speed Booster, Varia, Morphball.
   SamusHealth = 299;
   SamusHealthmax = SamusHealth;
   SamusMissiles = 20;
   SamusMaxMissiles = SamusMissiles;
   EventCounter = 0;








OneOf99

You should make this a wiki page, this is very useful!