testing disk generator
This commit is contained in:
parent
9e412b248b
commit
852d3a1b67
Binary file not shown.
Binary file not shown.
|
@ -0,0 +1,362 @@
|
||||||
|
/************************************************************************/
|
||||||
|
/* atr2unix.c */
|
||||||
|
/* */
|
||||||
|
/* Preston Crow */
|
||||||
|
/* Public Domain */
|
||||||
|
/* */
|
||||||
|
/* Extract files from an Atari DOS or MyDOS .ATR file */
|
||||||
|
/* */
|
||||||
|
/* Version History */
|
||||||
|
/* 5 Jun 95 Version 1.0 Preston Crow <crow@cs.dartmouth.edu> */
|
||||||
|
/* Initial public release */
|
||||||
|
/* 20 Dec 95 Version 1.1 Chad Wagner <cmwagner@gate.net> */
|
||||||
|
/* Ported to MS-DOS machines */
|
||||||
|
/* 10 Feb 98 Version 1.2 Preston Crow <crow@cs.dartmouth.edu> */
|
||||||
|
/* Expanded 256-byte sector support */
|
||||||
|
/* 2 Jan 22 Version 1.3 Preston Crow */
|
||||||
|
/* Enhanced debugging */
|
||||||
|
/************************************************************************/
|
||||||
|
|
||||||
|
/************************************************************************/
|
||||||
|
/* Portability macros */
|
||||||
|
/* 1 Jun 95 crow@cs.dartmouth.edu (Preston Crow) */
|
||||||
|
/************************************************************************/
|
||||||
|
#if defined(__MSDOS) || defined(__MSDOS__) || defined(_MSDOS) || \
|
||||||
|
defined(_MSDOS_)
|
||||||
|
#define MSDOS /* icky, icky, icky! */
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/************************************************************************/
|
||||||
|
/* Include files */
|
||||||
|
/************************************************************************/
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <ctype.h>
|
||||||
|
#include <sys/types.h>
|
||||||
|
#include <sys/stat.h>
|
||||||
|
#include <string.h>
|
||||||
|
|
||||||
|
#ifdef MSDOS
|
||||||
|
#include <dir.h>
|
||||||
|
#include <io.h>
|
||||||
|
#else
|
||||||
|
#include <unistd.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/************************************************************************/
|
||||||
|
/* Macros and Constants */
|
||||||
|
/************************************************************************/
|
||||||
|
#define ATRHEAD 16
|
||||||
|
#define USAGE "atr2unix [-dlmr-] atarifile.atr\n" \
|
||||||
|
" Flags:\n" \
|
||||||
|
"\t-l Convert filenames to lower case\n" \
|
||||||
|
"\t-m MyDOS format disk image\n" \
|
||||||
|
"\t-- Next argument is not a flag\n" \
|
||||||
|
"\t-d debugging\n" \
|
||||||
|
"\t-r={sector} Use non-standard root directory number\n" \
|
||||||
|
"\t-f Fake run; do not create any files\n"
|
||||||
|
|
||||||
|
#ifndef SEEK_SET
|
||||||
|
#define SEEK_SET 0 /* May be missing from stdio.h */
|
||||||
|
#endif
|
||||||
|
#define SEEK(n) (ddshortinit?SEEK1(n):SEEK2(n))
|
||||||
|
#define SEEK1(n) (ATRHEAD + ((n<4)?((n-1)*128):(3*128+(n-4)*secsize)))
|
||||||
|
#define SEEK2(n) (ATRHEAD + ((n-1)*secsize))
|
||||||
|
|
||||||
|
/************************************************************************/
|
||||||
|
/* Data types */
|
||||||
|
/************************************************************************/
|
||||||
|
struct atari_dirent {
|
||||||
|
unsigned char flag; /* set bits: 7->deleted 6->in use 5->locked 0->write open */
|
||||||
|
unsigned char countlo; /* Number of sectors in file */
|
||||||
|
unsigned char counthi;
|
||||||
|
unsigned char startlo; /* First sector in file */
|
||||||
|
unsigned char starthi;
|
||||||
|
char namelo[8];
|
||||||
|
char namehi[3];
|
||||||
|
};
|
||||||
|
|
||||||
|
struct atr_head {
|
||||||
|
unsigned char h0; /* 0x96 */
|
||||||
|
unsigned char h1; /* 0x02 */
|
||||||
|
unsigned char seccountlo;
|
||||||
|
unsigned char seccounthi;
|
||||||
|
unsigned char secsizelo;
|
||||||
|
unsigned char secsizehi;
|
||||||
|
unsigned char hiseccountlo;
|
||||||
|
unsigned char hiseccounthi;
|
||||||
|
unsigned char unused[8];
|
||||||
|
};
|
||||||
|
|
||||||
|
/************************************************************************/
|
||||||
|
/* Function Prototypes */
|
||||||
|
/************************************************************************/
|
||||||
|
void read_dir(FILE *in,int sector);
|
||||||
|
void read_file(char *name,FILE *in,FILE *out,int sector,int count,int filenum);
|
||||||
|
|
||||||
|
/************************************************************************/
|
||||||
|
/* Global variables */
|
||||||
|
/************************************************************************/
|
||||||
|
int ddshortinit=0; /* True indicates double density with first 3 sectors 128 bytes */
|
||||||
|
int secsize,seccount;
|
||||||
|
int mydos=0;
|
||||||
|
int lowcase=0;
|
||||||
|
int debug=0;
|
||||||
|
int fake=0;
|
||||||
|
|
||||||
|
/************************************************************************/
|
||||||
|
/* main() */
|
||||||
|
/* Process command line */
|
||||||
|
/* Open input .ATR file */
|
||||||
|
/* Interpret .ATR header */
|
||||||
|
/************************************************************************/
|
||||||
|
int main(int argc,char *argv[])
|
||||||
|
{
|
||||||
|
FILE *in;
|
||||||
|
struct atr_head head;
|
||||||
|
int root=361;
|
||||||
|
|
||||||
|
--argc; ++argv; /* Skip program name */
|
||||||
|
|
||||||
|
/* Process flags */
|
||||||
|
while (argc) {
|
||||||
|
int done=0;
|
||||||
|
|
||||||
|
if (**argv=='-') {
|
||||||
|
++*argv;
|
||||||
|
while(**argv) {
|
||||||
|
switch(**argv) {
|
||||||
|
case 'm': /* MyDos disk */
|
||||||
|
mydos=1;
|
||||||
|
break;
|
||||||
|
case '-': /* Last option */
|
||||||
|
done=1;
|
||||||
|
break;
|
||||||
|
case 'l': /* strlwr names */
|
||||||
|
lowcase=1;
|
||||||
|
break;
|
||||||
|
case 'f': /* fake */
|
||||||
|
fake=1;
|
||||||
|
break;
|
||||||
|
case 'd': /* debugging */
|
||||||
|
debug=1;
|
||||||
|
break;
|
||||||
|
case 'r': /* root directory sector */
|
||||||
|
++*argv;
|
||||||
|
while ( **argv && !isdigit(**argv) ) ++*argv;
|
||||||
|
root=atoi(*argv);
|
||||||
|
while ( argv[0][1] ) ++*argv;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
fprintf(stderr,USAGE);
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
++*argv;
|
||||||
|
}
|
||||||
|
--argc; ++argv;
|
||||||
|
}
|
||||||
|
else break;
|
||||||
|
if (done) break;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!argc) {
|
||||||
|
fprintf(stderr,USAGE);
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
in=fopen(*argv,"rb");
|
||||||
|
if (!in) {
|
||||||
|
fprintf(stderr,"Unable to open %s\n%s",*argv,USAGE);
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
--argc; ++argv;
|
||||||
|
if (argc) {
|
||||||
|
if (chdir(*argv)) {
|
||||||
|
fprintf(stderr,"Unable to change to directory: %s\n%s",*argv,USAGE);
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fread(&head,sizeof(head),1,in);
|
||||||
|
if ( head.h0 != 0x96 || head.h1 != 0x02 )
|
||||||
|
{
|
||||||
|
if ( debug ) printf("File does not have ATR signature\n");
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
secsize=head.secsizelo+256*head.secsizehi;
|
||||||
|
seccount=head.seccountlo+256*head.seccounthi;
|
||||||
|
if ( debug ) printf("ATR image: %d sectors, %d bytes each\n",seccount,secsize);
|
||||||
|
{
|
||||||
|
struct stat buf;
|
||||||
|
size_t expected;
|
||||||
|
fstat(fileno(in),&buf);
|
||||||
|
if (((buf.st_size-ATRHEAD)%256)==128) ddshortinit=1;
|
||||||
|
if (debug) {
|
||||||
|
if (ddshortinit && secsize==256) printf("DD, but first 3 sectors SD\n");
|
||||||
|
else if (secsize==256) printf("DD, including first 3 sectors\n");
|
||||||
|
}
|
||||||
|
expected = sizeof(head) + seccount * secsize - ((secsize - 128) * 3 * ddshortinit);
|
||||||
|
if ( (size_t)buf.st_size != expected ) {
|
||||||
|
if ( debug ) {
|
||||||
|
int seccount_real;
|
||||||
|
printf("File size wrong; expected %u bytes, observed %u bytes\n",(unsigned int)expected,(unsigned int)buf.st_size);
|
||||||
|
seccount_real = (buf.st_size - sizeof(head)) / secsize;
|
||||||
|
if ( ddshortinit )
|
||||||
|
{
|
||||||
|
if ( (size_t)buf.st_size <= sizeof(head) + 3 * 128 ) seccount_real = (buf.st_size - sizeof(head)) / 128;
|
||||||
|
else seccount_real = 3 + (buf.st_size - sizeof(head) - 3*128)/secsize;
|
||||||
|
}
|
||||||
|
printf("Sectors expected: %d, observed: %d\n",seccount,seccount_real);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
read_dir(in,root);
|
||||||
|
return(0);
|
||||||
|
}
|
||||||
|
|
||||||
|
/************************************************************************/
|
||||||
|
/* display_entry() */
|
||||||
|
/* Display the contents of one directory entry for debugging */
|
||||||
|
/************************************************************************/
|
||||||
|
void display_entry(int i,struct atari_dirent *f)
|
||||||
|
{
|
||||||
|
struct atari_dirent empty;
|
||||||
|
memset(&empty,0,sizeof(empty));
|
||||||
|
if ( memcmp(&empty,f,sizeof(empty)) == 0 )
|
||||||
|
{
|
||||||
|
printf("%2d: [entry is all zeros]\n",i);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
unsigned count = f->countlo + 256 * f->counthi;
|
||||||
|
unsigned start = f->startlo + 256 * f->starthi;
|
||||||
|
printf("%2d: %4d %4d %c%c%c%c%c%c%c%c.%c%c%c\n",i,count,start,
|
||||||
|
f->namelo[0],f->namelo[1],f->namelo[2],f->namelo[3],f->namelo[4],f->namelo[5],f->namelo[6],f->namelo[7],
|
||||||
|
f->namehi[0],f->namehi[1],f->namehi[2]);
|
||||||
|
}
|
||||||
|
|
||||||
|
/************************************************************************/
|
||||||
|
/* read_dir() */
|
||||||
|
/* Read the entries in a directory */
|
||||||
|
/* Call read_file() for files, read_dir() for subdirectories */
|
||||||
|
/************************************************************************/
|
||||||
|
void read_dir(FILE *in,int sector)
|
||||||
|
{
|
||||||
|
int i,j,k;
|
||||||
|
struct atari_dirent f;
|
||||||
|
FILE *out;
|
||||||
|
char name[13];
|
||||||
|
|
||||||
|
if ( debug ) printf("Parsing directory sector %d\n",sector);
|
||||||
|
|
||||||
|
for(i=0;i<64;++i) {
|
||||||
|
fseek(in,(long)SEEK(sector)+i*sizeof(f)+(secsize-128)*(i/8),SEEK_SET);
|
||||||
|
fread(&f,sizeof(f),1,in);
|
||||||
|
if ( debug ) display_entry(i,&f);
|
||||||
|
if ( fake ) continue;
|
||||||
|
if (!f.flag) /* No more entries */
|
||||||
|
{
|
||||||
|
if ( debug ) printf("Directory entry %d: zero indicates end of entries\n",i);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (f.flag&128) /* Deleted file */
|
||||||
|
{
|
||||||
|
if ( debug ) printf("Directory entry %d: deleted flag\n",i);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
for(j=0;j<8;++j) {
|
||||||
|
name[j]=f.namelo[j];
|
||||||
|
if (name[j]==' ') break;
|
||||||
|
}
|
||||||
|
name[j]='.';
|
||||||
|
++j;
|
||||||
|
for(k=0;k<3;++k,++j) {
|
||||||
|
name[j]=f.namehi[k];
|
||||||
|
if (name[j]==' ') break;
|
||||||
|
}
|
||||||
|
name[j]=0;
|
||||||
|
if (name[j-1]=='.') name[j-1]=0;
|
||||||
|
if(lowcase) for(j=0;name[j];++j) name[j]=tolower(name[j]);
|
||||||
|
|
||||||
|
if (f.flag ==0x47 ) { /* Seems to work */
|
||||||
|
printf("Warning: File %s has flag bit 1 set--file ignored\n",name);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
if (mydos && f.flag&16) { /* Subdirectory */
|
||||||
|
if (debug) printf("subdir %s (sec %d);\n",name,f.startlo+256*f.starthi);
|
||||||
|
#ifdef MSDOS
|
||||||
|
mkdir(name);
|
||||||
|
#else
|
||||||
|
mkdir(name,0777);
|
||||||
|
#endif
|
||||||
|
chdir(name);
|
||||||
|
read_dir(in,f.startlo+256*f.starthi);
|
||||||
|
chdir("..");
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
out=fopen(name,"wb");
|
||||||
|
if (!out) {
|
||||||
|
fprintf(stderr,"Unable to create file: %s\n",name);
|
||||||
|
exit(2);
|
||||||
|
}
|
||||||
|
if (debug) printf("readfile %s (sec %d,count %d,flags %x);\n",name,f.startlo+256*f.starthi,f.countlo+256*f.counthi,f.flag);
|
||||||
|
read_file(name,in,out,f.startlo+256*f.starthi,f.countlo+256*f.counthi,i);
|
||||||
|
if (f.flag&32) { /* Make locked files read-only */
|
||||||
|
#ifdef MSDOS
|
||||||
|
chmod(name,S_IREAD);
|
||||||
|
#else
|
||||||
|
mode_t um;
|
||||||
|
|
||||||
|
um=umask(022);
|
||||||
|
umask(um);
|
||||||
|
chmod(name,0444 & ~um);
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/************************************************************************/
|
||||||
|
/* read_file() */
|
||||||
|
/* Trace through the sector chain. */
|
||||||
|
/* Complications: Are the file numbers or high bits on the sector */
|
||||||
|
/* number? */
|
||||||
|
/* What about the last block code for 256-byte sectors? */
|
||||||
|
/************************************************************************/
|
||||||
|
void read_file(char *name,FILE *in,FILE *out,int sector,int count,int filenum)
|
||||||
|
{
|
||||||
|
unsigned char buf[256];
|
||||||
|
|
||||||
|
buf[secsize-1]=0;
|
||||||
|
while(count) {
|
||||||
|
if (sector<1) {
|
||||||
|
fprintf(stderr,"Corrupted file (invalid sector %d): %s\n",sector,name);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (buf[secsize-1]&128 && secsize==128) {
|
||||||
|
fprintf(stderr,"Corrupted file (unexpected EOF): %s\n",name);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (fseek(in,(long)SEEK(sector),SEEK_SET)) {
|
||||||
|
fprintf(stderr,"Corrupted file (next sector %d): %s\n",sector,name);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
fread(buf,secsize,1,in);
|
||||||
|
fwrite(buf,buf[secsize-1],1,out);
|
||||||
|
if (mydos) {
|
||||||
|
sector=buf[secsize-2]+buf[secsize-3]*256;
|
||||||
|
}
|
||||||
|
else { /* DOS 2.0 */
|
||||||
|
sector=buf[secsize-2]+(3&buf[secsize-3])*256;
|
||||||
|
if (buf[secsize-3]>>2 != filenum) {
|
||||||
|
fprintf(stderr,"Corrupted file (167: file number mismatch): %s\n",name);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
--count;
|
||||||
|
}
|
||||||
|
if (!(buf[secsize-1]&128) && secsize==128 && sector) {
|
||||||
|
fprintf(stderr,"Corrupted file (expected EOF, code %d, next sector %d): %s\n",buf[secsize-1],sector,name);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
fclose(out);
|
||||||
|
}
|
|
@ -0,0 +1,476 @@
|
||||||
|
/*
|
||||||
|
** dcmtoatr.c -- written by Chad Wagner
|
||||||
|
**
|
||||||
|
** I just wanted to throw in some personal comments, I wanted to thank
|
||||||
|
** Preston Crow, for his work on portability issues, as well as some of
|
||||||
|
** the ideas he put into this program, Bob Puff, for his hard work on
|
||||||
|
** The Disk Communicator, an excellent means for transferring disk images,
|
||||||
|
** and I feel it is the de facto standard, and should remain as such, and
|
||||||
|
** Jason Duerstock, for writing DCMTODSK and his documents on the DCM
|
||||||
|
** format, which did help me resolve some of the things I wasn't aware of.
|
||||||
|
** I am sure there is a few others. Unfortunately I only got one response
|
||||||
|
** from Bob Puff, he was attempting to help, but I believe he is very busy
|
||||||
|
** person, and just didn't have the time.
|
||||||
|
**
|
||||||
|
** Revision History:
|
||||||
|
** 31 May 95 cmwagner@gate.net
|
||||||
|
** 1 Jun 95 cmwagner@gate.net
|
||||||
|
** added in some portability macros from dcm.c
|
||||||
|
** added in read_atari16() function from dcm.c
|
||||||
|
** wrote write_atari16() function
|
||||||
|
** did a general clean-up of the code
|
||||||
|
** 1 Jun 95 crow@cs.dartmouth.edu
|
||||||
|
** did a clean-up of the code, hopefully resolving any
|
||||||
|
** portability issues
|
||||||
|
** 2 Jun 95 cmwagner@gate.net and crow@cs.dartmouth.edu
|
||||||
|
** Allow for multi-file DCM files, after they've been
|
||||||
|
** combined into a single file
|
||||||
|
** 5 Jun 95 cmwagner@gate.net
|
||||||
|
** Fixed decoding routines to handle double density diskettes
|
||||||
|
** 26 Jun 95 cmwagner@gate.net
|
||||||
|
** Added in support for creating DCMTOXFD, default compile is
|
||||||
|
** for DCMTOATR
|
||||||
|
** 3 Sep 95 cmwagner@gate.net
|
||||||
|
** Added in -x switch, which creates an XFD image, instead of the
|
||||||
|
** default ATR image.
|
||||||
|
** added in soffset() routine, changed around the SOFFSET define,
|
||||||
|
** so that xfd images could be created, without compiling a
|
||||||
|
** different version.
|
||||||
|
** 26 Jun 95 modification is no longer relevant because of this
|
||||||
|
** modification.
|
||||||
|
** wrote some more comments, about what certain functions are doing,
|
||||||
|
** when they were created, and who wrote them.
|
||||||
|
** 28 Sep 95 lovegrov@student.umass.edu
|
||||||
|
** Fixed bug in soffset() function, apparently sector 4 would return
|
||||||
|
** an offset of 16 for ATR images or 0 for XFD images, which is not
|
||||||
|
** correct.
|
||||||
|
*/
|
||||||
|
|
||||||
|
/* Include files */
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <string.h>
|
||||||
|
|
||||||
|
/* prototypes */
|
||||||
|
void decode_C1(void);
|
||||||
|
void decode_C3(void);
|
||||||
|
void decode_C4(void);
|
||||||
|
void decode_C6(void);
|
||||||
|
void decode_C7(void);
|
||||||
|
void decode_FA(void);
|
||||||
|
int read_atari16(FILE *);
|
||||||
|
void write_atari16(FILE *,int);
|
||||||
|
int read_offset(FILE *);
|
||||||
|
void read_sector(FILE *);
|
||||||
|
void write_sector(FILE *);
|
||||||
|
long soffset(void);
|
||||||
|
|
||||||
|
/*
|
||||||
|
** Portability macros
|
||||||
|
** 1 Jun 95 crow@cs.dartmouth.edu (Preston Crow)
|
||||||
|
*/
|
||||||
|
#if defined(__MSDOS) || defined(__MSDOS__) || defined(_MSDOS) || defined(_MSDOS_)
|
||||||
|
#define MSDOS /* icky, icky, icky! */
|
||||||
|
#endif
|
||||||
|
#ifndef SEEK_SET
|
||||||
|
#define SEEK_SET 0 /* May be missing from stdio.h */
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/* version of this program, as seen in usage message */
|
||||||
|
#define VERSION "1.4"
|
||||||
|
|
||||||
|
/* Global variables */
|
||||||
|
FILE *fin,*fout;
|
||||||
|
unsigned int secsize;
|
||||||
|
unsigned short cursec=0,maxsec=0;
|
||||||
|
unsigned char createdisk=0,working=0,last=0,density,buf[256],atr=16;
|
||||||
|
int doprint=1; /* True for diagnostic output */
|
||||||
|
|
||||||
|
/*
|
||||||
|
** main()
|
||||||
|
*/
|
||||||
|
int main(int argc,char **argv)
|
||||||
|
{
|
||||||
|
unsigned char archivetype; /* Block type for first block */
|
||||||
|
unsigned char blocktype; /* Current block type */
|
||||||
|
unsigned char tmp; /* Temporary for read without clobber on eof */
|
||||||
|
unsigned char imgin[256],imgout[256]; /* file names */
|
||||||
|
unsigned char done=0; /* completion flag */
|
||||||
|
char *self; /* program name from argv[0] */
|
||||||
|
|
||||||
|
#ifdef MSDOS
|
||||||
|
if ((self = strrchr(argv[0],'\\')) == NULL)
|
||||||
|
#else
|
||||||
|
if ((self = strrchr(argv[0],'/')) == NULL)
|
||||||
|
#endif
|
||||||
|
{
|
||||||
|
self = argv[0];
|
||||||
|
}
|
||||||
|
else
|
||||||
|
self++; /* Skip the slash */
|
||||||
|
|
||||||
|
--argc;++argv; /* Don't look at the filename anymore */
|
||||||
|
/* Process switches */
|
||||||
|
if (argc) while (*argv[0]=='-') {
|
||||||
|
int nomore=0;
|
||||||
|
|
||||||
|
++argv[0]; /* skip the '-' */
|
||||||
|
while(*argv[0]) {
|
||||||
|
switch(*argv[0]) {
|
||||||
|
case '-':
|
||||||
|
nomore=1;
|
||||||
|
break;
|
||||||
|
case 'q':
|
||||||
|
case 'Q':
|
||||||
|
doprint = !doprint;
|
||||||
|
break;
|
||||||
|
case 'x':
|
||||||
|
case 'X':
|
||||||
|
atr = 16 - atr;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
fprintf(stderr,"Unsupported switch: %c\n",*argv[0]);
|
||||||
|
fprintf(stderr,"%s "VERSION" by cmwagner@gate.net\n",self);
|
||||||
|
fprintf(stderr,"%s [-qx] input[.dcm] [output[.atr]]\n",self);
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
++argv[0]; /* We've processed this flag */
|
||||||
|
}
|
||||||
|
--argc;++argv; /* Done processing these flags */
|
||||||
|
if(nomore) break; /* Filename may begin with '-' */
|
||||||
|
}
|
||||||
|
|
||||||
|
if (argc<1 || argc>2) {
|
||||||
|
fprintf(stderr,"%s "VERSION" by cmwagner@gate.net\n",self);
|
||||||
|
fprintf(stderr,"%s [-qx] input[.dcm] [output[.atr]]\n",self);
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
strcpy(imgin,argv[0]);
|
||||||
|
if (strrchr(imgin,'.') == NULL)
|
||||||
|
strcat(imgin,".dcm");
|
||||||
|
|
||||||
|
if (argc==2)
|
||||||
|
strcpy(imgout,argv[1]);
|
||||||
|
else {
|
||||||
|
char *p;
|
||||||
|
|
||||||
|
strcpy(imgout,imgin);
|
||||||
|
if ((p = strrchr(imgout,'.')) != NULL)
|
||||||
|
*p = 0;
|
||||||
|
}
|
||||||
|
if (strrchr(imgout,'.') == NULL)
|
||||||
|
if (atr) {
|
||||||
|
strcat(imgout,".atr");
|
||||||
|
} else {
|
||||||
|
strcat(imgout,".xfd");
|
||||||
|
}
|
||||||
|
|
||||||
|
if ((fin = fopen(imgin,"rb")) == NULL) {
|
||||||
|
fprintf(stderr,"I couldn't open \"%s\" for reading.\n",imgin);
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
archivetype = blocktype = fgetc(fin);
|
||||||
|
switch(blocktype) {
|
||||||
|
case 0xF9:
|
||||||
|
case 0xFA:
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
fprintf(stderr,"0x%02X is an unknown header block.\n",blocktype);
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
if ((fout = fopen(imgout,"rb")) != NULL) {
|
||||||
|
fprintf(stderr,"I can't use \"%s\" for output, it already exists.\n",imgout);
|
||||||
|
exit(1);
|
||||||
|
} else {
|
||||||
|
fout = fopen(imgout,"wb");
|
||||||
|
}
|
||||||
|
|
||||||
|
rewind(fin);
|
||||||
|
|
||||||
|
do {
|
||||||
|
if(doprint) printf("\rCurrent sector: %4u",cursec);
|
||||||
|
|
||||||
|
#ifdef MSDOS
|
||||||
|
if (kbhit()) {
|
||||||
|
if (getch() == 27) {
|
||||||
|
fprintf(stderr,"\nProcessing terminated by user.\n");
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
if (feof(fin)) {
|
||||||
|
fflush(stdout); /* Possible buffered I/O confusion fix */
|
||||||
|
if ((!last) && (blocktype == 0x45) && (archivetype == 0xF9)) {
|
||||||
|
fprintf(stderr,"\nMulti-part archive error.\n");
|
||||||
|
fprintf(stderr,"To process these files, you must first combine the files into a single file.\n");
|
||||||
|
#ifdef MSDOS
|
||||||
|
fprintf(stderr,"\tCOPY /B file1.dcm+file2.dcm+file3.dcm newfile.dcm\n");
|
||||||
|
#else
|
||||||
|
fprintf(stderr,"\tcat file1.dcm file2.dcm file3.dcm > newfile.dcm\n");
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
fprintf(stderr,"\nEOF before end block.\n");
|
||||||
|
}
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
tmp = fgetc(fin); /* blocktype is needed on EOF error--don't corrupt it */
|
||||||
|
if (feof(fin)) continue; /* Will abort on the check at the top of the loop */
|
||||||
|
blocktype = tmp;
|
||||||
|
switch(blocktype) {
|
||||||
|
case 0xF9:
|
||||||
|
case 0xFA:
|
||||||
|
/* New block */
|
||||||
|
decode_FA();
|
||||||
|
break;
|
||||||
|
case 0x45:
|
||||||
|
/* End block */
|
||||||
|
working=0;
|
||||||
|
if (last) {
|
||||||
|
if (doprint) printf("\r%s has been successfully decompressed.\n",imgout);
|
||||||
|
fclose(fin);
|
||||||
|
fclose(fout);
|
||||||
|
done=1; /* Normal exit */
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case 0x41:
|
||||||
|
case 0xC1:
|
||||||
|
decode_C1();
|
||||||
|
break;
|
||||||
|
case 0x43:
|
||||||
|
case 0xC3:
|
||||||
|
decode_C3();
|
||||||
|
break;
|
||||||
|
case 0x44:
|
||||||
|
case 0xC4:
|
||||||
|
decode_C4();
|
||||||
|
break;
|
||||||
|
case 0x46:
|
||||||
|
case 0xC6:
|
||||||
|
decode_C6();
|
||||||
|
break;
|
||||||
|
case 0x47:
|
||||||
|
case 0xC7:
|
||||||
|
decode_C7();
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
fprintf(stderr,"\n0x%02X is an unknown block type. File may be "
|
||||||
|
"corrupt.\n",blocktype);
|
||||||
|
exit(1);
|
||||||
|
} /* end case */
|
||||||
|
|
||||||
|
if ((blocktype != 0x45) && (blocktype != 0xFA) &&
|
||||||
|
(blocktype != 0xF9)) {
|
||||||
|
if (!(blocktype & 0x80)) {
|
||||||
|
cursec=read_atari16(fin);
|
||||||
|
fseek(fout,soffset(),SEEK_SET);
|
||||||
|
} else {
|
||||||
|
cursec++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} while(!done); /* end do */
|
||||||
|
return(0); /* Should never be executed */
|
||||||
|
}
|
||||||
|
|
||||||
|
void decode_C1(void)
|
||||||
|
{
|
||||||
|
int secoff,tmpoff,c;
|
||||||
|
|
||||||
|
tmpoff=read_offset(fin);
|
||||||
|
c=fgetc(fin);
|
||||||
|
for (secoff=0; secoff<secsize; secoff++) {
|
||||||
|
buf[secoff]=c;
|
||||||
|
}
|
||||||
|
c=tmpoff;
|
||||||
|
for (secoff=0; secoff<tmpoff; secoff++) {
|
||||||
|
c--;
|
||||||
|
buf[c]=fgetc(fin);
|
||||||
|
}
|
||||||
|
write_sector(fout);
|
||||||
|
}
|
||||||
|
|
||||||
|
void decode_C3(void)
|
||||||
|
{
|
||||||
|
int secoff,tmpoff,c;
|
||||||
|
|
||||||
|
secoff=0;
|
||||||
|
do {
|
||||||
|
if (secoff)
|
||||||
|
tmpoff=read_offset(fin);
|
||||||
|
else
|
||||||
|
tmpoff=fgetc(fin);
|
||||||
|
for (; secoff<tmpoff; secoff++) {
|
||||||
|
buf[secoff]=fgetc(fin);
|
||||||
|
}
|
||||||
|
if (secoff == secsize)
|
||||||
|
break;
|
||||||
|
tmpoff=read_offset(fin);
|
||||||
|
c=fgetc(fin);
|
||||||
|
for (; secoff<tmpoff; secoff++) {
|
||||||
|
buf[secoff] = c;
|
||||||
|
}
|
||||||
|
} while(secoff < secsize);
|
||||||
|
write_sector(fout);
|
||||||
|
}
|
||||||
|
|
||||||
|
void decode_C4(void)
|
||||||
|
{
|
||||||
|
int secoff,tmpoff;
|
||||||
|
|
||||||
|
tmpoff=read_offset(fin);
|
||||||
|
for (secoff=tmpoff; secoff<secsize; secoff++) {
|
||||||
|
buf[secoff]=fgetc(fin);
|
||||||
|
}
|
||||||
|
write_sector(fout);
|
||||||
|
}
|
||||||
|
|
||||||
|
void decode_C6(void)
|
||||||
|
{
|
||||||
|
write_sector(fout);
|
||||||
|
}
|
||||||
|
|
||||||
|
void decode_C7(void)
|
||||||
|
{
|
||||||
|
read_sector(fin);
|
||||||
|
write_sector(fout);
|
||||||
|
}
|
||||||
|
|
||||||
|
void decode_FA(void)
|
||||||
|
{
|
||||||
|
unsigned char c;
|
||||||
|
|
||||||
|
if (working) {
|
||||||
|
fprintf(stderr,"\nTrying to start section but last section never had "
|
||||||
|
"an end section block.\n");
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
c=fgetc(fin);
|
||||||
|
density=((c & 0x70) >> 4);
|
||||||
|
last=((c & 0x80) >> 7);
|
||||||
|
switch(density) {
|
||||||
|
case 0:
|
||||||
|
maxsec=720;
|
||||||
|
secsize=128;
|
||||||
|
break;
|
||||||
|
case 2:
|
||||||
|
maxsec=720;
|
||||||
|
secsize=256;
|
||||||
|
break;
|
||||||
|
case 4:
|
||||||
|
maxsec=1040;
|
||||||
|
secsize=128;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
fprintf(stderr,"\nDensity type is unknown, density type=%u\n",density);
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (createdisk == 0) {
|
||||||
|
createdisk = 1;
|
||||||
|
if (atr) {
|
||||||
|
/* write out atr header */
|
||||||
|
/* special code, 0x0296 */
|
||||||
|
write_atari16(fout,0x296);
|
||||||
|
/* image size (low) */
|
||||||
|
write_atari16(fout,(short)(((long)maxsec * secsize) >> 4));
|
||||||
|
/* sector size */
|
||||||
|
write_atari16(fout,secsize);
|
||||||
|
/* image size (high) */
|
||||||
|
write_atari16(fout,(short)(((long)maxsec * secsize) >> 20));
|
||||||
|
/* 8 bytes unused */
|
||||||
|
write_atari16(fout,0);
|
||||||
|
write_atari16(fout,0);
|
||||||
|
write_atari16(fout,0);
|
||||||
|
write_atari16(fout,0);
|
||||||
|
}
|
||||||
|
memset(buf,0,256);
|
||||||
|
for (cursec=0; cursec<maxsec; cursec++) {
|
||||||
|
fwrite(buf,secsize,1,fout);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
cursec=read_atari16(fin);
|
||||||
|
fseek(fout,soffset(),SEEK_SET);
|
||||||
|
working=1;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
** read_atari16()
|
||||||
|
** Read a 16-bit integer with Atari byte-ordering.
|
||||||
|
** 1 Jun 95 crow@cs.dartmouth.edu (Preston Crow)
|
||||||
|
*/
|
||||||
|
int read_atari16(FILE *fin)
|
||||||
|
{
|
||||||
|
int ch_low,ch_high; /* fgetc() is type int, not char */
|
||||||
|
|
||||||
|
ch_low = fgetc(fin);
|
||||||
|
ch_high = fgetc(fin);
|
||||||
|
return(ch_low + 256*ch_high);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
** write_atari16()
|
||||||
|
** Write a 16-bit integer with Atari byte-ordering
|
||||||
|
** 1 Jun 95 cmwagner@gate.net (Chad Wagner)
|
||||||
|
*/
|
||||||
|
void write_atari16(FILE *fout,int n)
|
||||||
|
{
|
||||||
|
unsigned char ch_low,ch_high;
|
||||||
|
|
||||||
|
ch_low = (unsigned char)(n&0xff);
|
||||||
|
ch_high = (unsigned char)(n/256);
|
||||||
|
fputc(ch_low,fout);
|
||||||
|
fputc(ch_high,fout);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
** read_offset()
|
||||||
|
** Simple routine that 'reads' the offset from an RLE encoded block, if the
|
||||||
|
** offset is 0, then it returns it as 256.
|
||||||
|
** 5 Jun 95 cmwagner@gate.net (Chad Wagner)
|
||||||
|
*/
|
||||||
|
int read_offset(FILE *fin)
|
||||||
|
{
|
||||||
|
int ch; /* fgetc() is type int, not char */
|
||||||
|
|
||||||
|
ch = fgetc(fin);
|
||||||
|
if (ch == 0)
|
||||||
|
ch = 256;
|
||||||
|
|
||||||
|
return(ch);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
** read_sector()
|
||||||
|
** Simple routine that reads in a sector, based on it's location, and the
|
||||||
|
** sector size. Sectors 1-3, are 128 bytes, all other sectors are secsize.
|
||||||
|
** 5 Jun 95 cmwagner@gate.net (Chad Wagner)
|
||||||
|
*/
|
||||||
|
void read_sector(FILE *fin)
|
||||||
|
{
|
||||||
|
fread(buf,(cursec < 4 ? 128 : secsize),1,fin);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
** write_sector()
|
||||||
|
** Simple routine that writes in a sector, based on it's location, and the
|
||||||
|
** sector size. Sectors 1-3, are 128 bytes, all other sectors are secsize.
|
||||||
|
** 5 Jun 95 cmwagner@gate.net (Chad Wagner)
|
||||||
|
*/
|
||||||
|
void write_sector(FILE *fout)
|
||||||
|
{
|
||||||
|
fwrite(buf,(cursec < 4 ? 128 : secsize),1,fout);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
** soffset()
|
||||||
|
** calculates offsets within ATR or XFD images, for seeking.
|
||||||
|
** 28 Sep 95 lovegrov@student.umass.edu (Mike White)
|
||||||
|
*/
|
||||||
|
long soffset()
|
||||||
|
{
|
||||||
|
return (long)atr + (cursec < 4 ? ((long)cursec - 1) * 128 :
|
||||||
|
((long)cursec - 4) * secsize + 384);
|
||||||
|
}
|
File diff suppressed because it is too large
Load Diff
|
@ -0,0 +1,925 @@
|
||||||
|
/************************************************************************/
|
||||||
|
/* unix2atr.c */
|
||||||
|
/* */
|
||||||
|
/* Preston Crow */
|
||||||
|
/* Public Domain */
|
||||||
|
/* */
|
||||||
|
/* Extract files from a Unix directory tree and create a MyDOS */
|
||||||
|
/* ATR-format disk image file. */
|
||||||
|
/* */
|
||||||
|
/* To-do for version 1.0: */
|
||||||
|
/* Eliminate any bugs */
|
||||||
|
/* Fix up the DOS 2.5 boot sectors. */
|
||||||
|
/* * Adjust for DOS.SYS if it is there for DOS2.0/2.5. */
|
||||||
|
/* */
|
||||||
|
/* To-do after 1.0: */
|
||||||
|
/* Support for DOS2.0D?? (256-byte sectors without MyDOS) */
|
||||||
|
/* * Is it any different from 2.0S? */
|
||||||
|
/* Support for SpartaDOS */
|
||||||
|
/* * This will probably have to be coded by someone else, */
|
||||||
|
/* as I'm not terribly interested in it. */
|
||||||
|
/* Support for more MyDOS versions */
|
||||||
|
/* * Simply a matter of detecting the version and writing */
|
||||||
|
/* out the right boot sectors. */
|
||||||
|
/* */
|
||||||
|
/* Version History */
|
||||||
|
/* */
|
||||||
|
/* 14 Mar 98 Version 0.9 Preston Crow <crow@cs.dartmouth.edu> */
|
||||||
|
/* */
|
||||||
|
/* Auto detect MyDOS version and use correct boot sectors. */
|
||||||
|
/* This needs to be updated for additional versions; */
|
||||||
|
/* currently only 4.50 and 4.53 are supported. */
|
||||||
|
/* */
|
||||||
|
/* Fixed segfault with directories with > 64 files. */
|
||||||
|
/* */
|
||||||
|
/* Fixed a bug in the writing of file data--it's right now */
|
||||||
|
/* */
|
||||||
|
/* Cleaned up the MyDOS boot sector data. It may still */
|
||||||
|
/* be sensitive to different versions of MyDOS. */
|
||||||
|
/* */
|
||||||
|
/* 24 Feb 98 Version 0.8 Preston Crow <crow@cs.dartmouth.edu> */
|
||||||
|
/* Add '-s' option to skip the first 720 sectors. */
|
||||||
|
/* This is useful to protect against corruption from */
|
||||||
|
/* files that do raw sector I/O, and to save room to write */
|
||||||
|
/* the DOS files. */
|
||||||
|
/* Even with this flag, DOS.SYS will be written at sector 4 */
|
||||||
|
/* */
|
||||||
|
/* VTOC is now generated for DOS2.5 enhanced density images. */
|
||||||
|
/* */
|
||||||
|
/* Boot sectors are correct for MyDOS and DOS2.0/2.5, */
|
||||||
|
/* except that they aren't adjusted to reflect the disk */
|
||||||
|
/* parameters or the existence of DOS.SYS. */
|
||||||
|
/* */
|
||||||
|
/* DOS.SYS, DUP.SYS, and AUTORUN.SYS will be the first */
|
||||||
|
/* files written if they are found. */
|
||||||
|
/* */
|
||||||
|
/* Directory sorting is case-insensitive if '-u' is */
|
||||||
|
/* specified, so the resulting image has a sorted directory. */
|
||||||
|
/* */
|
||||||
|
/* 21 Feb 98 Version 0.7 Preston Crow <crow@cs.dartmouth.edu> */
|
||||||
|
/* Bug fix: ATR "sector" count is now correct. */
|
||||||
|
/* (Why did they use such a strange formula?) */
|
||||||
|
/* Initial writing of boot sector and VTOC. */
|
||||||
|
/* */
|
||||||
|
/* Still no support for extended DOS 2.5 VTOC. */
|
||||||
|
/* */
|
||||||
|
/* Should include file numbers for non-MyDOS disks. */
|
||||||
|
/* */
|
||||||
|
/* 7 Feb 98 Version 0.6 Preston Crow <crow@cs.dartmouth.edu> */
|
||||||
|
/* Bug fixes */
|
||||||
|
/* */
|
||||||
|
/* 7 Jun 95 Version 0.5 Preston Crow <crow@cs.dartmouth.edu> */
|
||||||
|
/* Mostly works except: */
|
||||||
|
/* MyDos format is the only one that works. */
|
||||||
|
/* bitmaps aren't written to the image */
|
||||||
|
/* boot sectors aren't created */
|
||||||
|
/* */
|
||||||
|
/************************************************************************/
|
||||||
|
|
||||||
|
/************************************************************************/
|
||||||
|
/* Include files */
|
||||||
|
/************************************************************************/
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <ctype.h>
|
||||||
|
#include <sys/types.h>
|
||||||
|
#include <sys/stat.h>
|
||||||
|
#include <sys/dir.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include <unistd.h>
|
||||||
|
|
||||||
|
/************************************************************************/
|
||||||
|
/* Macros and Constants */
|
||||||
|
/************************************************************************/
|
||||||
|
#define ATRHEAD 16
|
||||||
|
#define USAGE "unix2atr [-dumps] #sectors atarifile.atr [directory]\n Flags:\n\t-d Double density sectors\n\t-u Convert filenames to upper case\n\t-m MyDOS format disk image\n\t-s skip the first 720 sectors\n\t-p print debugging stuff\n"
|
||||||
|
/* SEEK: seek offset in the disk image file for a given sector number */
|
||||||
|
#define SEEK(n) (ATRHEAD + ((n<4)?((n-1)*128):(3*128+(n-4)*secsize)))
|
||||||
|
|
||||||
|
/************************************************************************/
|
||||||
|
/* Data types */
|
||||||
|
/************************************************************************/
|
||||||
|
struct atari_dirent {
|
||||||
|
unsigned char flag; /* set bits:
|
||||||
|
7->deleted
|
||||||
|
6->normal file
|
||||||
|
5->locked
|
||||||
|
4->MyDOS subdirectory
|
||||||
|
3->???
|
||||||
|
2->??? \ one for >720, one for >1024 ?
|
||||||
|
1->??? / all for MyDOS?
|
||||||
|
0->write open */
|
||||||
|
unsigned char countlo; /* Number of sectors in file */
|
||||||
|
unsigned char counthi;
|
||||||
|
unsigned char startlo; /* First sector in file */
|
||||||
|
unsigned char starthi;
|
||||||
|
char namelo[8];
|
||||||
|
char namehi[3];
|
||||||
|
};
|
||||||
|
|
||||||
|
struct atr_head {
|
||||||
|
unsigned char h0; /* 0x96 */
|
||||||
|
unsigned char h1; /* 0x02 */
|
||||||
|
unsigned char seccountlo;
|
||||||
|
unsigned char seccounthi;
|
||||||
|
unsigned char secsizelo;
|
||||||
|
unsigned char secsizehi;
|
||||||
|
unsigned char hiseccountlo;
|
||||||
|
unsigned char hiseccounthi;
|
||||||
|
unsigned char unused[8];
|
||||||
|
};
|
||||||
|
|
||||||
|
/************************************************************************/
|
||||||
|
/* Function Prototypes */
|
||||||
|
/************************************************************************/
|
||||||
|
void write_file(FILE *fin,int sector,int fileno); /* Write a file starting at the specified sector */
|
||||||
|
void write_dir(int sector); /* Write a directory */
|
||||||
|
void set_dos_version(char *fname); /* Determine which version of DOS.SYS it is */
|
||||||
|
int use_sector(void); /* Return a sector number that is free to use after marking it */
|
||||||
|
int use_8_sector(void); /* Get 8 sectors for a directory */
|
||||||
|
void write_boot(void); /* Write first 3 sectors */
|
||||||
|
void write_bitmaps(void); /* Write out the free bitmap */
|
||||||
|
int afnamecpy(char *an,const char *n);
|
||||||
|
|
||||||
|
/************************************************************************/
|
||||||
|
/* Global variables */
|
||||||
|
/************************************************************************/
|
||||||
|
int secsize;
|
||||||
|
int mydos=0;
|
||||||
|
int upcase=0;
|
||||||
|
int debug=0;
|
||||||
|
int seccount;
|
||||||
|
char bitmap[64*1024]; /* Free "bit" map */
|
||||||
|
int lastfree=4;
|
||||||
|
FILE *fout;
|
||||||
|
int rootdir; /* flag for sorting routine */
|
||||||
|
int dos=0; /* true if DOS.SYS is written */
|
||||||
|
int dosver=0; /* DOS.SYS version code */
|
||||||
|
|
||||||
|
/************************************************************************/
|
||||||
|
/* main() */
|
||||||
|
/* Process command line */
|
||||||
|
/* Open input .ATR file */
|
||||||
|
/* Interpret .ATR header */
|
||||||
|
/************************************************************************/
|
||||||
|
int main(int argc,char *argv[])
|
||||||
|
{
|
||||||
|
struct atr_head head;
|
||||||
|
int i;
|
||||||
|
unsigned char buf[256];
|
||||||
|
|
||||||
|
--argc; ++argv; /* Skip program name */
|
||||||
|
|
||||||
|
secsize=128;
|
||||||
|
/* Process flags */
|
||||||
|
while (argc) {
|
||||||
|
int done=0;
|
||||||
|
|
||||||
|
if (**argv=='-') {
|
||||||
|
++*argv;
|
||||||
|
while(**argv) {
|
||||||
|
switch(**argv) {
|
||||||
|
case 'd': /* DD */
|
||||||
|
secsize=256;
|
||||||
|
break;
|
||||||
|
case 'm': /* MyDos disk */
|
||||||
|
mydos=1;
|
||||||
|
break;
|
||||||
|
case '-': /* Last option */
|
||||||
|
done=1;
|
||||||
|
break;
|
||||||
|
case 'u': /* strupr names */
|
||||||
|
upcase=1;
|
||||||
|
break;
|
||||||
|
case 'p': /* debugging */
|
||||||
|
debug=1;
|
||||||
|
break;
|
||||||
|
case 's': /* skip early sectors */
|
||||||
|
lastfree=721;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
fprintf(stderr,USAGE);
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
++*argv;
|
||||||
|
}
|
||||||
|
--argc; ++argv;
|
||||||
|
}
|
||||||
|
else break;
|
||||||
|
if (done) break;
|
||||||
|
}
|
||||||
|
if (argc<2) {
|
||||||
|
fprintf(stderr,USAGE);
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Number of sectors */
|
||||||
|
seccount=atoi(*argv);
|
||||||
|
++argv;--argc;
|
||||||
|
if (seccount<368) {
|
||||||
|
fprintf(stderr,USAGE);
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
if ((seccount>1040||(seccount>720&&secsize==256))&&!mydos) {
|
||||||
|
fprintf(stderr,"Must use MyDos format if more than 1040 SD or 720 DD sectors\n");
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Open output file */
|
||||||
|
fout=fopen(*argv,"wb");
|
||||||
|
if (!fout) {
|
||||||
|
fprintf(stderr,"Unable to open %s\n%s",*argv,USAGE);
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
--argc; ++argv;
|
||||||
|
|
||||||
|
/* Change directories? */
|
||||||
|
if (argc) {
|
||||||
|
if (chdir(*argv)) {
|
||||||
|
fprintf(stderr,"Unable to change to directory: %s\n%s",*argv,USAGE);
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Initialize free sectors */
|
||||||
|
for(i=1;i<=seccount;++i) bitmap[i]=0;
|
||||||
|
for(i=seccount+1;i<64*1024;++i) bitmap[i]=1;
|
||||||
|
for(i=360;i<=368;++i) bitmap[i]=1;
|
||||||
|
for(i=0;i<=3;++i) bitmap[i]=1;
|
||||||
|
if (mydos) {
|
||||||
|
if (seccount>943+(secsize-128)*8) {
|
||||||
|
for(i=360-((seccount-943+(secsize*8-1))/(secsize*8));i<360;++i) bitmap[i]=1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
for(i=1024;i<=seccount;++i) {
|
||||||
|
bitmap[i]=0; /* Don't use sectors 1024 or above */
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (!mydos) bitmap[720]=1;
|
||||||
|
|
||||||
|
/* Initialize ATR header */
|
||||||
|
head.h0=0x96;
|
||||||
|
head.h1=0x02;
|
||||||
|
head.secsizelo=secsize&0xff;
|
||||||
|
head.secsizehi=secsize/0x100;
|
||||||
|
{
|
||||||
|
unsigned long paragraphs;
|
||||||
|
|
||||||
|
paragraphs=(seccount-3)*(secsize/16) + 3*128/16;
|
||||||
|
head.seccountlo=paragraphs&0xff;
|
||||||
|
head.seccounthi=(paragraphs>>8)&0xff;
|
||||||
|
head.hiseccountlo=(paragraphs>>16)&0xff;
|
||||||
|
head.hiseccounthi=(paragraphs>>24)&0xff;
|
||||||
|
}
|
||||||
|
bzero(head.unused,sizeof(head.unused));
|
||||||
|
|
||||||
|
fwrite(&head,sizeof(head),1,fout);
|
||||||
|
|
||||||
|
/* Initialize sectors */
|
||||||
|
if (debug)printf("Creating %d %d-byte sectors (%d byte file)\n",seccount,secsize,SEEK(seccount)+secsize);
|
||||||
|
for(i=0;i<256;++i)buf[i]=0;
|
||||||
|
fseek(fout,SEEK(1),SEEK_SET);
|
||||||
|
for(i=1;i<=3;++i) fwrite(buf,128,1,fout);
|
||||||
|
for(i=4;i<=seccount;++i) fwrite(buf,secsize,1,fout);
|
||||||
|
|
||||||
|
write_dir(361);
|
||||||
|
write_boot();
|
||||||
|
write_bitmaps();
|
||||||
|
return(0);
|
||||||
|
}
|
||||||
|
|
||||||
|
/************************************************************************/
|
||||||
|
/* write_file() */
|
||||||
|
/* Write a file starting at the specified sector */
|
||||||
|
/************************************************************************/
|
||||||
|
void write_file(FILE *fin,int sector,int fileno)
|
||||||
|
{
|
||||||
|
unsigned char buf[256];
|
||||||
|
int i;
|
||||||
|
int sc=1;
|
||||||
|
unsigned char c;
|
||||||
|
|
||||||
|
c=fgetc(fin);
|
||||||
|
while (!feof(fin)) {
|
||||||
|
int nsec=0;
|
||||||
|
bzero(buf,secsize);
|
||||||
|
if (!mydos) buf[secsize-3]=(fileno<<2);
|
||||||
|
for(i=0;i<secsize-3;++i) {
|
||||||
|
buf[i]=c;
|
||||||
|
++buf[secsize-1];
|
||||||
|
c=fgetc(fin);
|
||||||
|
if (feof(fin)) break;
|
||||||
|
}
|
||||||
|
/* Write the sector */
|
||||||
|
if (!feof(fin)) {
|
||||||
|
nsec=use_sector();
|
||||||
|
++sc;
|
||||||
|
buf[secsize-2]=nsec%256;
|
||||||
|
buf[secsize-3]+=nsec/256; /* add to fileno */
|
||||||
|
}
|
||||||
|
fseek(fout,SEEK(sector),SEEK_SET);
|
||||||
|
fwrite(buf,secsize,1,fout);
|
||||||
|
if (nsec && buf[secsize-1]!=secsize-3) {
|
||||||
|
printf("Something is very wrong!\n");
|
||||||
|
printf("sector: %d\n",sector);
|
||||||
|
printf("nsec: %d\n",nsec);
|
||||||
|
printf("bytes: %d\n",buf[secsize-1]);
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
if (debug && 0) printf("\t\t\tsector %d -> %d\n",sector,nsec);
|
||||||
|
sector=nsec;
|
||||||
|
}
|
||||||
|
if (debug) printf("\t\tFile written, %d sectors\n",sc);
|
||||||
|
}
|
||||||
|
|
||||||
|
/************************************************************************/
|
||||||
|
/* mydirsort() */
|
||||||
|
/* */
|
||||||
|
/* Compare two directory entries for use in sorting. */
|
||||||
|
/* Essentially alphabetical ordering, except for special files that */
|
||||||
|
/* go first: DOS.SYS, DUP.SYS, and AUTORUN.SYS. */
|
||||||
|
/* */
|
||||||
|
/* Note that MyDOS 4.53 seems to use '*AR0' instead of 'AUTORUN.SYS' */
|
||||||
|
/* as the auto-loaded menu program. I don't know why. */
|
||||||
|
/************************************************************************/
|
||||||
|
int mydirsort(const struct dirent *const*a,const struct dirent *const*b)
|
||||||
|
{
|
||||||
|
char an[12],bn[12];
|
||||||
|
|
||||||
|
/* If the filename isn't valid for Atari, it's order doesn't matter */
|
||||||
|
if (!afnamecpy(an,(*a)->d_name)) return(0);
|
||||||
|
if (!afnamecpy(bn,(*b)->d_name)) return(0);
|
||||||
|
|
||||||
|
/* Place certain files first in the root directory */
|
||||||
|
if (rootdir) {
|
||||||
|
if (strcmp(an,"DOS SYS")==0) return(-1);
|
||||||
|
if (strcmp(bn,"DOS SYS")==0) return( 1);
|
||||||
|
if (strcmp(an,"DUP SYS")==0) return(-1);
|
||||||
|
if (strcmp(bn,"DUP SYS")==0) return( 1);
|
||||||
|
if (strcmp(an,"AUTORUN SYS")==0) return(-1);
|
||||||
|
if (strcmp(bn,"AUTORUN SYS")==0) return( 1);
|
||||||
|
if (strcmp(an,"AUTORUN AR0")==0) return(-1);
|
||||||
|
if (strcmp(bn,"AUTORUN AR0")==0) return( 1);
|
||||||
|
#if 1 /* force some reordering to make me happy */
|
||||||
|
if (strcmp(an,"FILES LST")==0) return(-1);
|
||||||
|
if (strcmp(bn,"FILES LST")==0) return( 1);
|
||||||
|
if (strcmp(an+2,bn+2)==0) return(strcmp(an,bn));
|
||||||
|
if (strcmp(an+2," ")==0) return( 1);
|
||||||
|
if (strcmp(bn+2," ")==0) return(-1);
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Compare the converted filenames */
|
||||||
|
return(strcmp(an,bn));
|
||||||
|
}
|
||||||
|
|
||||||
|
/************************************************************************/
|
||||||
|
/* write_dir() */
|
||||||
|
/************************************************************************/
|
||||||
|
#define SENTRY(n) (secsize==128?n:(n/8)*8+n)
|
||||||
|
void write_dir(int sector)
|
||||||
|
{
|
||||||
|
struct direct **d;
|
||||||
|
int used;
|
||||||
|
int i;
|
||||||
|
int e;
|
||||||
|
int count;
|
||||||
|
int start;
|
||||||
|
char aname[12];
|
||||||
|
struct atari_dirent dir[128]; /* 64 + 64 DD wasted space */
|
||||||
|
int lastfreesave=0;
|
||||||
|
|
||||||
|
aname[11]=0;
|
||||||
|
for(i=0;i<8*256;++i) ((char *)dir)[i]=0;
|
||||||
|
|
||||||
|
rootdir=(sector==361);
|
||||||
|
i=scandir(".",&d,NULL,mydirsort);
|
||||||
|
used=0;
|
||||||
|
while (i) {
|
||||||
|
/* Process **d */
|
||||||
|
do {
|
||||||
|
struct stat sbuf;
|
||||||
|
int subdir;
|
||||||
|
|
||||||
|
/* Hidden files--ignore silently */
|
||||||
|
if ((*d)->d_name[0]=='.') break;
|
||||||
|
|
||||||
|
if (lastfreesave) {
|
||||||
|
lastfree=lastfreesave;
|
||||||
|
lastfreesave=0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Convert name */
|
||||||
|
if (!afnamecpy(aname,(*d)->d_name)) {
|
||||||
|
printf("Warning: %s: Can't convert to Atari name\n",(*d)->d_name);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* If it's DOS.SYS, start at sector 4, even if we're reserving the first 720 sectors */
|
||||||
|
if (rootdir) {
|
||||||
|
if (strcmp(aname,"DOS SYS")==0) {
|
||||||
|
set_dos_version((*d)->d_name);
|
||||||
|
}
|
||||||
|
if (
|
||||||
|
strcmp(aname,"DOS SYS")==0 ||
|
||||||
|
strcmp(aname,"DUP SYS")==0 ||
|
||||||
|
strcmp(aname,"AUTORUN SYS")==0
|
||||||
|
) {
|
||||||
|
lastfreesave=lastfree;
|
||||||
|
lastfree=3;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Determine if it's a file or directory */
|
||||||
|
if (stat((*d)->d_name,&sbuf)) {
|
||||||
|
printf("Warning: %s: Can't stat file\n",(*d)->d_name);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
subdir=0;
|
||||||
|
if (!sbuf.st_mode&(S_IFDIR|S_IFREG)) {
|
||||||
|
printf("Warning: %s: Not a normal file or directory\n",(*d)->d_name);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (sbuf.st_mode&S_IFDIR) subdir=1;
|
||||||
|
if (subdir && !mydos) {
|
||||||
|
printf("Warning: %s/: Can't process subdirectory for standard Atari images\n",(*d)->d_name);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Create the entry */
|
||||||
|
e=SENTRY(used);
|
||||||
|
if (used>63) {
|
||||||
|
printf("Warning: More than 64 files in this directory\n");
|
||||||
|
printf(" Additional files or subdirectories ignored\n");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
strcpy(dir[e].namelo,aname);
|
||||||
|
if (subdir) {
|
||||||
|
dir[e].flag=16;
|
||||||
|
count=8;
|
||||||
|
start=use_8_sector();
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
dir[e].flag=0x46;
|
||||||
|
if (!sbuf.st_mode&0000200) dir[e].flag &=32; /* locked */
|
||||||
|
count=(sbuf.st_size+(secsize-3)-1)/(secsize-3);
|
||||||
|
start=use_sector();
|
||||||
|
}
|
||||||
|
dir[e].countlo=count&0xff;
|
||||||
|
dir[e].counthi=count/0x100;
|
||||||
|
dir[e].startlo=start&0xff;
|
||||||
|
dir[e].starthi=start/0x100;
|
||||||
|
|
||||||
|
/* Write the directory sector */
|
||||||
|
fseek(fout,SEEK(sector),SEEK_SET);
|
||||||
|
fwrite(dir,secsize,8,fout);
|
||||||
|
++used;
|
||||||
|
|
||||||
|
/* Write the file/subdir */
|
||||||
|
if (!subdir) {
|
||||||
|
FILE *fin;
|
||||||
|
|
||||||
|
fin=fopen((*d)->d_name,"rb");
|
||||||
|
if (!fin) {
|
||||||
|
printf("Warning: %s: Can't open file\n",(*d)->d_name);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
if (debug) printf("\tWriting file %s starting at sector %d\n",(*d)->d_name,start);
|
||||||
|
write_file(fin,start,used-1);
|
||||||
|
fclose(fin);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
if (debug) printf("\tWriting directory %s\n",(*d)->d_name);
|
||||||
|
if (chdir((*d)->d_name)) {
|
||||||
|
fprintf(stderr,"Unable to change to directory: %s\n",(*d)->d_name);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
write_dir(start);
|
||||||
|
chdir("..");
|
||||||
|
}
|
||||||
|
} while(0); /* for break */
|
||||||
|
free(*d);
|
||||||
|
++d;--i;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/************************************************************************/
|
||||||
|
/* set_dos_version() */
|
||||||
|
/* Read the first K of dos.sys and make an educated guess as to which */
|
||||||
|
/* version it is. */
|
||||||
|
/************************************************************************/
|
||||||
|
void set_dos_version(char *fname)
|
||||||
|
{
|
||||||
|
FILE *dosfile;
|
||||||
|
unsigned char buf[1024];
|
||||||
|
|
||||||
|
dosfile=fopen(fname,"rb");
|
||||||
|
if (!dosfile) return;
|
||||||
|
fread(buf,1,1024,dosfile);
|
||||||
|
fclose(dosfile);
|
||||||
|
if (buf[18]==0x08) dosver=450; /* MyDOS 4.50 */
|
||||||
|
if (buf[18]==0xFD) dosver=453; /* MyDOS 4.53/4 */
|
||||||
|
if (dosver==0) {
|
||||||
|
printf("Warning: Unable to determine DOS.SYS version\n");
|
||||||
|
}
|
||||||
|
dos=1;
|
||||||
|
}
|
||||||
|
|
||||||
|
/************************************************************************/
|
||||||
|
/* use_sector() */
|
||||||
|
/* Return a sector number that is free to use after marking it used. */
|
||||||
|
/************************************************************************/
|
||||||
|
int use_sector(void)
|
||||||
|
{
|
||||||
|
while (lastfree<=seccount&&bitmap[lastfree]) ++lastfree;
|
||||||
|
|
||||||
|
|
||||||
|
if (lastfree>seccount) {
|
||||||
|
fprintf(stderr,"Disk image full\n");
|
||||||
|
write_bitmaps();
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
bitmap[lastfree]=1;
|
||||||
|
return(lastfree);
|
||||||
|
}
|
||||||
|
|
||||||
|
/************************************************************************/
|
||||||
|
/* use_8_sector() */
|
||||||
|
/* Get 8 consecutive sectors for a directory */
|
||||||
|
/************************************************************************/
|
||||||
|
int use_8_sector(void)
|
||||||
|
{
|
||||||
|
int i=lastfree;
|
||||||
|
int j;
|
||||||
|
|
||||||
|
while ((bitmap[i+0]||bitmap[i+1]||bitmap[i+2]||bitmap[i+3]||
|
||||||
|
bitmap[i+4]||bitmap[i+5]||bitmap[i+6]||bitmap[i+7])
|
||||||
|
&& i+7<64*1024) ++i;
|
||||||
|
if (i+7<64*1024) {
|
||||||
|
for (j=0;j<8;++j) bitmap[i+j]=1;
|
||||||
|
return(i);
|
||||||
|
}
|
||||||
|
fprintf(stderr,"Disk image full--no room for directory\n");
|
||||||
|
write_bitmaps();
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
/************************************************************************/
|
||||||
|
/* write_boot() */
|
||||||
|
/* Write out the first 3 sectors */
|
||||||
|
/************************************************************************/
|
||||||
|
void write_boot(void)
|
||||||
|
{
|
||||||
|
/*
|
||||||
|
* Sectors 1 through 3
|
||||||
|
*
|
||||||
|
* Copied from a blank 720-sector DOS2.0S-formatted disk
|
||||||
|
* DOS2.5 generates the same data for 720- and 1040-sector disks.
|
||||||
|
*
|
||||||
|
* Writing DOS files may change some bytes, but I haven't checked
|
||||||
|
* to see which bytes change.
|
||||||
|
*/
|
||||||
|
char dos20init[128*3]={
|
||||||
|
0x00,0x03,0x00,0x07,0x40,0x15,0x4c,0x14,0x07,0x03,0x03,0x00,0x7c,0x1a,0x00,0x04,
|
||||||
|
0x00,0x7d,0xcb,0x07,0xac,0x0e,0x07,0xf0,0x36,0xad,0x12,0x07,0x85,0x43,0x8d,0x04,
|
||||||
|
0x03,0xad,0x13,0x07,0x85,0x44,0x8d,0x05,0x03,0xad,0x10,0x07,0xac,0x0f,0x07,0x18,
|
||||||
|
0xae,0x0e,0x07,0x20,0x6c,0x07,0x30,0x17,0xac,0x11,0x07,0xb1,0x43,0x29,0x03,0x48,
|
||||||
|
0xc8,0x11,0x43,0xf0,0x0e,0xb1,0x43,0xa8,0x20,0x57,0x07,0x68,0x4c,0x2f,0x07,0xa9,
|
||||||
|
0xc0,0xd0,0x01,0x68,0x0a,0xa8,0x60,0x18,0xa5,0x43,0x6d,0x11,0x07,0x8d,0x04,0x03,
|
||||||
|
0x85,0x43,0xa5,0x44,0x69,0x00,0x8d,0x05,0x03,0x85,0x44,0x60,0x8d,0x0b,0x03,0x8c,
|
||||||
|
0x0a,0x03,0xa9,0x52,0xa0,0x40,0x90,0x04,0xa9,0x57,0xa0,0x80,0x8d,0x02,0x03,0x8c,
|
||||||
|
0x03,0x03,0xa9,0x31,0xa0,0x0f,0x8d,0x00,0x03,0x8c,0x06,0x03,0xa9,0x03,0x8d,0xff,
|
||||||
|
0x12,0xa9,0x00,0xa0,0x80,0xca,0xf0,0x04,0xa9,0x01,0xa0,0x00,0x8d,0x09,0x03,0x8c,
|
||||||
|
0x08,0x03,0x20,0x59,0xe4,0x10,0x1d,0xce,0xff,0x12,0x30,0x18,0xa2,0x40,0xa9,0x52,
|
||||||
|
0xcd,0x02,0x03,0xf0,0x09,0xa9,0x21,0xcd,0x02,0x03,0xf0,0x02,0xa2,0x80,0x8e,0x03,
|
||||||
|
0x03,0x4c,0xa2,0x07,0xae,0x01,0x13,0xad,0x03,0x03,0x60,0xaa,0x08,0x14,0x0b,0xbe,
|
||||||
|
0x0a,0xcb,0x09,0x00,0x0b,0xa6,0x0b,0x07,0x85,0x44,0xad,0x0a,0x07,0x8d,0xd6,0x12,
|
||||||
|
0xad,0x0c,0x07,0x85,0x43,0xad,0x0d,0x07,0x85,0x44,0xad,0x0a,0x07,0x8d,0x0c,0x13,
|
||||||
|
0xa2,0x07,0x8e,0x0d,0x13,0x0e,0x0c,0x13,0xb0,0x0d,0xa9,0x00,0x9d,0x11,0x13,0x9d,
|
||||||
|
0x29,0x13,0x9d,0x31,0x13,0xf0,0x36,0xa0,0x05,0xa9,0x00,0x91,0x43,0xe8,0x8e,0x01,
|
||||||
|
0x03,0xa9,0x53,0x8d,0x02,0x03,0x20,0x53,0xe4,0xa0,0x02,0xad,0xea,0x02,0x29,0x20,
|
||||||
|
0xd0,0x01,0x88,0x98,0xae,0x0d,0x13,0x9d,0x11,0x13,0xa5,0x43,0x9d,0x29,0x13,0xa5,
|
||||||
|
0x44,0x9d,0x31,0x13,0x20,0x70,0x08,0x88,0xf0,0x03,0x20,0x70,0x08,0xca,0x10,0xb2,
|
||||||
|
0xac,0x09,0x07,0xa2,0x00,0xa9,0x00,0x88,0x10,0x01,0x98,0x9d,0x19,0x13,0x98,0x30,
|
||||||
|
0x0d,0xa5,0x43,0x9d,0x39,0x13,0xa5,0x44,0x9d,0x49,0x13,0x20,0x70,0x08,0xe8,0xe0,
|
||||||
|
0x10,0xd0,0xe2,0xa5,0x43,0x8d,0xe7,0x02,0xa5,0x44,0x8d,0xe8,0x02,0x4c,0x7e,0x08,
|
||||||
|
0x18,0xa5,0x43,0x69,0x80,0x85,0x43,0xa5,0x44,0x69,0x00,0x85,0x44,0x60,0xa0,0x7f
|
||||||
|
};
|
||||||
|
/*
|
||||||
|
* Sectors 1 through 3
|
||||||
|
*
|
||||||
|
* Rick D. <rldetlefsen@delphi.com> reported:
|
||||||
|
> MYDOS will store the same info in the boot sector as any other DOS. This is
|
||||||
|
> because the OS must use it to locate and load DOS into ram.
|
||||||
|
> Sector 1, byte offset 0-19 hold the useful info. b14=1=DOS;=0=No DOS,
|
||||||
|
> B15 & 16=sector to start of DOS, B18 & B19=DOS load address, B9= #file buffers,
|
||||||
|
> B10=drive bits, and B17=Disp to sector link(effectivly, disk density). The
|
||||||
|
> rest of the stuff is either in DOS(ramdisk config), or Mydos guese, i.e. >720
|
||||||
|
> sectors, or double sided.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
char mydosinit453[3*128]={
|
||||||
|
0x4d,0x03,0x00,0x07,0xe0,0x07,0x4c,0x14,0x07,0x03,0x09,0x01,0xe8,0x1b,0x02,0x04
|
||||||
|
,0x00,0xfd,0x0a,0x0b,0xac,0x12,0x07,0xad,0x13,0x07,0x20,0x58,0x07,0xad,0x10,0x07
|
||||||
|
,0xac,0x0f,0x07,0x18,0xae,0x0e,0x07,0xf0,0x1d,0x20,0x63,0x07,0x30,0x18,0xac,0x11
|
||||||
|
,0x07,0xb1,0x43,0x29,0xff,0x48,0xc8,0x11,0x43,0xf0,0x0e,0xb1,0x43,0x48,0x20,0x4d
|
||||||
|
,0x07,0x68,0xa8,0x68,0x90,0xdd,0xa9,0xc0,0xa0,0x68,0x0a,0xa8,0x60,0xad,0x11,0x07
|
||||||
|
,0x18,0x65,0x43,0xa8,0xa5,0x44,0x69,0x00,0x84,0x43,0x85,0x44,0x8c,0x04,0x03,0x8d
|
||||||
|
,0x05,0x03,0x60,0x8d,0x0b,0x03,0x8c,0x0a,0x03,0xa0,0x03,0xa9,0x52,0x90,0x02,0xa9
|
||||||
|
,0x50,0x84,0x48,0x8d,0x02,0x03,0x18,0x8c,0x06,0x03,0xa9,0x80,0xca,0xf0,0x0d,0xae
|
||||||
|
,0x0b,0x03,0xd0,0x07,0xae,0x0a,0x03,0xe0,0x04,0x90,0x01,0x0a,0x8d,0x08,0x03,0x2a
|
||||||
|
,0x8d,0x09,0x03,0xa0,0x31,0x8c,0x00,0x03,0xc6,0x48,0x30,0x16,0xae,0x02,0x03,0xe8
|
||||||
|
,0x8a,0xa2,0x40,0x29,0x06,0xd0,0x02,0xa2,0x80,0x8e,0x03,0x03,0x20,0x59,0xe4,0x88
|
||||||
|
,0x30,0xe6,0xa6,0x2e,0xc8,0x98,0x60,0x10,0x69,0x01,0x00,0x80,0xf6,0x00,0x00,0x00
|
||||||
|
,0x23,0x28,0x50,0x4d,0x02,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x12,0x52,0xd2,0xd2
|
||||||
|
,0xd2,0xd2,0xd2,0xd2,0x5c,0x0c,0x5c,0x0e,0x62,0x0d,0xc6,0x0d,0x50,0x0e,0x67,0x10
|
||||||
|
,0xa9,0x69,0x8d,0xb8,0x07,0xa9,0x01,0x8d,0xb9,0x07,0xa2,0x08,0x8e,0x01,0x03,0x20
|
||||||
|
,0xb6,0x0b,0xbd,0xcb,0x07,0x30,0x12,0x20,0x9a,0x0b,0xf0,0x0d,0xbd,0xcb,0x07,0xc9
|
||||||
|
,0x40,0xb0,0x06,0xbc,0xc3,0x07,0x20,0x24,0x0b,0xca,0xd0,0xe0,0xa0,0xae,0x8a,0x99
|
||||||
|
,0x55,0x08,0x88,0xd0,0xfa,0xee,0x59,0x08,0xad,0x0c,0x07,0x8d,0xe7,0x02,0xac,0x0d
|
||||||
|
,0x07,0xa2,0x0f,0xec,0x09,0x07,0x90,0x05,0xde,0xdd,0x08,0x30,0x05,0x98,0x9d,0xed
|
||||||
|
,0x08,0xc8,0xca,0x10,0xee,0x8c,0xe8,0x02,0xe8,0xe8,0xe8,0xbd,0x18,0x03,0xf0,0x04
|
||||||
|
,0xc9,0x44,0xd0,0xf4,0xa9,0x44,0x9d,0x18,0x03,0xa9,0xd4,0x9d,0x19,0x03,0xa9,0x07
|
||||||
|
,0x9d,0x1a,0x03,0x4c,0x79,0x1a,0x00,0x00,0xff,0x01,0x00,0x00,0x00,0x00,0x00,0x00
|
||||||
|
,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xc8,0x80
|
||||||
|
,0xfd,0x00,0x03,0x04,0x00,0x00,0x00,0x00,0x00,0x69,0x01,0x00,0x00,0x00,0x00,0x00
|
||||||
|
};
|
||||||
|
char mydosinit450[3*128]={
|
||||||
|
0x4d,0x03,0x00,0x07,0xe0,0x07,0x4c,0x14,0x07,0x03,0xff,0x01,0xe9,0x1b,0x02,0x04
|
||||||
|
,0x00,0xfd,0x15,0x0b,0xac,0x12,0x07,0xad,0x13,0x07,0x20,0x58,0x07,0xad,0x10,0x07
|
||||||
|
,0xac,0x0f,0x07,0x18,0xae,0x0e,0x07,0xf0,0x1d,0x20,0x63,0x07,0x30,0x18,0xac,0x11
|
||||||
|
,0x07,0xb1,0x43,0x29,0xff,0x48,0xc8,0x11,0x43,0xf0,0x0e,0xb1,0x43,0x48,0x20,0x4d
|
||||||
|
,0x07,0x68,0xa8,0x68,0x90,0xdd,0xa9,0xc0,0xa0,0x68,0x0a,0xa8,0x60,0xad,0x11,0x07
|
||||||
|
,0x18,0x65,0x43,0xa8,0xa5,0x44,0x69,0x00,0x84,0x43,0x85,0x44,0x8c,0x04,0x03,0x8d
|
||||||
|
,0x05,0x03,0x60,0x8d,0x0b,0x03,0x8c,0x0a,0x03,0xa0,0x03,0xa9,0x52,0x90,0x03,0xad
|
||||||
|
,0x79,0x07,0x84,0x48,0x8d,0x02,0x03,0x18,0xa9,0x57,0x8c,0x06,0x03,0xa9,0x80,0xca
|
||||||
|
,0xf0,0x0d,0xae,0x0b,0x03,0xd0,0x07,0xae,0x0a,0x03,0xe0,0x04,0x90,0x01,0x0a,0x8d
|
||||||
|
,0x08,0x03,0x2a,0x8d,0x09,0x03,0xa0,0x31,0x8c,0x00,0x03,0xc6,0x48,0x30,0x16,0xae
|
||||||
|
,0x02,0x03,0xe8,0x8a,0xa2,0x40,0x29,0x06,0xd0,0x02,0xa2,0x80,0x8e,0x03,0x03,0x20
|
||||||
|
,0x59,0xe4,0x88,0x30,0xe6,0xa6,0x2e,0xc8,0x98,0x60,0x10,0x71,0x01,0x00,0x80,0xf6
|
||||||
|
,0x23,0x28,0x50,0x4d,0x01,0x02,0x00,0x00,0x00,0x00,0x00,0x00,0x52,0x12,0xd2,0xd2
|
||||||
|
,0xd2,0xd2,0xd2,0xd2,0x5c,0x0c,0x5c,0x0e,0x62,0x0d,0xc6,0x0d,0x50,0x0e,0x67,0x10
|
||||||
|
,0xa9,0x69,0x8d,0xbb,0x07,0xa9,0x01,0x8d,0xbc,0x07,0xa2,0x08,0x8e,0x01,0x03,0x20
|
||||||
|
,0xb6,0x0b,0xbd,0xcb,0x07,0x30,0x1d,0x20,0x9a,0x0b,0xf0,0x18,0xa0,0x09,0xb9,0x25
|
||||||
|
,0x0b,0x99,0x02,0x03,0x88,0x10,0xf7,0xbd,0xcb,0x07,0xc9,0x40,0xb0,0x06,0xbc,0xc3
|
||||||
|
,0x07,0x20,0x2f,0x0b,0xca,0xd0,0xd5,0xa0,0xae,0x8a,0x99,0x60,0x08,0x88,0xd0,0xfa
|
||||||
|
,0xee,0x64,0x08,0xad,0x0c,0x07,0x8d,0xe7,0x02,0xac,0x0d,0x07,0xa2,0x0f,0xec,0x09
|
||||||
|
,0x07,0x90,0x05,0xde,0xe8,0x08,0x30,0x05,0x98,0x9d,0xf8,0x08,0xc8,0xca,0x10,0xee
|
||||||
|
,0x8c,0xe8,0x02,0xe8,0xe8,0xe8,0xbd,0x18,0x03,0xf0,0x04,0xc9,0x44,0xd0,0xf4,0xa9
|
||||||
|
,0x44,0x9d,0x18,0x03,0xa9,0xd4,0x9d,0x19,0x03,0xa9,0x07,0x9d,0x1a,0x03,0x4c,0x8c
|
||||||
|
,0x1a,0x00,0x00,0xff,0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00
|
||||||
|
,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xc8,0x80,0xfd,0x00,0x03,0x04,0x00
|
||||||
|
};
|
||||||
|
char *mydosinit;
|
||||||
|
|
||||||
|
if (debug && mydos) {
|
||||||
|
printf("Mydos version: %d\n",dosver);
|
||||||
|
}
|
||||||
|
switch (dosver) {
|
||||||
|
case 450:
|
||||||
|
mydosinit=mydosinit450;
|
||||||
|
break;
|
||||||
|
case 453:
|
||||||
|
mydosinit=mydosinit453;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
mydosinit=mydosinit450;
|
||||||
|
if (mydos && dos) {
|
||||||
|
printf("Warning: Failed to detect MyDOS version, may not boot\n");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
mydosinit[0]='M'; /* Indicate MyDOS 4.5 or later */
|
||||||
|
mydosinit[1]=3; /* number of sectors in the boot */
|
||||||
|
mydosinit[9]=3; /* Max number of open files at one time */
|
||||||
|
mydosinit450[10]=255; /* Ram Disk unit number */
|
||||||
|
mydosinit453[10]=9; /* Ram Disk unit number */
|
||||||
|
mydosinit[11]=1; /* Default unit number (D:) */
|
||||||
|
/* [12],[13]: First byte of free memory */
|
||||||
|
mydosinit[14]=((secsize==256)?2:1);
|
||||||
|
mydosinit[15]=4;mydosinit[16]=0; /* DOS.SYS start sector */
|
||||||
|
mydosinit[17]=secsize-3; /* Offset to the sector link field */
|
||||||
|
/* [18],[19]: Address to load dos.sys into */
|
||||||
|
if (dos) {
|
||||||
|
mydosinit450[18]=21;
|
||||||
|
mydosinit453[18]=10;
|
||||||
|
}
|
||||||
|
/*
|
||||||
|
* The following seemed to be correct based on experimentation:
|
||||||
|
*/
|
||||||
|
mydosinit453[196]=((secsize==256)?2:1);
|
||||||
|
mydosinit453[368]=secsize-3;
|
||||||
|
|
||||||
|
fseek(fout,SEEK(1),SEEK_SET);
|
||||||
|
fwrite(mydos?mydosinit:dos20init,128,3,fout);
|
||||||
|
}
|
||||||
|
|
||||||
|
/************************************************************************/
|
||||||
|
/* write_bitmaps() */
|
||||||
|
/* Write out the free bitmap (VTOC) */
|
||||||
|
/* I'm a bit clueless on much of this, but it tries to do what I've */
|
||||||
|
/* observed from real disk images. */
|
||||||
|
/************************************************************************/
|
||||||
|
void write_bitmaps(void)
|
||||||
|
{
|
||||||
|
char sec360[256] /******** ={
|
||||||
|
0x02,0xc3,0x02,0xc3,0x02,0x00,0x00,0x00,0x00,0x00,0x0f,0xff,0xff,0xff,0xff,0xff,
|
||||||
|
0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
|
||||||
|
0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
|
||||||
|
0xff,0xff,0xff,0xff,0xff,0xff,0xff,0x00,0x7f,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
|
||||||
|
0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
|
||||||
|
0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
|
||||||
|
0xff,0xff,0xff,0xff,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
|
||||||
|
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00
|
||||||
|
}********/;
|
||||||
|
int i;
|
||||||
|
int byte,bit;
|
||||||
|
int free;
|
||||||
|
|
||||||
|
for(i=0;i<256;++i)sec360[i]=0;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* We need to clean up the computation of total data sectors.
|
||||||
|
*
|
||||||
|
* For non-MyDos>720, we need to take into account the second VTOC
|
||||||
|
* For MyDos, we need to count 720, but not additional VTOC sectors.
|
||||||
|
*/
|
||||||
|
{
|
||||||
|
int total;
|
||||||
|
|
||||||
|
total=seccount-3-9-1; /* Boot, VTOC+DIR, 720 */
|
||||||
|
|
||||||
|
if (mydos) {
|
||||||
|
total=seccount-3-8; /* boot and dir */
|
||||||
|
total-=(1+(seccount-(943+(secsize-128)*8)+(secsize*8-1))/(secsize*8)); /* VTOC */
|
||||||
|
}
|
||||||
|
else if (seccount>720) {
|
||||||
|
if (total>1023-3-8-1-1) total=1023-3-8-1-1;
|
||||||
|
}
|
||||||
|
sec360[2]=(total)/256;
|
||||||
|
sec360[1]=(total)%256;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Record the number of free sectors
|
||||||
|
* For DOS2.5, this is the number of free sectors in this VTOC.
|
||||||
|
*/
|
||||||
|
free=0;
|
||||||
|
for(i=0;i<=(mydos?seccount:720);++i) {
|
||||||
|
if (bitmap[i]==0) ++free;
|
||||||
|
}
|
||||||
|
sec360[4]=free/256;
|
||||||
|
sec360[3]=free%256;
|
||||||
|
if (debug) {
|
||||||
|
printf("%d sectors %sfree\n",free,mydos?"":"<720 ");
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* I'm clueless--is this some sort of version code?
|
||||||
|
* I think this agrees with how MyDOS and DOS2.5 set this byte.
|
||||||
|
*/
|
||||||
|
sec360[0]=2;
|
||||||
|
if (mydos && seccount>943) sec360[0]+=(seccount-943+(secsize*8-1))/(secsize*8)+1;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* bitmap[i] is true if the sector has been used
|
||||||
|
*
|
||||||
|
* The corresponding bit should be one if the sector is *free*
|
||||||
|
*/
|
||||||
|
if (!mydos) {
|
||||||
|
for(i=0;i<720;++i) {
|
||||||
|
byte=10+i/8;
|
||||||
|
bit=i%8;
|
||||||
|
bit=7-bit;
|
||||||
|
bit=1<<bit;
|
||||||
|
if(bitmap[i]) {
|
||||||
|
sec360[byte]&= ~bit;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
sec360[byte]|=bit;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Write sector 360 */
|
||||||
|
fseek(fout,SEEK(360),SEEK_SET);
|
||||||
|
fwrite(sec360,128,1,fout);
|
||||||
|
|
||||||
|
if(seccount>720) {
|
||||||
|
/* Copy most of first VTOC */
|
||||||
|
for(i=0;i<128-16;++i)sec360[i]=sec360[i+16];
|
||||||
|
|
||||||
|
free=0;
|
||||||
|
for(i=720;i<1024;++i) {
|
||||||
|
byte=i/8-6;
|
||||||
|
bit=i%8;
|
||||||
|
bit=7-bit;
|
||||||
|
bit=1<<bit;
|
||||||
|
if(bitmap[i]) {
|
||||||
|
sec360[byte]&= ~bit;
|
||||||
|
++free;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
sec360[byte]|=bit;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Record number of free extended sectors */
|
||||||
|
sec360[123]=free/256;
|
||||||
|
sec360[122]=free%256;
|
||||||
|
|
||||||
|
fseek(fout,SEEK(1024),SEEK_SET);
|
||||||
|
fwrite(sec360,128,1,fout);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
for(i=0;i<=943;++i) {
|
||||||
|
byte=10+i/8;
|
||||||
|
bit=i%8;
|
||||||
|
bit=7-bit;
|
||||||
|
bit=1<<bit;
|
||||||
|
if(bitmap[i]) {
|
||||||
|
sec360[byte]&= ~bit;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
sec360[byte]|=bit;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Write sector 360 */
|
||||||
|
fseek(fout,SEEK(360),SEEK_SET);
|
||||||
|
fwrite(sec360,128,1,fout);
|
||||||
|
|
||||||
|
if(seccount>943) {
|
||||||
|
int ss;
|
||||||
|
int sn=359;
|
||||||
|
for(ss=944;ss<=seccount;ss+=8*128,--sn) {
|
||||||
|
for(i=0;i<128;++i)sec360[i]=0;
|
||||||
|
for(i=0;i<8*128;++i) {
|
||||||
|
byte=i/8;
|
||||||
|
bit=i%8;
|
||||||
|
bit=7-bit;
|
||||||
|
bit=1<<bit;
|
||||||
|
if(bitmap[i+ss]) {
|
||||||
|
sec360[byte]&= ~bit;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
sec360[byte]|=bit;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
/* Write sector */
|
||||||
|
{
|
||||||
|
int s,o;
|
||||||
|
if (secsize==128) {
|
||||||
|
s=sn;
|
||||||
|
o=0;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
/*
|
||||||
|
* Hack for DD sectors
|
||||||
|
*/
|
||||||
|
s=360-sn;
|
||||||
|
o=(s&1)*128;
|
||||||
|
s=s/2;
|
||||||
|
s=360-s;
|
||||||
|
}
|
||||||
|
fseek(fout,SEEK(s)+o,SEEK_SET);
|
||||||
|
fwrite(sec360,128,1,fout);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/************************************************************************/
|
||||||
|
/* afnamecpy() */
|
||||||
|
/* Convert a Unix filename to an Atari filename. */
|
||||||
|
/* Return 0 on failure. */
|
||||||
|
/************************************************************************/
|
||||||
|
int afnamecpy(char *an,const char *n)
|
||||||
|
{
|
||||||
|
int i;
|
||||||
|
for(i=0;i<11;++i) an[i]=' '; /* Space fill the Atari name */
|
||||||
|
an[11]=0;
|
||||||
|
for(i=0;i<8;++i) {
|
||||||
|
if (!*n) return(1); /* Ok */
|
||||||
|
if (*n=='.') break; /* Extension */
|
||||||
|
if (*n==':') return(0); /* Illegal name */
|
||||||
|
if (upcase) an[i]=toupper(*n);
|
||||||
|
else an[i]= *n;
|
||||||
|
++n;
|
||||||
|
}
|
||||||
|
if (*n=='.') ++n;
|
||||||
|
for(i=8;i<11;++i) {
|
||||||
|
if (!*n) return(1); /* Ok */
|
||||||
|
if (*n=='.') return(0); /* Illegal name */
|
||||||
|
if (*n==':') return(0); /* Illegal name */
|
||||||
|
if (upcase) an[i]=toupper(*n);
|
||||||
|
else an[i]= *n;
|
||||||
|
++n;
|
||||||
|
}
|
||||||
|
if (*n) return(0); /* Extension too long or more than 11 characters */
|
||||||
|
return(1);
|
||||||
|
}
|
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
|
@ -0,0 +1,57 @@
|
||||||
|
51 REM ATARI RAM TEST PROGRAM
|
||||||
|
52 REM BY ED STEWART 03/82
|
||||||
|
53 REM 11025 SAGEBRUSH AVE
|
||||||
|
54 REM UNIONTOWN OHIO 44685
|
||||||
|
99 REM SETUP SOME REQUIRED CONSTANTS
|
||||||
|
100 N1 = 1 : N2 = N1 + N1 : N255 = 255 : N256 = N255 + N1
|
||||||
|
200 DIM S$(N2) : S$(N1, N1) = CHR$(157) : S$(N2, N2) = CHR$(159)
|
||||||
|
299 REM READ IN THE MACHINE LANGUAGE PROGRAM
|
||||||
|
300 GOSUB 2900
|
||||||
|
399 REM GET LOW AND HIGH MEMORY BOUNDS
|
||||||
|
400 L = PEEK(15) * N256 : H = PEEK(742) * N256 : IF PEEK(14)< >NO THEN L = L + N256
|
||||||
|
499 REM DISPLAY BOUNDS AND GET REPLY
|
||||||
|
500 ? CHR$(125); S$; "ATARI MEMORY TEST PROGRAM"; CHR$(155); S$; "MEMORY
|
||||||
|
BOUNDS ARE"
|
||||||
|
600 ? S$; "LOW = "; L : ? S$; "HIGH = "; H
|
||||||
|
700 ? S$; "GIVE TEST BOUNDS"; CHR$(155)
|
||||||
|
800 TRAP 800 : ? S$; "LOW = "; : INPUT LOW : IF LOW < L OR LOW > H THEN 800
|
||||||
|
900 TRAP 900 : ? S$; "HIGH = "; : INPUT HIGH : IF HIGH > H OR HIGH < L OR
|
||||||
|
HIGH-LOW < N256 THEN 900
|
||||||
|
999 REM SETUP BOUNDS FOR THE MLP
|
||||||
|
1000 POKE 205, NO : POKE 206, INT(HIGH/N256)
|
||||||
|
1100 TRAP 32767 : POKE 203, NO : POKE 204, INT(LOW/N256)
|
||||||
|
1200 POKE 764, N255
|
||||||
|
1299 REM INVOKE THE MLP TO DO THE TEST
|
||||||
|
1300 POKE 559, NO : POKE 764, N255 : X = USR(1536)
|
||||||
|
1399 REM CHECK RETURN FROM MLP
|
||||||
|
1400 IF PEEK(208) = NO THEN 2200
|
||||||
|
1499 REM SHOW MEMORY ERROR ON SCREEN
|
||||||
|
1500 ? " ERROR AT "; (PEEK(203) + PEEK(204) * N256); " EXP =
|
||||||
|
"; PEEK(207); " ACT = "; PEEK(209)
|
||||||
|
1600 SOUND NO, PASS, 6, 8 : FOR I = N1 TO 5 : NEXT I : SOUND NO, NO, NO, NO
|
||||||
|
1699 REM SETUP NEXT BYTE TO TEST SO WE DONT STOP WITH FIRST ERROR
|
||||||
|
1700 IF PEEK(203) = N255 THEN POKE 204, (PEEK(204) + N1) : POKE 203, NO : GOTO 1900
|
||||||
|
1800 POKE 203, (PEEK(203) + N1)
|
||||||
|
1900 POKE 764, N255 : POKE 559, 34
|
||||||
|
1999 REM CONTINUE ONLY IF KEY PRESSED
|
||||||
|
2000 IF PEEK(764) = N255 THEN 2000
|
||||||
|
2099 REM CONTINUE TESTING BAD RANGE
|
||||||
|
2100 GOTO 1300
|
||||||
|
2199 REM GOOD TEST PASS SO SAY SO
|
||||||
|
2200 PASS = PASS + N1 : ? " GOOD PASS NUMBER "; PASS : SOUND NO, PASS, 10, 8
|
||||||
|
2300 FOR I = N1 TO 5 : NEXT I : SOUND NO, NO, NO, NO
|
||||||
|
2399 REM STOP AND DISPLAY STUFF IF KEY IS PRESSED
|
||||||
|
2400 IF PEEK(764)< >N255 THEN 2600
|
||||||
|
2499 REM CONTINUE WITH NEXT PASS
|
||||||
|
2500 GOTO 1100
|
||||||
|
2600 POKE 764, N255
|
||||||
|
2699 REM WAIT HERE UNTIL A KEY IS PRESSED
|
||||||
|
2700 POKE 559, 34 : IF PEEK(764) = N255 THEN 2700
|
||||||
|
2799 REM CONTINUE WITH NEXT PASS
|
||||||
|
2800 GOTO 1100
|
||||||
|
2899 REM READ IN MACHINE LANGUAGE PROGRAM
|
||||||
|
2900 FOR L = 1536 TO 1576 : READ H : POKE L, H : NEXT L : RETURN
|
||||||
|
3000 DATA 104, 169, 0, 160, 0, 24, 145, 203, 209, 203, 208, 18, 105,
|
||||||
|
1, 208, 246, 200, 208, 242, 230, 204, 166, 204, 228, 206
|
||||||
|
3100 DATA 208, 234, 133, 208, 96, 133, 207, 177, 203, 133, 209, 169,
|
||||||
|
1, 133, 208, 96
|
|
@ -0,0 +1,57 @@
|
||||||
|
51 REM ATARI RAM TEST PROGRAM
|
||||||
|
52 REM BY ED STEWART 03/82
|
||||||
|
53 REM 11025 SAGEBRUSH AVE
|
||||||
|
54 REM UNIONTOWN OHIO 44685
|
||||||
|
99 REM SETUP SOME REQUIRED CONSTANTS
|
||||||
|
100 N1 = 1 : N2 = N1 + N1 : N255 = 255 : N256 = N255 + N1
|
||||||
|
200 DIM S$(N2) : S$(N1, N1) = CHR$(157) : S$(N2, N2) = CHR$(159)
|
||||||
|
299 REM READ IN THE MACHINE LANGUAGE PROGRAM
|
||||||
|
300 GOSUB 2900
|
||||||
|
399 REM GET LOW AND HIGH MEMORY BOUNDS
|
||||||
|
400 L = PEEK(15) * N256 : H = PEEK(742) * N256 : IF PEEK(14)< >NO THEN L = L + N256
|
||||||
|
499 REM DISPLAY BOUNDS AND GET REPLY
|
||||||
|
500 ? CHR$(125); S$; "ATARI MEMORY TEST PROGRAM"; CHR$(155); S$; "MEMORY
|
||||||
|
BOUNDS ARE"
|
||||||
|
600 ? S$; "LOW = "; L : ? S$; "HIGH = "; H
|
||||||
|
700 ? S$; "GIVE TEST BOUNDS"; CHR$(155)
|
||||||
|
800 TRAP 800 : ? S$; "LOW = "; : INPUT LOW : IF LOW < L OR LOW > H THEN 800
|
||||||
|
900 TRAP 900 : ? S$; "HIGH = "; : INPUT HIGH : IF HIGH > H OR HIGH < L OR
|
||||||
|
HIGH-LOW < N256 THEN 900
|
||||||
|
999 REM SETUP BOUNDS FOR THE MLP
|
||||||
|
1000 POKE 205, NO : POKE 206, INT(HIGH/N256)
|
||||||
|
1100 TRAP 32767 : POKE 203, NO : POKE 204, INT(LOW/N256)
|
||||||
|
1200 POKE 764, N255
|
||||||
|
1299 REM INVOKE THE MLP TO DO THE TEST
|
||||||
|
1300 POKE 559, NO : POKE 764, N255 : X = USR(1536)
|
||||||
|
1399 REM CHECK RETURN FROM MLP
|
||||||
|
1400 IF PEEK(208) = NO THEN 2200
|
||||||
|
1499 REM SHOW MEMORY ERROR ON SCREEN
|
||||||
|
1500 ? " ERROR AT "; (PEEK(203) + PEEK(204) * N256); " EXP =
|
||||||
|
"; PEEK(207); " ACT = "; PEEK(209)
|
||||||
|
1600 SOUND NO, PASS, 6, 8 : FOR I = N1 TO 5 : NEXT I : SOUND NO, NO, NO, NO
|
||||||
|
1699 REM SETUP NEXT BYTE TO TEST SO WE DONT STOP WITH FIRST ERROR
|
||||||
|
1700 IF PEEK(203) = N255 THEN POKE 204, (PEEK(204) + N1) : POKE 203, NO : GOTO 1900
|
||||||
|
1800 POKE 203, (PEEK(203) + N1)
|
||||||
|
1900 POKE 764, N255 : POKE 559, 34
|
||||||
|
1999 REM CONTINUE ONLY IF KEY PRESSED
|
||||||
|
2000 IF PEEK(764) = N255 THEN 2000
|
||||||
|
2099 REM CONTINUE TESTING BAD RANGE
|
||||||
|
2100 GOTO 1300
|
||||||
|
2199 REM GOOD TEST PASS SO SAY SO
|
||||||
|
2200 PASS = PASS + N1 : ? " GOOD PASS NUMBER "; PASS : SOUND NO, PASS, 10, 8
|
||||||
|
2300 FOR I = N1 TO 5 : NEXT I : SOUND NO, NO, NO, NO
|
||||||
|
2399 REM STOP AND DISPLAY STUFF IF KEY IS PRESSED
|
||||||
|
2400 IF PEEK(764)< >N255 THEN 2600
|
||||||
|
2499 REM CONTINUE WITH NEXT PASS
|
||||||
|
2500 GOTO 1100
|
||||||
|
2600 POKE 764, N255
|
||||||
|
2699 REM WAIT HERE UNTIL A KEY IS PRESSED
|
||||||
|
2700 POKE 559, 34 : IF PEEK(764) = N255 THEN 2700
|
||||||
|
2799 REM CONTINUE WITH NEXT PASS
|
||||||
|
2800 GOTO 1100
|
||||||
|
2899 REM READ IN MACHINE LANGUAGE PROGRAM
|
||||||
|
2900 FOR L = 1536 TO 1576 : READ H : POKE L, H : NEXT L : RETURN
|
||||||
|
3000 DATA 104, 169, 0, 160, 0, 24, 145, 203, 209, 203, 208, 18, 105,
|
||||||
|
1, 208, 246, 200, 208, 242, 230, 204, 166, 204, 228, 206
|
||||||
|
3100 DATA 208, 234, 133, 208, 96, 133, 207, 177, 203, 133, 209, 169,
|
||||||
|
1, 133, 208, 96
|
|
@ -0,0 +1,52 @@
|
||||||
|
51 REM ATARI RAM TEST PROGRAM
|
||||||
|
52 REM BY ED STEWART 03/82
|
||||||
|
53 REM 11025 SAGEBRUSH AVE
|
||||||
|
54 REM UNIONTOWN OHIO 44685
|
||||||
|
99 REM SETUP SOME REQUIRED CONSTANTS
|
||||||
|
100 N1 = 1 : N2 = N1 + N1 : N255 = 255 : N256 = N255 + N1
|
||||||
|
200 DIM S$(N2) : S$(N1, N1) = CHR$(157) : S$(N2, N2) = CHR$(159)
|
||||||
|
299 REM READ IN THE MACHINE LANGUAGE PROGRAM
|
||||||
|
300 GOSUB 2900
|
||||||
|
399 REM GET LOW AND HIGH MEMORY BOUNDS
|
||||||
|
400 L = PEEK(15) * N256 : H = PEEK(742) * N256 : IF PEEK(14) <> NO THEN L = L + N256
|
||||||
|
499 REM DISPLAY BOUNDS AND GET REPLY
|
||||||
|
500 ? CHR$(125); S$; "ATARI MEMORY TEST PROGRAM"; CHR$(155); S$; "MEMORY BOUNDS ARE "
|
||||||
|
600 ? S$; "LOW = "; L : ? S$; "HIGH = "; H
|
||||||
|
700 ? S$; "GIVE TEST BOUNDS"; CHR$(155)
|
||||||
|
800 TRAP 800 : ? S$; "LOW = "; : INPUT LOW : IF LOW < L OR LOW > H THEN 800
|
||||||
|
900 TRAP 900 : ? S$; "HIGH = "; : INPUT HIGH : IF HIGH > H OR HIGH < L OR HIGH-LOW < N256 THEN 900
|
||||||
|
999 REM SETUP BOUNDS FOR THE MLP
|
||||||
|
1000 POKE 205, NO : POKE 206, INT(HIGH/N256)
|
||||||
|
1100 TRAP 32767 : POKE 203, NO : POKE 204, INT(LOW/N256)
|
||||||
|
1200 POKE 764, N255
|
||||||
|
1299 REM INVOKE THE MLP TO DO THE TEST
|
||||||
|
1300 POKE 559, NO : POKE 764, N255 : X = USR(1536)
|
||||||
|
1399 REM CHECK RETURN FROM MLP
|
||||||
|
1400 IF PEEK(208) = NO THEN 2200
|
||||||
|
1499 REM SHOW MEMORY ERROR ON SCREEN
|
||||||
|
1500 ? " ERROR AT "; (PEEK(203) + PEEK(204) * N256); " EXP = "; PEEK(207); " ACT = "; PEEK(209)
|
||||||
|
1600 SOUND NO, PASS, 6, 8 : FOR I = N1 TO 5 : NEXT I : SOUND NO, NO, NO, NO
|
||||||
|
1699 REM SETUP NEXT BYTE TO TEST SO WE DONT STOP WITH FIRST ERROR
|
||||||
|
1700 IF PEEK(203) = N255 THEN POKE 204, (PEEK(204) + N1) : POKE 203, NO : GOTO 1900
|
||||||
|
1800 POKE 203, (PEEK(203) + N1)
|
||||||
|
1900 POKE 764, N255 : POKE 559, 34
|
||||||
|
1999 REM CONTINUE ONLY IF KEY PRESSED
|
||||||
|
2000 IF PEEK(764) = N255 THEN 2000
|
||||||
|
2099 REM CONTINUE TESTING BAD RANGE
|
||||||
|
2100 GOTO 1300
|
||||||
|
2199 REM GOOD TEST PASS SO SAY SO
|
||||||
|
2200 PASS = PASS + N1 : ? " GOOD PASS NUMBER "; PASS : SOUND NO, PASS, 10, 8
|
||||||
|
2300 FOR I = N1 TO 5 : NEXT I : SOUND NO, NO, NO, NO
|
||||||
|
2399 REM STOP AND DISPLAY STUFF IF KEY IS PRESSED
|
||||||
|
2400 IF PEEK(764) <> N255 THEN 2600
|
||||||
|
2499 REM CONTINUE WITH NEXT PASS
|
||||||
|
2500 GOTO 1100
|
||||||
|
2600 POKE 764, N255
|
||||||
|
2699 REM WAIT HERE UNTIL A KEY IS PRESSED
|
||||||
|
2700 POKE 559, 34 : IF PEEK(764) = N255 THEN 2700
|
||||||
|
2799 REM CONTINUE WITH NEXT PASS
|
||||||
|
2800 GOTO 1100
|
||||||
|
2899 REM READ IN MACHINE LANGUAGE PROGRAM
|
||||||
|
2900 FOR L = 1536 TO 1576 : READ H : POKE L, H : NEXT L : RETURN
|
||||||
|
3000 DATA 104, 169, 0, 160, 0, 24, 145, 203, 209, 203, 208, 18, 105, 1, 208, 246, 200, 208, 242, 230, 204, 166, 204, 228, 206
|
||||||
|
3100 DATA 208, 234, 133, 208, 96, 133, 207, 177, 203, 133, 209, 169, 1, 133, 208, 96
|
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Loading…
Reference in New Issue