SelectWare Archive
Format type | Archive |
---|---|
Max files | Unlimited |
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:
- Blue Force
- Dune II
- Jet Fighter 2
- Maelstrom
- Microcosm
- Shadow President
- The Complete House
- The Selfish Giant
- Darklands
- CyberRace
- The Peter Norton Productivity Pack
- Casino Master Gold Edition
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 | Platform | Extract files? | Decompress on extract? | Create new? | Modify? | Compress on insert? | Access hidden data? | Edit metadata? | Notes |
---|---|---|---|---|---|---|---|---|---|
Librarian | Windows | Yes | N/A | No | No | N/A | N/A | No |
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!)