WC2 Cinematics reverse-engineering thread

Discussion in 'Fan Projects & Editing' started by delMar, Apr 14, 2018.

  1. delMar

    delMar Rear Admiral

    Messages:
    326
    Likes Received:
    57
    Trophy Points:
    22,935
    Gender:
    Male
    Location:
    Austria
    Just a space for collecting any findings.
    Anyone looking for more condensed information might want to prefer the thread over here: https://www.wcnews.com/chatzone/threads/wing-commander-toolbox.27769

    INCIDENT.S00 SceneGroup/ScriptGroup:
    Code:
            <SceneGroup>
              <ScriptGroup>
                <OffsetChunk file="INCIDENT.S00-ContainerBlock078-ContainerGroup-SceneGroup-ScriptGroup-OffsetChunk.bin" />
                <SymbolChunk>
                  <SymbolChunk.Items>
                    <SymbolItem Text="doit" />
                  </SymbolChunk.Items>
                </SymbolChunk>
              </ScriptGroup>
            </SceneGroup>
    I recognized that the SymbolItem Text (eg doit) always relates to the contents of the .bin files.
    eg: ScriptGroups called doit always have the following bytes in the .bin
    Code:
    01 00 04 00 00 00 23 88 16 22 0E FB FF
    Any .bin of ScriptGroups called WARPSHOT contains
    Code:
    01 00 04 00 00 00 23 88 00 89 4E 88 17 22 0E F7 FF
    Of course, I haven't verified all 114 containers, so I might be wrong.

    We have 114 Container Blocks. Except the blocks mentioned below, they all contain "doit".
    Code:
    Block 14: LoseFinale
    Block 15: LoseFinale
    Block 16: LoseFinale
    Block 28: WHAMMO
    Block 29: _TRAITOR_TALKS_
    Block 30: _TECH_IN_DOORWAY_
    Block 31: _TECH_TALKS_
    Block 32: _TECH_WALKS_UP_
    Block 33: _TECH_SEES_SCREEN_
    Block 34: _TRAITOR_TALKS_
    Block 35: _GUNSHOT_
    Block 36: _TECH_FALLS_
    Block 37: _DEAD_TECH_
    Block 38: WARPSHOT
    Block 39: WARPSHOT
    Block 40: WARPSHOT
    Block 41: WARPSHOT
    Block 42: WARPSHOT
    Block 43: WARPSHOT
    Block 44: _DEALING_CARDS_DEALT_
    Block 45: _CALL_AND_RAISE_
    Block 46: _COUNTING_CHIPS_
    Block 47: _HOBBES_GETS_CARDS_
    Block 48: _SPARKS_WORKING_
    Block 49: _DISMISS_
    Block 50: thefuneral
    Block 51: _TRAITOR_STANDING_
    Block 52: LockedOnJazz
    Block 53: _THREE_FOR_JAZZ_
    Block 54: Thrak_Walk
    Block 55: Kneel
    Block 56: Kneel
    Block 57: Kneel
    Block 58: Terran_Grasp
    Block 59: _SPIRIT_DEATH_
    Block 60: _SHADOW_DEATH_
    Block 61: Olympus
    Block 62: WARPSHOT
    Block 63: WARPSHOT
    Block 64: _EXPLOSION_ON_THE_FLIGHT_DECK_
    Block 65: WARPSHOT
    Block 69: hello
    Block 70: _PILOTS_LEAVE_BRIEF_
    Block 71: _PILOTS_ENTER_BRIEF_
    Block 72: _PILOTS_SITTING_
    Block 73: _EJECT_DEATH_
    Block 74: _EJECT_RESCUE_
    Block 75: _EST_NIVEN_
    Block 76: LockedOnJazz
    Block 77: SETUP_SCALE_FACTOR
    Block 80: _JAZZ_PULLS_GUN_
    Block 87: null
    Block 95: _kiss_
    Block 96: _kiss_
    Block 97: _kiss_
    Block 98: runthething
    Block 99: runthething
    Block 100: runthething
    Block 101: runthething
    Block 102: runthething
    Block 103: _BRIEFING_BACKGROUND_
    Block 104: _JAZZ_RESCUE_
    Block 105: dumdedum
    Block 113: runit
    Block 114: Kneel
    
     
  2. delMar

    delMar Rear Admiral

    Messages:
    326
    Likes Received:
    57
    Trophy Points:
    22,935
    Gender:
    Male
    Location:
    Austria
    Code:
    INCIDENT.S00-ContainerBlock078-SpriteGroup
    -----------------------------------------------------
    
    #background images, not moving, displayed permanently
    24 00 46 25 90 01 47                      23 0E FE FF 
    24 00 46 24 00    47                      23 0E FE FF
    24 00 46 25 C8 00 47                      23 0E FE FF
    
    #sprites for "ORIGIN Presents...", not moving, shown and hidden
    24 3C    46 24 40 47 9E 00 78 01 00 00 03 23 0E FE FF
    25 8C 00 46 24 40 47 9E 00 78 01 01 00 03 23 0E FE FF
    
    #sprites for "A Chris Roberts game", not moving, shown and hidden
    24 32    46 24 46 47 9E 00 78 01 02 00 03 23 0E FE FF
    24 47    46 24 46 47 9E 00 78 01 03 00 03 23 0E FE FF
    25 83 00 46 24 46 47 9E 00 78 01 04 00 03 23 0E FE FF
    25 DC 00 46 24 49 47 9E 00 78 01 05 00 03 23 0E FE FF
    
    #sprites for "Directed by Stephen Beeman", not moving, shown and hidden
    24 5A    46 24 37 47 9E 00 78 01 06 00 03 23 0E FE FF
    25 BE 00 46 24 3A 47 9E 00 78 01 07 00 03 23 0E FE FF
    24 46    46 24 4F 47 9E 00 78 01 08 00 03 23 0E FE FF
    25 A0 00 46 24 4C 47 9E 00 78 01 09 00 03 23 0E FE FF
    
    #WC2 Logo, not moving, shown and hidden
    24 14    46 24 03 47 9E 00 78 01 00 00 02 23 0E FE FF
    
    
    This is the Intro-Sequence again, Visualized in a different way.
    We see three different ways of data-definition.
    The first three lines are now more or less known. 23 0E FE FF is still not known, but ends every line in the file.

    The part
    Code:
    9E 00 78 01 00 00 03
    exists for all sprites that appear and disappear.
    The fifth part references the actual sprites, where 00 is ORIGIN and 09 is "Beeman"
    Code:
    9E 00 78 01 00 00 03 #ORIGIN
    9E 00 78 01 01 00 03 #Presents...
    9E 00 78 01 02 00 03 #asprite
    
    Their sequence is zero-based.

    The last line - displaying the WC2 Logo - is again different, in that the 13th byte is 02 instead of 03 and the index for the logo should be 0A, but is 00.

    So, the three background sprites (Starfields and Tiger's Claw) are not referenced in this part at all.
    The WC2 Logo is referenced, but not indexed according to all the other sprites.
     
    Last edited: Apr 14, 2018
  3. delMar

    delMar Rear Admiral

    Messages:
    326
    Likes Received:
    57
    Trophy Points:
    22,935
    Gender:
    Male
    Location:
    Austria
    SERIES.S00

    As most other files, this consists of a series of "Groups", most notably the TextGroup.
    But, as you can see in the snippet below, this comes without any specific information on the timings of backgrounds, sprites, text color, music, etc.
    In WC1, a cinematic description contains of
    • Background sprite
    • Foreground sprite(s)
    • Delay
    • Text color
    • branching information (eg Pilot still alive, ...)
    • facial expressions
    • Lip animation codes
    • the actual text :)
    So, all this information must be available in WC2 somehow, too.
    The text is easy, UnnamedCharacter has that already decoded.

    Code:
            <TextGroup>
              <SymbolChunk>
                <SymbolChunk.Items>
                  <SymbolItem Text="Observation Deck, TCS Concordia." />
                  <SymbolItem Text="ë, please join us.&#xA;Have you heard about Specialist McGuffin?" />
                  <SymbolItem Text="Somebody blew him away in the Commo Room." />
                  <SymbolItem Text="Do they have any clue&#xA;who might have done it?" />
                  <SymbolItem Text="Nothing yet.&#xA;At least, nothing they're letting out..." />
                  <SymbolItem Text="Could this be connected to the explosion on the flight deck?" />
                  <SymbolItem Text="That's possible.  Strange things have happened lately..." />
                  <SymbolItem Text="...and it all started right about&#xA;the time you came aboard, ë." />
                  <SymbolItem Text="Are you suggesting something, Major Colson?" />
                  <SymbolItem Text="Not at all, Captain.&#xA;Not at all." />
                  <SymbolItem Text="Briefing Room, TCS Concordia." />
                  <SymbolItem Text="Before we begin,&#xA;I wish to make a statement." />
                  <SymbolItem Text="You've all heard about the death&#xA;of Specialist McGuffin." />
                  <SymbolItem Text="Some of what you've heard is true.&#xA;McGuffin was murdered by a spy..." />
                  <SymbolItem Text="...a traitor, who was broadcasting&#xA;important data to the Kilrathi." />
                  <SymbolItem Text="We have reason to believe&#xA;the traitor is a fighter pilot." />
                  <SymbolItem Text="That is why the security team searched&#xA;all of the pilots' quarters this morning." />
                  <SymbolItem Text="Is that why Stingray isn't on the flight roster today?" />
                  <SymbolItem Text="There will be no loose talk&#xA;on this subject, Major." />
                  <SymbolItem Text="Stingray will return to duty tomorrow." />
                  <SymbolItem Text="With that out of the way,&#xA;let us get down to business." />
                  <SymbolItem Text="In a few minutes, the Concordia is jumping into the Ghorah Khar system." />
                  <SymbolItem Text="Reconnaissance near Niven indicates&#xA;that the Kilrathi moved through the Niven system..." />
                  <SymbolItem Text="...but their real target is Ghorah Khar,&#xA;the rogue Kilrathi colony that joined&#xA;the Confederation ten years ago." />
                  <SymbolItem Text="Angel assigns scout wings to clear&#xA;a route from the jump point to Ghorah Khar.&#xA;Your assignment is the last." />
                  <SymbolItem Text="å, you're back in your Ferret&#xA;for this one." />
                  <SymbolItem Text="You'll be flying a wide scout pattern&#xA;to the Concordia's port side." />
                  <SymbolItem Text="Pilots, you are dismissed." />
                  <SymbolItem Text=" " />
                  <SymbolItem Text="Welcome back, sir." />
                  <SymbolItem Text="Looks like it was a tough battle, sir!" />
                  <SymbolItem Text="Glad you made it back alive, sir." />
                  <SymbolItem Text="Colonel Devereaux's Office, TCS Concordia." />
                  <SymbolItem Text="What happened to your flight recorder,&#xA; å?" />
                  <SymbolItem Text="My flight recorder?" />
                  <SymbolItem Text="The Flight Deck officer said it was damaged,&#xA;that the data disk was destroyed." />
                  <SymbolItem Text="I must have taken a hit in combat..." />
                  <SymbolItem Text="...but that doesn't matter.&#xA;Angel, there are Kilrathi stealth fighters&#xA;in this system!" />
                  <SymbolItem Text="You are joking with me, non?" />
                  <SymbolItem Text="Angel, don't you believe me?&#xA;Those stealth fighters were real!" />
                  <SymbolItem Text="What am I supposed to do?" />
                  <SymbolItem Text="You have no flight recorder to prove&#xA;an encounter with these invisible fighters." />
                  <SymbolItem Text="Dammit, I trashed ç of those ships!" />
                  <SymbolItem Text="But there is no proof!" />
                  <SymbolItem Text="I will enter a record&#xA;that you killed ç Drakhri fighters..." />
                  <SymbolItem Text="...but no one will believe&#xA;this story of stealth ships." />
                  <SymbolItem Text="Dammit, I killed one of those bastards!" />
                  <SymbolItem Text="But there is no proof!" />
                  <SymbolItem Text="I will enter a record that&#xA;you killed a Drakhri ship..." />
                  <SymbolItem Text="...but no one will believe this story&#xA;of stealth fighters." />
                  <SymbolItem Text="It was a tough fight...&#xA;I couldn't nail a single one of them!" />
                  <SymbolItem Text="Angel, you have to tell Tolwyn&#xA;about this immediately!" />
                  <SymbolItem Text="I am sorry, å,&#xA;but I cannot take this to the Admiral." />
                  <SymbolItem Text="You've never believed&#xA;the stealth fighters exist, have you?" />
                  <SymbolItem Text="Not now, and not ten years ago,&#xA;when they destroyed the Tiger's Claw at &#xA; K'Tithrak Mang..." />
                  <SymbolItem Text="Angel, do you really believe I'm responsible&#xA;for the destruction of the Tiger's Claw?" />
                  <SymbolItem Text="Get some rest, å.&#xA;We'll talk about this later." />
                  <SymbolItem Text="Dammit, Jeannette!&#xA;Tell me what you think!" />
                  <SymbolItem Text="Please, ë.  I must go to the Bridge now.&#xA;We will talk later." />
                  <SymbolItem Text="Do you have anything to report, å?" />
                  <SymbolItem Text="It was an uneventful patrol, Angel." />
                  <SymbolItem Text="You are dismissed, Captain." />
                </SymbolChunk.Items>
              </SymbolChunk>
            </TextGroup>
    All the other information mentioned above seems to be contained in the SequenceGroup
    I'm using parts of SERIES.S00-ContainerBlock006-ContainerGroup-SequenceGroup-ScriptGroup-OffsetChunk.bin as an example, matching the XML above.
    I'm skipping the header here for brevity, the following snippet starts at offset 114.
    Code:
    23 92 00 00 9E 0C 85 2E 90 2E 24 00 28 FF 
    Both appearances of 2E refer to the background music.
    Change this to 3F, and you have piano music from the observation deck as background music for the cutscene at Niven (wc2 Origin s2 m2, for those who want to verify)

    If byte #12 (0x00) is changed to 0x01, debris passes by outside of the window behind Doomsday just as if we were in space. It only moves very slow, though.
    Also very interesting: debris is shown in the closeup and the full view. So, it seems to be a cutscene-wide setting, not just related to a single screen.

    In general, I think that "sections" in the binary most of the times start with 0x15 (of course, many others, too) and with 0xFF.
    The following part is at offset 192
    Code:
    28 88 06 24 22 28 FF
    byte 5 (0x22) is background for bluehair closeups and directly references the filename CLOSEUP.V00-Block034-Image000 (and Image001) - see the screenshot for a different background.

    Doomsday's closeup backgrounds are at offset 219:
    Code:
    28 88 06 24 21 28 FF
    This time the value is 0x21, referencing to CLOSEUP.V00-Block033-Image000

    The other groups' binaries are very small and also seem to contain duplicate information, just like most of the XML snippets
    PlaneGroup: 51 out of 51 are similar
    Code:
    01 00 FF FF FF FF
    SpriteGroup: 30 out of 51 are similar
    Code:
    08 00 FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF[CODE]
    
    SceneGroup: 49 out of 51 are similar
    [CODE]01 00 04 00 00 00 23 24 0F 81 26 04 24 00 1B 0F 07 00 88 16 0E 43 00 26 04 24 01 1B 0F 07 00 88 17 0E 36 00 26 04 24 02 1B 0F 07 00 88 18 0E 29 00 26 04 24 03 1B 0F 07 00 88 19 0E 1C 00 26 04 24 04 1B 0F 07 00 88 1A 0E 0F 00 26 04 24 05 1B 0F 07 00 88 1B 0E 02 00 83 00 00 FF 0E A9 FF
    All of this took the better part of the weekend. Not too much of a result here, but a first step.
    Unnamed's theory about the stack-based interpreter makes total sense. I just can't figure out, which commands there are in total.
    The 0x24 and 0x25 are great for orientation, however. If it wouldn't have been for that information, I wouldn't have much of a progress at all...
     

    Attached Files:

  4. delMar

    delMar Rear Admiral

    Messages:
    326
    Likes Received:
    57
    Trophy Points:
    22,935
    Gender:
    Male
    Location:
    Austria
    More on the block at offset 187.
    Code:
    15 24 00 28 FF #byte 3 (0x00) changes flightsuit of bluehair in closeup and full-view (screenshot)
    28 88 06 24 22 28 FF #byte 5 (0x22) is background for bluehair closeups (mentioned in previous post)
    28 88 08 24 22 28 FF
    1E 24 0A 24 01 00 28 FF #byte 3 (0x0A) changing this to 0x09 shows Doomsday looking into the other direction in closeups
    
     

    Attached Files:

  5. lskovlun

    lskovlun Spaceman

    Messages:
    4
    Likes Received:
    12
    Trophy Points:
    125
    There are 186 opcodes in total, but you also need to know the encoding of each, which isn't consistent. A disassembler is pretty much a prerequisite; trying to investigate these files as data is pretty much doomed.
    The offsets in my disassemblies seem to be off by a bit compared to your hex-editor screenshots, so take them with a grain of salt. Looking at INCIDENT.S00(78), the code for the tigerscreen sprite begins with $24 $00, meaning PUSH_CONSTB 0, followed by $46, SET_SPRITE_FIELD_2B - setting whatever field that is to zero. Then $25, $90, $01 (PUSH_CONSTW 400) and $47 (SET_SPRITE_FIELD_2D) to set that sprite field to 400.
    The $23, $0E, $FE, $FF thing is interesting. It corresponds to two instructions (YIELD and JUMP_RELATIVE -2). The first instruction makes the routine exit. But the JUMP_RELATIVE instruction creates a small infinite loop. I've toyed with various execution models because I can't experiment, and it looks like there is some sort of coroutine system (hence the name YIELD), and the infinite loop may be related to that. I am not sure about the specifics though.

    The tigerscreen code in full looks like:

    Code:
    Contents of sprite section of entry point 78:
    tigerscreen:
    0058 PUSH_CONSTB 0
    005a SET_SPRITE_FIELD_2B
    005b PUSH_CONSTW 400
    005e SET_SPRITE_FIELD_2D
    005f YIELD
    0060 JUMP_RELATIVE code_005f
    
    You'll notice that there is no reference to a graphics file here. Some of the other sprites perform that setup in their sprite routine, but not this one. The setup for tigerscreen comes later:
    Code:
    Contents of sequence section of entry point 78:
    __flicker__:
    005c LINK 1
    005e YIELD
    005f SELECT_SPRITE starfield
    0061 MUSIC2 0
    0063 SET_SPRITE_DAT 1, 0, 0, field.v00(1)
    0068 SELECT_SPRITE starfield2
    006a MUSIC2 0
    006c SET_SPRITE_DAT 1, 0, 0, field.v00(1)
    0071 SELECT_SPRITE tigerscreen
    0073 MUSIC2 0
    0075 SET_SPRITE_DAT 4, 0, 87, tiger.v00(0)
    007a PUSH_CONSTB 1
    007c SET_SPRITE_FIELD_4
    007d PUSH_CONSTB 0
    007f SELECT_PLANE bigscreen
    0081 SET_PLANE_TOP
    (much more code to perform the scrolling sequence)
    
    The contents of the bigscreen plane is set up in its routine:
    Code:
    Contents of plane section of entry point 78:
    bigscreen:
    0008 Opcode121 0, tigerscreen
    000b Opcode121 0, starfield
    000e Opcode121 0, starfield2
    0011 YIELD
    0012 JUMP_RELATIVE code_0011
    
    and the whole thing is started off from the scene section:
    Code:
    Contents of scene section of entry point 78:
    doit:
    0004 YIELD
    0005 RUN_SEQUENCE __flicker__
    0007 VM_RETVAL_ZERO
    0008 JUMP_RELATIVE code_0004
    
    which is called from SERIES.S00 as I showed in the other thread.
     
    delMar, L.I.F. and Quarto like this.
  6. Quarto

    Quarto Unknown Enemy

    Messages:
    11,881
    Likes Received:
    276
    Trophy Points:
    69,385
    Location:
    Poland
    I utterly love this. Someone comes along, registers to the forum, and in his first posts explains how he's been disassembling WC2 cutscenes, something that no one else has ever been able to do. Goodness, I wish we had more new users in general, but new users like this are the best :D. This stuff is wonderful, please keep it up!
     
    PopsiclePete, Shades2585 and L.I.F. like this.
  7. delMar

    delMar Rear Admiral

    Messages:
    326
    Likes Received:
    57
    Trophy Points:
    22,935
    Gender:
    Male
    Location:
    Austria
    I was thinking the same :)

    So, welcome Iskovlun :)
     
    PopsiclePete and L.I.F. like this.
  8. UnnamedCharacter

    UnnamedCharacter Ensign

    Messages:
    122
    Likes Received:
    106
    Trophy Points:
    2,235
    It seems appropriate that we should start compiling a list of all the instructions; so here is the beginning of it.

    Code:
    Dec Hex              Operands           Stack Behaviour   Flow Control  Description
    --- ---              --------           ---------------   ------------  -----------
    
    0   00  ADD                             Pop,Pop  Push     Next          Adds two numeric values, returning a new numeric value.
    1   01  SUB                             Pop,Pop  Push     Next          Subtracts one value from another, returning a new numeric value.
    2   02  MUL                             Pop,Pop  Push     Next          Multiplies two values.
    3   03  DIV                             Pop,Pop  Push     Next          Divides two values.
    ...
    35  23  YIELD                                             Yield/Return
    36  24  PUSH_CONSTB  int8               None     Push     Next          Pushes the supplied int8 value onto the stack.
    37  25  PUSH_CONSTW  int16              None     Push     Next          Pushes the supplied int16 value onto the stack.
    ...
    
    See the attached CSV file for the complete list (rename from txt).
     

    Attached Files:

    Shades2585 and delMar like this.
  9. lskovlun

    lskovlun Spaceman

    Messages:
    4
    Likes Received:
    12
    Trophy Points:
    125
    I'll just paste in my opcode list, as of today. A few things are recent and uncertain. This doesn't cover the opcode formats which are ostensibly the second parameter here, but some of these are actually deferred to the main loop code, so this doesn't tell the full story. One important opcode format detail is the variable-length integer. It is completely silly and inefficient, but for some reason they used it anyway. In some opcodes. It uses repeated bytes of $FF to signify multiples of 255 and then a remainder. Thus, $28 $FF $19 is POP_SET_GLOBAL 280 (255 + 25) and $28 $FF $FF $19 is POP_SET_GLOBAL 535. The list also doesn't say when values are popped off the stack.
    Code:
        Opcode("ADD", "", false),
       Opcode("SUB", "", false),
       Opcode("IMUL", "", false),
       Opcode("IDIV", "", false),
       Opcode("IMOD", "", false),
       Opcode("LOG_AND", "", false),
       Opcode("LOG_OR", "", false),
       Opcode("LOG_NOT", "", false),
       Opcode("RAND_RANGE", "", false),
       Opcode("SHL", "", false),
       Opcode("SHR", "", false),
       Opcode("BIN_AND", "", false),
       Opcode("BIN_OR", "", false),
       Opcode("BIN_XOR", "", false),
       Opcode("JUMP_RELATIVE", "o", false),
       Opcode("JUMP_IF_FALSE", "o", false),
       Opcode("UNUSED16", "", false),
       Opcode("UNUSED17", "", false),
       Opcode("UNUSED18", "", false),
       Opcode("UNUSED19", "", false),
       Opcode("UNUSED20", "", false),
       Opcode("UNUSED21", "", false),
       Opcode("UNUSED22", "", false),
       Opcode("COMPARE_LT", "", false),
       Opcode("COMPARE_GT", "", false),
       Opcode("COMPARE_LE", "", false),
       Opcode("COMPARE_GE", "", false),
       Opcode("COMPARE_EQ", "", false),
       Opcode("COMPARE_NE", "", false),
       Opcode("IS_ZERO", "", false),
       Opcode("IS_NONZERO", "", false),
       Opcode("SELECT_SPRITE", "e", false),
       Opcode("SELECT_PLANE", "e", false),
       Opcode("SELECT_SEQUENCE", "b", false),
       Opcode("VM_RETVAL_ZERO", "", false),
       Opcode("YIELD", "", false),
       Opcode("PUSH_CONSTB", "B", false),
       Opcode("PUSH_CONSTW", "w", false),
       Opcode("PUSH_GLOBAL", "v", false),
       Opcode("PUSH_ARRAY_INDEX", "w", false),
       Opcode("POP_SET_GLOBAL", "v", false),
       Opcode("POP_SET_ARRAY_INDEX", "w", false),
       Opcode("CYCLE_SPRITE_FWD", "", false),
       Opcode("CYCLE_SPRITE_BKWD", "", false),
       Opcode("PUSH_SPRITE_FIELD_0", "", false),
       Opcode("PUSH_SPRITE_VISIBLE", "", false),
       Opcode("PUSH_SPRITE_FIELD_4", "", false),
       Opcode("PUSH_SPRITE_FIELD_A", "", false),
       Opcode("PUSH_SPRITE_CEL", "", false),
       Opcode("PUSH_SPRITE_MAX_CEL", "", false),
       Opcode("PUSH_SPRITE_FIELD_1C", "", false),
       Opcode("PUSH_SPRITE_FIELD_22", "", false),
         Opcode("PUSH_SPRITE_FIELD_2B", "", false),
       Opcode("PUSH_SPRITE_FIELD_2D", "", false),
       Opcode("PUSH_SPRITE_FIELD_2F", "", false),
       Opcode("PUSH_SPRITE_FIELD_31", "", false),
       Opcode("PUSH_SPRITE_SCALE_FACTOR", "", false),
       Opcode("PUSH_SPRITE_FIELD_35", "", false),
       Opcode("PUSH_SPRITE_FIELD_28", "", false),
       Opcode("PUSH_SPRITE_FIELD_29", "", false),
       Opcode("PUSH_SPRITE_FIELD_2A", "", false),
       Opcode("PUSH_SPRITE_LOCAL", "b", false),
       Opcode("SET_SPRITE_FIELD_0", "", false),
       Opcode("SET_SPRITE_VISIBLE", "", false),
       Opcode("SET_SPRITE_FIELD_4", "", false),
       Opcode("SET_SPRITE_FIELD_A", "", false),
       Opcode("SET_SPRITE_CEL", "", false),
       Opcode("SET_SPRITE_MAX_CEL", "", false),
       Opcode("SET_SPRITE_FIELD_1C", "", false),
       Opcode("SET_SPRITE_FIELD_22", "", false),
       Opcode("SET_SPRITE_FIELD_2B", "", false),
       Opcode("SET_SPRITE_FIELD_2D", "", false),
       Opcode("SET_SPRITE_FIELD_2F", "", false),
       Opcode("SET_SPRITE_FIELD_31", "", false),
       Opcode("SET_SPRITE_SCALE_FACTOR", "", false),
       Opcode("SET_SPRITE_FIELD_35", "", false),
       Opcode("SET_SPRITE_FIELD_28", "", false),
       Opcode("SET_SPRITE_FIELD_29", "", false),
       Opcode("SET_SPRITE_FIELD_2A", "", false),
       Opcode("SET_SPRITE_LOCAL", "b", false),
       Opcode("PUSH_PLANE_FIELD_0", "", false),
       Opcode("PUSH_PLANE_FIELD_1", "", false),
       Opcode("PUSH_PLANE_FIELD_17", "", false),
       Opcode("PUSH_PLANE_TOP", "", false),
       Opcode("PUSH_PLANE_FIELD_1B", "", false),
       Opcode("PUSH_PLANE_FIELD_1D", "", false),
       Opcode("PUSH_PLANE_FIELD_1F", "", false),
       Opcode("PUSH_PLANE_LOCAL", "b", false),
       Opcode("PUSH_PLANE_FIELD_21", "", false),
       Opcode("PUSH_PLANE_FIELD_14", "", false),
       Opcode("PUSH_PLANE_FIELD_15", "", false),
       Opcode("PUSH_PLANE_FIELD_16", "", false),
       Opcode("SET_PLANE_FIELD_0", "", false),
       Opcode("SET_PLANE_FIELD_1", "", false),
       Opcode("SET_PLANE_FIELD_17", "", false),
       Opcode("SET_PLANE_TOP", "", false),
       Opcode("SET_PLANE_FIELD_1B", "", false),
       Opcode("SET_PLANE_FIELD_1D", "", false),
       Opcode("SET_PLANE_FIELD_1F", "", false),
       Opcode("SET_PLANE_LOCAL", "b", false),
       Opcode("SET_PLANE_FIELD_21", "", false),
       Opcode("SET_PLANE_FIELD_14", "", false),
       Opcode("SET_PLANE_FIELD_15", "", false),
       Opcode("SET_PLANE_FIELD_16", "", false),
       Opcode("PUSH_SEQ_FIELD_0", "", false),
       Opcode("SET_SEQ_FIELD_0", "", false),
       Opcode("PUSH_SEQ_FIELD_17", "", false),
       Opcode("DELAY_SEQ", "", false),
       Opcode("RUN_PLANE", "e", false),
       Opcode("RUN_SPRITE", "e", false),
       Opcode("PRINT_VIEWPORT", "b", false),
       Opcode("GET_TEXT", "E", false),
       Opcode("PUSH_SEQ_LOCAL", "b", false),
       Opcode("SET_SEQ_LOCAL", "b", false),
       Opcode("UNUSED114", "", false),
       Opcode("UNUSED115", "", false),
       Opcode("PUSH_SCENE_LOCAL", "", false), // These won't work, because LINK can't create
       Opcode("SET_SCENE_LOCAL", "", false),  // the necessary globals
       Opcode("UNUSED118", "", false),
       Opcode("LINK", "b", false), // Allocate local variables for current routine
       Opcode("SET_SPRITE_DAT", "bbbV", false),
       Opcode("ADD_TO_PLANE", "be", false), // Other subfunctions too, but never used in game
       Opcode("Opcode122", "be", false), // Several subfunctions used in game
       Opcode("LIST_FUNCS", "b", false), // Several subfunctions
       Opcode("Opcode124", "", false),
       Opcode("AWAIT_KEYPRESS", "", false), // I Think???
       Opcode("DELAY", "", false),
       Opcode("SET_GFVIEW_TOP", "B", false),
       Opcode("VIEWPORT_STUFF1", "", false),
       Opcode("SET_STYLE_COLOR", "", false),
       Opcode("SELECT_FONT", "bb", false),
       Opcode("SET_PALETTE", "bbb", false),
       Opcode("INIT_FX", "e", false),
       Opcode("MUSIC3", "e", false),
       Opcode("SET_???", "", false),
       Opcode("SAY_WITH", "Ee", false),
       Opcode("RUN_SEQUENCE", "e", false),
       Opcode("RUN_SCENE", "e", false),
       Opcode("MOUTH_STUFF", "e", false), // Only called from one location
       Opcode("VIEWPORT_STUFF2", "", false),
       Opcode("FADE_OUT", "", false),
       Opcode("SET_ANIM_DELAY", "", false),
       Opcode("SET_UNUSED1", "", false),
       Opcode("SET_ANIM_DELAY2", "", false), // Different units, also sets something else
       Opcode("MUSIC4", "e", false),
       Opcode("ALLOC_FX", "b", false),
       Opcode("MUSIC1", "w", false),
       Opcode("DISCARD_FX", "b", false),
       Opcode("CLEAR_VIEWPORT", "b", false),
       Opcode("SET_UNUSED2", "", false),
       Opcode("DISCARD_FONT", "", false),
       Opcode("DISCARD_MUSIC", "b", false),
       Opcode("UNINIT_FX", "", false),
       Opcode("DISCARD_SPRITE", "V", false),
       Opcode("DISCARD_SPRITES", "", false),
       Opcode("PUSH_???", "", false),
       Opcode("PUSH_???", "", false),
       Opcode("SKIP_TO_NEXT?", "", false), // Detects ESC presses. Scripts use this periodically  and jump to the end if true
       Opcode("MUSIC2", "b", false),
       Opcode("SET_FX_STUFF", "", false),
       Opcode("UNUSED160", "", false),
       Opcode("MEM_REPORT", "", false), // On screen and in log file
       Opcode("PRELOAD_SPEECH", "e", false),
       Opcode("IS_DEBUG_ON", "", false),
       Opcode("MANIP_SKIP", "", false), // Various subfunctions based on TOS
       Opcode("WIPE", "b", false),
       Opcode("NAV_MAP", "eE", false),
       Opcode("SHOW_COMM", "", false),
       Opcode("COPY_SPRITE", "ee", false),
       Opcode("IS_WINGMAN_DAMAGED?", "", false),
       Opcode("SET_PLANE_FIELD_25", "", false),
       Opcode("PUSH_PLANE_FIELD_25", "", false),
       Opcode("COPY_SPRITE2", "ee", false),
       Opcode("FREE_SPRITE", "e", false),
       Opcode("SET_PRINT_RECT", "b", false),
       Opcode("SCROLL_CREDITS", "b", false),
       Opcode("SPEAK_AUDIO", "", false),
       Opcode("LOG_CONST", "w", false),
       Opcode("SET_VOLUME", "b", false),
       Opcode("PRINT_VIEWPORT2", "", false),
       Opcode("MIDI_STUFF", "", false),
       Opcode("ALLOC_COMM", "", false),
       Opcode("FREE_COMM", "", false),
       Opcode("GRAPHICS_???", "", false),
       Opcode("POP", "", false),
       Opcode("LOG_POPPED", "E", false),
    
     
  10. Stinger

    Stinger Vice Admiral

    Messages:
    860
    Likes Received:
    118
    Trophy Points:
    29,535
    Thanks for this; it may come in handy for wcdx later.
     
  11. delMar

    delMar Rear Admiral

    Messages:
    326
    Likes Received:
    57
    Trophy Points:
    22,935
    Gender:
    Male
    Location:
    Austria
    Ha, finally I know why skipping cinematics sometimes takes multiple keypresses until it finally does skip.
     
  12. UnnamedCharacter

    UnnamedCharacter Ensign

    Messages:
    122
    Likes Received:
    106
    Trophy Points:
    2,235
    See the attached CSV file for the updated list (rename from txt).
     

    Attached Files:

  13. UnnamedCharacter

    UnnamedCharacter Ensign

    Messages:
    122
    Likes Received:
    106
    Trophy Points:
    2,235
    Scene Transitions

    There appears to be three kinds of transition wipes: line, diagonal, and iris. They are conveniently all located in the same file: CAMPAIGN.S00; Block 000; Sequence Script; Entry 020 (doshow). And they are selected using OpCode 165; "SELECT_WIPE wipeIndex". As for the wipe index, the following values are possible:
    • 0: wipe down; horizontal line wipe (from top to bottom)
    • 1: wipe left; vertical line wipe (from right to left)
    • 2: wipe up; horizontal line wipe (from bottom to top)
    • 3: wipe right; vertical line wipe (from left to right)
    • 4: wipe diagonal (from top left to bottom right)
    • 5: wipe diagonal (from top right to bottom left)
    • 6: wipe diagonal (from bottom right to top left)
    • 7: wipe diagonal (from bottom left to top right)
    • 8: iris from center to edges
    • 9: iris from edges to center
    Code:
    .entry ;  20
    
      _0011:  c038         388                      ; get global[<uintvar:index>]
      _0014:  c036           1                      ; push constant, byte
      _0016:  c027                                  ; ==
      _0017:  c015       _0022                      ; jz
      _001a:  c038         390                      ; get global[<uintvar:index>]
      _001d:  c165           8                      ; select wipe <int8:index>
      _001f:  c014       _00bb                      ; jmp
      _0022:  c038         388                      ; get global[<uintvar:index>]
      _0025:  c036           2                      ; push constant, byte
      _0027:  c027                                  ; ==
      _0028:  c015       _0033                      ; jz
      _002b:  c038         390                      ; get global[<uintvar:index>]
      _002e:  c165           9                      ; select wipe <int8:index>
      _0030:  c014       _00bb                      ; jmp
    
    And some examples:

    wc2_transition1-031.png wc2_transition1-032.png wc2_transition1-033.png

    wc2_transition5-030.png wc2_transition5-031.png wc2_transition5-032.png

    wc2_transition8-029.png wc2_transition8-030.png wc2_transition8-031.png
     
  14. Shades2585

    Shades2585 none

    Messages:
    596
    Likes Received:
    22
    Trophy Points:
    26,185
    Wow! Nice work!! Keep it up! :D
     
  15. lskovlun

    lskovlun Spaceman

    Messages:
    4
    Likes Received:
    12
    Trophy Points:
    125
    Problem: In practice, SERIES does not call the the WIPE opcode directly, but uses it indirectly through the standard library. SERIES doesn't even call doshow directly, but rather some other higher-level things (INCIDENT does call doshow directly). When doing it this way, you set global 388 (and possibly global 390, to set the duration it seems, but this is never used in the game), but the wipe indices you put there do not match those passed to the WIPE opcode! This same issue is true of other things like setting faces and background scenes: You can't directly match the high-level variable settings (in SERIES/INCIDENT) to the graphics files used and their indices without reading the code.

    So, using your list as a basis, but permuting it according to the doshow routine, we get:
    • 0: no transition animation
    • 1: iris from center to edges
    • 2: iris from edges to center
    • 3: wipe right; vertical line wipe (from left to right)
    • 4: wipe left; vertical line wipe (from right to left)
    • 5: wipe down; horizontal line wipe (from top to bottom)
    • 6: wipe up; horizontal line wipe (from bottom to top)
    • 7: wipe diagonal (from bottom left to top right)
    • 8: wipe diagonal (from top left to bottom right)
    • 9: wipe diagonal (from top right to bottom left)
    • 10: wipe diagonal (from bottom right to top left)
    Notice the top one... according to your list there is no way to specify "no wipe" when calling WIPE directly while there is when setting global 388. But this whole thing is kind of a WTF.
     
  16. wcnut

    wcnut Rear Admiral

    Messages:
    466
    Likes Received:
    44
    Trophy Points:
    24,135
    Wow they really did take a lot from george lucas :)
     
    UnnamedCharacter likes this.

Share This Page