Jul 252015

I’m mostly writing this for my own notes, but on the off-chance my incoherent notes are useful to others, I decided to put it here. Most of this is going to be devoid of context, but for reference’s sake, I’m using a combination of XWA Opt Editor, Blender, XWA Texture Replacer (XTR), and finally OPTech to create the XvT/TIE-compatible OPTs. I’ll probably add more to this as I go.

Clean Up Unused Materials

There’s an addon that ships with Blender but is dormant by default called Material Utils that has a function to remove unused materials from an object (Clean Material Slots (Material Utils)). Use this once you’ve finished futzing with materials.

Clean Up UVTextures

These garbage up the exported OBJ with bad materials long after you’ve done any material editing. The following script obliterates them:

import bpy

objects = bpy.context.selected_objects

if (objects is None):
	print("You must select at least one object") # This warning will only show in the Blender console
for ob in objects:
	uvTexData = ob.data.uv_textures.active.data[:]
	print("Active UV on %s has %s faces of data" % (ob.name, len(uvTexData))) # Purely informational; can be omitted if desired
	for i in range(0, len(uvTexData)):
		if (uvTexData[i].image is not None): # We do not want ANY uv textures!
			print("Face %s: %s" % (i, uvTexData[i].image.name)) # Purely informational; what face has what UV texture
			uvTexData[i].image = None
			print("Cleaned UV texture from face")

Material and Texture Naming

Materials and Textures (the Blender concept of a Texture, not the actual filename) must be named TEX*, with a 5-digit numeric identifier (starting at 00000 and incrementing by 1) in order to behave properly. I tried a bunch of different naming schemes in the hopes that I could keep human-meaningful names applied to either Materials or Textures, but this inevitably caused problems once trying to check the model in XTR or OPTech. XWA Opt Editor handles it fine, though. I wrote several python scripts to do this, based on whatever previous iteration of material naming I had. Here was the most recent:

import bpy, re

materials = bpy.data.materials
idx = 0

for mat in materials:
	if mat.name[0] == 'X': # Detecting whether a material was prefixed with X, which was the previous naming scheme for my top-level LOD
		newName = "TEX%s" % format(idx,'05') # 0-pad to 5 digits
		print("Renaming %s to %s" % (mat.name, newName)) # Informational
		mat.name = newName # Rename the material
		imgEx = mat.active_texture.image.name[-4:] # Get the extension on the Texture
		print("Renaming %s to %s%s" (mat.active_texture.image.name, newName, imgEx)) # Informational
		mat.active_texture.image.name = "%s%s" % (newName, imgEx) # Rename the texture; NOT the file, though
		idx += 1 # Only increment if we matched above

Export Settings

Make sure Selected Only is enabled if you only want to export your selection (which I did/do, since I had multiple LODs in the same Blender file) and make sure Triangulate Faces is turned on. Optionally, turn off Include Edges, which I think will keep the OBJ from having two-vertex mesh objects treated as full faces (if you have these, you probably did something wrong).

Texture Format Doesn’t (Seem To) Matter

One thing I tried was converting all the PNGs exported by XWA OPT Editor to BMPs before loading them into Blender, but this didn’t ultimately make a difference when then re-importing the exported OBJ back to XWA OPT Editor; they still came in as 32-bit images and had to be internally converted to 8-bit. Irritating limitation of the tool, I guess. One issue I’ve variously encountered is garbage material/palette names that I thought might be connected to this in some way. The solution here, though, seemed to simply be saving the imported OPT as soon as it was imported from the OBJ, then running the 32 -> 8-bit conversion. That resulted in non-garbage palette names. Of course, this may also be related to the previous note about naming and have nothing to do with the conversion order of operations.

Look, Up, Right Vectors

I’m not actually sure about any of this yet, because I haven’t tested it, but I wrote the following script to compute my best-guess for the OPT convention for what “Look”, “Up,” and “Right” vectors should be, based on an input selection of vertices and the average of their normals. The idea here is to use it to define rotational axes and such for rotary gun turrets and other moving model parts. For most parts, this isn’t necessary.

import bpy
from mathutils import Vector

selVerts = [i.index for i in bpy.context.active_object.data.vertices if i.select == True]
retNormal = Vector((0,0,0)) # The resulting vector we'll calculate from the selection

for i in selVerts:
	vertNormal = bpy.context.object.data.vertices[i].normal
	retNormal += vertNormal # Add to the calculated normal
retNormal = retNormal / len(selVerts) # Average the summed normals by the number of vertices involved
retNormal = retNormal * bpy.context.active_object.matrix_world * 32767 # Scale to the OPT convention and multiply by the world matrix to get global normals instead of local

# The idea is to take the computed average normal from Blender's coordsys and convert it to the OPT coordsys displayed in XWA Opt Editor
lookVector = Vector((retNormal.y, retNormal.z, retNormal.x))
upVector = Vector((retNormal.z, retNormal.x*-1, retNormal.y))
rightVector = Vector((retNormal.x, retNormal.y*-1, retNormal.z*-1))

print("Look: %s\nUp: %s\nRight: %s\n------" % (lookVector, upVector, rightVector))

Getting a Coordinate for a Hardpoint

Rather than manually copying every vertex I wanted to use as a hardpoint, I wrote this script.

import bpy, os

objLoc = bpy.context.active_object.location
objWorldMatrix = bpy.context.active_object.matrix_world
objVerts = bpy.context.active_object.data.vertices
selVerts = [i.index for i in verts if i.select == True]

for i in selVerts:
	# Need to do the following vector/matrix math to get the value 
	# actually reported as a Global coordinate by Blender for a 
	# selected vertex
	# (Local vertex coordinate + (object location * object world matrix)) * inverse object world matrix 
	vertLocalPos = objVerts[i].co
	vertGlobalPos = (vertLocalPos + (objLoc * objWorldMatrix)) * objWorldMatrix.inverted()
	# Flip the y value to match OPT coordinate space
	vertGlobalPos.y = vertGlobalPos.y * -1
	# Dump the string to the clipboard
	optStr = "%s; %s; %s" % (vertPos.x, vertPos.y, vertPos.z)
	print(optStr) # Informational
	os.system("echo %s | clip" % optStr)
Jul 022015

Putting this here for posterity and in case it’s useful to others.

Updated 2015-07-06 with clarifications for the re-orchestrated music section. New entries are marked with an asterisk.

Updated 2015-07-23 with specific instructions on how to apply the “Laser Patch” for Star Destroyers, so they actually shoot and general instructions on adding enhanced models to the game.

This specifically applies only to people who have the Windows CD version of TIE Fighter (the one released using the XvT engine). If you have the old DOS version or the GOG.com version, these instructions may/will not apply to you. These steps are directly adapted from this guide, distilled into the minimal form of the steps I followed. That guide also has instructions for the older DOS version and GOG.com versions, if that’s your thing. Additionally, this is specifically for users of Windows 7 x64. I make no guarantees of applicability to other versions of Windows.

Primary Instructions

  1. Download Tie95-win7.zip
  2. Extract Tie95-Win7.zip to a temporary location (henceforth %TIE95-WIN7_DIR%)
  3. Insert the TIE Fighter CD. Close/exit autostart if it opens.
  4. Open the TIE95 disc in Explorer instead.
  5. Copy all files on disc to your hard drive somewhere (henceforth %TIECD_DIR%)
  6. Run XCS_TIE95_MSI_v1.0.0.0.exe from %TIE95-WIN7_DIR% and point it at the place where you copied the game files.
  7. Run XCS - TIE Fighter 95.msi from %TIECD_DIR%. Accept defaults (or change them as desired; I didn’t try; henceforth, this install path is henceforth %TIE_PATH%).
  8. Copy tie95.bat from %TIE95-WIN7_DIR% to %TIE_PATH%. This file closes Explorer when the game launches (possible color issues) and restarts it again when the game exits. Do not be alarmed.
  9. Locate the TIE Fighter 95 shortcut in the start menu, right-click and choose “Properties”
  10. Change TIESTART.EXE to tie95.bat
  11. Click ‘Apply’, then ‘Change Icon…’, then select the TIE95.EXE and click ‘OK’
  12. Click ‘OK’ to close the properties window.
  13. In your video card profile settings (e.g. NIVIDA Control Panel), create a profile for TIE95.EXE
    • Disable anti-aliasing. Having it on leads to weird color flickering.
    • Enable 16x Anisotropic Filtering
  14. Open XWTIE95.zip from %TIE95-WIN7_DIR% and run XWTIE95.exe to prevent D3D crashes.
  15. Make sure the disc is in the drive
  16. Copy B6M3GW.TIE from %TIE95-WIN7_DIR% to %TIE_PATH%\Mission (official LucasArts patch for this mission)
  17. Make sure you have a joystick plugged in. Game won’t cooperate without one.
  18. Run the game from your shortcut

Reorchestrated Music

To get the original music and improved voice, you basically need to rebuild the TIE CD disc with the Reorchestrated data files.

  1. Ensure you have a way to create and virtually “mount” ISO and BIN/CUE disc images
  2. *Download TF95ReorchestratedMusic.zip
  3. Download TF95ReochestratedDatav1.zip
  4. *Extract TF95ReorchestratedMusic.zip (doesn’t matter where). You should have a .bin and a .cue file.
  5. *Burn the BIN/CUE image to a blank CD (DVD will not cut it). Critically, there is no data (other than an empty blank.txt file) on this disc! It’s writing audio tracks layered with a data track and the game is expecting to find these audio tracks. This is key to make the in-flight battle music play.
  6. *This disc is now the physical disc you must have present when you play, not your original CD. Instead, the following steps will replace the physical CD with a virtual one.
  7. Extract TF95ReochestratedDatav1.zip to %TIECD_DIR%
  8. Replace %TIE_PATH%\TIE95.EXE with the one in the Data zip’s INSTALL folder.
  9. Create an image of %TIECD_DIR% and be sure to name it TIE95 (so it matches the original game disc)
  10. Mount it as TIE95 using some kind of virtual mounting software.
  11. *Ensure the original game disc is no longer in your drive and you are instead using the newly-created music disc.
  12. Run the game from your shortcut
  13. You may get prompted that there is no disc in the original drive. Click ‘Cancel’ and the game should launch anyway. It will not show this warning on subsequent runs.

Laser Patch

The original release of the game had a bug wherein ISDs wouldn’t shoot anything other than missiles. As you might imagine, this has/had a rather deleterious effect on mission balance for several missions (Battle 11 Mission 2, in particular, is all but impossible without your Star Destroyer dishing out firepower alongside you). This problem was fan-patched back when it was first discovered, but with all the binary file changes involved in the above, those patches don’t really work. I managed to figure out where in the executable the patches made their changes, though, by comparing byte-code before and after of a binary that I could patch. If you’re feeling brave and want to edit hexadecimal byte code directly, follow the following instructions.

  1. Obtain some way to edit binary files. I like frhed.
  2. Make a backup of your TIE95.exe file! I cannot stress this enough. If you screw up the binary, you’re SOL and will have to repeat everything above all over again.
  3. Open TIE95.exe in your hex editor.
  4. Locate offset 00dd89c and change these four bytes from 34 35 35 37 to 34 36 36 37.
  5. Locate offset 00ee834 and change the first of the four bytes at this location from 00 to 03.
  6. Locate offset 00ee844 and change the last of the four bytes at this location from 35 to 34.
  7. Locate offset 00ee848 and change these four bytes from 02 00 03 01 to 00 45 03 21.
  8. Locate offset 00ee84c and change these four bytes from 00 03 1c 0c to 00 04 00 fa.
  9. Locate offset 00ee850 and change these four bytes from 84 03 00 00 to 00 7d 00 00.
  10. Save your modified binary.
  11. Give it a spin. Star Destroyers should now shoot.

Enhanced Ship Models

It is possible to use more advanced ship models, such as those in XvT, XWA, or the high-quality models produced by the XWAU project, in TIE Fighter. I’m not going to enumerate every step involved, but you’ll need a program called OPTech (the site’s hideous, but the tool’s good), which can read and write OPT model files in both the format used by X-wing Alliance and the older XvT-style format used by the Window release of TIE Fighter. Create a new project in OPTech, import an OPT, save it as XvT format, rename it as necessary, and drop it into your %TIE_PATH%/IVFILES directory, deleting any OP1 files that may also share the same name.


Sep 202010

TIE Fighter case artIf that post title got you excited, I apologize.

For a while now, I’ve toyed with the idea of doing some kind of Star Wars fan film, being both a Star Wars nerd and an amateur filmmaker. One idea that popped into my head recently, while recollecting fond and cherished memories of playing the TIE Fighter computer game, was to adapt the game’s story into a TV (well, web) series. The game was story-driven enough that I think it could work, and had enough characters that it could be interesting. I’m not suggesting I’m going to do this. I barely have the time and energy to do all of the current projects I’ve saddled onto myself, let alone adding something as megalithic as this. But it’s still fun to think about.

According to lore, the TIE Fighter player assumes the mantle of Maarek Steele. Seems like a good choice for the series’ protagonist. As the game progresses, a number of major secondary characters and antagonists are introduced. Among them are then-Vice Admiral Thrawn, the rogue admirals Harkov and Zaarin, and Darth Vader puts in a cameo, too. Including the Imperial officer that briefs Steele before each mission, as well as the member of the Emperor’s Secret Order that provides secondary objectives, might work as well.

In terms of adapting the game, I think I’d first just go through the game mission-by-mission and isolate the major story components from each. These would get woven into the major arc of the series, which itself might even be split into seasons to mirror the distinct campaigns in the game. Once that had been done, the next step would be to pick out key bits of dialog from the game and weave those into the episode script. Nostalgia, man! It wouldn’t have to be line-for-line, but it’d be a fun callback to hit some of the key lines.

I might visit the idea some time in the distance future. TIE Fighter stands as my favorite game of all time (yes, even over WoW), and it nicely dovetails with the desire to do a Star Wars fanfilm. Of course, I’m not sure if I will ever be able to commit the amount of time doing an entire series would require. But hey, it’s fun to dream.