DF-21 Forums Forum Index DF-21 Forums
The Dark Forces Community
 
DF-21.net Home | FAQ | Search | Memberlist  | Register 
Profile | Log in to check your private messages | Log in

MZZT.DarkForces.Formats - .NET library for DF textures

 
Post new topic   Reply to topic    DF-21 Forums Forum Index -> Dark Forces Levels & Editing
View previous topic :: View next topic  
Author Message
The MAZZTer
Death Star
Death Star

Joined: 25 Sep 2003

PostPosted: Jul 24, 2009 03:01    Post subject: MZZT.DarkForces.Formats - .NET library for DF textures View user's profile Send private message Send e-mail Reply with quote

My library is complete! Well as far as features go at least, and I still have to write a front end app to allow for easy editing of file types. However the back end is complete and I've decided to release a sort of public beta as long as I have it done.

Of course it could contain bugs but everything I've thrown at it so far has been successful.

http://junk.mzzt.net/MZZT.DarkForces.Formats.dll

Features:
- Full PAL, CMP, BM, FME, WAX, FNT, PLTT, ANIM, DELT, and FONT support for reading and writing and modifying all properties.
- Supports all DF compression types, even getting better rates than the DF devs did.
- For file types without compression, reading and writing a file will (should) result in a 1:1 exact same file.
- For file types that do support compression, reading and writing will often result in a smaller, more compact file that will (should) still function.
- Integration between different types. WAX objects are composed of FME objects which you can manipulate as if you loaded them from individual FME files. Similarly ANIMs are composed of DELTs.
- Loading and saving can be directed to any object that inherits from System.IO.Stream, meaning you should be able to load/save from many different sources. An obvious application is to open a GOB, move the stream position to the start of a BM file, and then use my classes to read the BM in without having to write it to disk first.

I would appreciate testings:
- Make sure files saved with this lib work in Dark Forces. For testing I just made sure the lib could load back files that it saved. However obviously testing needs to be done to be sure Dark Forces can handle the files as well.
- Make sure lots of different files from different converter tools load correctly.

Things that aren't supported and will probably cause exceptions:
- Using the wrong pixel format on bitmaps will probably cause exceptions when saving. I check for non-palletized bitmaps but you probably need to use 8bpp bitmaps only.
- Bitmaps that have sizes unsupported by the file format you're trying to save will either be caught by my library or just throw an exception. IE: font bitmaps must all be the same height, BMs that aren't weapons must have height/width that is a power of 2, etc. These won't be caught when you set the Bitmap object on the DFBM or DFFNT or whatever.
- You can do stuff that works in the library but won't work ingame. Example: WAXs can have 32 "Waxes" inside of it, and usually only have a few at the beginning and the rest are null. However, you can assign #32 to a Wax and the rest null. This will probably work with loading and saving, but Dark Forces itself probably won't like it.

Feel free to decompile and look at the source using .NET Reflector or similar tools.

Instructions for use:

First you need Visual Studio, Sharp Develop, or some .NET IDE. The instructions will assume Visual Studio. First save this DLL file to your drive and then load a project or create a new one. In Solution Explorer, right click References and click Add Reference. Go to the Browse tab and open my DLL. That's it! My library will be loaded under the MZZT.DarkForces.Formats namespace.

Now here is a quick start guide to using the library:

There are some base classes which all file format classes derive from:

DFFile - Basis for all file format classes.
- Load(Stream) - Loads a file from an arbitrary Stream
- Load(String) - Loads a file
- Save(Stream) - Saves a file to an arbitrary Stream.
- Save(String) - Saves a file

All classes that inherit from DFFile also allow for passing a Stream or String in the constructor to call Load.

DFPaletteFile - Inherits from DFFile. The base class for PAL and PLTT.
- Colors - Returns a 0-indexed array of all the colors in the palette. For PLTTs indices into this array needs to be offset by the First index to get the actual color index (or use PLTT's PaletteIndex).
- ToColorPalette() - Converts a palette to a System.Drawing.Imaging.ColorPalette which you can then assign to a Bitmap (or a DFImageFile).

DFImageFile - An interface instead of a class because 1) some classes that use this interface don't implement Loading or Saving because they are individual pages inside of a BM for example 2) VB.NET can't do multiple inheritance 3) all the implementations for these functions vary so there was little point in using a class instead of an interface.
- Bitmap - Returns the loaded System.Drawing.Bitmap image of the file. You can also assign to it to overwrite the image. Note that initally, loaded images use the default VGA palette (IE the wrong one) instead of a Dark Forces one so you will need to assign one manually using Palette. For multi-page images, Bitmap returns the first image and overwrites the first image when you set it.
- Palette - Returns Bitmap's Palette, and allows you to set it. A shortcut, basically. For multi-page images, setting this will set the palette in ALL pages.
- ToTransparentBitmap - This will make a copy of Bitmap and apply proper transparency when needed (IE if it's a transparent BM, or an FME/WAX which is always transparent). If you just use Bitmap you will not get any transparency.

There is also an RLE helper class which does some of the RLE stuff but you don't need to concern yourself with it.

Now onto the file format classes. Remember that all have Load/Save/New as described above. Remember that DFPAL and DFPLTT also have Colors and ToColorPalette.

DFPAL - Inherits from DFPaletteFile.
- New/DFPAL() - Creates a new palette, using a steady gradient from black to white as the default colors.
- New/DFPAL(ColorPalette) - Creates a PAL from a System.Drawing.Imaging.ColorPalette object.
- ImportPLTT(DFPLTT) - Merges a PLTT with the PAL.
- ExportPLTT(Byte, Byte) - Takes a range of colors described by the two Bytes (first, lasT) and returns a DFPLTT.

DFCMP - Inherits from DFFile.
- New/DFCMP() - Creates a new CMP. All light levels have each color mapped to itself by default. the headlight uses a steady linear gradient.
- LitColorIndex(Byte, Byte) - The first byte is a light level, the second is a palette index. This returns the light-adjusted palette index.
- LitColor(Byte, Byte) - If you assigned a PAL to the CMP, this returns a Color instead of an index as above.
- HeadlightLevels() - Returns an array of 128 bytes representing the headlight levels (see DF Specs).
- Palette() - Allows you to assign a palette so you can use functions like LitColor and LightLEvelTODFPAL
- LightLevelToDFPAL(Byte) - Returns a PAL object representing the palette when adjusted for the light level indicated in the byte. You can then call .ToColorPalette on this PAL and assign it to a Bitmap to see what it looks like in that light level.

DFBM - Inherits from DFFile and implements DFImageFile. Note that this class handles all BM types transparently; if you have only one Page it will be saved as a single, otherwise a multiple.
- New/DFBM() - Creates a single 1x1 BM.
- New/DFBM(Size) - Creates a single BM of the indicated size.
- New/DFBM(Integer, Size) - Creates a single/multiple BM with Integer pages and the indicated Size in all pages.
- New/DFBM(Bitmap) - Creates a single BM using the image.
- New/DFBM(Bitmap()) - Creates a single/multiple BM using the images in the array to generate pages.
- SaveOptimal(Stream/String) - Saves to a Stream/File, testing each compression type until it finds the one that produces the smallest file, then writes it to the Stream/File.
- Pages() allows access to the images in the DFBM (see DFBM.Page class below). You can add/remove pages at whim.
- Bitmap - Returns/Sets the first Bitmap in a single/multiple BM.
- Palette - Returns the first Bitmap's palette or sets all Bitmaps' palettes.
- FrameRate() - Adjusts the framerate for multiple BMs.
- ToTransparentBitmap - Returns a copy of the first Bitmap, adjusted for transparency if it is a transparent BM.

DFBM.Page - Implements DFImageFile, represents an image in a single/multiple BM.
- New/Page() - Creates a 1x1 BM page.
- New/Page(Size) - Creates a BM page of the indicated size.
- New/Page(Bitmap) - Creates a BM page from the passed bitmap.
- Bitmap - Get/Set the bitmap associated with the page.
- Palette - Get/Set the bitmap's palette
- Flags - Contains the transparent/weapon flags for the BM page.
- Compression - Allows you to set the type of compression used for the page (no effect on multiple BMs).
- Unknown - Three bytes that are present in BM pages, but no-one knows why!
- ToTransparentBitmap - Takes a copy of the Bitmap and adjusts it for transparency if the transparency flag is set.

DFFME - Inherits DFFile, implements DFImageFile
- New/DFFME() - Creates a 1x1 FME.
- New/DFFME(Size) - Creates an FME of the indicated size.
- New/DFFME(Bitmap) - Creates an FME from the passed Bitmap.
- SaveOptimal(Stream/String) - Determines whether a smaller filesize can be achieved with compression or without and then writes the file to the Stream or to disk.
- Bitmap - Gets/Sets the bitmap associated with the FME.
- Palette - Gets/Sets the bitmap's palette.
- InsertionPoint - Determines the offset of the FME when it is rendered.
- StoreFlipped - DF will render the image flipped. Note that when loading images with this set, my lib will automatically flip them so they appear as they would in-game. Similarly saving images with this set will not affect how they appear in-game; just how they are stored in the FME. If you want to flip the image manipulate the Bitmap yourself. Razz
- Compressed - True or False, if you want to use RLE0 compression or not on the FME.
- ToTransparentBitmap - Makes a copy of the bitmap and applies transparency to color index 0.

DFWAX - Inherits from DFFile, implements DFImageFile. Note that many waxes reduce redundancy in images by having the multiple pointers in the file point to the same sequence, or frame. This redundancy is represented in .NET as the following:

- Waxes, Sequences, and Frames that are "duplicated' this way are represented as the same object. For example, if Wax #1 -> Sequence #1 -> Frame #1 and Wax #2 -> Sequence #1 -> Frame #1 both point to the same frame, then Waxes(1).Sequences(1).Frames(1) will return the same object as Waxes(2).Sequences(1).Frames(1). VB allows you to compare returned objects to see if they are the same with the Is keyword.
- Cells that are "duplicated" will have the same Bitmap objects shared between Frames.
- DFWAX will, when saving, not attempt to find and prune any redundant data itself. It will only look for objects that are the same instance (as above) to find redundancy. So basically if you have two Frames that are exactly alike but are not the same object instance, they will not be combined in the .WAX file. But if you assign a frame like so:

Waxes(1).Sequences(1).Frames(2) = Waxes(1).Sequences(1).Frames(1)

they will be considered the same when you Save the WAX file and only one copy will be written and pointed to by both frame pointers.

Members:
- New/DFWAX() - Creates a WAX with one Wax, one Sequence, and one DFFME frame with default constructor.
- New/DFWAX(Size/Bitmap) - Creats a WAX with one Wax, one Sequence, and one DFFME, passing the Size/Bitmap to the DFFME constructor.
- New/DFWAX(Bitmap()()()) - Creates a hierarchy of Waxes, Sequences, and Frames using the staggered array values.
- SaveOptimal(Stream/String) - Saves the file, using SaveOptimal on the DFFMEs instead of the normal Save.
- Waxes - Returns the collection of 32 Wax objects. Many will probably be null. See DFWAX.Wax.
- Bitmap - Returns Waxes(0).Sequences(0).Frames(0).Bitmap, and allows you to set it.
- Palette - Returns the above bitmap's palette and allows you to set the palette for all frames' bitmaps.
- ToTransparentBitmap - Returns a copy of the above bitmap, adjusted for transparency.

DFWAX.Wax - A "Wax" in the WAX file (see DF Specs for info about this stuff).
- Sequences - Returns the array of 32 sequences. Some may be null.
- WorldSize - The size of the Wax in the world. I guess.
- FrameRate - Animation rate of the Wax.

DFWAX.Sequence - A sequence.
- Frames - Array of 32 DFFMEs. Some may be null. You can manipulate/set these like any other DFFME.

DFFNT - Inherits DFFile, implements DFImageFile.
- New/DFFNT() - Creates a new FNT with a new 1x1 character at #0 (change with .First).
- New/DFFNT(Size) - Creates a new FNT with a Size chatacter #0 (change with .First).
- New/DFFNT(Integer, Size) - Creates a new FNT with Integer characters starting at #0 (change with .First), of Size size.
- New/DFFNT(Bitmap) - Creates a new FNT and sets character #0 (change with .First) to the Bitmap.
- New/DFFNT(Bitmap()) - Creates a new FNT using the character Bitmaps, starting with character #0 (change with .First).
- Pages - Returns a 0-indexed list of the characters. (See DFFNT.Page)
- Character(Byte) - Returns a DFFNT.Page for the indicated character. Like Pages but adjusted for the First character and not 0-indexed.
- Unknown - Three bytes with unknown values in every DFFNT.
- First - The ASCII character index the first page is.
- Last - Returns the ASCII character index of the last page based on First and the number of pages.
- SetRange(Byte, Byte) - Changes the font range destructively. Basically, if the new first and last Bytes lie outside the existing range the font will be wiped. If there is overlap the old characters lying in both ranges will be preserved. This function is useful if you have a FNT with A-Z and want to change it to 0-z without needing to move the A-Z character by hand (changing First to 0 would just make the A character wind up in the slot for 0).
- Bitmap - The First character's bitmap.
- Palette - Returns the palette for the First character, set to set for the whole font.
- ToTransparentBitmap - Returns a copy of the First character, adjusted for transparency.

DFFNT.Page - A single font character. Implements DFImageFile.
- New/Page() - Creates 1x1 character.
- New/Page(Size) - Creates character of a specific size.
- New/Page(Bitmap) - Creates a character from the Bitmap.
- Bitmap - The character
- Palette - The character's palette
- ToTransparentBitmap - Takes a copy of Bitmap and adjusts the palette to make color 0 transparent.

DFPLTT - Inherits from DFPaletteFile.
- New/DFPLTT(Byte, Byte) - Creates a new PLTT with the first and last colors in the range specified in the bytes. All colors are black.
- New/DFPLTT(ColorPalette, Byte) - Creates a PLTT from the ColorPalette, using the byte to determine the color index in the DFPLTT that the first color in the ColorPalette represents. The number of colors in the ColorPalette is used to compute the Last color index.
- PaletteIndex(Byte) - Returns the color specified by Byte, valid range is from First to Last
- First - The first color index
- Last - Returns the last color index based on the length of the Colors array and First
- SetRange(Byte, Byte) - Changes the color range destructively, just like DFFNT's SetRange works.

DFDELT - Inherits from DFFile, implements DFImageFile
- New/DFDELT() - Creates 1x1 DELT.
- New/DFDELT(Size) - Creates DELT of a specific size.
- New/DFDELT(Bitmap) - Creates a DELT from the Bitmap.
- SaveOptimal(Stream/String) - DELTs can have RLE0 compression or not per line, so the logic is a bit more complex here, but the general idea is still to figure out how to generate the smallest file and save it.
- Bitmap - The image
- Palette - The image's palette
- Compressed - If not set, Save will save uncompressed. If set, Save will use SaveOptimal's logic.
- Offset - Controls the relative position of where DF draws the image. I suppose.
- ToTransparentBitmap - Copies Bitmap, sets the palette's color index 0 to transparent (is this right?) and returns the copy.

DFANIM - Inherits DFFile, implements DFImageFile
- New/DFANIM() - Creates an ANIM with a 1x1 DELT.
- New/DFANIM(Size) - Creates an ANIM with one DELT with the indicated size.
- New/DFANIM(Integer, Size) - Creates an ANIM with Integer DELTs of the indicated size.
- New/DFANIM(Bitmap) - Creates a DELT from the image and turns it into an ANIM.
- New/DFANIM(Bitmap()) - Creates DELTs from the images and bundles them into one ANIM.
- SaveOptimal(Stream/String) - Calls SaveOptimal on each DELT when saving to the ANIM.
- Pages - Returns the list of DFDELTs in the ANIM. Add/remove/go nuts.
- Bitmap - The first DELT's bitmap.
- Palette - The above's palette, set it to set all pages' palettes.
- ToTransparentBitmap - The first DELT's bitmap copied and adjusted to make color index 0 transparent.

DFFONT - Inherits from DFFile and implements DFImageFile. NOTE: All bitmaps used here must be 1bpp.
- New/DFFONT() - Creates a new FONT with a new 1x1 character at #0 (change with .First).
- New/DFFONT(Size) - Creates a new FONT with a Size chatacter #0 (change with .First).
- New/DFFONT(Integer, Size) - Creates a new FONT with Integer characters starting at #0 (change with .First), of Size size.
- New/DFFONT(Bitmap) - Creates a new FONT and sets character #0 (change with .First) to the Bitmap.
- New/DFFONT(Bitmap()) - Creates a new FONT using the character Bitmaps, starting with character #0 (change with .First).
- Pages - Returns a 0-indexed list of the characters. (See DFFONT.Page)
- Character(Byte) - Returns a DFFONT.Page for the indicated character. Like Pages but adjusted for the First character and not 0-indexed.
- Unknown - A short int who's purpose is unknown.
- First - The ASCII character index the first page is.
- Last - Returns the ASCII character index of the last page based on First and the number of pages.
- SetRange(Byte, Byte) - Changes the font range destructively, just like in DFFNT.
- Bitmap - The First character's bitmap.
- Palette - Returns the 2-color palette palette for the First character, set to set for the whole font. Usually not relevant since FONTs technically don't have color indices for a palette. DON'T try to set a PAL or PLTT's palette here, only 2-color palettes.
- ToTransparentBitmap - Returns a copy of the First character, adjusted for transparency.

DFFONT.Page - A single font character. Implements DFImageFile. NOTE: All bitmaps here must be 1bpp.
- New/Page() - Creates 1x1 character.
- New/Page(Size) - Creates character of a specific size.
- New/Page(Bitmap) - Creates a character from the Bitmap.
- Bitmap - The character
- Palette - The character's 2-color palette. By default it's white on black. Don't assign a PAL or PLTT's color palette.
- ToTransparentBitmap - Takes a copy of Bitmap and adjusts the palette to make color 0 transparent.

Code sample which demonstrates some basic PAL/BM/CMP stuff:

Code:
Imports MZZT.DarkForces.Formats

Public Module Program
    Public Sub Main()
        Dim bm as New DFBM("DEFAULT.BM")
        bm.SaveOptimal("TEST.BM") ' Save with compression
        bm.Load("TEST.BM") ' Test to make sure it loads correctly

        Dim pal as New DFPAL("SECBASE.PAL")
        bm.Palette = pal.ToColorPalette
        bm.ToTransparentBitmap ' Function returns a Bitmap ready for painting or setting to a PictureBox

        Dim cmp as New DFCMP("SECBASE.CMP")
        cmp.Palette = pal
        bm.Palette = cmp.LightLevelToDFPAL(16)
        bm.ToTransparentBitmap ' Function returns a Bitmap that shows us how DEFAULT.BM looks like at half light level

        Dim b as New Bitmap(1, 1, Imaging.PixelFormat.Format8bppIndexed)
        bm = New DFBM(b)
        bm.Save("BLACK.BM") ' Default color in the Bitmap will be 0, which is black on SECBASE.PAL
    End Sub
End Module


_________________
http://www.mzzt.net/ | I am a respectable admin with a respectable sig.

Burning Gundam
Kell Dragon

Joined: 28 Sep 2003

PostPosted: Jul 24, 2009 08:01    Post subject: View user's profile Send private message Send e-mail Reply with quote

Holy crap....

_________________
I don't think outside the box... I customize it.

The MAZZTer
Death Star
Death Star

Joined: 25 Sep 2003

PostPosted: Jul 24, 2009 12:41    Post subject: View user's profile Send private message Send e-mail Reply with quote

It's not THAT impressive. Hardest parts were compression and WAX support. Razz

I AM glad someone finally commented on this after I posted pic after pic in the other thread.

_________________
http://www.mzzt.net/ | I am a respectable admin with a respectable sig.

Jimmy Chicken
Gamorrean

Joined: 09 Dec 2003

PostPosted: Aug 29, 2009 21:30    Post subject: View user's profile Send private message Reply with quote

Just curious, did you make an visual application to go along with this library, were users can open, save, and preview the formats?

_________________
"if you see a wall with the blast marks DF 21 shot into it, I was there"

The MAZZTer
Death Star
Death Star

Joined: 25 Sep 2003

PostPosted: Aug 30, 2009 03:57    Post subject: View user's profile Send private message Send e-mail Reply with quote

It's in the works. Right now you can open and view resources, need to work on editing as well as WAX management stuff.

But I did the backend stuff first so I figured it might be useful to someone.

_________________
http://www.mzzt.net/ | I am a respectable admin with a respectable sig.

Burning Gundam
Kell Dragon

Joined: 28 Sep 2003

PostPosted: Aug 30, 2009 07:49    Post subject: View user's profile Send private message Send e-mail Reply with quote

So if I understand this correctly, this will replace my need to use BMPDF to make custom textures?

_________________
I don't think outside the box... I customize it.

The MAZZTer
Death Star
Death Star

Joined: 25 Sep 2003

PostPosted: Aug 30, 2009 13:21    Post subject: View user's profile Send private message Send e-mail Reply with quote

Yeah.

_________________
http://www.mzzt.net/ | I am a respectable admin with a respectable sig.

DF Veteran
Ree-Yees

Joined: 24 Nov 2005

PostPosted: Mar 25, 2010 06:42    Post subject: View user's profile Send private message Reply with quote

Wow. I started working on an editor for all things DF a while ago, but school, life and work got in the way. Your work is definately impressive.

One thing I was going to impliment in my editor was to map colors to different keys on the keyboard, like 1 through 0 because I hated continually grabbing new colors with the mouse when I wanted to shade or something like that. Then I could just hit a few keys to map the colors I needed for that texture and then hit one key when I needed to recall that color. Would you considder putting this in your editor? You can take credit for the idea, too, if you want. Wink

I could even help out with the project if you needed as well. It'd be a fun project to work on. Although, being a programmer myself I know how projects become our 'babies' so you may just want to work on it yourself. What lang are you writing it in?

DF Veteran
Ree-Yees

Joined: 24 Nov 2005

PostPosted: Mar 25, 2010 06:43    Post subject: View user's profile Send private message Reply with quote

Wow, I just realized how old this thread was.

Display posts from previous:   
Post new topic   Reply to topic    DF-21 Forums Forum Index -> Dark Forces Levels & Editing All times are GMT
Page 1 of 1

 
Jump to:  
You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum
You cannot vote in polls in this forum


Powered by phpBB © 2001, 2005 phpBB Group