Wing Commander Toolbox

Discussion in 'Fan Projects & Editing' started by UnnamedCharacter, Feb 26, 2015.

  1. UnnamedCharacter

    UnnamedCharacter Ensign

    Messages:
    156
    Likes Received:
    161
    Trophy Points:
    2,385
    They are within the WING2.TIM file. The file has three blocks dividing the effects by audio format: MIDI, SoundBlaster, PC Speaker. If you unpack the TIM file and view the content of individual files (ex: WING2.TIM-Block000Midi-Audio009.tim), you will see the effect name.

    There is also the file FX.000 which as to do with sound effects, but I have no idea what it does. It seems specific to the cinematic scenes only.
     
    delMar likes this.
  2. delMar

    delMar Rear Admiral

    Messages:
    326
    Likes Received:
    57
    Trophy Points:
    23,035
    Gender:
    Male
    Location:
    Austria
    Nice.
    What do I need to do to have files that I can actually play in VLC for example?
    Just changing the file extension doesn't work :)

    I'm especially interested in the SoundBlaster files, btw
     
  3. UnnamedCharacter

    UnnamedCharacter Ensign

    Messages:
    156
    Likes Received:
    161
    Trophy Points:
    2,385
    I don't think these files are "playable". My guess is these files are patches for an audio system. You will probably have more luck experimenting with the Roland MT-32 sounds within the game as there seems to be good tooling for these.
     
  4. delMar

    delMar Rear Admiral

    Messages:
    326
    Likes Received:
    57
    Trophy Points:
    23,035
    Gender:
    Male
    Location:
    Austria
    Alright, thanks.

    Hm, speech files are in .voc format.
    Maybe these are just .voc files without the header...
     
  5. delMar

    delMar Rear Admiral

    Messages:
    326
    Likes Received:
    57
    Trophy Points:
    23,035
    Gender:
    Male
    Location:
    Austria
    I wanted to take a look into cinematics.
    For reverse engineering, it's best to start with a piece that's small and (supposedly) easy to understand.

    I looked a bit into INCIDENT.S00, especially into INCIDENT.S00-ContainerBlock078-ContainerGroup-PlaneGroup-ScriptGroup-OffsetChunk.bin

    ContainerBlock 078 deals with the short cutscene right after clicking "New Game" up to destroying the Tiger's Claw.
    Prince Thrakath talking to the Emperor is not part of this anymore.

    So, what we see in this cinematic is
    • A background of stars
    • The words "ORIGIN Presents..."
    • "A Chris Roberts game"
    • "Directed by Stephen Beeman"

    This is far from complete, but I just wanted to keep track of what I'm doing. And everyone loves updates, right? :)

    The content of the .bin file mentioned above is as follows
    Code:
    02 00 FF FF FF FF 04 00 00 00 79 00 08 79 00 09 79 00 0A 23 0E FE FF
    All the relevant XML is shown below.

    I found out the following about the .bin file:
    • I think the 02 00 at the beginning refers to "backdrop" and "bigscreen" of PlaneGroup/ScriptGroup
    • The FF FF FF FF seems to be some kind of placeholder. I don't think it's actually interpreted.
    • 04 00 00 00 might refer to 4 blocks that are following. These 4 blocks are as follows
    1. 79 00 08
    2. 79 00 09
    3. 79 00 0A
    4. 23 0E FE FF
    The 08, 09 and 0A at the end refer to SpriteGroup/ScriptGroup SymbolItems and describe the index of the Sprite.
    If you replace the 08 with 10 (which is actually 16, as it's all hex numbers here), you wouldn't see the background of stars scrolling up, but the sprite holding the word "game" from "A game by Chris Roberts".
    So, 08 is tigerscreen, 09 is starfield, and 0A is starfield2
    starfield and starfield2 actually refer to the same image (the second image stored in field.v00).
    I have no idea, what 23 0E FE FF mean.
    Changing 79 to 78 or 80 crashed the game
    Changing the 23 0E to anything else crashed the game.
    I think the FE FF is just some kind of terminator to end the datablock

    I also checked INCIDENT.S00-ContainerBlock078-ContainerGroup-SpriteGroup-ScriptGroup-OffsetChunk.bin

    upload_2018-4-13_20-52-37.png

    The 16 00 at the beginning seems to be an offset to when data actually starts (FF FF x 16)
    After that, we have numbers like 38 00 00 00 3F 00 00 00 etc. 14 of them in total.
    14 matches the SpriteGroup/ScriptGroup SymbolItems, when ignoring the __slot ones.
    What could these 38, 3F, 45 mean?
    Well, I think they are lengths for the datablocks that are following these 14 values.
    I'm pretty sure they match the list of sprites again.
    The blocks are:
    Code:
    24 00 46 25 90 01 47 23 0E FE FF #tigerscreen
    24 00 46 24 00 47 23 0E FE FF #starfield
    24 00 46 25 C8 00 47 23 0E FE FF #starfield2
    
    24 3C 46 24 40 47 9E 00 78 01 00 00 03 23 0E FE FF #origin
    25 8C 00 46 24 40 47 9E 00 78 01 01 00 03 23 0E FE FF #presents
    
    24 32 46 24 46 47 9E 00 78 01 02 00 03 23 0E FE FF #asprite
    24 47 46 24 46 47 9E 00 78 01 03 00 03 23 0E FE FF #chris
    25 83 00 46 24 46 47 9E 00 78 01 04 00 03 23 0E FE FF #roberts
    25 DC 00 46 24 49 47 9E 00 78 01 05 00 03 23 0E FE FF #game
    
    24 5A 46 24 37 47 9E 00 78 01 06 00 03 23 0E FE FF #directed
    25 BE 00 46 24 3A 47 9E 00 78 01 07 00 03 23 0E FE FF #by
    24 46 46 24 4F 47 9E 00 78 01 08 00 03 23 0E FE FF #stephen
    25 A0 00 46 24 4C 47 9E 00 78 01 09 00 03 23 0E FE FF #beeman
    
    24 14 46 24 03 47 9E 00 78 01 00 00 02 23 0E FE FF #logosprite
    
    To take one example, I was pretty sure I figured out some more details:
    Code:
    24 32 46 24 46 47 9E 00 78 01 02 00 03 23 0E FE FF #asprite
    32 could be the x-position of the sprite. It matches my measures from screenshots.
    Changing that value actually moved the sprite, but just to x-pos=0, not to the position I specified... (see two screenshots attached to see the result)
    47 could be the y-position, but just changing it didn't show the expected results.
    These x and y values match the coordinates of all 14 sprites, so I'm pretty convinced it's something related to that.
    23 0E FE FF is at the end of each line, just like in the other .bin file I described before.

    In general: FileEntryItem-Identifier in FileEntryItem always refers to the index of FileEntryNameItems in FileChunk.Names.
    So, Block="0" Identifier="0" refers to the first entry in tiger.v00 (which one that is can be read in tiger.v00.xml when using xmlunpack on it)

    As I said, not too much to see here, but in case anyone else is looking into this, I wanted to share my findings.

    Things still missing:
    • investigating SequenceGroup
    • investigating SceneGroup
    They probably keep information about timings, actual actions (like scroll up, fade-in, display, remove, ...)

    @UnnamedCharacter let me know if you prefer things like these to be in a separate thread.

    Code:
       
      <ContainerBlock.Chunks>
          <ContainerGroup>
            <TextGroup>
              <SymbolChunk>
                <SymbolChunk.Items>
                  <SymbolItem Text="TCS Tiger's Claw.&#xA;On attack approach to K'Tithrak Mang,&#xA;Kilrathi Sector HQ." />
                </SymbolChunk.Items>
              </SymbolChunk>
            </TextGroup>
            <ShapeGroup>
              <FileChunk>
                <FileChunk.Entries>
                  <FileEntryItem Block="0" Identifier="0" />
                  <FileEntryItem Block="1" Identifier="1" />
                  <FileEntryItem Block="0" Identifier="2" />
                  <FileEntryItem Block="0" Identifier="3" />
                </FileChunk.Entries>
                <FileChunk.Names>
                  <FileEntryNameItem Name="tiger.v00" />
                  <FileEntryNameItem Name="field.v00" />
                  <FileEntryNameItem Name="logo.v00" />
                  <FileEntryNameItem Name="titles.v00" />
                </FileChunk.Names>
              </FileChunk>
            </ShapeGroup>
            <FilmGroup>
              <FileChunk>
                <FileChunk.Entries>
                  <FileEntryItem Block="48" Identifier="0" />
                </FileChunk.Entries>
                <FileChunk.Names>
                  <FileEntryNameItem Name="series.s00" />
                </FileChunk.Names>
              </FileChunk>
            </FilmGroup>
            <SpriteGroup>
              <ScriptGroup>
                <OffsetChunk file="INCIDENT.S00-ContainerBlock078-ContainerGroup-SpriteGroup-ScriptGroup-OffsetChunk.bin" />
                <SymbolChunk>
                  <SymbolChunk.Items>
                    <SymbolItem Text="__slot0" />
                    <SymbolItem Text="__slot1" />
                    <SymbolItem Text="__slot2" />
                    <SymbolItem Text="__slot3" />
                    <SymbolItem Text="__slot4" />
                    <SymbolItem Text="__slot5" />
                    <SymbolItem Text="__slot6" />
                    <SymbolItem Text="__slot7" />
                    <SymbolItem Text="tigerscreen" />
                    <SymbolItem Text="starfield" />
                    <SymbolItem Text="starfield2" />
                    <SymbolItem Text="origin" />
                    <SymbolItem Text="presents" />
                    <SymbolItem Text="asprite" />
                    <SymbolItem Text="chris" />
                    <SymbolItem Text="roberts" />
                    <SymbolItem Text="game" />
                    <SymbolItem Text="directed" />
                    <SymbolItem Text="by" />
                    <SymbolItem Text="stephen" />
                    <SymbolItem Text="beeman" />
                    <SymbolItem Text="logosprite" />
                  </SymbolChunk.Items>
                </SymbolChunk>
              </ScriptGroup>
            </SpriteGroup>
            <PlaneGroup>
              <ScriptGroup>
                <OffsetChunk file="INCIDENT.S00-ContainerBlock078-ContainerGroup-PlaneGroup-ScriptGroup-OffsetChunk.bin" />
                <SymbolChunk>
                  <SymbolChunk.Items>
                    <SymbolItem Text="backdrop" />
                    <SymbolItem Text="bigscreen" />
                  </SymbolChunk.Items>
                </SymbolChunk>
              </ScriptGroup>
            </PlaneGroup>
            <SequenceGroup>
              <ScriptGroup>
                <OffsetChunk file="INCIDENT.S00-ContainerBlock078-ContainerGroup-SequenceGroup-ScriptGroup-OffsetChunk.bin" />
                <SymbolChunk>
                  <SymbolChunk.Items>
                    <SymbolItem Text="removeall" />
                    <SymbolItem Text="showslot" />
                    <SymbolItem Text="hideslot" />
                    <SymbolItem Text="delmediumslot" />
                    <SymbolItem Text="setupmediumslot" />
                    <SymbolItem Text="mediumshot" />
                    <SymbolItem Text="setupuniform" />
                    <SymbolItem Text="setupbackdrop" />
                    <SymbolItem Text="setupbackground" />
                    <SymbolItem Text="initshardrun" />
                    <SymbolItem Text="talking" />
                    <SymbolItem Text="settalker" />
                    <SymbolItem Text="vidit" />
                    <SymbolItem Text="printit" />
                    <SymbolItem Text="closeup" />
                    <SymbolItem Text="restoredefaultfont" />
                    <SymbolItem Text="removeperson" />
                    <SymbolItem Text="addplanet" />
                    <SymbolItem Text="removeplanet" />
                    <SymbolItem Text="narrating" />
                    <SymbolItem Text="doshow" />
                    <SymbolItem Text="sidewaysthrusters" />
                    <SymbolItem Text="__flicker__" />
                  </SymbolChunk.Items>
                </SymbolChunk>
              </ScriptGroup>
            </SequenceGroup>
            <SceneGroup>
              <ScriptGroup>
                <OffsetChunk file="INCIDENT.S00-ContainerBlock078-ContainerGroup-SceneGroup-ScriptGroup-OffsetChunk.bin" />
                <SymbolChunk>
                  <SymbolChunk.Items>
                    <SymbolItem Text="doit" />
                  </SymbolChunk.Items>
                </SymbolChunk>
              </ScriptGroup>
            </SceneGroup>
          </ContainerGroup>
        </ContainerBlock.Chunks>
      </ContainerBlock>
    
     

    Attached Files:

    Quarto and Shades2585 like this.
  6. UnnamedCharacter

    UnnamedCharacter Ensign

    Messages:
    156
    Likes Received:
    161
    Trophy Points:
    2,385
    Yes, thank you. I think all this information could become a long thread indeed. Hopefully it will become a very long thread as there is a lot of information to be compiled.

    I have been making some progress as well on this. From what I have gathered, the game appears to use a Stack-Based Bytecode Interpreter; it pushes/pops values on a stack. I have reformatted your code examples to show the structure of *.bin files. See also previous post for *.bin file header details.

    Code:
    // INCIDENT.S00-ContainerBlock078-ContainerGroup-PlaneGroup-ScriptGroup-OffsetChunk.bin
    //
    // Entries:   2
    // Offsets:       -1     4
    
    // entry 0 (empty)
    
    // entry 1
    79 00 08
    79 00 09
    79 00 0A
    23
    0E FEFF
    
    Code:
    // INCIDENT.S00-ContainerBlock078-ContainerGroup-SpriteGroup-ScriptGroup-OffsetChunk.bin
    //
    // Entries:  22
    // Offsets:       -1    -1    -1    -1    -1    -1    -1    -1    56    63    69    76    89   103   116   129   143   157   170   184   197   211
    
    // entry 0-7 (empty)
    
    // entry 8
    24 00       // push.i1   0 ( 8-bit integer)
    46          // set x
    25 9001     // push.i2 400 (16-bit integer)
    47          // set y
    23
    0E FEFF
    
    // entry 9
    ...
    
     
    Last edited: Apr 17, 2018
  7. delMar

    delMar Rear Admiral

    Messages:
    326
    Likes Received:
    57
    Trophy Points:
    23,035
    Gender:
    Male
    Location:
    Austria
  8. lskovlun

    lskovlun Spaceman

    Messages:
    4
    Likes Received:
    12
    Trophy Points:
    125
    Hi everyone, I'm new here. I've been spending some time writing a disassembler for the SERIES.xxx, INCIDENT.xxx, GAMEFLOW.xxx and CAMPAIGN.xxx files in WC2, and it actually works pretty well at this point. I wanted to try out the WC Toolbox to make sure we're on the same page regarding terminology and such, but I can't get WC Toolbox to work with my WC2 files; I get an "unsupported source file" error (tried with both SERIES.S00 and INCIDENT.S00). So with that caveat out of the way, on to my findings.

    I haven't read delMar's monster post in full yet, but I have a few comments. While starting with small pieces is indeed a good idea, the stuff in the INCIDENT files require a good understanding of the animation system in WC2, whereas SERIES is mostly repeats of the same things (set up some variables, print some dialogue, make a subroutine call to INCIDENT, and little else). Very repetitive, and therefore very good to start with. In particular, the opening scene that delMar refers to requires understanding of scrolling planes to understand the code. Knowledge that I don't have, so I use opcode names like SET_SPRITE_FIELD_2B and such. I also don't have an assembler for these files yet, so I can't experiment.

    Anyway, a disassembled extract from SERIES.S00 reads:
    Code:
    Contents of sprite section of entry point 0:
    Contents of plane section of entry point 0:
    Contents of sequence section of entry point 0:
    Talk1:
    0070 YIELD
    0071 MUSIC1 0
    0074 MUSIC2 12
    0076 MUSIC3 music.r00(41)
    0078 MUSIC4 music.r00(41)
    007a RUN_SEQUENCE removeall
    007c GET_TEXT "  "
    007f RUN_SCENE incident.s00(78)
    0081 PUSH_CONSTB 0
    0083 MANIP_SKIP
    0084 MUSIC1 0
    0087 MUSIC2 12
    0089 MUSIC3 music.r00(53)
    008b MUSIC4 music.r00(53)
    008d PUSH_CONSTB 16
    008f POP_SET_GLOBAL 297
    0092 PUSH_CONSTB -1
    0094 POP_SET_GLOBAL 296
    0097 RUN_SEQUENCE initshardrun
    0099 PUSH_GLOBAL 276
    009c POP_SET_GLOBAL 295
    009f PUSH_CONSTW 200
    00a2 POP_SET_GLOBAL 276
    00a5 RUN_SEQUENCE settalker
    00a7 PUSH_GLOBAL 295
    00aa POP_SET_GLOBAL 276
    00ad RUN_SEQUENCE removeall
    00af GET_TEXT "K'Tithrak Mang \n Kilrathi Sector HQ"
    00b2 RUN_SCENE incident.s00(69)
    00b4 PUSH_CONSTB 3
    00b6 POP_SET_GLOBAL 388
    00b9 PUSH_CONSTB 16
    00bb POP_SET_GLOBAL 297
    00be PUSH_CONSTB -1
    00c0 POP_SET_GLOBAL 296
    00c3 RUN_SEQUENCE initshardrun
    00c5 PUSH_CONSTB 0
    00c7 PRELOAD_SPEECH speech.s00(0)
    00c9 PUSH_CONSTB 0
    00cb POP_SET_GLOBAL 761
    00cf PUSH_GLOBAL 276
    00d2 POP_SET_GLOBAL 295
    00d5 PUSH_CONSTB 26
    00d7 POP_SET_GLOBAL 276
    00da RUN_SEQUENCE settalker
    00dc PUSH_GLOBAL 295
    00df POP_SET_GLOBAL 276
    00e2 RUN_SEQUENCE removeall
    00e4 GET_TEXT "I will speak with Prince Thrakhath alone.\nGuards, you are dismissed."
    00e7 RUN_SCENE incident.s00(49)
    
    As you can see, a large part of the task ahead is documenting the variable names. (PUSH_GLOBAL, POP_SET_GLOBAL). They are needed because subroutine calls cannot pass arguments in any other way, and they contribute greatly to the structure of the code.
    Also, the opcode names are not set in stone at all.
     
    Last edited: Apr 17, 2018
    L.I.F., ChrisReid, Quarto and 3 others like this.
  9. delMar

    delMar Rear Admiral

    Messages:
    326
    Likes Received:
    57
    Trophy Points:
    23,035
    Gender:
    Male
    Location:
    Austria
    Boy, geniuses all over the place in this here forum :)
    Awesome, thanks for sharing
     
  10. UnnamedCharacter

    UnnamedCharacter Ensign

    Messages:
    156
    Likes Received:
    161
    Trophy Points:
    2,385
    @lskovlun

    You are way ahead than I am; the Toolbox has no support for the bytecode data.

    As for the "unsupported source file" error on SERIES.S00 and INCIDENT.S00, you might not be using the latest version, otherwise the following should work:
    WC2ToolsCmd.exe extract INCIDENT.S00​

    Nice work, keep it up.
     
  11. UnnamedCharacter

    UnnamedCharacter Ensign

    Messages:
    156
    Likes Received:
    161
    Trophy Points:
    2,385
    I put together a simple assembler/disassembler. Although it lacks the sophistication demonstrated by @lskovlun, it does have the basic functionality of managing jump targets. Unfortunately, it does have problems with two files, when disassembled they will not re-assemble:

    SERIES.S00-ContainerBlock005-ContainerGroup-SequenceGroup-ScriptGroup-OffsetChunk.asm
    error: undefined symbol: _08b2

    SERIES.S00-ContainerBlock013-ContainerGroup-SequenceGroup-ScriptGroup-OffsetChunk.asm
    error: undefined symbol: _2442​

    The problem are jump values that appear to be too large, they jump beyond the end of the file. For the time, avoid these two files.

    In any case, here are some examples of the disassembly:

    Code:
    ; SERIES.S00-ContainerBlock000-ContainerGroup-SceneGroup-ScriptGroup-OffsetChunk.asm
    
    .entry ;   0
      _0000:  c035                                  ; yield
      _0001:  c036          15                      ; push constant, byte
      _0003:  c129     
      _0004:  c038           4                      ; get global[<uintvar:index>]
      _0006:  c036           0                      ; push constant, byte
      _0008:  c027                                  ; ==
      _0009:  c015       _0011                      ; jz
      _000c:  c136          22                      ; run sequence
      _000e:  c014       _0052                      ; jmp
      _0011:  c038           4                      ; get global[<uintvar:index>]
      _0013:  c036           1                      ; push constant, byte
      _0015:  c027                                  ; ==
      _0016:  c015       _001e                      ; jz
      _0019:  c136          23                      ; run sequence
      _001b:  c014       _0052                      ; jmp
      _001e:  c038           4                      ; get global[<uintvar:index>]
      _0020:  c036           2                      ; push constant, byte
      _0022:  c027                                  ; ==
      _0023:  c015       _002b                      ; jz
      _0026:  c136          24                      ; run sequence
      _0028:  c014       _0052                      ; jmp
      _002b:  c038           4                      ; get global[<uintvar:index>]
      _002d:  c036           3                      ; push constant, byte
      _002f:  c027                                  ; ==
      _0030:  c015       _0038                      ; jz
      _0033:  c136          25                      ; run sequence
      _0035:  c014       _0052                      ; jmp
      _0038:  c038           4                      ; get global[<uintvar:index>]
      _003a:  c036           4                      ; push constant, byte
      _003c:  c027                                  ; ==
      _003d:  c015       _0045                      ; jz
      _0040:  c136          26                      ; run sequence
      _0042:  c014       _0052                      ; jmp
      _0045:  c038           4                      ; get global[<uintvar:index>]
      _0047:  c036           5                      ; push constant, byte
      _0049:  c027                                  ; ==
      _004a:  c015       _0052                      ; jz
      _004d:  c136          27                      ; run sequence
      _004f:  c014       _0052                      ; jmp
      _0052:  c131           0,     0,   255
      _0056:  c014       _0000                      ; jmp
    
    Code:
    ; INCIDENT.S00-ContainerBlock000-ContainerGroup-SequenceGroup-ScriptGroup-OffsetChunk.asm
    
    .entry ;  22
      _0000:  c035                                  ; yield
      _0001:  c036           0                      ; push constant, byte
      _0003:  c036           0                      ; push constant, byte
      _0005:  c110           3
      _0007:  c109           8
      _0009:  c136          20                      ; run sequence
      _000b:  c037         300                      ; push constant, word
      _000e:  c107                                  ; set sequence field, +23, timer
      _000f:  c106                                  ; get sequence field, +23, timer
      _0010:  c015       _0016                      ; jz
      _0013:  c014       _000f                      ; jmp
      _0016:  c153           0
      _0018:  c034                                  ; return value to zero
      _0019:  c014       _0000                      ; jmp
    
    And here is a functional example, changed the text and inserted two instructions:

    WC2ToolsCmd.exe xmlunpack INCIDENT.S00
    WC2Assembler.exe INCIDENT.S00-ContainerBlock078-*.bin

    WC2Assembler.exe INCIDENT.S00-ContainerBlock078-*.asm
    WC2ToolsCmd.exe xmlpack INCIDENT.S00.XML​

    Code:
    <!-- INCIDENT.S00.XML -->
    
      <ContainerBlock><!-- 078 -->
        <ContainerBlock.Chunks>
          <ContainerGroup>
            <TextGroup>
              <SymbolChunk>
                <SymbolChunk.Items>
                  <SymbolItem Text="TCS Tiger's Claw.&#xA;Beautiful ship, shame it will be destroyed.&#xA;Kilrathi Sector HQ." />
                </SymbolChunk.Items>
              </SymbolChunk>
      ...
    
    Code:
    ; INCIDENT.S00-ContainerBlock078-ContainerGroup-SequenceGroup-ScriptGroup-OffsetChunk.asm
    
    .entry ;  22, position:     94
      _0000:  c119           1                      ; link
      _0002:  c035                                  ; yield
      
              c037         212  ; push value
              c148           3  ; fill canvas (3, subtitle) using the pushed color (212)
      
      _0003:  c031           9                      ; select sprite
      _0005:  c158           0
      _0007:  c120           1,     0,     0,     1 ; set sprite data
      _000c:  c031          10                      ; select sprite
      _000e:  c158           0
    ...
    
    WC2TCDestruction2.png
     

    Attached Files:

    delMar, Shades2585 and Quarto like this.
  12. UnnamedCharacter

    UnnamedCharacter Ensign

    Messages:
    156
    Likes Received:
    161
    Trophy Points:
    2,385
    Work on the toolbox has continued and this release begins support for Privateer 1.

    This update adds the ability to create or edit many of the Privateer file types: IFF, PAK, PAL, PFC, SHP, TRE, VPF, VPK; it expands the number of image formats supported: BMP, GIF, PNG, and TIFF; and also provides the ability to create compressed files where appropriate. All of this new functionality is specific to the Privateer tools.

    See first post for the file attachment.

    sample1.png sample2.png

    There are major changes introduced in Privateer, such as the extensive use of files within files, the use of many different color palettes, and the move toward the Interchange File Format (IFF). With all these changes, I ended up taking a completely different approach for the Privateer tooling; it is actually modeled after the Prophecy development tools. I am leveraging the overall design approach used in the Prophecy tools such as the use of custom script files to guide the creation of new files. I am also making use of the existing Extended MakeIFF compiler (XMIFF) an old DOS program from the Prophecy tools for creating IFF files. All of this has the obvious benefit of saving me the effort of creating similar functionality.

    See below for a series of posts describing each command, the custom scripts, and how to use the Extended MakeIFF compiler (XMIFF).


    intro1.PNG intro2.PNG

    intro3.PNG intro4.PNG intro5.PNG intro6.PNG intro7.PNG
     
    Last edited: Aug 30, 2018
    delMar, Shades2585, Quarto and 2 others like this.
  13. UnnamedCharacter

    UnnamedCharacter Ensign

    Messages:
    156
    Likes Received:
    161
    Trophy Points:
    2,385
    Privateer 1 Tools Commands: tree / untree

    You can use these commands to create a tree (TRE) file from imported files, or reverse a tree file into exported files.

    A tree file is a container file which internally uses a directory structure mapping the file paths to file content.

    To unmake a tree file:

    Priv1ToolsCmd untree source [destination]

    Priv1ToolsCmd untree SPACE.TRE​

    This will output the content of each file into an actual directory structure, create a padding file, and a script to run which will remake the tree file.

    Code:
    outputfile SPACE.TRE
    
    padding SPACE.TRE.PADDING
    
    file ..\..\DATA\MISSIONS\S7MB.IFF
    file ..\..\DATA\MISSIONS\S5MD.IFF
    file ..\..\DATA\MISSIONS\S5MC.IFF
    file ..\..\DATA\MISSIONS\S5MB.IFF
    ...
    
    The file paths are prefixed because the tree file expects it, but these prefixes are ignored when finding the actual files. As for the padding file, I have no idea what this padding is for, but just in case it is useful I preserve it.

    To make a tree file:

    Priv1ToolsCmd tree script

    Priv1ToolsCmd tree SPACE.TRE.SCR​
     
    Last edited: Aug 29, 2018
  14. UnnamedCharacter

    UnnamedCharacter Ensign

    Messages:
    156
    Likes Received:
    161
    Trophy Points:
    2,385
    Privateer 1 Tools Commands: pack / unpack

    You can use these commands to create a pack (PAK) file from imported files, or reverse a pack file into exported files.

    A pack file is a container file which divides the content internally as individual packets. It is analogous to a DataFile in the tools for WC1/2. Pack files may use different file extensions, such as: VPK for VoicePack (Male), VPF for VoicePackFemale.

    To unmake a pack file:

    Priv1ToolsCmd unpack source [destination]

    Priv1ToolsCmd unpack DATA\OPTIONS\CU.PAK​

    This will output each packet as a file, and a script to run which will remake the pack file.

    Code:
    outputfile CU.PAK
    
    flag -32
    file CU.PAK-Packet000.PCK
    flag -32
    file CU.PAK-Packet001.PCK
    flag -32
    file CU.PAK-Packet002.PCK
    ...
    
    The flag value indicates the format of the packet, such as compressed.

    To make a pack file:

    Priv1ToolsCmd pack script

    Priv1ToolsCmd pack CU.PAK.SCR​
     
    Last edited: Aug 29, 2018
  15. UnnamedCharacter

    UnnamedCharacter Ensign

    Messages:
    156
    Likes Received:
    161
    Trophy Points:
    2,385
    Privateer 1 Tools Commands: palette / unpalette

    You can use these commands to create a palette (PAL) file from an image, or reverse a palette file into an image.

    A palette file obviously contains the color values of a palette, but instead of 8-bit per color channel (RGB), the values are in 6-bit form, as expected by VGA. The conversion to/from an image will transformed the values to/from 8-bit, making the colors display as expected. There are also two variations, a full palette of 256 colors, or a half palette of 128 colors.

    To unmake a palette file:

    Priv1ToolsCmd unpalette source [destination] [/format:(BMP|GIF|PNG|TIF)]

    Priv1ToolsCmd unpalette DATA\PALETTE\SPACE.PAL​

    This will output an image representing the palette, and a script to run which will remake the palette file.

    palette1.PNG

    Code:
    outputfile SPACE.PAL
    
    composite   0 256 # startindex colorcount
    
    inputfile SPACE.PAL.PNG
    
    Since palettes can be joined, there is a small amount of metadata to indicate how to combine them; the start index and the color count of a composite palette.

    To make a palette file:

    Priv1ToolsCmd palette script

    Priv1ToolsCmd palette SPACE.PAL.SCR​
     
    Last edited: Aug 30, 2018
  16. UnnamedCharacter

    UnnamedCharacter Ensign

    Messages:
    156
    Likes Received:
    161
    Trophy Points:
    2,385
    Privateer 1 Tools Commands: shape / unshape

    You can use these commands to create a shape (SHP) file from encoded images, or reverse a shape file into decoded images.

    A shape file is a container file which divides the content internally as individual shapes. It is analogous to an ImageBlock in the tools for WC1/2. An image must be specified to be used as a palette since shapes contain no color values.

    To unmake a shape file:

    Priv1ToolsCmd unshape source [destination] [/format:(BMP|GIF|PNG|TIF)] /palette:image

    Priv1ToolsCmd unshape DATA\OPTIONS\JOYCALIB.SHP /p:JOYCALIB.PAL.PNG​

    This will output each shape as an image, and a script to run which will remake the shape file.

    shape1.PNG

    Code:
    outputfile JOYCALIB.SHP
    
    origin   0  59
    inputfile JOYCALIB.SHP-Shape000.PNG
    origin   0   4
    inputfile JOYCALIB.SHP-Shape001.PNG
    origin   0   4
    inputfile JOYCALIB.SHP-Shape002.PNG
    ...
    
    The origin is the xy-coordinates of the image which will often times be used as the insertion point.

    To make a shape file:

    Priv1ToolsCmd shape script

    Priv1ToolsCmd shape JOYCALIB.SHP.SCR​
     
    Last edited: Aug 30, 2018
  17. UnnamedCharacter

    UnnamedCharacter Ensign

    Messages:
    156
    Likes Received:
    161
    Trophy Points:
    2,385
    Privateer 1 Tools Command: unmake

    You can use this command to reverse various data files (IFF, PFC, etc) into a custom format.

    To unmake a data file:

    Priv1ToolsCmd unmake source [destination] [/encoding: (code page|name)] /template:(Conversation|Interchange|Palette)​

    To unmake a conversation file:

    Priv1ToolsCmd unmake DATA\CONV\CARGO.PFC /t:Conversation​

    This will output a code file which can be processed by XMIFF to remake the data file.

    Code:
    char 0
    char[9] "rand_npc"
    char[9] "normal"
    char[9] "shpdlr_1"
    short 159,  9 // xy
    cstring "Good choice, but far be it for me to pass up a sale..."
    char 224 // palette index
    
    char 0
    char[9] "rand_npc"
    char[9] "normal"
    char[9] "shpdlr_1"
    short 159,  9 // xy
    cstring "...I can't afford to take advantage of a customer."
    char 224 // palette index
    ...
    
    To unmake an interchange file:

    Priv1ToolsCmd unmake DATA\CONV\RUMORS.IFF /t:Interchange​

    This will output a code file which can be processed by XMIFF to remake the data file.

    Code:
    FORM "RUMR"
    {
        CHUNK "CHNC"
        {
            short 20 // chance buzzoff
            short 40 // chance base
            short 40 // chance plot
            short 40 // chance general
        }
    }
    
    To make a data file (from DOSBox if in 64-bit Windows):

    XMIFF CARGO.XMF CARGO.PFC

    XMIFF RUMORS.XMF RUMORS.IFF​
     
    Last edited: Aug 30, 2018
  18. UnnamedCharacter

    UnnamedCharacter Ensign

    Messages:
    156
    Likes Received:
    161
    Trophy Points:
    2,385
    The following is an example for extracting the external ship views. Since the game data is divided among multiples files, and is contained in files within files, a multi step process is used.

    We start by extracting the files from two tree files:

    Priv1ToolsCmd.exe untree MIDGAMES.TRE
    Priv1ToolsCmd.exe untree OBJECTS.TRE​

    Next we convert a palette file into an image:

    Priv1ToolsCmd.exe unpalette DATA\PALETTE\SPACE.PAL​

    Next we unmake an interchange file since it contains the shapes we need:

    Priv1ToolsCmd.exe unmake DATA\APPEARNC\BRDSWORD.IFF /t:Interchange​

    Finally, we convert the shapes into images:

    Priv1ToolsCmd.exe unshape BRDSW000.* /p:SPACE.PAL.PNG​


    example-ship1.PNG example-ship2.PNG example-ship3.PNG
     
    Shades2585 and KrisV like this.
  19. Stinger

    Stinger Vice Admiral

    Messages:
    876
    Likes Received:
    125
    Trophy Points:
    29,535
    Nice work!
     
  20. Quarto

    Quarto Unknown Enemy

    Messages:
    11,922
    Likes Received:
    290
    Trophy Points:
    69,385
    Location:
    Poland
    Wow! That's a lot of info to take in all at once. Impressive!
     

Share This Page