Visual Studio… Why?

This post is just a rant venting frustration with Visual Studio. Feel free to ignore.

Last year I switched employment from a somewhat .NET shop to a predominantly python shop with a bit of a node sprinkled in where it won’t be noticed. As such the only times I need to use Visual Studio now are when I’m doing work for my brother, or whenever I dust off old projects. That is probably the absolute worst way to use Visual Studio.

So, I’m not entirely sure how I got into this situation, but my main ‘pack up and go’ laptop has a single version of Visual Studio on it- 2015 Community Edition (I’m really unclear on this as it should have professional edition). And I use it once every few months.

So. I go to a job site. In the middle of nowhere. I open up a project in Visual Studio, what do I get?

A prompt.

A prompt asking me to sign in to my gods damned useless Microsoft Account because it wants me to sign in every 90 days.

No internet access? Don’t want to sign in? No development for you. Visual Studio shuts down. All for what? So Microsoft can advertise their hosted TFS service that I wouldn’t touch with a 10 foot pole? So they can gather anonymous usage data that will help them… do something?

I will grant, they’re providing a (very large) tool for free and are more then welcome to impose any terms they’d like. I just wish they’d chosen terms that weren’t making me reconsider my off hours tech stack.

Unrelated but equally annoying, I had ReSharper on this VS2015 release. Somehow the two got into a really bad conflict. Would get IntelliSense from both tools, neither would work, and various key strokes would be ignored in favor of closing the useless IntelliSense pop ups. Coding when key strokes are randomly swallowed is painful.

Further annoyance: package management. I come back to my Tachyon Model Viewer project after (too long) a hiatus, and I can’t build the damn thing. The packages the project depends on are listed as installed, but for whatever reason they’re not referenced. And unless my solution of browsing to the installation location and manually choosing each assembly reference is the actual intended solution, there’s no obvious way of referencing them.


How much of this is my fault? Almost certainly all of it. I’m sure I screwed up my installation two years ago by, say, removing an older version of VS or something. Don’t know why I would have done that, but I could see it happening. And the package management could just be I’m using it in the exact wrong way. But, I don’t really care. Same way I’m sure there’s a VS2017 or a VSCode that I should be using if I want to be up to date, which probably does improve package management. But, as I said, I don’t really care- I’m on the internet, mildly annoyed, and basically talking to myself. I hate being stuck in the Javascript ecosystem using 30 different tools to build a web page, but I hate the Microsoft ecosystem more, where you have 1 tool that only usually works.

Oh well. To the Rust Rabbit Hole!

Aside. You may have noticed I don’t keep this blog active. Realistically that’s not going to change. This is a ‘when I feel like it’ thing, and sadly that doesn’t happen as often as I’d like. But, I do have a few things on my To Do list. One odd thing I’d like to figure out is getting this site and a few others into a docker container. I’d like to get to the point where I’m not spinning up new EC2 instances to run new side websites. Nothing major in the scheme of things, but it is some house keeping I’d like to do. Especially if it means I can continue ignoring actual house keeping.

Nicking assets from Tachyon: The Fringe, Part 2: The PFF Archive

The first file we’ll look at on our foray into pixel piracy is the PFF Archive. This is an archive file containing all of the game assets for Tachyon. There’s just the one,¬†Tachyon.pff, and it’s nearly 400MB in size (no compression, but when extracted the contents¬†usually take ~2GB on disk, due to a lot of small files). (This was back in the day when 2GB was a lot). This file format has been used by several NovaLogic games, most prominently the Delta Force series. Later versions of the format seem to support compression, but the format we’re working with is basically straight storage.

Technically the PFF format isn’t vital for our model extraction project- extractors have been around for the past 20 years, and we could just as easily work off an already extracted archive. However, that makes moving between computers a bit annoying, as you then need to find the extractor, extract the directory, point the app at the directory. Too much work, easier to point the app at a single file (especially as we aren’t looking to modification of underlying files). This also serves as a starting point for the blog series, to play with formatting and such before the content is important.

Thankfully at least one of the PFF extractors (from Devil’s Claw) also came with source code; so no reverse engineering required, just a minor port. Thank you Devil’s Claw.

On with the show.



General format of the file is a Header, a set of File Entries, a Footer, and then a massive blob of data.



Size Type Name Value Comments
4 int Header Size 20
4 char[4] Version String PFF3 PFF3, PFF4, etc
4 int File Count 8134 Number of File Entries
4 int File Segment Size 36 Size of Individual record, 32 to 40 bytes
4 int File List Offset 0x16C6A7F1 Start of File Entry Array, near end of file in this case

One interesting bit about the header is that the version string is lies (according to the old code). File Segment Size varies by PFF version, from 32 bytes for “V2”, 36 for V3, 40 for V4. But, “V2” and V3 have the same version string: PFF3.

File Segment Entry

Size Type Name Comments
4 int Deleted 0 for “not deleted”
4 int File Position Index into PFF where file content starts
4 int File Length
4 int Creation Date Guessing unix like timestamp; all around 2000 if true
16 char* File Name Null terminated string
4 int Modified Date Optional based on Segment Size, present in our data set, and has some weird values for timestamps (2020s+)
4 int Compression Level Optional based on Segment Size


Size Type Name Comments
4 int System IP Who packed the file, a 192.168.*.* address.
4 int Reserved/Unknown
4 char[] KING tag. Value=KING… Magic value, at a guess?

Appears after all of the File Entries. At a guess the KING tag is intended as a magic value to check that the file is otherwise valid.


It’s a straightforward archive format, with some support for extensions built in. It’s not bad, and kind of elegant for the goal of ‘single file archive’. It’s a bit wasteful though- what I usually see, when size matters, is the entries will have a bit field, with some fields defined, and others reserved for future use. IE deleted and compression level don’t need 8 bytes all to themselves. Though I’ll grant, for this use you’re talking about 8 bytes across 8000 entries- 64KB of semi-wasted space in a 400MB file.

Source code for the C# reader can be found here, and the Source for the Devils Claw extractor is here.

Other Notes: I wrote this a long time ago and never got around to publishing it because I wanted to get formatting for the tables right. Giving up on that for now, and just publishing to get the process started again. This’ll be a bigger problem in some of the next file formats, unfortunately, but we’ll see what happens. I also may use this as an opportunity to learn Rust, as Visual Studio is getting on my nerves.