From f9dcbdd176785dfc9d49f3113ec6110199e9a246 Mon Sep 17 00:00:00 2001 From: "B. Watson" Date: Fri, 10 May 2024 17:24:40 -0400 Subject: import ken siders atr utilities. --- ksiders/Makefile | 67 +++ ksiders/README.txt | 77 +++ ksiders/atdos.h | 137 +++++ ksiders/atr.c | 1422 ++++++++++++++++++++++++++++++++++++++++++++++++++++ ksiders/atr.h | 65 +++ ksiders/atr.txt | 521 +++++++++++++++++++ ksiders/atrdir.1 | 65 +++ ksiders/atrdir.c | 89 ++++ ksiders/atrextr.1 | 64 +++ ksiders/atrextr.c | 63 +++ ksiders/atrsrc.zip | Bin 0 -> 18785 bytes ksiders/kboot.h | 61 +++ ksiders/makeatr.1 | 92 ++++ ksiders/makeatr.c | 41 ++ ksiders/sortatr.1 | 80 +++ ksiders/sortatr.c | 39 ++ ksiders/unmakatr.c | 43 ++ 17 files changed, 2926 insertions(+) create mode 100644 ksiders/Makefile create mode 100644 ksiders/README.txt create mode 100644 ksiders/atdos.h create mode 100644 ksiders/atr.c create mode 100644 ksiders/atr.h create mode 100644 ksiders/atr.txt create mode 100644 ksiders/atrdir.1 create mode 100644 ksiders/atrdir.c create mode 100644 ksiders/atrextr.1 create mode 100644 ksiders/atrextr.c create mode 100644 ksiders/atrsrc.zip create mode 100644 ksiders/kboot.h create mode 100644 ksiders/makeatr.1 create mode 100644 ksiders/makeatr.c create mode 100644 ksiders/sortatr.1 create mode 100644 ksiders/sortatr.c create mode 100644 ksiders/unmakatr.c (limited to 'ksiders') diff --git a/ksiders/Makefile b/ksiders/Makefile new file mode 100644 index 0000000..674b3e6 --- /dev/null +++ b/ksiders/Makefile @@ -0,0 +1,67 @@ + +# This Makefile has been tested with GNU make and /usr/ccs/bin/make +# on a Solaris 2.6 (SunOS 5.6) system. + +CC=gcc +COPT=-O2 +CFLAGS=-Wall $(COPT) -ansi -fpack-struct + +# -pedantic complains about some perfectly harmless signed/unsigned +# char pointer stuff. + +# Note: -fpack-struct works on gcc's at least as old as 2.95.3 +# If you're not using gcc, find your compiler's equivalent option +# (/Zp on Microsoft compilers). + +DESTDIR= +PREFIX=/usr/local +BINDIR=$(PREFIX)/bin +MANDIR=$(PREFIX)/man +MAN1DIR=$(MANDIR)/man1 + +# some systems need this instead: +#MANDIR=$(PREFIX)/share/man + +# Comment out next line if your system does not support gzip'ed man pages +GZIP_MAN=y + +EXES=atrdir atrextr makeatr sortatr unmakatr +MANS=atrdir atrextr makeatr sortatr + +all: $(EXES) + +clean: + rm -f $(EXES) atr.o tags *~ *.bak + +install: all + mkdir -p $(DESTDIR)$(BINDIR) $(DESTDIR)$(MANDIR) ;\ + for exe in $(EXES) ; do \ + strip $$exe ;\ + cp $$exe $(DESTDIR)$(BINDIR)/$$exe ;\ + done ;\ + for man in $(MANS) ; do \ + if [ "$(GZIP_MAN)" = "y" ]; then \ + gzip -c < $$man.1 > $(DESTDIR)$(MAN1DIR)/$$man.1.gz ;\ + else \ + cp $$man.1 $(DESTDIR)$(MAN1DIR) ; \ + fi ;\ + done + if [ "$(GZIP_MAN)" = "y" ]; then \ + cd $(DESTDIR)$(MAN1DIR) && rm -f unmakatr.1.gz && ln -s makeatr.1.gz unmakatr.1.gz ;\ + else \ + cd $(DESTDIR)$(MAN1DIR) && rm -f unmakatr.1 && ln -s makeatr.1 unmakatr.1 ;\ + fi + + +atr.o: atr.c atr.h atdos.h kboot.h + +atrdir: atrdir.c atr.o + +atrextr: atrextr.c atr.o + +makeatr: makeatr.c atr.o + +sortatr: sortatr.c atr.o + +unmakatr: unmakatr.c atr.o + diff --git a/ksiders/README.txt b/ksiders/README.txt new file mode 100644 index 0000000..b6c5934 --- /dev/null +++ b/ksiders/README.txt @@ -0,0 +1,77 @@ + +This is a quick & dirty Linux/UNIX port of Ken Siders' old Atr Utils +package for MS-DOS. + +The original MS-DOS sources can be found in the file atrsrc.zip, or +you can download them from Ken's page: + http://atari.ksiders.tzo.com/a8emulators.html + +Please do NOT contact Ken Siders about bugs or issues with these ported +and modified versions of his utilities. They are provided as-is, by me, +B. Watson (urchlay at urchlay dot com). + +The utilities are: + +atrdir - Get a directory of an ATR image +atrextr - Extract files from an ATR image to the current directory +makeatr - Make a bootable "K-file" disk from an Atari executable +sortatr - Sort the directory of an ATR image in alphabetical order +unmakatr - Reverse of makeatr: extracts the Atari exe from a K-file disk + +All utilities work only with AtariDOS 2.x or MyDOS compatible images. +SpartaDOS, AtariDOS 3/4, DOS XE, and other non-MyDOS-compatible formats +are not supported. Atari DOS 2.5 images are only partially supported. + +All utilities have been tested on Linux (with gcc-3.4.4) and Solaris 2.6 +(with gcc-2.95.3). They produce identical output on both platforms. +However, Solaris 2.6 doesn't support gzipped man pages, so you have +to install with "make install GZIP_MAN=n". + +I've written rudimentary man pages for the utilities. Any errors in the +man pages are my own fault. + +I've made a few changes to the library (atr.c). Some are bugfixes, some +are feature enhancements, and a few are just to make the utilities behave +more like UNIX utilities are expected to behave. + +- AtariDirectory() (used by atrdir) now partly supports DOS 2.5 extended +files (using sectors > 720). They are listed (with "<"), but their size +is not (shows up as "??"). (The original DOS version was "blind" to +files like these, like DOS 2.0S is). + +- AtariDirectory(): Also, MyDOS directories are now listed (with ":"), +though their size is listed as "??". + +- AtariDirectory(): Stop listing files after the first unused entry, +as Atari DOSes do. For normal disks, this really wasn't a problem, but +e.g. the HomeSoft games disks store file data in the higher-numbered +(unused) directory sectors, cause atrdir to print garbage to the terminal. + +- PatternMatch() (used by atrdir and atrextr) now always matches all +files, if the wildcard pattern is "*" or "*.*". Also, wildcard patterns +are now case-insensitive. + +- SortAtariDir() (used by sortatr) now correctly fills unused characters +in the filename with spaces, as Atari DOSes do. Previously, they were +filled with nulls (Atari heart character). + +- ExtractAtariFile() (used by atrextr) no longer includes a trailing +dot in the extracted filename, if the file in the image has no 3-character +extender. + +- ExtractAtariFile(): extract path now may be up to 4096 bytes, and +UNIX-style / is used for delimiter instead of DOS \ + +- atrextr: file argument is now optional (defaults to *.* if missing +or blank). + +- atrextr: added optional dir argument. Files will be extracted to this +directory (which will be created if necessary). + +- all utilities: exit status is now 0 for success, non-zero for any error. + +- atr.c (all utilities): Added support for detecting endianness and +swapping bytes in start sector and sector count, if needed. Atari and +PC are both little-endian platforms, so the DOS sources didn't need to +support big-endian platforms. Tested on Solaris 2.6 on Sparc hardware +(big-endian). diff --git a/ksiders/atdos.h b/ksiders/atdos.h new file mode 100644 index 0000000..34849b6 --- /dev/null +++ b/ksiders/atdos.h @@ -0,0 +1,137 @@ +/* Copyright 1997 Ken Siders */ + +/* dos compatability types */ +#define DOS_ATARI 1 +#define DOS_MYDOS 2 +#define DOS_SPARTADOS 3 +#define DOS_LJK 4 + +#define MAX_ATARI_FILES 64 + +/* disk format types */ +#define FORMAT_SD 1 +#define FORMAT_ED 2 +#define FORMAT_DD 3 +#define FORMAT_SD_CUSTOM 4 +#define FORMAT_DD_CUSTOM 5 +#define FORMAT_DEFAULT 6 + +/* open modes */ +#define ATARI_OPEN_READ 4 +#define ATARI_OPEN_WRITE 8 +#define ATARI_OPEN_DIR 6 + +/* these will be in variables later */ +#define firstDirSector 361 +#define lastDirSector 368 +#define vtocSector 360 +#define vtocSector2 0 +#define dirEntrySize 16 +#define dirEntriesPerSector 8 + +#define DELETED_FLAG 0x80 +#define INUSE_FLAG 0x40 +#define LOCKED_FLAG 0x20 +#define MYDOSDIR_FLAG 0x10 +#define OPENOUTPUT_FLAG 0x01 +#define DOS25EXT_FLAGS 0x03 + +struct S_AtariDosDirEntry + { + char flag; + unsigned short sectorCount; + unsigned short startSector; + char fileName[8]; + char extender[3]; + }; + +typedef struct S_AtariDosDirEntry AtariDosDirEntry; +typedef AtariDosDirEntry *AtariDosDirEntryPtr; + +/* 20070518 bkw: + Nothing actually uses this struct, and it's got endianness + issues... */ +#if 0 +struct S_AtariDosLink + { + int fileNo:6; + int nextSector:10; + int shortSector:1; + int bytesInSector:7; + + }; + +typedef struct S_AtariDosLink AtariDosLink; +typedef AtariDosLink *AtariDosLinkPtr; +#endif + +struct S_AtariVtoc + { + byte reserved[10]; + byte vtoc[118]; + }; + + + + +struct S_AtariFile + { + AtrFilePtr atr; + unsigned short startSector; + unsigned short currentSector; + unsigned short sectorSize; + unsigned short numberOfSectors; /* no. of sectors in file */ + unsigned long fileSize ; /* not used yet */ + byte openFlag; + byte eofFlag; + short currentOffset; + short bytesData; + short sectorLinkOffset; + short fileNo; + unsigned char sectorBuffer[256]; + + }; + +typedef struct S_AtariFile AtariFile; +typedef AtariFile * AtariFilePtr; + + + + +struct S_AtariFileInfo + { + unsigned long fileSize; /* not implemented */ + unsigned short startSector; + unsigned short sectorCount; + char fileName[13]; + int locked; + int attrib; /* internal */ + int dirSector; /* internal */ + int dirEntry; /* internal */ + char *pattern; /* internal */ + char *atrName; /* internal */ + int dosType; + short fileNo; + int flag; /* from dos */ + }; + +typedef struct S_AtariFileInfo AtariFileInfo; +typedef AtariFileInfo *AtariFileInfoPtr; + + + +/* function prototypes */ + +void MakeFileName( char *result, char *fileName, char *extender ); +int PatternMatch( char *pattern, char *fileName, char *extender); +int AtariFindFirst( char *atrName, unsigned attrib, + char *pattern, AtariFileInfoPtr fileInfo ); +int AtariFindNext( AtariFileInfoPtr fileInfo ); +AtariFilePtr OpenAtariFile( char *atrName, char *fileName, byte mode); +int AtariDirectory( char *atrName, char *pattern); +long ReadAtariFile( AtariFilePtr atFile, char *buffer, long bytes ); +int CloseAtariFile( AtariFilePtr atFile ); +int EofAtariFile( AtariFilePtr atFile ); +long AtariFileSize( char *atrFile, char *fileName ); +int FixAtariFileNo( char *atrName, char *fileName, int fileNo ); + diff --git a/ksiders/atr.c b/ksiders/atr.c new file mode 100644 index 0000000..2c3942f --- /dev/null +++ b/ksiders/atr.c @@ -0,0 +1,1422 @@ +/********************************************************************* + ATR/XFD File handling library + (C) Copyright 1997 Ken Siders + + This file can be used in any freeware or public domain software + as long as credit is given. + + +History + +00.000 6/16/97 Initial version +00.001 6/24/97 Fixed AtariFileSize, Added EofAtariFile and + ExtractAtariFile functions +00.002 6/26/97 Added SortDirectory Function +00.003 7/14/97 Fixed Double density to treat first 3 sectors as + Single Density. +00.004 7/16/97 Added CreateBootAtr +00.005 8/22/97 Added ExtractExeFromBootAtr +00.006 9/04/97 Fix signature check + +********************************************************************* + +To do: + +1 Clean up warnings + make more portable +2 Allow opening write-protected ATRs +3 Allow more than one reference to an ATR file to be opened so more + than one atari file can be opened at once. (Keep a count) +4 More specific error returns +5 Implement XFD handling +6 Create documentation +7 Optimize if necessary +8 Implement DCM images (maybe) + + +*********************************************************************/ + +#define wide 1 + + +/* compile with /Zp option */ +/* 20070518 bkw: or -fpack-struct on gcc */ + + +#include +#include +#include +#include +#include +#include +#include +#include "atr.h" +#include "atdos.h" +#include "kboot.h" + +AtrHeader hdr; + +int lastAtariError = 0; + +static unsigned char sectorBuffer[256]; +static int CompareName( const void *a, const void *b ); +static int verbose = 0; + +/* 20070518 bkw: min() isn't standard on Linux. If you're porting to + some other UNIX and get errors about min() already being defined, + just comment this out. */ +static int min(int a, int b) { + return ((a < b) ? a : b); +} + +/* 20070518 bkw: As written, the DOS sources aren't portable to + big-endian architectures. To fix this, EndianFix() will swap + the high and low bytes of startSector and sectorCount in a + dir entry on a big-endian arch (and leave them alone on a little- + endian arch). Must be called just after reading, and just before + writing. + + The Intel x86 arch and the Atari's 6502 both happen to be + little-endian, which is why Ken could ignore the endianness + issue in the original MS-DOS sources. + */ +#define LITTLE_END 0 +#define BIG_END 1 + +static int InitEndian() { + /* code based on Wikipedia "Endianness" entry */ + union { + short s; + char c[sizeof(short)]; + } un; + + un.s = 0x0102; + + if(sizeof(short) == 2) { + if(un.c[0] == 1 && un.c[1] == 2) + return BIG_END; + else if(un.c[0] == 2 && un.c[1] == 1) + return LITTLE_END; + } + + printf("WARNING: Can't determine endianness of this platform!\n"); + printf("Assuming little-endian, hoping for the best. Expect trouble.\n"); + return LITTLE_END; +} + +static void EndianFix(AtariDosDirEntryPtr entry) { + static int endian = -1; + unsigned short tmp; + + if(endian == -1) + endian = InitEndian(); + + /* don't do anything on little-endian platforms */ + if(endian == LITTLE_END) + return; + + tmp = entry->startSector; + entry->startSector = ((tmp & 0xff) << 8) | ((tmp & 0xff00) >> 8); + + tmp = entry->sectorCount; + entry->sectorCount = ((tmp & 0xff) << 8) | ((tmp & 0xff00) >> 8); +} + +/****************************************************************** +SetVerbose - Sets verbose flag, returns last value of flag +******************************************************************/ + +int SetVerbose( int verb ) + { + int last; + + last = verbose; + verbose = verb; + return(last); + } + + + +/****************************************************************** + OpenAtr - opens ATR file specified for read/write (if writeable). + Returns Atr Pointer if successful, 0 if not +******************************************************************/ + +AtrFilePtr OpenAtr(char *file ) + { + AtrFilePtr atr; + int bytes; + unsigned short signature; + + atr = malloc(sizeof(AtrFile)); + + atr->dosType = DOS_ATARI; /* assume atari dos disk */ + + + atr->atrIn = fopen(file, "rb+"); + if ( !atr->atrIn ) + { + free(atr); + return 0; + } + bytes = fread(&hdr, 1, 16, atr->atrIn); + if ( !bytes ) + { + free(atr); + return 0; + } + + signature = hdr.idLow | hdr.idHigh << 8; + atr->imageSize = 16L * (hdr.paraLow | hdr.paraHigh * 256L | hdr.paraHigher * 65536L); + atr->secSize = hdr.secSizeLow | hdr.secSizeHigh << 8; + atr->crc = hdr.crc1 | hdr.crc2 * 256L | hdr.crc3 * 65536L | hdr.crc4 *256L * 65536L ; + atr->sectorCount = atr->imageSize / atr->secSize; + atr->flags = hdr.flags; + atr->writeProtect = atr->flags&1; + atr->authenticated = (atr->flags >> 1) & 1; + + if ( atr->sectorCount > 721 ) + atr->dosType = DOS_MYDOS; + + if ( signature == 0x296 ) + return atr; + else + { + free(atr); + return 0; + } + return atr; + } + + +/****************************************************************** + CloseAtr - closes ATR file specified in an Atr Pointer from + and Atr Open. Returns 0 if successful +******************************************************************/ + +int CloseAtr( AtrFilePtr atr ) + { + if ( atr ) + return(fclose(atr->atrIn)); + else + return 1; + } + + +/****************************************************************** + ReadSector - Reads specified sector from the ATR file specified + info buffer which must be big enough for the sector + size of teh file. Returns number of bytes read or + 0 if error. +******************************************************************/ + +int ReadSector(AtrFilePtr atr, unsigned short sector, char *buffer) + { + unsigned long pos; + size_t bytes; + + if ( !atr ) + { + lastAtariError = 12; + return 0; + } +/* calculate offset into file */ + if ( atr->secSize > 128 && sector > 3 ) + pos = (unsigned long)(sector-4) * atr->secSize + 400L; + else + pos = (unsigned long)(sector-1) * 128L + 16; + +/* position file pointer at that offset */ + if ( fseek(atr->atrIn, pos, SEEK_SET) ) + { + lastAtariError = 13; + return 0; + } + +/* read the data */ + bytes = fread(buffer, 1, atr->secSize, atr->atrIn); + if ( bytes & 127 ) + { + lastAtariError = 14; + return 0; + } + return bytes; + } + +/****************************************************************** + WriteSector - Writes specified sector from the ATR file specified + from buffer specified. Returns number of bytes + written or 0 if error. Image must be writeable. +******************************************************************/ + +int WriteSector(AtrFilePtr atr, unsigned short sector, char *buffer) + { + unsigned long pos; + size_t bytes; + + if ( !atr ) + { + lastAtariError = 12; + return 0; + } + +/* calculate offset into file */ + if ( atr->secSize > 128 && sector > 3 ) + pos = (unsigned long)(sector-4) * atr->secSize + 400L; + else + pos = (unsigned long)(sector-1) * 128L + 16; + +/* set file pointer to that position */ + if ( fseek(atr->atrIn, pos, SEEK_SET) ) + { + lastAtariError = 13; + return 0; + } + +/* sector # to high? */ + if ( pos + atr->secSize > atr->imageSize ) + { + lastAtariError = 15; + return 0; + } + +/* write the data */ + bytes = fwrite(buffer, 1, atr->secSize, atr->atrIn); + if ( bytes & 127 ) + { + lastAtariError = 14; + return 0; + } + return bytes; +} + +/****************************************************************** + CreateAtr - Creates an ATR file with parameters specified. Sector + size must be a multiple of 128 bytes. Return 0 for + success +******************************************************************/ + +int CreateAtr( char *file, unsigned short sectors, + unsigned short sectorSize ) + { + FILE *fp; + AtrHeader hdr = {0}; + unsigned long imageSize; + int bytes; + +/* sector size must be a multiple of 128 */ + if ( sectorSize & 127 ) + return 1; +/* determine the file size for the image */ + + if ( sectorSize > 128 && sectors > 2) + imageSize = (unsigned long)(sectorSize-3) * sectors + 384; + else + imageSize = (unsigned long)sectorSize * sectors; + +/* create the file */ + fp = fopen(file, "wb"); + if ( !fp ) + return 1; + +/* set up the ATR header */ + hdr.idHigh = 0x02; + hdr.idLow = 0x96; + hdr.paraLow = (imageSize >> 4) & 255; + hdr.paraHigh = (imageSize >> 12) & 255; + hdr.paraHigher = imageSize >> 20; + hdr.secSizeLow = sectorSize & 255; + hdr.secSizeHigh = sectorSize >> 8; + bytes = fwrite(&hdr, 1, 16, fp); + if ( bytes != 16 ) + return 1; + +/* seek to last position needed in file - 1 */ + if ( fseek(fp,(unsigned long)sectors * sectorSize - 1 , SEEK_SET) ) + return 1; +/* write one null byte */ + if ( fputc( 0, fp ) == EOF ) + return 1; + if ( fclose(fp) ) + return 1; + return 0; + } + +/****************************************************************** + GetAtrInfo - returns info for an open ATR image via pointers. + non 0 returned is error. +******************************************************************/ + +int GetAtrInfo( AtrFilePtr atr, unsigned short *sectorSize, + unsigned short *sectorCount, byte *protected) + { + if ( !atr ) + return 1; +/* duh */ + *sectorSize = atr->secSize; + *sectorCount = atr->sectorCount; + *protected = atr->writeProtect; + return 0; + } + + + + + +/*-----------------------------------------------------------------*/ +/* ATARI 8-bit File IO routines */ +/*-----------------------------------------------------------------*/ + +/****************************************************************** + MakeFileName - Creates a filename.ext string from a zero padded + raw fileName and extender. Result is stored in + string pointed to be result. There is no return + value. +******************************************************************/ + +void MakeFileName( char *result, char *fileName, char *extender ) + { + int i; + + for(i=0; i<8; i++) + { + if (fileName[i] == ' ' || !fileName[i] ) + break; + *(result++) = fileName[i]; + } + *(result++) = '.'; + for(i=0; i<3; i++) + { + if (extender[i] == ' ' || !extender[i] ) + break; + *(result++) = extender[i]; + } + *(result++) = 0; + } + + +/****************************************************************** + PatternMatch - Returns 1 if fileName+extender matches pattern in + pattern. Wildcards are the standard '?' and '*' + as supported by all Atari Dos's. Returns 0 if + it does not match. +******************************************************************/ +int PatternMatch( char *pattern, char *fileName, char *extender) + { + int i=0; + char file[13]; + + /* 20070518 bkw: Special case: "*" and "*.*" always match anything */ + if(strcmp(pattern, "*.*") == 0 || strcmp(pattern, "*") == 0) + return 1; + + MakeFileName(file, fileName, extender); + + while (*pattern && file[i] ) + { + if ( !file[i] && *pattern ) + return 0; + if ( file[i] && !*pattern ) + return 0; + + if ( *pattern == '*') + { + while ( file[i] && file[i] != '.') + i++; + while ( *pattern && *pattern != '.') + pattern++; + if ( file[i] == '.' && *pattern == '.' ) + { + pattern++; + i++; + continue; + } + continue; + } + + if ( *pattern == '?' && file[i] != '.' ) + { + i++; + pattern++; + continue; + } + + if ( toupper(*pattern) != file[i] ) + return 0; + + i++; + pattern++; + } + + if ( !*pattern && !file[i] ) + return 1; + else + return 0; + } + + +/****************************************************************** + AtariFindFirst - Finds first match for pattern and sets struct + with file information. returns 0 for success, + -1 if not found, other for error. This is + similiar to _dosfindfist in the DOS world. +******************************************************************/ + +int AtariFindFirst( char *atrName, unsigned attrib, + char *pattern, AtariFileInfoPtr fileInfo ) + { + char buffer[256]; + AtrFilePtr atr; + int i,j; + AtariDosDirEntryPtr dirEntry; + unsigned short sectorSize, sectorCount; + byte protected; + +/* open the ATR image */ + atr = OpenAtr(atrName); + if ( atr == NULL ) + return 2; + +/* Get some info about the ATR image and save */ + if ( GetAtrInfo( atr, §orSize, §orCount, &protected) ) + { + free(atr); + return 3; + } + +/* look for the file in the directory, if found initilize the fileInfo + structure with data from the directory sector */ + + for( i = firstDirSector, fileInfo->fileNo = 0; i <= lastDirSector; i++ ) + { + if (! ReadSector(atr, (unsigned short) i, buffer) ) + return 4; + for( j=0; j< dirEntriesPerSector; j++, fileInfo->fileNo++ ) + { + dirEntry = (AtariDosDirEntryPtr)(buffer + dirEntrySize * j ); + EndianFix(dirEntry); + fileInfo->locked = (dirEntry->flag & LOCKED_FLAG) ? 1 : 0; + if (dirEntry->flag & DELETED_FLAG ) + continue; + if ( (/* (dirEntry->flag == DOS25EXT_FLAGS) || */ (dirEntry->flag & INUSE_FLAG)) && + PatternMatch(pattern, + dirEntry->fileName, dirEntry->extender) ) + { + fileInfo->flag = dirEntry->flag; + fileInfo->startSector = dirEntry->startSector; + fileInfo->sectorCount = dirEntry->sectorCount; + fileInfo->dirSector = i; + fileInfo->dirEntry = j; + fileInfo->attrib = attrib; + fileInfo->pattern = pattern; + fileInfo->atrName = atrName; + MakeFileName( fileInfo->fileName, dirEntry->fileName, + dirEntry->extender); + if ( CloseAtr(atr) ) + return 5; + return( 0 ); /* success */ + } + } + } + if ( CloseAtr(atr) ) + return 6; + + return -1; + } + +/****************************************************************** + AtariFindNext - Returns next matching file after previous + AtariFindFirst or AtariFindNext call. The fileinfo + structure passed should not be altered from the + previous call. Also the ATR file name and pattern + from the initial AtariFindFirst call must still be + in scope. Similiar to _dosfindnext in DOS world. +******************************************************************/ + +int AtariFindNext( AtariFileInfoPtr fileInfo ) + { + char buffer[256]; + AtrFilePtr atr; + int i,j; + AtariDosDirEntryPtr dirEntry; + unsigned short sectorSize, sectorCount; + byte protected; + + atr = OpenAtr(fileInfo->atrName); + if ( atr == NULL ) + return 1; + + if ( GetAtrInfo( atr, §orSize, §orCount, &protected) ) + { + free(atr); + return 2; + } + i = fileInfo->dirSector; + j = fileInfo->dirEntry; + + j++; + if ( j >= dirEntriesPerSector ) + { + j=0; + i++; + } + + for( ; i <= lastDirSector; i++ , j = 0) + { + if (! ReadSector(atr, (unsigned short) i, buffer) ) + return 3; + for( ; j< dirEntriesPerSector; j++, fileInfo->fileNo++ ) + { + dirEntry = (AtariDosDirEntryPtr)(buffer + dirEntrySize * j ); + EndianFix(dirEntry); + fileInfo->locked = (dirEntry->flag & LOCKED_FLAG) ? 1 : 0; + if (dirEntry->flag & DELETED_FLAG ) + continue; + if ( (dirEntry->flag & INUSE_FLAG) && PatternMatch(fileInfo->pattern, + dirEntry->fileName, dirEntry->extender) ) + { + fileInfo->flag = dirEntry->flag; + fileInfo->startSector = dirEntry->startSector; + fileInfo->sectorCount = dirEntry->sectorCount; + fileInfo->dirSector = i; + fileInfo->dirEntry = j; + MakeFileName( fileInfo->fileName, dirEntry->fileName, + dirEntry->extender); + if ( CloseAtr(atr) ) + return 4; + return( 0 ); + } + } + } + if ( CloseAtr(atr) ) + return 5; + + return -1; + } + + +/****************************************************************** + OpenAtariFile - Opens file in an ATR image in the mode specified + (ATARI_OPEN_READ, ATARI_OPEN_WRITE, or + ATARI_OPEN_DIR. Returns pointer to atari file + structure or 0 on error. +******************************************************************/ + +AtariFilePtr OpenAtariFile( char *atrName, char *fileName, byte mode) + { + AtariFilePtr atFile; + byte protected; + unsigned short sectorSize; + unsigned short sectorCount; + AtariFileInfo fileInfo; + +/* bad open mode? */ + if ( mode != ATARI_OPEN_READ && mode != ATARI_OPEN_WRITE && + mode != ATARI_OPEN_DIR ) + { + lastAtariError = 2; + return NULL; + } + + atFile = malloc(sizeof(AtariFile)); +/* open the atr image */ + atFile->atr = OpenAtr(atrName); + if ( atFile->atr == NULL ) + { + free(atFile); + lastAtariError = 1; + return NULL; + } +/* get some info on the ATR file and store */ + if ( GetAtrInfo( atFile->atr, §orSize, §orCount, &protected) ) + { + CloseAtr(atFile->atr); + free(atFile); + lastAtariError = 3; + return NULL; + } + +/* set file parameters */ + atFile->sectorSize = sectorSize; + atFile->openFlag = mode; + atFile->eofFlag = 0; + +/* is ATR write protected? (APE extension?) */ + if ( protected && (mode & ATARI_OPEN_WRITE) ) + { + CloseAtr(atFile->atr); + free(atFile); + lastAtariError = 4; + return NULL; + } + +/* read directory, find start sector and number of sectors and set + in atFile. Initialize current sector to start sector also */ + + if ( AtariFindFirst(atrName, 0, fileName, &fileInfo) ) + { + lastAtariError = 5; + return NULL; + } + +/* is the file the ATR is lcoated in write protected? */ + if ( fileInfo.locked && (mode & ATARI_OPEN_WRITE) ) + { + lastAtariError = 6; + return NULL; + } + +/* set some file info data in the structure */ + atFile->startSector = atFile->currentSector = fileInfo.startSector; + atFile->fileNo = fileInfo.fileNo; + atFile->numberOfSectors = fileInfo.sectorCount; + atFile->openFlag = mode; + atFile->currentOffset = 0; + if (sectorSize == 128) + atFile->sectorLinkOffset = 125; + else if (sectorSize == 256 ) + atFile->sectorLinkOffset = 253; + else + { + lastAtariError = 7; + return NULL; + } + return atFile; + } + + +/****************************************************************** + ReadAtariFile - reads bytes bytes from the open atari file specified + in atFile and stores them in buffer. buffer must be big enough. + Returns bytes actually read. +******************************************************************/ + +long ReadAtariFile( AtariFilePtr atFile, char *buffer, long bytes ) +{ + /* int lastSector = 0; */ + long bytesRead = 0; + + if ( !bytes || atFile->eofFlag) + return 0; + if ( !(atFile->openFlag & ATARI_OPEN_READ) ) + return 0; + if ( !atFile->currentOffset ) + { + /* read sector */ + if (ReadSector(atFile->atr, atFile->currentSector, atFile->sectorBuffer) != atFile->sectorSize ) + { + if ( !lastAtariError ) + lastAtariError = 19; + return 0; + } + if ( atFile->sectorSize == 128 ) + atFile->bytesData = atFile->sectorBuffer[atFile->sectorLinkOffset+2] + & 127; + else + atFile->bytesData = atFile->sectorBuffer[atFile->sectorLinkOffset+2]; + } + while( bytes ) + { + while ( atFile->currentOffset < atFile->bytesData && bytes) + { + *(buffer++) = atFile->sectorBuffer[atFile->currentOffset++]; + bytes--; + bytesRead++; + } + + if ( bytes ) + { + /* read next sector */ + atFile->currentOffset = 0; + if (atFile->atr->dosType == DOS_MYDOS) + atFile->currentSector = + (atFile->sectorBuffer[atFile->sectorLinkOffset] << 8) | + atFile->sectorBuffer[atFile->sectorLinkOffset+1]; + else /* assume atari dos */ + atFile->currentSector = + ((atFile->sectorBuffer[atFile->sectorLinkOffset] & 3) << 8) | + (atFile->sectorBuffer[atFile->sectorLinkOffset+1]); + + if (!atFile->currentSector ) + { + atFile->eofFlag = 1; + return bytesRead; + } + + ReadSector(atFile->atr, atFile->currentSector, atFile->sectorBuffer); + if ( atFile->sectorSize == 128 ) + atFile->bytesData = atFile->sectorBuffer[atFile->sectorLinkOffset+2] & 127; + else + atFile->bytesData = atFile->sectorBuffer[atFile->sectorLinkOffset+2]; + } + + } + return bytesRead; + } + + +/****************************************************************** + CloseAtariFile - Closes Atari File +******************************************************************/ + +int CloseAtariFile( AtariFilePtr atFile ) + { + int stat; + /* simple enough */ + stat = CloseAtr( atFile->atr ); + free( atFile ); + return stat; + } + + +/****************************************************************** + EofAtariFile - Returns 1 if at EOF of atari file, 0 if not +******************************************************************/ + +int EofAtariFile( AtariFilePtr atFile ) + { + /* simple enough */ + return atFile->eofFlag; + } + +/****************************************************************** + AtariDirectory - Displays atari directory of disk image to screen + return 0 for success. atrName is the ATR file + name, pattern is mask to use. use "*.*" for all + files. Wide if non zero displays actual file + length instead of just a sector count. +******************************************************************/ + +int AtariDirectory( char *atrName, char *pattern) + { + char buffer[256]; + char fileName[14]; + byte protected; + unsigned short sectorSize; + unsigned short sectorCount; + AtrFilePtr atr; + int i,j,cnt = 0; + char locked; + long fileSize; + AtariDosDirEntryPtr dirEntry; + + atr = OpenAtr(atrName); + if ( atr == NULL ) + return 1; + + if ( GetAtrInfo( atr, §orSize, §orCount, &protected) ) + { + free(atr); + return 1; + } + + printf("sector size = %hu sector count = %hu\n\n", sectorSize, + sectorCount); + + + printf("\nDirectory of '%s':\n\n", atrName); + + if ( !wide ) + { + printf("no f filename ext secs startSec\n"); + printf("-- - -------- --- ---- --------\n"); + } + else + { + printf("no f filename ext secs length startSec\n"); + printf("-- - -------- --- ---- ------ --------\n"); + } + for( i = firstDirSector; i <= lastDirSector; i++ ) + { + char printbuf[101]; + int done = 0; + if (! ReadSector(atr, (unsigned short) i, buffer) ) + return 1; + for( j=0; j< dirEntriesPerSector; j++ ) + { + dirEntry = (AtariDosDirEntryPtr)(buffer + dirEntrySize * j ); + EndianFix(dirEntry); + locked = (dirEntry->flag & LOCKED_FLAG) ? '*' : ' '; + if (dirEntry->flag & DELETED_FLAG ) + locked = 'D'; + else if (dirEntry->flag & MYDOSDIR_FLAG ) { + locked = ':'; + } else if(dirEntry->flag == DOS25EXT_FLAGS) { + locked = '<'; + } + if ( (dirEntry->flag == DOS25EXT_FLAGS) || + ((dirEntry->flag & (INUSE_FLAG | MYDOSDIR_FLAG)) && + PatternMatch(pattern, dirEntry->fileName, dirEntry->extender)) ) + { + if ( wide ) + { + CloseAtr(atr); + MakeFileName(fileName, dirEntry->fileName, dirEntry->extender); + fileSize = AtariFileSize(atrName, fileName); + if(fileSize < 0) + sprintf(printbuf, "??"); + else + sprintf(printbuf, "%-6ld", fileSize); + + atr = OpenAtr(atrName); + if ( !atr ) + return 1; + printf("%2u %c %-8.8s %-3.3s %4.3hu %-6s %hu\n", cnt, locked, + dirEntry->fileName, dirEntry->extender, + dirEntry->sectorCount, printbuf, dirEntry->startSector); + } + else + printf("%2u %c %-8.8s %-3.3s %4.3hu %hu\n", cnt, locked, + dirEntry->fileName, dirEntry->extender, + dirEntry->sectorCount, dirEntry->startSector); + } else { + /* 20070518 bkw: Atari DOS stops at the first "never used" + dirent, so do the same here. */ + done = 1; + break; + } + cnt++; + } + if(done) break; + } + + if ( CloseAtr(atr) ) + return 1; + + return 0; + } + + +/****************************************************************** + AtariFileSize - Returns size of atari file or -1 on error +******************************************************************/ + +long AtariFileSize( char *atrFile, char *fileName ) + { + long count = 0; + long bytes; + static char buffer[16]; + AtariFilePtr input; + + /* open the atari file on the ATR image */ + input = OpenAtariFile(atrFile, fileName, ATARI_OPEN_READ); + if ( input == NULL ) + return -1; + /* count how many bytes we can actually read */ + while( (bytes=ReadAtariFile(input, buffer, sizeof(buffer))) > 0 ) + count+= bytes; + CloseAtariFile(input); + return(count); + } + + +/****************************************************************** + ExtractAtariFile - returns no. files extracted, -no for error. + file is stored with same name in dosPath + directory. (don't add the trailing '\'). + Wildcards are allowed for atari file. Use NULL + for dosPath to extract to current directory +******************************************************************/ + +int ExtractAtariFile( char *atrFile, char *fileName, char *unixPath ) +{ + int count = 0; + long bytes, bytesOut; + static char buffer[16]; + AtariFilePtr input; + char outName[4096]; + FILE *output; + AtariFileInfo info; + + + if ( !AtariFindFirst(atrFile, 0, fileName, &info) ) + { + do { + if ( unixPath != NULL) + { + strcpy(outName, unixPath); + strcat(outName,"/"); + } + else + outName[0] = 0; + strcat(outName, info.fileName); + + /* 20070518 bkw: Get rid of trailing dots for files with no extension */ + if(outName[strlen(outName)-1] == '.') + outName[strlen(outName)-1] = '\0'; + + output = fopen(outName, "wb"); + if (output == NULL ) + { + lastAtariError = 30; + return -count-1; + } + input = OpenAtariFile(atrFile, info.fileName, ATARI_OPEN_READ); + if ( input == NULL ) + { + return -count-1; + } + if ( verbose ) + printf("Extracting '%s'...", outName); + while( (bytes=ReadAtariFile(input, buffer, sizeof(buffer))) > 0 ) + { + bytesOut = fwrite(buffer, 1, (int)bytes, output); + if ( bytes != bytesOut ) + { + fclose( output ); + CloseAtariFile(input); + lastAtariError = 31; + if (verbose ) + printf("\n"); + return -count-1; + } + } + fclose( output ); + CloseAtariFile(input); + if ( verbose ) + printf(" done\n"); + count ++; + } while ( !AtariFindNext(&info) ); + } + else + { + return 0; + } + return(count); +} + + +/****************************************************************** + UpdateAtariFileNo - For atari dos, will fix the file no in each + sector within the file. For use after a + directory is sorted. returns 0 for success +******************************************************************/ + +int FixAtariFileNo( char *atrName, char *fileName, int fileNo ) +{ + /* int cnt=0; */ + AtariFilePtr atFile; + + atFile = OpenAtariFile( atrName, fileName, ATARI_OPEN_READ); + if ( atFile == NULL ) + return 1; + + if ( atFile->atr->dosType != DOS_ATARI ) + { + CloseAtariFile(atFile); + return 0; + } + + + while (atFile->currentSector) + { + if (ReadSector(atFile->atr, atFile->currentSector, sectorBuffer) != atFile->sectorSize ) + { + if ( !lastAtariError ) + lastAtariError = 19; + CloseAtariFile(atFile); + return 1; + } + + /* set the file no in the file */ + sectorBuffer[atFile->sectorLinkOffset] &= 3; + sectorBuffer[atFile->sectorLinkOffset] |= (atFile->fileNo<<2); + + /* write the sector */ + if (WriteSector(atFile->atr, atFile->currentSector, sectorBuffer) != atFile->sectorSize ) + { + if ( !lastAtariError ) + lastAtariError = 19; + CloseAtariFile(atFile); + return 1; + } + + /* get next sector in link */ + atFile->currentSector = + ((sectorBuffer[atFile->sectorLinkOffset] & 3) << 8) | + sectorBuffer[atFile->sectorLinkOffset+1]; + } + CloseAtariFile(atFile); + return 0; + } + + + + + + + +static int ClearAtariDirectory( char *file ); + + +/****************************************************************** + SortAtariDir - +******************************************************************/ + +int SortAtariDir( char *atrName ) + { + AtrFilePtr atr; + char *pos; + AtariFileInfoPtr files[64]; + AtariFileInfo info; + AtariDosDirEntryPtr entry; + int offset; + unsigned short sector; + + int i, cnt = 0; + + /* read file info for all files, allocate memory and store in array */ + + if ( !AtariFindFirst(atrName, 0, "*.*", &info) ) + { + do { + files[cnt] = malloc( sizeof(info) ); + memcpy( files[cnt], &info, sizeof(info) ); + cnt ++; + } while ( !AtariFindNext(&info) ); + } + else + { + return 1; + } + + /* sort the files by name */ + + qsort( (void *)files, (size_t) cnt, (size_t) sizeof(AtariFileInfoPtr), CompareName ); + + /* clear out the directory */ + if ( ClearAtariDirectory(atrName) ) + return 1; + + /* write the entries in sorted order to the directory sectors */ + + offset = 0; + sector = firstDirSector; + + atr = OpenAtr( atrName ); + + for( i=0; istartSector = files[i]->startSector; + entry->sectorCount = files[i]->sectorCount; + entry->flag = files[i]->flag; + EndianFix(entry); + pos = strchr( files[i]->fileName, '.' ); + + /* 20070518 bkw: init to all spaces, else you get filenames + like "DOS\0\0\0\0\0SYS" (\0 shows up as Atari heart character) */ + memset(entry->fileName, ' ', 8); + memset(entry->extender, ' ', 3); + + if ( pos != NULL) + { + + strncpy( entry->fileName, files[i]->fileName, + min(pos-files[i]->fileName,8) ); + strncpy( entry->extender, pos+1, 3 ); + } + else + { + strncpy( entry->fileName, files[i]->fileName, 8); + } + offset += 16; + if (offset >= 128) + { + if ( WriteSector( atr, sector, sectorBuffer) != atr->secSize ) + { + CloseAtr( atr ); + return 1; + } + sector ++; + offset = 0; + memset(sectorBuffer, 0, sizeof(sectorBuffer)); + } + } + if ( offset > 0 ) + if ( WriteSector( atr, sector, sectorBuffer) != atr->secSize ) + { + CloseAtr( atr ); + return 1; + } + + CloseAtr( atr ); + + + /* This should have no effect on Mydos extended format disks */ + for( i=0; ifileName, i) ) + return 1; + free( files[i] ); + } + return 0; + } + +/* function for above used as arg to qsort */ +static int CompareName( const void *a, const void *b ) + { + AtariFileInfoPtr aa = *(AtariFileInfoPtr *)a, + bb = *(AtariFileInfoPtr *)b; + + return strcmp( aa->fileName, bb->fileName ); + } + +/******************************************************************* +ClearAtariDirectory - internal routine +*******************************************************************/ + +static int ClearAtariDirectory( char *file ) + { + AtrFilePtr atr; + int i; + + memset(sectorBuffer, 0, sizeof(sectorBuffer) ); + atr = OpenAtr( file ); + + for( i = firstDirSector; i <= lastDirSector; i++ ) + if ( WriteSector(atr, i, sectorBuffer) != atr->secSize ) + return 1; + return 0; + CloseAtr(atr); + } + + +/******************************************************************** + CreateBootAtr - creates a minimally sized bootable ATR image from + an atari executable. The executable must not need + DOS to run. +********************************************************************/ + +int CreateBootAtr( char *atrName, char *fileName) + { + unsigned long fileSize; + unsigned long sectorCnt; + AtrHeader hdr; + unsigned long paras; + FILE * atrFile, *inFile; + size_t padding, bytes, bytes2; + struct stat fileInfo; + int status; + int first = 1; + +/* get file's size */ + + status = stat(fileName, &fileInfo); + if ( status ) + return 11; + fileSize = (unsigned long) fileInfo.st_size; + if ( !fileSize ) + return 12; + +/* determine number of sectors required */ + + sectorCnt = (unsigned short) ((fileSize + 127L) / 128L + 3L); + paras = sectorCnt * 16; + +/* create ATR header */ + memset(&hdr, 0, sizeof(hdr)); + hdr.idLow = (byte) 0x96; + hdr.idHigh = (byte) 0x2; + hdr.paraLow = (byte) (paras & 0xFF); + hdr.paraHigh = (byte) ((paras >> 8) & 0xFF); + hdr.paraHigher = (byte) ((paras >> 16) & 0xFF); + hdr.secSizeLow = (byte) 128; + +/* open output file */ + atrFile = fopen(atrName, "wb"); + if ( atrFile == NULL ) + return 1; + +/* Write the ATR Header */ + bytes = fwrite(&hdr, 1, sizeof(hdr), atrFile); + if ( bytes != sizeof(hdr) ) + { + fclose(atrFile); + return 2; + } + +/* plug the file size into the boot sectors at offset 9 (4 bytes)*/ + bootData[9] = (byte)(fileSize & 255); + bootData[10] = (byte)((fileSize >> 8) & 255); + bootData[11] = (byte)((fileSize >> 16) & 255); + bootData[12] = 0; + +/* write the three boot sectors */ + bytes = fwrite(bootData, 1, 384, atrFile); + if ( bytes != 384 ) + { + fclose(atrFile); + return 6; + } + +/* open the input file and copy/append the file's data to output file */ + + inFile = fopen(fileName, "rb"); + if ( inFile == NULL ) + { + fclose(atrFile); + return 13; + } + + bytes = 384; + while (bytes == 384) + { + bytes = fread(bootData, 1, 384, inFile); + if ( !bytes ) + break; + + /* 20070518 bkw: Make sure it really is an Atari bin load file */ + if(first) { + if((bootData[0] != 0xff) && (bootData[1] != 0xff)) { + fclose(inFile); + fclose(atrFile); + return 20; + } + + first = 0; + } + + bytes2 = fwrite(bootData, 1, bytes, atrFile); + if ( bytes != bytes2 ) + { + fclose(inFile); + fclose(atrFile); + return 19; + } + } + if ( !feof(inFile) ) + { + fclose(inFile); + fclose(atrFile); + return 19; + } + + fclose(inFile); + + +/* pad to even sector size (data has no meaning) */ + padding = (size_t) ((sectorCnt-3) * 128 - fileSize ); + if ( padding ) + { + bytes = fwrite(bootData, 1, padding, atrFile); + if ( bytes != padding ) + { + fclose(atrFile); + return 7; + } + } + +/* close output */ + fclose(atrFile); + + return 0; + } + +/******************************************************************** +ExtractExeFromBootAtr - undoes a CreateBootAtr by extracting the + original executable +returns 0 for error, or file length in bytes of file extracted +!!This function needs to have code added to distinguish error types. +********************************************************************/ + +long ExtractExeFromBootAtr( char *atrName, char *fileName) + { + FILE *atrFile, *exeFile; + unsigned char *buffer; + AtrHeader hdr = {0}; + /* long fileSize; */ + size_t bytes,bytes2,readCnt; + unsigned long fSize, size; + +/* get some memory */ + buffer = malloc(384); + if ( !buffer) + return 0; + +/* open the atr file */ + atrFile = fopen(atrName, "rb"); + if ( !atrFile ) + { + free(buffer); + return 0; + } + +/* read Atr header */ + + if ( fread(&hdr, 1, 16, atrFile) != 16 ) + { + free(buffer); + fclose(atrFile); + return 0; + } + +/* verify it is an ATR file */ + + if ( hdr.idHigh != 0x02 || hdr.idLow != 0x96 ) + { + free(buffer); + fclose(atrFile); + return 0; + } + +/* read first 3 (boot) sectors */ + + if ( fread(buffer, 1, 384, atrFile) != 384 ) + { + free(buffer); + fclose(atrFile); + return 0; + } + +/* set the file size in bootData from the file so we can compare*/ + bootData[9] = buffer[9]; + bootData[10] = buffer[10]; + bootData[11] = buffer[11]; + bootData[12] = buffer[12]; + +/* check if ATR was created by MakeBootAtr */ + if ( memcmp(buffer, bootData, 384) ) + { + free(buffer); + fclose(atrFile); + return 0; + } +/* Get size of file to extract */ + fSize = size = ((unsigned long)buffer[9]|(((unsigned long)buffer[10])<<8)|(((unsigned long)buffer[11])<<16)); + +/* Open output file */ + exeFile = fopen(fileName, "wb"); + if ( !exeFile ) + { + fclose(atrFile); + free(buffer); + return 0; + } +/* copy 'size' bytes from the Atr file to the exe file */ + bytes = 384; + while (bytes == 384 && fSize) + { + readCnt = min(384, fSize); + bytes = fread(buffer, 1, readCnt, atrFile); + if ( !bytes ) + break; + bytes2 = fwrite(buffer, 1, bytes, exeFile); + if ( bytes != readCnt ) + { + fclose(exeFile); + fclose(atrFile); + free(buffer); + return 0; + } + fSize -= bytes; + } + +/* clean up and get out of here */ + fclose(exeFile); + fclose(atrFile); + free(buffer); + + return size; + } + + diff --git a/ksiders/atr.h b/ksiders/atr.h new file mode 100644 index 0000000..53ca6be --- /dev/null +++ b/ksiders/atr.h @@ -0,0 +1,65 @@ +/* Copyright 1997 Ken Siders */ + +#ifndef ATR_H_INCLUDED +#define ATR_H_INCLUDED + +/* constants */ +#define ATR_HEADER_SIZE 16 + + +/* typedefs */ +typedef unsigned char byte; + + +/* structure definitions */ + +struct S_HDR +{ +byte idLow, idHigh; +byte paraLow, paraHigh; +byte secSizeLow, secSizeHigh; +byte paraHigher; +byte crc1, crc2, crc3, crc4; +byte unused1, unused2, unused3, unused4; +byte flags; +}; + +typedef struct S_HDR AtrHeader; + +struct S_AtrFile { + FILE *atrIn; + unsigned long imageSize; + unsigned short secSize; + unsigned long crc; + unsigned long sectorCount; + byte flags; + byte writeProtect; + byte authenticated; + unsigned short currentSector; + unsigned char dosType; +}; + +typedef struct S_AtrFile AtrFile; +typedef AtrFile *AtrFilePtr; + + +/* function prototypes */ +AtrFilePtr OpenAtr(char *file ); + +int CloseAtr( AtrFilePtr atr ); +int ReadSector(AtrFilePtr atr, unsigned short sector, char *buffer); +int WriteSector(AtrFilePtr atr, unsigned short sector, char *buffer); +int CreateAtr( char *file, unsigned short sectors, + unsigned short sectorSize ); +int GetAtrInfo( AtrFilePtr atr, unsigned short *sectorSize, + unsigned short *sectorCount, byte *protected); +int CreateBootAtr( char *atrName, char *fileName); +long ExtractExeFromBootAtr(char *, char *); + +int SortAtariDir( char *atrName ); +int SetVerbose( int verb ); +int ExtractAtariFile( char *atrFile, char *fileName, char *dosPath ); + +#endif + + diff --git a/ksiders/atr.txt b/ksiders/atr.txt new file mode 100644 index 0000000..44c2b06 --- /dev/null +++ b/ksiders/atr.txt @@ -0,0 +1,521 @@ +All files Copyright 1997 Ken Siders + +Ken's ATR manipulation C library. This has only been used under Microsoft +C/C++ version 8.0. It will probably work on 7.0 and possibly earlier +versions. You are on your own for porting to other compilers. + +With Microsoft C, you must use the /Zp option to pack structure members +on byte boundries. I have no idea how this translates to other compilers. + + +To Do +1 Clean up warnings + make more portable +2 Allow opening write-protected ATRs +3 Allow more than one reference to an ATR file to be opened so more + than one atari file can be opened at once. +4 More specific error returns +5 Implement XFD handling +6 Create documentation +7 Optimize if necessary +8 Implement DCM images (maybe) + +---------------------------------------------------------------------------- + +This source is a work in progress and in distributed for those wanting +to write ATR related programs. I had planned to tidy them up a lot before +releasing them, but have been sidetracked by other projects. Feel free to +use them in your own freeware and public domain programs if credit is given. + +These have all been compiled with Microsoft C version 8.0. They should +compile with 7.0 and possibly earlier versions. They may need +some tweaking for use on other compilers. The /Zp option must be used +on the Microsoft compiler to pack structures on byte boundries. I don't +know how this is done on other compilers. + +Files: +The file that does all of the work is ATR.C. The other programs do some +basic processing and call fucntions in ATR.C to do the work. + +The other C files, all build the ATR utilities that are on my Atari +web page. They, of course must be linked with the main ATR file. + +There are two header files: ATR.H and ATRDOS.H both of which will be +required by most programs. ATR.H contains definitions for ATR image related +functions. ATRDOS.H contains definitions for referencing Mydos and +Atari Dos files located on ATR images. Hopefully the short descriptions +in the source are enough to allow one to figure out what each function does. +There is also a third header file with the Boot disk routine. + + +Note: You cannot open write protected images yet and you can only have +one ATR open at a time. If you Open an ATR and then call a function like +ATRDirectory, an error will result. You must Close the ATR first, call +the function and then reopen the ATR. This also means you can't have two +files open in a single ATR at the same time. This will hopefully be +rectified soon. Good Luck. + + + +mailto: ken_siders@compuserve.com +http://ourworld.compuserve.com/homepages/ken_siders/atari.htm + + +PS: I still am looking for info on other disk formats such as SpartaDOS. +Also info on subdirectory format, how to distinquish Dos 2.5 enhanced +density and MyDos enhanced density, etc..... + +----------------------------------------------------------------------------- + +*********************************************************************** +Structures +*********************************************************************** +ATR File pointer structure definition. Most of this info comes from +the ATR header: + +struct S_AtrFile { + FILE *atrIn; pointer to the file. + unsigned long imageSize; image size + unsigned short secSize; sector size: 128/256 + unsigned long crc; crc - ATR extension (not used) + unsigned long sectorCount; number of sectors in image + byte flags; flags byte from ATR image. + byte writeProtect; image write protected? + byte authenticated; ATR extension (not used) + unsigned short currentSector; don't know what I have this here for. + unsigned char dosType; ataridos, mydos? see atr.h for constants +}; +typedef struct S_AtrFile AtrFile; +typedef AtrFile *AtrFilePtr; + + +Atari File pointer structure definition. This is info required to read and +write atari files in an ATR image as well as related functions. + +struct S_AtariFile + { + AtrFilePtr atr; atr file is in + unsigned short startSector; start sector of file + unsigned short currentSector; current sector pointer + unsigned short sectorSize; sector size: 128 or 256 + unsigned short numberOfSectors; number of sectors in file + unsigned long fileSize ; size of file in bytes + byte openFlag; flag used in AtariOpenFile + byte eofFlag; set if at eof + short currentOffset; current offset into sector + short bytesData; bytes of data in current sector + short sectorLinkOffset; offset to link data. usually 125 or 253 + short fileNo; file No for Atari Dos + unsigned char sectorBuffer[256]; buffer with current sector + }; +typedef struct S_AtariFile AtariFile; +typedef AtariFile * AtariFilePtr; + + +*********************************************************************** +Image Functions - These functions are used for low level access to + ATR disk images. +*********************************************************************** + +OpenAtr AtrFilePtr OpenAtr(char *file ) + + Description: + Opens an ATR image so sectors can be read or written or information + on the image can be obtained. + + Parameters: + file - the filename of the ATR. Use the full drive and pathname if + the file is not in the current directory. You must add the + .ATR extension. + + Returns: + An ATR file pointer that is used with other functions to access the + image's data. + + +CloseAtr int CloseAtr( AtrFilePtr atr ) + + Description: + Closes an ATR image opened with OpenATR. + + Parameters: + atr - the ATR file pointer that was returned by the OpenAtr function. + + Returns: + 0 for success, 1 if an error occured. + + +ReadSector int ReadSector(AtrFilePtr atr, unsigned short sector, + char *buffer) + + Description: + Reads specified sector from the ATR file specified into buffer which + must be big enough for the sector size of the ATR image file (128 or + 256 bytes). + + Parameters: + atr - Atr file pointer returned from an OpenAtr function call. + sector - Sector number to read. + buffer - A pointer that points to a buffer large enough to hold a + sector of data. Usually you want this to be 256 bytes. + + Returns: + Number of bytes read or 0 if error. + + +WriteSector int WriteSector(AtrFilePtr atr, unsigned short sector, + char *buffer) + + Description: + Writes specified sector from the ATR file specified from buffer + specified. + + Parameters: + atr - Atr file pointer returned from an OpenAtr function call. + sector - Sector number to write. + buffer - A pointer that points to a buffer containing the sector + data to write. Usually 128 or 256 bytes. + + Returns: + Number of bytes written or 0 if error. + + +CreateAtr int CreateAtr( char *file, unsigned short sectors, + unsigned short sectorSize ) + + Description: + Creates an new ATR file with parameters specified. + + Parameters: + file - Name of the ATR file to create. If file exists it will + be overwritten. + sectors - The number of sectors in the image. Common values are + 720 (single/double density) or 1040 (1050 double) but + smaller an huge images may also be created. + sectorSize - This should be 128 (single/1050 double density) or + 256 (double density). + + Returns: + 0 for success, 1 on failure. + + +GetAtrInfo int GetAtrInfo( AtrFilePtr atr, unsigned short *sectorSize, + unsigned short *sectorCount, byte *protected) + + Descriptions: + Returns the sector size, and sector count for an image. It also + returns info if the disk is write protected or not. (Write protect + status is not fully implemented yet.) + + Parameters: + atr - the ATR file pointer that was returned by the OpenAtr function. + sectorSize - A pointer to a variable in which to return the sector + size. + sectorCount - A pointer to a variable in which to return the sector + count. + protected - A pointer to a variable in which to return the write + protect status. 1 = protected, 0 = not. If the image + write protected or if the APE extension bit for write + protect is set, this will be 1. Not implemented yet. + + Returns: 0 for success, 1 if error. + + +AtariFindFirst int AtariFindFirst( char *atrName, unsigned attrib, + char *pattern, + AtariFileInfoPtr fileInfo ) + Description: + Finds first match for pattern and sets struct with file information. + For those using Microsoft C compilers, this is similiar to + _dosfindfirst. + + Parameters: + atrName - Name of ATR image in which to look for the file. + attrib - Not used yet. Use 0. + pattern - The atari file to look for. * and ? are accepted as normal + atari wildcards. Use only and 8.3 file name, no drive or + directory specifications. + fileInfo - A pointer to your file info structure in which to return + the information. This structure will also be use by + the AtariFindNext function. + + Returns: + 0 if a match was found. + -1 if a match was not found. + a positive number if an error occurred. + + +AtariFindNext int AtariFindFirst( AtariFileInfoPtr fileInfo ) + + Description: + Searches for the next match after a previous AtariFindFirst or + AtariFindNext. Sets struct with file information. For those using + Microsoft C compilers, this is similiar to _dosfindnext. The + fileInfo structure should not be modified prior to calling this + function. + + Parameters: + fileInfo - A pointer to your file info structure in which to return + the information. This structure should still have + unmodified info from the last AtariFindFirst or + AtariFindNext function call. + + Returns: + 0 if a match was found. + -1 if a match was not found. + a positive number if an error occurred. + +CreateBootAtr - int CreateBootAtr( char *atrName, char *fileName) + + Description: + Will create a minimally sized bootable ATR image from an Atari + Executable. The ATR file will be just long enough to hold + three boot sectors and the file's data. The executable must + consist of only one file and not need DOS for any reason. Note: + Not all Atari computer and peripheral emulators may support + non-standard sized images. When booting from the image, the + screen will turn red if an error occurs. + + Parameters: + atrName - The ATR file name. + fileName - The name of the MSDOS file to convert. + + Returns: + 0 for success. + + +ExtractExeFromBootAtr - long ExtractExeFromBootAtr( char *atrName, + char *fileName) + + Description: + Undoes a CreateBootAtr by extracting the original executable from + the ATR image. + + Parameters: + atrName - ATR file name of a disk created with CreateBootAtr. + fileName - The name of the MSDOS file to write the output to. + + Returns: + Returns 0 for error, or file length in bytes of file extracted. + An error will result if the file was not created with CreateBootAtr. + + +*********************************************************************** +Dos Functions - These functions are used to reference atari files + stored on ATR disk images. +*********************************************************************** + +OpenAtariFile - AtariFilePtr OpenAtariFile( char *atrName, char *fileName, + byte mode) + + Description: + Opens file in an ATR image in the mode specified: ATARI_OPEN_READ, + ATARI_OPEN_WRITE, or ATARI_OPEN_DIR. ATARI_OPEN_DIR is not supported + yet. + + Parameters: + atrName - Name of ATR image in which to look for the file. + fileName - Filename of the atari file in the ATR image to open. + mode - ATARI_OPEN_READ to open the file for read, ATARI_OPEN_WRITE + to open it for write. "Or" the two together for both. + ATARI_OPEN_DIR is not implemented yet. + + Returns: + An Atari file pointer that can be used in functions to read or + write from the file. NULL is returned on error. + + +ReadAtariFile - long ReadAtariFile( AtariFilePtr atFile, char *buffer, + long bytes ) + + Description: + Reads bytes bytes from an open atari file (opened with OpenAtariFile). + + Parameters: + atFile - An Atari file pointer that was set from an OpenAtariFile function + call + buffer - A pointer to a buffer to read the bytes into. Must be big + enough to hold the number of bytes requested. + bytes - Number of bytes to read. + + Returns: + Number of bytes actually read. May be less than bytes if EOF was + reached. You can use EofAtariFile to see if the EOF was reached + or if an error occurred. + + +CloseAtariFile - int CloseAtariFile( AtariFilePtr atFile ) + + Description: + Closes an atari file opened with OpenAtariFile. + + Parameters: + atFile - An atari file pointer used in an OpenAtariFile function + call. + + Returns: + 0 if successful. + + +EofAtariuFile - int EofAtariFile( AtariFilePtr atFile ) + + Description: + Determines if pointer is at the end of an atari file. + + Parameters: + atFile - An atari file pointer returned from an OpenAtariFile + function call. + + Returns: + Returns 1 if at EOF of atari file, 0 if not + + +AtariDirectory - int AtariDirectory( char *atrName, char *pattern) + + Description: + Displays atari directory of disk image to screen. The disk image + must be Atari Dos, MyDos, or compatable. + + Parameters: + atrName - The ATR file name. + pattern - filename mask to use. use "*.*" for all files. + + Returns: + 0 for no errors. + + +AtariFileSize long AtariFileSize( char *atrFile, char *fileName ) + + Description: + Get the actual length in bytes of an atari file in an ATR image. + + Parameters: + atrName - The ATR file name. + fileName - The atari filename in 8.3 to look for. No wildcards. + + Returns: + Length of file in bytes or -1 for error. + + +ExtractAtariFile - int ExtractAtariFile( char *atrFile, char *fileName, + char *dosPath ) + + Description: + Extracts an Atari file from an ATR image. Atari Dos and MyDos + formats are supported for the image. + + Parameters: + atrName - The ATR file name. + fileName - Atari filename in 8.3 format. Wildcards * and ? are + allowed. If verbose is on, files will be displayed + as they are extracted. + dosPath - Directory to store the file in. File is stored with same + name in dosPath directory. (don't add the trailing '\'). + Use NULL for dosPath to extract to current directory. + + Returns: + number of file extracted. If the result is negative, an error + occured but the Absolute value of that number of files were + extracted successfully before the error occurred. + + +FixAtariFileNo - int FixAtariFileNo( char *atrName, char *fileName, + int fileNo ) + + Description - For atari dos, will fix the file no in each sector within + the file. Used internally after a directory is sorted but + their may be other uses. For larger MyDos disks the + function has no effect. I currently don't know how to + distinquish DOS 2.5 1050 double density disks and Mydos + disks so this may not work on Dos 2.5 1050 double density + disks. + + Parameters: + atrName - The ATR file name. + fileName - Atari filename in 8.3 format to fix. No wildcard's + allowed. + fileNo - File number to give the file. This could probably be + made to be automatic. + + Returns: + 0 for success. + + +SortAtariDir - int SortAtariDir( char *atrName ) + + Description: + Sorts the files in an ATR image. BUT: 1. May not work on Dos 2.5 + 1050 double density disks. 2. Doesn't allow DOS.SYS and DUP.SYS, + or other files to be specified not to be sorted. + + Parameters: + atrName - The ATR file name. + + Returns: + 0 for success. + + + +*********************************************************************** +Other Functions - Other functions. +*********************************************************************** + + +SetVerbose int SetVerbose( int verb ) + + Description: + Used to set verbose flag to 1 (on) or 0 (off). Currently the only + function that uses this is ExtractAtariFile. + + Parameters: + verb - 1 for verbose, 0 for not verbose + + Returns: + Previous state of verbose flag. + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/ksiders/atrdir.1 b/ksiders/atrdir.1 new file mode 100644 index 0000000..6e2d0bf --- /dev/null +++ b/ksiders/atrdir.1 @@ -0,0 +1,65 @@ +.TH ATRDIR "1" "April 2007" "atrdir" "Ken Siders' Atari 8-bit Tools" +.SH NAME +\fBatrdir\fR \- print the directory of an ATR disk image +.SH SYNOPSIS +\fBatrdir\fR \fIimagefile.atr\fR [\fIwildcard\fR] +.SH DESCRIPTION +\fBatrdir\fR prints the directory of an Atari DOS 2.x or MyDOS compatible +ATR disk image. Sample output: +.PP +.nf +--------------------------------------------------------------------- +Directory of dos_20s.atr:*.*: +sector size = 128 sector count = 720 + + +Directory of 'dos_20s.atr': + +no f filename ext secs length startSec +-- - -------- --- ---- ------ -------- + 0 * DOS SYS 039 4875 4 + 1 * DUP SYS 042 5126 43 + 2 AUTORUN SYS 001 88 85 +--------------------------------------------------------------------- +.fi +.PP +The \fIf\fR column contains an asterisk (\fI*\fR) for a locked file, +a \fID\fR for a deleted file, \fI:\fR for a MyDOS subdirectory, +\fI<\fR for a DOS 2.5 file that uses sectors above 720, +or nothing for any other file. +.PP +\fIwildcard\fR is an optional glob pattern, such as \fI*.sys\fR. If not +given, the default is \fI*.*\fR. \fIwildcard\fR is case insensitive; +\fI*.txt\fR is equivalent to \fI*.TXT\fR. Most shells will require the argument +to be quoted, to avoid the shell's normal wildcard expansion. The +globbing semantics are similar to those of Atari DOS or POSIX sh, but +are not identical to either. +.PP +\fBatrdir\fR does not take any other options. +.SH NOTES +.PP +DOS 2.5 disk images are not fully supported. Specifically, \fBatrdir\fR +is unable to determine the size of files that use sectors above 720 (those +that are listed with \fI<\fR). Instead, the size will be reported as \fB??\fR. +.PP +MyDOS large disk images (aka hard disk images) are supported. +.PP +XFD format images are not supported. +.PP +The current version of \fBatrdir\fR cannot determine the size of a MyDOS +directory. Instead, the size is reported as \fB??\fR. +.PP +\fBatrdir\fR cannot print the contents of MyDOS subdirectories. +.PP +Exit status is zero for success, non-zero for failure. +.SH AUTHOR +Ken Siders <\fBatari8bit@columbus.rr.com\fR> +.PP +Man page by B. Watson <\fBurchlay@urchlay.com\fR> +.SH SEE ALSO +\&\fIatrextr\fR\|(1), \&\fImakeatr\fR\|(1), \&\fIsortatr\fR\|(1), +\&\fIunmakatr\fR\|(1). +.PP +Ken Siders Atari 8\-bit page: +.br +http://atari.ksiders.tzo.com/a8emulators.html diff --git a/ksiders/atrdir.c b/ksiders/atrdir.c new file mode 100644 index 0000000..62920c0 --- /dev/null +++ b/ksiders/atrdir.c @@ -0,0 +1,89 @@ +/* Copyright 1997 Ken Siders */ + +#include +#include +#include +#include "atr.h" +#include "atdos.h" + +void help(void) + { + printf("usage: atrdir atrname.atr [filespec]\n"); + printf("\n"); + printf("\n\n"); + } + + +int main( int argc, char **argv) + { + AtrFilePtr atr; + int minCnt; + char option; + static char mask[80]; + + + printf("AtrDir Version 0.9u (c)1997 Ken Siders\n"); + printf("Ported and modified by B. Watson, 2007\n"); + printf("This program may be freely distributed\n\n"); + + if (argc < 2) + { + help(); + exit(2); + } + + if (argv[1][0] == '-') + { + option = argv[1][1]; + minCnt = 3; + } + else + { + option = 0; + minCnt = 2; + } + + if ( argc != minCnt && argc != minCnt + 1) + { + help(); + exit(4); + } + + if (option && option != 'W' && option != 'w' ) + { + help(); + exit(5); + } + + atr = OpenAtr(argv[minCnt-1]); + if (atr == 0) + { + printf("Error reading ATR file: %s\n", argv[1]); + exit(2); + } + else + { + CloseAtr(atr); + } + + if (argc == minCnt) + strcpy(mask, "*.*"); + else + strcpy(mask, argv[minCnt]); + printf("Directory of %s:%s:\n", argv[minCnt-1], mask); + AtariDirectory( argv[minCnt-1], mask); + + + + + + + + /* printf("\n%d file(s)\n", count); */ + + exit(0); + } + + + + diff --git a/ksiders/atrextr.1 b/ksiders/atrextr.1 new file mode 100644 index 0000000..9912f76 --- /dev/null +++ b/ksiders/atrextr.1 @@ -0,0 +1,64 @@ +.TH ATREXTR "1" "April 2007" "atrextr" "Ken Siders' Atari 8-bit Tools" +.SH NAME +\fBatrextr\fR \- extract files from an ATR image + +.SH SYNOPSIS +\fBatrextr\fR \fIimagefile.atr\fR [\fIfile\fR] [\fIdir\fR] + +.SH DESCRIPTION +\fBatrextr\fR extracts one or more files from an Atari DOS 2.x or MyDOS +compatible ATR disk image. Extracted files are written to the current +directory. +.PP +\fIfile\fR is an optional filename or wildcard pattern, +such as \fIautorun.sys\fR or \fI*.sys\fR. If not +given, the default is \fI*.*\fR. \fIfile\fR is case insensitive: +\fIreadme.txt\fR is equivalent to \fIREADME.TXT\fR, and +\fI*.txt\fR is equivalent to \fI*.TXT\fR. If a wildcard is used, +most shells will require the argument +to be quoted, to avoid the shell's normal wildcard expansion. The +wildcard semantics are similar to those of Atari DOS or POSIX sh, but +are not identical to either. +.PP +\fIdir\fR is the directory to extract files to. If omitted, the default +is the current directory. If \fIdir\fR is to be given, \fIfile\fR must +also be given (although it may be specified as \fI""\fR, equivalent +to \fI"*.*"\fR). +.PP +\fBatrextr\fR does not take any other options. +.SH NOTES +DOS 2.5 disk images are not fully supported. Specifically, \fBatrextr\fR +is unable to extract files that use sectors above 720 (those +that are listed with \fI<\fR, in \fBatrdir\fR or Atari DOS 2.5). These +files will be silently skipped, exactly as Atari DOS 2.0S does when reading +a 2.5 enhanced density disk. +.PP +MyDOS subdirectories are not supported. Only files in the root directory +of a disk image can be extracted. +.PP +MyDOS large disk images (aka hard disk images) are supported, though +without subdirectory support, \fBatrextr\fR can't extract most of the +files in a typical hard disk image. +.PP +XFD format images are not supported. Neither are SpartaDOS, Atari DOS 3/4, +DOS XE, or other non-standard DOS formats. +.PP +There should be options to translate Atari EOL characters to and from +UNIX newlines, and to convert the extracted filenames to lowercase. +.PP +Exit status is zero if all files were extracted successfully, or +non-zero if any errors occurred. In case of a non-zero return, +some files may still have been extracted (though some or all of them +may be truncated or corrupt). +.SH AUTHOR +Ken Siders <\fBatari8bit@columbus.rr.com\fR> +.PP +Man page by B. Watson <\fBurchlay@urchlay.com\fR> + +.SH SEE ALSO +\&\fIatrdir\fR\|(1), \&\fImakeatr\fR\|(1), \&\fIsortatr\fR\|(1), +\&\fIunmakatr\fR\|(1). +.PP +Ken Siders Atari 8-bit page: +.br +http://atari.ksiders.tzo.com/a8emulators.html diff --git a/ksiders/atrextr.c b/ksiders/atrextr.c new file mode 100644 index 0000000..2aeb898 --- /dev/null +++ b/ksiders/atrextr.c @@ -0,0 +1,63 @@ +/* Copyright 1997 Ken Siders */ + +#include +#include +#include +#include +#include +#include "atr.h" +#include "atdos.h" + +int main( int argc, char **argv) { + AtrFilePtr atr; + int stat = 0, ret = 0; + char *file = "*.*"; + char *path = NULL; + + printf("AtrExtr Version 0.9u (c)1997 Ken Siders\n"); + printf("Ported and modified by B. Watson, 2007\n"); + printf("This program may be freely distributed\n\n"); + + if(argc < 2 || argc > 4) { + printf("usage: atrextr atrname.atr [file] [dir]\n" + "Wildcards may be used for file (default: *.*)\n" + "dir will be created, if it does not exist\n"); + exit(-1); + } + + atr = OpenAtr(argv[1]); + if(atr == 0) { + printf("Error reading ATR file: %s\n", argv[1]); + CloseAtr(atr); + exit(2); + } + + CloseAtr(atr); + + if(argc >= 3 && argv[2][0]) + file = argv[2]; + + if(argc == 4) { + path = argv[3]; + mkdir(path, 0777); /* ignore errors (ExtractAtariFile() will fail instead) */ + } + + while ( !stat ) { + SetVerbose(1); + stat = ExtractAtariFile( argv[1], file, path ); + SetVerbose(0); + } + + if( stat < 0 ) { + printf("\nError encountered when extracting file(s)\n"); + printf("some files may have been extracted incorrectly\n"); + stat = -stat; + ret = 1; + } + + printf("\n%d file(s) extracted\n", stat); + + exit(ret); +} + + diff --git a/ksiders/atrsrc.zip b/ksiders/atrsrc.zip new file mode 100644 index 0000000..7a70fb5 Binary files /dev/null and b/ksiders/atrsrc.zip differ diff --git a/ksiders/kboot.h b/ksiders/kboot.h new file mode 100644 index 0000000..02576f5 --- /dev/null +++ b/ksiders/kboot.h @@ -0,0 +1,61 @@ +/* Copyright 1997 Ken Siders */ + +/* This is the code used in the first three (boot) sectors when + creating an ATR from an Atari executable + +History: + Ver 0.01 07/17/97 - Initial version +*/ + + +unsigned char bootData[384] = { + 0x00, 0x03, 0x00, 0x07, 0x14, 0x07, 0x4C, 0x14, + 0x07, 0x00, 0x00, 0x00, 0x00, 0xA9, 0x46, 0x8D, + 0xC6, 0x02, 0xD0, 0xFE, 0xA0, 0x00, 0xA9, 0x6B, + 0x91, 0x58, 0x20, 0xD9, 0x07, 0xB0, 0xEE, 0x20, + 0xC4, 0x07, 0xAD, 0x7A, 0x08, 0x0D, 0x76, 0x08, + 0xD0, 0xE3, 0xA5, 0x80, 0x8D, 0xE0, 0x02, 0xA5, + 0x81, 0x8D, 0xE1, 0x02, 0xA9, 0x00, 0x8D, 0xE2, + 0x02, 0x8D, 0xE3, 0x02, 0x20, 0xEB, 0x07, 0xB0, + 0xCC, 0xA0, 0x00, 0x91, 0x80, 0xA5, 0x80, 0xC5, + 0x82, 0xD0, 0x06, 0xA5, 0x81, 0xC5, 0x83, 0xF0, + 0x08, 0xE6, 0x80, 0xD0, 0x02, 0xE6, 0x81, 0xD0, + 0xE3, 0xAD, 0x76, 0x08, 0xD0, 0xAF, 0xAD, 0xE2, + 0x02, 0x8D, 0x70, 0x07, 0x0D, 0xE3, 0x02, 0xF0, + 0x0E, 0xAD, 0xE3, 0x02, 0x8D, 0x71, 0x07, 0x20, + 0xFF, 0xFF, 0xAD, 0x7A, 0x08, 0xD0, 0x13, 0xA9, + 0x00, 0x8D, 0xE2, 0x02, 0x8D, 0xE3, 0x02, 0x20, + 0xAE, 0x07, 0xAD, 0x7A, 0x08, 0xD0, 0x03, 0x4C, + 0x3C, 0x07, 0xA9, 0x00, 0x85, 0x80, 0x85, 0x81, + 0x85, 0x82, 0x85, 0x83, 0xAD, 0xE0, 0x02, 0x85, + 0x0A, 0x85, 0x0C, 0xAD, 0xE1, 0x02, 0x85, 0x0B, + 0x85, 0x0D, 0xA9, 0x01, 0x85, 0x09, 0xA9, 0x00, + 0x8D, 0x44, 0x02, 0x6C, 0xE0, 0x02, 0x20, 0xEB, + 0x07, 0x85, 0x80, 0x20, 0xEB, 0x07, 0x85, 0x81, + 0xA5, 0x80, 0xC9, 0xFF, 0xD0, 0x10, 0xA5, 0x81, + 0xC9, 0xFF, 0xD0, 0x0A, 0x20, 0xEB, 0x07, 0x85, + 0x80, 0x20, 0xEB, 0x07, 0x85, 0x81, 0x20, 0xEB, + 0x07, 0x85, 0x82, 0x20, 0xEB, 0x07, 0x85, 0x83, + 0x60, 0x20, 0xEB, 0x07, 0xC9, 0xFF, 0xD0, 0x09, + 0x20, 0xEB, 0x07, 0xC9, 0xFF, 0xD0, 0x02, 0x18, + 0x60, 0x38, 0x60, 0xAD, 0x09, 0x07, 0x0D, 0x0A, + 0x07, 0x0D, 0x0B, 0x07, 0xF0, 0x79, 0xAC, 0x79, + 0x08, 0x10, 0x50, 0xEE, 0x77, 0x08, 0xD0, 0x03, + 0xEE, 0x78, 0x08, 0xA9, 0x31, 0x8D, 0x00, 0x03, + 0xA9, 0x01, 0x8D, 0x01, 0x03, 0xA9, 0x52, 0x8D, + 0x02, 0x03, 0xA9, 0x40, 0x8D, 0x03, 0x03, 0xA9, + 0x80, 0x8D, 0x04, 0x03, 0xA9, 0x08, 0x8D, 0x05, + 0x03, 0xA9, 0x1F, 0x8D, 0x06, 0x03, 0xA9, 0x80, + 0x8D, 0x08, 0x03, 0xA9, 0x00, 0x8D, 0x09, 0x03, + 0xAD, 0x77, 0x08, 0x8D, 0x0A, 0x03, 0xAD, 0x78, + 0x08, 0x8D, 0x0B, 0x03, 0x20, 0x59, 0xE4, 0xAD, + 0x03, 0x03, 0xC9, 0x02, 0xB0, 0x22, 0xA0, 0x00, + 0x8C, 0x79, 0x08, 0xB9, 0x80, 0x08, 0xAA, 0xAD, + 0x09, 0x07, 0xD0, 0x0B, 0xAD, 0x0A, 0x07, 0xD0, + 0x03, 0xCE, 0x0B, 0x07, 0xCE, 0x0A, 0x07, 0xCE, + 0x09, 0x07, 0xEE, 0x79, 0x08, 0x8A, 0x18, 0x60, + 0xA0, 0x01, 0x8C, 0x76, 0x08, 0x38, 0x60, 0xA0, + 0x01, 0x8C, 0x7A, 0x08, 0x38, 0x60, 0x00, 0x03, + 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 + }; + diff --git a/ksiders/makeatr.1 b/ksiders/makeatr.1 new file mode 100644 index 0000000..fc2ab5a --- /dev/null +++ b/ksiders/makeatr.1 @@ -0,0 +1,92 @@ +.TH MAKEATR,UNMAKATR "1" "April 2007" "makeatr, unmakatr" "Ken Siders' Atari 8-bit Tools" +.SH NAME +\fBmakeatr\fR \- convert an Atari executable to a "K-file" bootable disk +.br +\fBunmakatr\fR \- extract original executable from a disk made with \fBmakeatr\fR + +.SH SYNOPSIS +\fBmakeatr\fR \fIimagefile.atr\fR \fIatari-exe\fR +.br +\fBunmakeatr\fR \fIimagefile.atr\fR \fIatari-exe\fR + +.SH DESCRIPTION +For various reasons, it's sometimes useful to make a bootable disk image +of an Atari executable. \fBmakeatr\fR does exactly that. +.PP +If you have a bootable image made with \fBmakeatr\fR, but you've lost the +original executable, you can extract it from the image with \fBunmakatr\fR. +.PP +.SH NOTES +\fBmakeatr\fR is only useful for single\-file games or other programs that +don't need DOS disk access to run: the bootable image won't contain +any DOS at all, or even a DOS file structure (you can't read the directory). +.PP +\fBunmakatr\fR only works for images created by \fBmakeatr\fR. It is not +a general-purpose bootdisk-to-executable utility. +.PP +Disks made with \fBmakeatr\fR are recognizable when booted on the Atari, +because they display GR.0 screen with a lowercase \fIk\fR +(screen is otherwise blank). +.PP +Disk images made with \fBmakeatr\fR are only created with enough sectors +to hold the executable. AtariSIO can handle these images fine, as can +most other ATR utilities, but the smaller-than-regulation size may cause +problems with some utilities. +.PP +There is only one Atari executable format, regardless of filename extension. +All .XEX, .COM, .BIN, .EXE, etc. files for the Atari are the same file type, +regardless of the name, and regardless of what you may have read on some +forum site. Atari DOS doesn't care about the filename; it only exists for +human consumption (and for filetype association with emulators, these +days). + +.SH DIAGNOSTICS +\fBmakeatr\fR's error messages are not well documented. They consist only +of an internal error number code, listed here: +.PP +.B 1 +\- Unable to open ATR image for writing +.br +.B 2 +\- Unable to write image ATR header +.br +.B 6 +\- Unable to write boot sectors to ATR image +.br +.B 7 +\- Error while padding ATR image to an even sector size +.br +.B 11 +\- Unable to stat the input file (not found, permission denied, etc) +.br +.B 12 +\- Input file is 0 bytes in length +.br +.B 13 +\- Can't open input file +.br +.B 19 +\- Error writing to ATR image, \fBor\fR trailing junk in the input image +.br +.B 20 +\- Input file is not an Atari executable (missing 0xFF 0xFF signature) +.br +.PP +\fBunmakatr\fR reports "Error #0" for any and all errors it may encounter. +.PP +Both \fBmakeatr\fR and \fBunmakatr\fR return a 0 exit status to the caller +for success, or non-zero status for failure (and print one of the above +error messages, as well). Error messages are printed to standard \fBoutput\fR, +not standard error output. + +.SH AUTHOR +Ken Siders <\fBatari8bit@columbus.rr.com\fR> +.PP +Man page by B. Watson <\fBurchlay@urchlay.com\fR> + +.SH SEE ALSO +\&\fIatrdir\fR\|(1), \&\fIatrextr\fR\|(1), \&\fIsortatr\fR\|(1). +.PP +Ken Siders Atari 8-bit page: +.br +http://atari.ksiders.tzo.com/a8emulators.html diff --git a/ksiders/makeatr.c b/ksiders/makeatr.c new file mode 100644 index 0000000..457e0e5 --- /dev/null +++ b/ksiders/makeatr.c @@ -0,0 +1,41 @@ +/* Copyright 1997 Ken Siders */ + +#include +#include +#include +#include "atr.h" +#include "atdos.h" + + +/******************************************************************** + Testing +********************************************************************/ + + +int main( int argc, char **argv) + { + int stat = 0; + + printf("MakeAtr Version 0.9u (c)1997 Ken Siders\n"); + printf("Ported and modified by B. Watson, 2007\n"); + printf("This program may be freely distributed\n\n"); + + + if (argc != 3) + { + printf("usage: makeatr atrname.atr file\n\n"); + } + else + { + stat = CreateBootAtr( argv[1], argv[2] ); + if ( stat ) + printf("Error #%d encountered in conversion\n\n", stat); + else + printf("No errors, %s created successfully\n\n", argv[1]); + } + + exit(stat); + +} + + diff --git a/ksiders/sortatr.1 b/ksiders/sortatr.1 new file mode 100644 index 0000000..98301b3 --- /dev/null +++ b/ksiders/sortatr.1 @@ -0,0 +1,80 @@ +.TH SORTATR "1" "April 2007" "sortatr" "Ken Siders' Atari 8-bit Tools" +.SH NAME +\fBsortatr\fR \- sort Atari DOS directory in an ATR image + +.SH SYNOPSIS +\fBsortatr\fR \fIimagefile.atr\fR + +.SH DESCRIPTION +\fBsortatr\fR sorts the directory entries in an Atari DOS 2.0S or MyDOS +compatible ATR images. The sort is alphabetical, and the disk image +is modified in place. +.PP +\fBatrextr\fR does not take any options. +.SH WARNINGS +\fBDO NOT USE\fR this utility with DOS 2.5 disk images! +.PP +\fBDO NOT USE\fR this utility with MyDOS images containing subdirectories! +.PP +\fBDATA LOSS\fR will occur if these warnings are not heeded! The modified +directory in the image will not contain any references to DOS 2.5 files +using sectors above 720, or to MyDOS subdirectories. This effectively +\fBdeletes\fR these files from the image. +.PP +If in doubt, list the image's directory with \fBatrdir\fR. If you see +files marked with a \fI:\fR (colon) or \fI<\fR (less-than), then +\fBsortatr\fR should not be used on the image. Even if your purpose +is actually to delete these files/dirs, you should use some other +utility (or DOS on a real or emulated Atari) to delete them, because +\fBsortatr\fR doesn't free the sectors occupied by the files/dirs. +.PP +If you ignore these warnings and manage to delete files or directories +from your disk image, it should be possible to recover them with a good +Atari undelete or disk\-repair utility. Although the affected files/dirs +have been removed from the disk directory, the data sectors have not +been overwritten nor marked as free (meaning they won't be overwritten +by later write operations, unlike most "undelete" situations). +First, you have to +find the starting sector of the missing file/dir and +create a directory entry for it in the directory at sectors 36-368. You +will probably also have to change the file number in the sector link +bytes, or else delete the file in the new directory that's using the +file number of the old (deleted) file. +.PP +Further warnings: +.PP +\fBDO NOT USE\fR this utility with any non-standard (non\-AtariDOS, +non-MyDOS compatible) disk image. +.PP +Boot disks with no directory, +SpartaDOS, Atari DOS 3/4, DOS XE, or other non\-standard DOS formatted +disks might (if you're lucky) just cause an error message. If +you're not lucky, they may be corrupted. There is no easy way to +recover an image that gets damaged in this way. +.PP +\fBDO NOT USE\fR this utility with \fIany\fR image without creating a +backup first! +.PP +Any image you use with \fBsortatr\fR is modified in-place, +and no backup is made by \fBsortatr\fR. \fBAlways\fR make a backup +copy of an ATR image before you use \fBsortatr\fR on it. \fIYou have +been warned\fI. +.SH NOTES +XFD format images are not supported. +.PP +Exit status is zero if the sort was successful, or +non-zero if any errors occurred. In case of a non-zero return, +the disk image may be truncated, or its directory sectors may be +damaged. Hope you had a backup of that image! +.SH AUTHOR +Ken Siders <\fBatari8bit@columbus.rr.com\fR> +.PP +Man page by B. Watson <\fBurchlay@urchlay.com\fR> + +.SH SEE ALSO +\&\fIatrdir\fR\|(1), \&\fIatrextr\fR\|(1), \&\fImakeatr\fR\|(1), +\&\fIunmakatr\fR\|(1). +.PP +Ken Siders Atari 8-bit page: +.br +http://atari.ksiders.tzo.com/a8emulators.html diff --git a/ksiders/sortatr.c b/ksiders/sortatr.c new file mode 100644 index 0000000..394dc28 --- /dev/null +++ b/ksiders/sortatr.c @@ -0,0 +1,39 @@ +/* Copyright 1997 Ken Siders */ + +#include +#include +#include +#include "atr.h" +#include "atdos.h" + +/* SortAtr */ + + +int main( int argc, char **argv) + { + int stat; + + printf("SortATR v0.9 (C)1997 Ken Siders\n"); + printf("This program may be freely distributed\n\n"); + + if ( argc != 2 ) + { + printf("usage: sortatr atrname\n"); + exit(2); + } + stat = SortAtariDir( argv[1] ); + if ( stat ) + { + printf("Error sorting directory\n"); + exit(3); + } + else + { + printf("no errors\n"); + exit(0); + } + + +} + + diff --git a/ksiders/unmakatr.c b/ksiders/unmakatr.c new file mode 100644 index 0000000..c50b55d --- /dev/null +++ b/ksiders/unmakatr.c @@ -0,0 +1,43 @@ +/* Copyright 1997 Ken Siders */ + +#include +#include +#include +#include "atr.h" +#include "atdos.h" + + +/******************************************************************** + Testing +********************************************************************/ + + +int main( int argc, char **argv) + { + long size = 0; + + printf("MakeAtr Version 0.9u (c)1997 Ken Siders\n"); + printf("Ported and modified by B. Watson, 2007\n"); + printf("This program may be freely distributed\n\n"); + + + if (argc != 3) + { + printf("usage: unmakatr atrname.atr file\n\n"); + } + else + { + size = ExtractExeFromBootAtr( argv[1], argv[2] ); + if ( size <= 0 ) { + printf("Error #%ld encountered in extracting\n\n", -size); + exit(size); + } else { + printf("No errors, %s extracted successfully (%ld bytes)\n\n", argv[2], size); + } + } + + exit(0); + +} + + -- cgit v1.2.3