SelectWare Archive

From ModdingWiki
Jump to navigation Jump to search
SelectWare Archive
Format typeArchive
Max filesUnlimited
File Allocation Table (FAT)Embedded
Filenames?Yes, 8.3
Metadata?None
Supports compression?No
Supports encryption?No
Supports subdirectories?Yes
Hidden data?No
Games

The SelectWare Archive format is a format used by The SelectWare System, a quick-launch mechanism used by the company SelectWare Technologies to publish software, mostly shareware demos. It appears in a number of Selectware releases.

Use

The most prominent collection containing this format is the SelectWare Gold Medal 12 Pack; a collection containing the following programs and games:

Besides that, the company also distributed several shareware CDs.

Header

The format starts with the following header.

Offset Data type Name Description
0x00 BYTE[0x28] Signature The text "SelectWare Technologies demo file", followed by bytes 0x0A 0x1A, and filled to the end with zeroes.
0x28 UINT32LE FreeSpace Minimum disk free space required for this software (sizes of all files inside archive + some free space).

File entry

Following the header are the actual files, each one preceded by a file header that indicates its length and some other information.

Offset Data type Name Description
0x00 INT16LE DirLevel Current directory level. Used as flag for files in directories. Directory entries will be treated as the root of the deeper level, so their DirLevel will be one higher than that of the files at the same tree depth.
0x02 FileInfoRec FileInfo Structure from FindFirst / FindNext DOS services. This data contains the file size, a flag indicating whether the entry is a directory, and a date stamp.
0x2D BYTE Padding Padding to align whole structure to the even boundary.

The file contents of the described file immediately follow this file header, and have the length indicated in FileInfoRec.

Since there is no index in advance, nor a number of files, reading of the archive continues until the end of the file is reached.

For understanding DOS FileInfoRec structure see also DOS File Attribute and DOS Packed File Date/Time Format.

Traversing the directory tree

There is always an explicit entry for the directory before encountering files at a deeper level in the directory tree. From the FileInfo information, the file attributes can be checked to see if an entry is a directory. With the combined information of this directory flag and the DirLevel, code traversing the data can keep track of the location in the directory tree, by going deeper at the moment a directory is found, and going back when a file with a lower DirLevel or a directory with the same DirLevel is found.

For practical purposes, it is probably more straightforward to decrease the read DirLevel of directory entries by 1, so it always indicates the level of the entry's parent directory. This allows the number to be treated the same way for files and directories.

Archive extracting example source code

C

/*
Copyright 2021 CTPAX-X Team
This source code licensed under the Apache License, Version 2.0 (the "License"):
https://www.apache.org/licenses/LICENSE-2.0
*/

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <malloc.h>
#include <stdint.h>
#include <direct.h>

#pragma pack(push, 1)
typedef struct {
  char signature[40]; /* ignored */
  uint32_t disksize;  /* required minimum free disk space for software to run */
} swt_head;           /* (size of all files inside archive + some free space) */

/* DOS FileInfoRec structure for FindFirst / FindNext services */
typedef struct {
  uint8_t  reserved[21];
  uint8_t  dos_attr;
  uint16_t dos_time;
  uint16_t dos_date;
  uint32_t filesize;
  char     filename[13];
} dos_find;

typedef struct {
  int16_t  dirlevel; /* current directory level */
  dos_find fileinfo;
  uint8_t  padding; /* padding to align whole structure to the even boundary */
} swt_item;
#pragma pack(pop)

int main (int argc, char *argv[]) {
char path[260], s[260];
swt_head sh;
swt_item si;
int16_t dold;
FILE *fl, *f;
size_t i;
void *p;
  puts("SelectWare Technologies demo file extractor\n");
  if (argc != 2) {
    puts("Usage: unswtpak <filename.swt>\n");
    return(1);
  }
  fl = fopen(argv[1], "rb");
  if (!fl) {
    puts("Error: can't open input file.\n");
    return(2);
  }
  fread(&sh, sizeof(sh), 1, fl);
  /* TODO: check minimum free disk space before extracting */
  dold = 0;
  path[0] = 0;
  do {
    memset(&si, 0, sizeof(si));
    fread(&si, sizeof(si), 1, fl);
    /* no more records */
    if (!si.fileinfo.filename[0]) { break; }
    /* going up */
    while (si.dirlevel <= dold) {
      /* in this level can go up only for directory (will replace current) */
      if ((si.dirlevel == dold) && (!(si.fileinfo.dos_attr & 0x10))) { break; }
      /* cut last directory */
      i = strlen(path);
      if (i) {
        i--;
        while (i) {
          if (path[i - 1] == '\\') { break; }
          i--;
        }
        path[i] = 0;
      }
      dold--;
    }
    /* update current location */
    dold = si.dirlevel;
    /* it's directory */
    if (si.fileinfo.dos_attr & 0x10) {
      /* going down */
      strcat(path, si.fileinfo.filename);
      mkdir(path);
      strcat(path, "\\");
    } else {
      /* it's file */
      p = malloc(si.fileinfo.filesize);
      if (p) {
        fread(p, si.fileinfo.filesize, 1, fl);
        /* build path */
        strcpy(s, path);
        strcat(s, si.fileinfo.filename);
        puts(s);
        /* dump file to disk */
        f = fopen(s, "wb");
        if (f) {
          fwrite(p, si.fileinfo.filesize, 1, f);
          /* TODO: set file date, time and attributes */
          fclose(f);
        } else {
          puts("Error: can't create output file.");
        }
        free(p);
      } else {
        /* not enough memory - skip file */
        fseek(fl, si.fileinfo.filesize, SEEK_CUR);
        puts("Error: not enough memory for output file.");
      }
    }
  } while (si.fileinfo.filename[0]);
  fclose(fl);
  puts("\ndone\n");
  return(0);
}

Tools

The following tools are able to work with files in this format.

Name PlatformExtract files? Decompress on extract? Create new? Modify? Compress on insert? Access hidden data? Edit metadata? Notes
Librarian WindowsYesN/ANoNoN/AN/ANo

Credits

This file format was first reverse engineered by SirNickity on the VOGONS forum, with further research done by Nyerguds and CTPAX-X Team. If you find this information helpful in a project you're working on, please give credit where credit is due. (A link back to this wiki would be nice too!)