Digital Research
This commit is contained in:
2020-11-06 18:50:37 +01:00
parent 621ed8ccaf
commit 31738079c4
8481 changed files with 1888323 additions and 0 deletions

View File

@@ -0,0 +1,675 @@
/*----------------------------------------------------------------------*\
| |
| DISK COPY PROGRAM |
| ================= |
| |
| Created: November 4,1982 |
| ------- |
| |
| Last Modified: January 15,1982 |
| ------------- |
| |
| Description: |
| ----------- This program will copy all or portions of |
| one disk to another compatible disk. |
| |
| Needed Files: |
| ------------ <STDIO.H>,<PORTAB.H> |
| |
| Must be linked to the 'C' runtime library. |
| ------------------------------------------ |
| |
| (c) COPYRIGHT DIGITAL RESEARCH 1983 |
| ALL RIGHTS RESERVED |
| |
\*----------------------------------------------------------------------*/
char *copyrt="CP/M-68K(tm), Version 1.1, Copyright 1983, Digital Research";
char *serial="XXXX-0000-654321";
/************************************************************************\
* Here are the Include Files *
\************************************************************************/
/********************************/
#include <stdio.h> /* Standard I/O library */
/********************************/
/************************************************************************\
* DEFINES for Copy.c *
\************************************************************************/
/********************************/
#define ON 1 /* Option is valid for this copy*/
#define OFF 0 /* Option is not valid */
#define BAD 0 /* Illegal mode flag */
#define MATCH 0 /* used by strcmp */
#define SDRIVE 1 /* source drive */
#define DDRIVE 2 /* destination drive */
#define _ALL 0 /* copy whole disk */
#define _BOOT 1 /* copy boot tracks */
#define _FILES 2 /* copy non-boot tracks */
#define _END 3 /* end this program */
#define RDERR 0 /* read error flag */
#define WRERR 1 /* write error flag */
#define NULLB '\0' /* NULL byte */
#define isupper(c) ('A' <= (c) && (c) <= 'Z')/*upper case */
#define islower(c) ('a' <= (c) && (c) <= 'z')/*lower case */
#define tolower(c) (isupper(c) ? ((c)+040):(c))/* */
#define toupper(c) (islower(c) ? ((c)-040):(c))/* */
/********************************/
/************************************************************************\
* GLOBAL definitions *
\************************************************************************/
/********************************/
GLOBAL BYTE *choice[] = /* Copy Modes available */
{"all","boot","files","end"}; /* ---------------------- */
/********************************/
GLOBAL BYTE mode; /* Hold the current copy mode */
/********************************/
/* ------- OPTIONS ------- */
GLOBAL BYTE verbose = ON; /* Prompt the user if ON */
GLOBAL BYTE verify = OFF; /* Check newly written track */
/* againist source track. */
/********************************/
/* Prompts........... */
GLOBAL BYTE *msg1 = "Enter SOURCE drive: "; /* SDRIVE */
GLOBAL BYTE *msg2 = "Enter DESTINATION drive: "; /* DDRIVE */
GLOBAL BYTE *msg3 = "READ error ----> "; /* Read error */
GLOBAL BYTE *msg4 = "WRITE error ----> "; /* Write error */
/********************************/
/********************************/
GLOBAL BYTE *bracket = "["; /* Marks beginning of option */
/* indicators on the cmd line */
/********************************/
GLOBAL struct _dpb /* Define disk parm block */
{ /*------------------------------*/
WORD spt; /* Logical sectors per track */
BYTE bsh; /* Allocation block shift factor*/
BYTE blm; /* Block mask */
BYTE exm; /* Extent mask */
BYTE dpbjunk; /* Alignment byte */
WORD dsm; /* Total storage of the disk */
WORD drm; /* Total directory entries */
BYTE al0; /* Flag reserved for dir blocks */
BYTE al1; /* Flag reserved for dir blocks */
WORD cks; /* Directory check vector size */
WORD off; /* The number of reserved tracks*/
}; /* */
/********************************/
GLOBAL struct _dph /* Define disk parm header */
{ /*------------------------------*/
BYTE *xltp; /* Pointer to sector trans table*/
WORD dphscr[3]; /* Scratchpad values for BDOS */
BYTE *dirbufp; /* Pointer to dir scratchpad */
struct _dpb *dpbp; /* Pointer to disk parm block */
BYTE *csvp; /* Pointer to scratchpad area */
BYTE *alvp; /* Pointer to scratchpad area */
}; /********************************/
EXTERN LONG __BDOS(); /* BDOS Caller in CLIB */
#define bdos(a,b) (struct _dph*)__BDOS(a,b) /* Declare a bogus function */
/********************************/
GLOBAL struct _biospb /* Bios Pararmeter Block */
{ /*------------------------------*/
UWORD funcnum; /* Bios function number */
LONG parm1; /* Bios parameter 1 */
LONG parm2; /* Bios parameter 2 */
}; /* */
GLOBAL struct _biospb biospb; /* Define it */
/********************************/
GLOBAL BYTE trkbuf[128*26*6]; /* buffer big enough to hold 6 */
/* tracks of bytes */
GLOBAL BYTE verbuf[128*26*6]; /* buffer for verification opt */
/********************************/
/************************************************************************\
* FUNCTION definitions *
\************************************************************************/
/********************************/
UWORD illegal(); /* Decides if the mode is a */
/* legal one. */
/*------------------------------*/
VOID get_mode(); /* If the mode was not there */
/* or an illegal one,get_mode */
/* will print a menu and keep */
/* prompting the user for a */
/* legal mode. */
/*------------------------------*/
BYTE get_drive(); /* Reads in a drive character */
/* from the console. If the */
/* drive is in the range(A-P), */
/* the drive is returned. If */
/* not,the value BAD is returned*/
/*------------------------------*/
VOID wait_for(); /* Holds the copy program in a */
/* wait state so the user can */
/* make sure his or her disk is */
/* in the proper drive. */
/*------------------------------*/
BYTE scan(); /* Picks off the source and */
/* destination drives from the */
/* command line. If they do */
/* not exist,or the specified */
/* drives are illegal,scan */
/* prompts the user. */
/*------------------------------*/
VOID get_options(); /* Scans the command line until */
/* a '[' is found. A list of */
/* of options is checked. Flags */
/* are turned on by the option */
/* indicators found after the */
/* square bracket. */
/*------------------------------*/
VOID copy(); /* If the two disk parameter */
/* blocks are identical,a track */
/* for track copy is made. */
/* If an serious error occurs, */
/* the copy is aborted and the */
/* program ends. */
/********************************/
VOID read_wr(); /* This routine does the actual */
/* reading and writing of the */
/* compatible disks. */
/********************************/
/************************************************************************/
/************************************************************************\
* *
* BEGIN MAIN PROGRAM *
* *
\************************************************************************/
main(argc,argv)
WORD argc;
BYTE *argv[];
{
BYTE answer,source,dest,optfound;
optfound = FALSE;
printf("Copy Ver 1.1\n"); /* Copy version message */
/*------------------------------*\
| If there is an mode on |
| on the command line or the |
| command line mode is not |
| recognized,print a menu |
| and have the user input a |
| a legal copy mode. |
\*------------------------------*/
argc--; argv++; /* point to first arg after cmd */
if(illegal(*argv))
get_mode();
else /* point to 2nd arg past cmd */
{
argv++;
argc--;
}
if(mode == _END)
cpyexit();
/*------------------------------*\
| Look for the '[' as the |
| start of the options. |
| This allows the following |
| |
| copy <mode> [options |
| ==================== |
| or |
| copy [options |
| ============= |
| |
| I will not allow the drives|
| to be specified after the |
| options though!!!!! |
\*------------------------------*/
if(strncmp(bracket,*argv,1) == MATCH)
{
argc = 0;
get_options(*argv++);
source = scan(argc,*argv++,SDRIVE);
dest = scan(argc,*argv,DDRIVE);
}
else
/*------------------------------*\
| Otherwise I assume that the |
| command line looks like |
| this: |
| |
| copy <mode> <sd> <dd> [opt |
| ========================== |
\*------------------------------*/
{
source = scan(argc--,*argv++,SDRIVE);
dest = scan(argc--,*argv,DDRIVE);
if(strncmp(bracket,*argv,1) == MATCH)
{
optfound = TRUE;
get_options(*argv);
}
while(argc-- > 0)
/* scan cmd line to find a '[' */
if(strncmp(bracket,*++argv,1) == MATCH &&
(!optfound))
{
get_options(*argv);
break;
}
else
printf("\nExtraneous argument ignored: %s",*argv);
}
if(source == dest)
{
printf("\nSource and Destination must be different");
cpyexit();
}
/*------------------------------*\
| REPEAT the copy as many |
| times as the user wishes |
\*------------------------------*/
while(TRUE)
{
if(verbose)
wait_for(source,dest);
copy((toupper(source) - 'A'),(toupper(dest) - 'A'));
printf("\nCopy complete");
if(verbose)
printf("\nDo you wish to repeat the copy? ");
else
break;
answer = __BDOS(1,(long)0);
if(toupper(answer) != 'Y')
break;
}
}
/************************/
UWORD illegal(_mode) /* Check command line */
/* aganist mode table */
/* Return mode code if */
/* found,return false */
/* if the mode is not */
/* found in the table */
/************************/
BYTE *_mode;
{
REG UWORD i;
for(i = 0;i <= 3;i++)
if(strcmp(_mode,choice[i]) == MATCH)
{
mode = i;
return(FALSE);
}
mode = -1;
return(TRUE);
}
/************************/
VOID get_mode() /* Prompt the user for */
/* a legal mode. Keep */
/* prompting until you */
/* get one. */
/************************/
{
REG UWORD i;
BYTE buf[256];
printf("\nMODE\tFUNCTION\n");
printf("\nALL\tCopy the whole disk");
printf("\nBOOT\tCopy the boot tracks");
printf("\nFILES\tCopy the non-boot tracks");
printf("\nEND\tEnd this program\n");
do
{
printf("\nEnter your copy mode: ");
gets(buf);
for(i = 0;buf[i] != NULLB;i++)
buf[i] = tolower(buf[i]);
}
while(illegal(buf));
}
/************************/
BYTE get_drive() /* Read in a drive. */
/************************/
{
BYTE drive[10];
gets(drive);
if(strlen(drive) > 1)
return(BAD);
drive[0] = toupper(drive[0]);
if(drive[0] < 'A' || drive[0] > 'P')
return(BAD);
else
return(drive[0]);
}
/************************/
VOID wait_for(source,dest) /* Wait for the user */
/* to put the disks */
/* in the proper drives*/
/************************/
BYTE source;
BYTE dest;
{
BYTE wait_buf[5];
BYTE *upchoice[3];
upchoice[0] = "ALL";
upchoice[1] = "BOOT";
upchoice[2] = "FILES";
wait_buf[0] = 3;
do
{
printf("\n(^C to ABORT)");
printf("\nRETURN to copy %s",upchoice[mode]);
printf(" from %c to %c",source,dest);
__BDOS(10,&wait_buf[0]);
}
while(wait_buf[1] != 0);
}
/************************/
BYTE scan(argc,argv,which_drive) /* Scan the command */
/* for the drives. */
/* If I can't find them*/
/* or they are illegal */
/* keep prompting the */
/* user for them. */
/************************/
WORD argc;
BYTE *argv;
UWORD which_drive;
{
BYTE *prompt,drive;
if(argc > 0 && strlen(argv) == 1)
{
sscanf(argv,"%c",&drive);
drive = toupper(drive);
if(drive >= 'A' && drive <= 'P')
return(drive);
}
switch(which_drive)
{
case SDRIVE : prompt = &msg1[0];
break;
case DDRIVE : prompt = &msg2[0];
}
printf("\n");
do
{
printf("%s",prompt);
}
while((drive = get_drive()) == BAD);
return(drive);
}
/************************/
VOID get_options(argv) /* Scan cmd line for */
/* supported options */
/************************/
BYTE *argv;
{
argv++; /* skip the square bracket */
while(*argv != NULLB)
{
switch(*argv)
{
case 'A' :
case 'a' :
verbose = OFF;
break;
case 'v' :
case 'V' : verify = ON;
break;
case ']' : return(0);
default : printf("\nUndefined option: %c",*argv);
}
argv++;
}
}
/************************/
VOID copy(source,dest) /* Select the disks. */
/* If I can't select or*/
/* the disk have diff- */
/* erent parameter blks*/
/* then print error msg*/
/************************/
BYTE source;
BYTE dest;
{
REG struct _dpb *dskpblk;
REG struct _dph *h1,*h2;
REG LONG *ptr1,*ptr2;
REG LONG endtrk,begtrk;
LONG numtrks,temp;
BYTE *sectran;
REG UWORD i;
biospb.funcnum = 9; /* Select the disks */
biospb.parm1 = (long)source; /* first the source disk */
biospb.parm2 = (long)0; /* set least sig bit to 0 */
if((h1 = bdos(50,&biospb))!= NULL)
{
biospb.parm1 = (long)dest;
if((h2 = bdos(50,&biospb))!= NULL)
{ /*----------------------------------------------*/
/* check the parameter blocks(must be identical)*/
/*----------------------------------------------*/
dskpblk = (*h1).dpbp; /* pointer to dpb */
sectran = (*h1).xltp; /* pointer to sect tran tb*/
h1 = (*h1).dpbp; /* h1 points to dpb */
ptr1 = (long)h1; /* compare long words */
h2 = (*h2).dpbp; /* h2 points to dpb */
ptr2 = (long)h2; /* compare long words */
for(i = 0;i <= 3;i++)
{
if(*ptr1 != *ptr2)
{
printf("\nIncompatible disks");
cpyexit();
}
ptr1++;
ptr2++;
}
}
else
{
printf("\nDisk select error on Destination");
cpyexit();
}
}
else
{
printf("\nDisk select error on Source");
cpyexit();
}
/*------------------------------------------------------*\
| |
| Compute beginning and ending track |
| |
\*------------------------------------------------------*/
temp = (((*dskpblk).dsm + 1)*((*dskpblk).blm + 1));
numtrks = temp/(*dskpblk).spt;
if((numtrks*(*dskpblk).spt) < temp)
numtrks++;
numtrks += (*dskpblk).off;
switch(mode)
{
case _ALL : begtrk = 0;
endtrk = numtrks - 1;
break;
case _BOOT: begtrk = 0;
endtrk = (*dskpblk).off - 1;
break;
case _FILES: begtrk = (*dskpblk).off;
endtrk = numtrks - 1;
}
read_wr(source,dest,begtrk,endtrk,sectran,dskpblk);
}
/************************************************************************/
/* */
/* Do the actual read write operations */
/* =================================== */
/* */
/************************************************************************/
VOID read_wr(source,dest,begtrk,endtrk,sectran,dskpblk)
/********************************/
BYTE source; /* source disk */
BYTE dest; /* destination disk */
REG LONG begtrk; /* beginning track to copy */
REG LONG endtrk; /* ending track to copy */
REG BYTE *sectran; /* sector translate table */
struct _dpb *dskpblk; /* ptr to disk parameter block */
/********************************/
{
REG BYTE *dma;
REG UWORD i,k;
printf("\n***Copying Tracks***\n");
for(i = begtrk;i <= endtrk;i++)
{
dma = &trkbuf;
biospb.funcnum = 12; /* set the dma address */
biospb.parm1 = dma; /* set it to beginning of trkbuf*/
biospb.parm2 = 0;
__BDOS(50,&biospb); /* call the bios via the bdos */
biospb.funcnum = 9; /* select the source diskette */
biospb.parm1 = (long)source;
biospb.parm2 = (long)0xFFFFFFFF;
__BDOS(50,&biospb); /* call the bios via the bdos */
biospb.funcnum = 10; /* set the track */
biospb.parm1 = (long)(i);
biospb.parm2 = 0;
__BDOS(50,&biospb); /* call bios via bdos */
/*----------------------------------------------*\
| Read a track's worth of sectors |
\*----------------------------------------------*/
for(k = 0;k < (*dskpblk).spt;k++)
{
biospb.funcnum = 16; /* translate sector*/
biospb.parm1 = (long)k; /* logical sect */
biospb.parm2 = sectran;
biospb.parm1 = __BDOS(50,&biospb);
biospb.funcnum = 11; /* set physical sec*/
biospb.parm2 = 0;
__BDOS(50,&biospb); /* call the bios */
/*--------------------------------------*\
| READ a sector |
\*--------------------------------------*/
biospb.funcnum = 13;
if(__BDOS(50,&biospb) != 0)
error(i,k,RDERR);
dma += 128;
biospb.funcnum = 12;
biospb.parm1 = dma;
__BDOS(50,&biospb);
}
dma = &trkbuf;
biospb.funcnum = 12; /* reset the dma addr to trkbuf */
biospb.parm1 = dma;
biospb.parm2 = 0;
__BDOS(50,&biospb); /* call the bios */
biospb.funcnum = 9; /* select the destination disk */
biospb.parm1 = (long)dest;
biospb.parm2 = (long)0xFFFFFFFF;
__BDOS(50,&biospb); /* call the bios */
/*----------------------------------------------*\
| Write out a Track's worth of Sectors |
\*----------------------------------------------*/
for(k = 0;k < (*dskpblk).spt;k++)
{
biospb.funcnum = 16;
biospb.parm1 = (long)k;
biospb.parm2 = sectran;
biospb.parm1 = __BDOS(50,&biospb);
biospb.funcnum = 11;
biospb.parm2 = 0;
__BDOS(50,&biospb);
/*--------------------------------------*\
| Write a Sector |
\*--------------------------------------*/
biospb.funcnum = 14;
biospb.parm1 = (long)2;
if(__BDOS(50,&biospb) != 0)
error(i,k,WRERR);
dma += 128;
biospb.funcnum = 12;
biospb.parm1 = dma;
__BDOS(50,&biospb);
}
if(verify)
{
dma = &verbuf;
biospb.funcnum = 12;
biospb.parm1 = dma;
__BDOS(50,&biospb); /* reset dma addr */
for(k = 0;k < (*dskpblk).spt;k++)
{
biospb.funcnum = 16;
biospb.parm1 = (long)k;
biospb.parm2 = sectran;
biospb.parm1 = __BDOS(50,&biospb);
biospb.funcnum = 11;
biospb.parm2 = 0;
__BDOS(50,&biospb);
/*------------------------------*\
| Read a sector |
\*------------------------------*/
biospb.funcnum = 13;
if(__BDOS(50,&biospb) != 0)
error(i,k,RDERR);
dma += 128;
biospb.funcnum = 12;
biospb.parm1 = dma;
__BDOS(50,&biospb);
}
/*--------------------------------------*\
| Verify the TRACK write |
\*--------------------------------------*/
for(k = 0;k < (((*dskpblk).spt)*128);k++)
if(trkbuf[k] != verbuf[k])
error(i,(k/128),WRERR);
}
printf("\r %d",i);
}
}
/************************/
error(track,sector,phase) /* Read/Write Error */
/* handler */
/************************/
UWORD track;
UWORD sector;
BYTE phase;
{
REG BYTE *addr;
if(phase == RDERR)
addr = &msg3[0];
else
addr = &msg4[0];
printf("\n\n\n%s",addr);
printf("Track: %d Sector: %d",track,sector);
cpyexit();
}
cpyexit() /* bios select what the bdos thinks is the default disk */
{
biospb.funcnum = 9;
biospb.parm1 = __BDOS(25,(long)0);
biospb.parm2 = 0;
bdos(50,&biospb);
exit(0);
}

View File

@@ -0,0 +1,158 @@
*********************************************************
* *
* Disk Formatting Program for CP/M-68K (tm) *
* *
* Copyright Digital Research 1982 *
* *
*********************************************************
*
*
*
prntstr = 9
readbuf = 10
*
seldsk = 9
settrk = 10
setsec = 11
setdma = 12
write = 14
sectran = 16
flush = 21
format = 63
*
.text
*
start: link a6,#0
move.l 8(a6),a0
add #$81,a0
scan: cmpi.b #$20,(a0)+
beq scan
cmpi.b #$61,-(a0)
blt upper
sub #$20,(a0)
upper: cmpi.b #$41,(a0)
blt erxit
cmpi.b #$50,(a0)
bgt erxit
query: move.b (a0),d0
move.b d0,msgdskx
ext.w d0
sub.w #$41,d0
move.w d0,dsk
move.w #prntstr,d0
move.l #msgdsk,d1
trap #2
move.w #readbuf,d0
move.l #buf,d1
trap #2
move.b buf+2,d0
cmpi.b #$59,d0
beq doit
cmpi.b #$79,d0
bne exit
*
doit: clr.l d0
clr.l d1
*
* Select the disk to format
*
move.w #seldsk,d0
move.w dsk,d1
clr.b d2
trap #3
tst.l d0
beq selerx
move.l d0,a0
move.l (a0),xlt
move.l 14(a0),a0
move.w (a0),spt
move.w 8(a0),drm
move.w 14(a0),trk
clr.w sect
clr.w count
*
* Call the format function
*
move.w #format,d0
move.w dsk,d1
trap #3
tst.w d0
bne fmterx
lea buf,a0
move.l #$e5e5e5e5,d0
move.w #31,d1
bloop: move.l d0,(a0)+
dbf d1,bloop
move.w #setdma,d0
move.l #buf,d1
trap #3
*
dloop: move.w count,d0
cmp.w drm,d0
bgt exit
move.w sect,d1
cmp.w spt,d1
blt sok
clr.w sect
add.w #1,trk
sok: move.w #settrk,d0
move.w trk,d1
trap #3
move.w #sectran,d0
move.w sect,d1
move.l xlt,d2
trap #3
move.w d0,d1
move.w #setsec,d0
trap #3
move.w #write,d0
clr.w d1
trap #3
tst.w d0
bne wrterx
add #1,sect
add #1,count
bra dloop
*
exit: move.w #flush,d0
trap #3
unlk a6
rts
*
erxit: move.l #erstr,d1
erx: move.w #prntstr,d0
trap #2
bra exit
*
fmterx: move.l #fmtstr,d1
bra erx
selerx: move.l #selstr,d1
bra erx
wrterx: move.l #wrtstr,d1
bra erx
*
.data
msgdsk: .dc.b 'Do you really want to format disk '
msgdskx:.dc.b 'x ? $'
*
.even
buf: .dc.b 126,0
.ds.b 126
*
xlt: .ds.l 1
spt: .ds.w 1
drm: .ds.w 1
sect: .ds.w 1
trk: .ds.w 1
dsk: .ds.w 1
count: .ds.w 1
*
fmtstr: .dc.b 'Formatting Error',13,10,'$'
erstr: .dc.b 'Error',13,10,'$'
selstr: .dc.b 'Select Error',13,10,'$'
wrtstr: .dc.b 'Write Error',13,10,'$'
*
copyrt: .dc.b 'CP/M-68K(tm), Version 1.1, Copyright 1983, Digital Research'
serial: .dc.b 'XXXX-0000-654321'
*
.end

View File

@@ -0,0 +1,141 @@
*********************************************************
* *
* Disk Initialization Program for CP/M-68K (tm) *
* *
* Copyright Digital Research 1983 *
* *
*********************************************************
*
*
*
prntstr = 9 BDOS Functions
readbuf = 10
*
seldsk = 9 BIOS Functions
settrk = 10
setsec = 11
setdma = 12
write = 14
sectran = 16
flush = 21
*
.text
*
start: link a6,#0
move.l 8(a6),a0 base page address
add #$81,a0 first character of command tail
scan: cmpi.b #$20,(a0)+ skip over blanks
beq scan
cmpi.b #$61,-(a0) get disk letter
blt upper upshift
sub #$20,(a0)
upper: cmpi.b #$41,(a0) compare with range A - P
blt erxit
cmpi.b #$50,(a0)
bgt erxit
query: move.b (a0),d0 put disk letter in message
move.b d0,msgdskx
ext.w d0 put disk letter into range 0 - 15
sub.w #$41,d0
move.w d0,dsk
move.w #prntstr,d0 ask whether it's really ok to init
move.l #msgdsk,d1
trap #2
move.w #readbuf,d0 read reply
move.l #buf,d1
trap #2
move.b buf+2,d0 if answer isn't Y then exit
cmpi.b #$59,d0
beq doit
cmpi.b #$79,d0
bne exit
*
doit: lea buf,a0 init disk buffer to empty directory entries
move.l #$e5e5e5e5,d0
move.w #31,d1
bloop: move.l d0,(a0)+
dbf d1,bloop
move.w #setdma,d0 set up dma address for write
move.l #buf,d1
trap #3
move.w #seldsk,d0 select the disk
move.w dsk,d1
clr.b d2
trap #3
tst.l d0 check for select error
beq selerx
move.l d0,a0 get translate table address for sectran
move.l (a0),xlt
move.l 14(a0),a0 get DPB address
move.w (a0),spt get sectors per track
move.w 8(a0),drm get directory entry count - 1
move.w 14(a0),trk get starting track (=offset)
clr.w sect start at sector 0
clr.w count count of initialized sectors
*
dloop: move.w count,d0 while count <= drm ...
cmp.w drm,d0
bgt exit
move.w sect,d1 check for end-of-track
cmp.w spt,d1
blt sok
clr.w sect advance to new track
add.w #1,trk
sok: move.w #settrk,d0 set the track
move.w trk,d1
trap #3
move.w #sectran,d0 do sector translate
move.w sect,d1
move.l xlt,d2
trap #3
move.w d0,d1 set sector
move.w #setsec,d0
trap #3
move.w #write,d0 and write
clr.w d1
trap #3
tst.w d0 check for write error
bne wrterx
add #1,sect increment sector number
add #4,count increment count of directory entries
bra dloop and loop
*
exit: move.w #flush,d0 exit location - flush bios buffers
trap #3
unlk a6
rts and exit to CCP
*
erxit: move.l #erstr,d1 miscellaneous errors
erx: move.w #prntstr,d0 print error message and exit
trap #2
bra exit
*
selerx: move.l #selstr,d1 disk select error
bra erx
wrterx: move.l #wrtstr,d1 disk write error
bra erx
*
.data
msgdsk: .dc.b 'Do you really want to init disk '
msgdskx:.dc.b 'x ? $'
*
.even
buf: .dc.b 126,0 dual use buffer -- console input & dsk output
.ds.b 126
*
xlt: .ds.l 1 translate table address
spt: .ds.w 1 sectors per track
drm: .ds.w 1 maximum directory entry number
sect: .ds.w 1 current sector
trk: .ds.w 1 current track
dsk: .ds.w 1 selected disk
count: .ds.w 1 number of directory entries written so far
*
erstr: .dc.b 'Error',13,10,'$'
selstr: .dc.b 'Select Error',13,10,'$'
wrtstr: .dc.b 'Write Error',13,10,'$'
*
copyrt: .dc.b 'CP/M-68K(tm), Version 1.1, Copyright 1983, Digital Research'
serial: .dc.b 'XXXX-0000-654321'
*
.end

View File

@@ -0,0 +1,194 @@
*********************************************************
* *
* Program to Write Boot Tracks for CP/M-68K (tm) *
* *
* Copyright Digital Research 1982 *
* *
*********************************************************
*
*
*
prntstr = 9 BDOS Functions
dseldsk = 14
open = 15
readseq = 20
dsetdma = 26
*
seldsk = 9 BIOS Functions
settrk = 10
setsec = 11
isetdma = 12
write = 14
sectran = 16
flush = 21
*
bufcnt = $80
bufsize = $80*bufcnt
*
.text
*
start: link a6,#0
move.l 8(a6),a0 base page address
lea $5c(a0),a1
move.l a1,fcb
clr.b hflag
add #$81,a0 first character of command tail
scan: cmpi.b #$20,(a0)+ skip over blanks
beq scan
sub.l #1,a0
scan1: tst.b (a0)
beq erxit
cmpi.b #$2d,(a0)+ check for -H flag
bne nohyph
cmpi.b #$48,(a0)+
bne erxit
tst.b hflag
bne erxit
move.b #$ff,hflag
sub.l #$24,fcb change to 2nd default fcb
bra scan
nohyph: cmpi.b #$20,(a0)
bne scan1
scan2: cmpi.b #$20,(a0)+
beq scan2
cmpi.b #$61,-(a0) get disk letter
blt upper upshift
sub #$20,(a0)
upper: cmpi.b #$41,(a0) compare with range A - P
blt erxit
cmpi.b #$50,(a0)
bgt erxit
move.b (a0),d0
ext.w d0 put disk letter into range 0 - 15
sub.w #$41,d0
move.w d0,dsk
*
* open file to copy
*
move.w #open,d0
move.l fcb,d1
trap #2
cmpi.w #$00ff,d0
bne openok
move.l #opnfl,d1
jmp erx
openok: move.l fcb,a0
clr.b 32(a0)
*
* read
*
move.l #buf,d2
clr.w count
rloop: move.w #dsetdma,d0
move.l d2,d1
trap #2
move.w #readseq,d0
move.l fcb,d1
trap #2
tst.w d0
bne wrtout
add.l #128,d2
add.w #1,count
cmpi.w #bufcnt,count
bgt bufoflx
bra rloop
*
* write
*
wrtout: move.w #seldsk,d0 select the disk
move.w dsk,d1
clr.b d2
trap #3
tst.l d0 check for select error
beq selerx
move.l d0,a0
move.l 14(a0),a0 get DPB address
move.w (a0),spt get sectors per track
move.w 14(a0),off get offset
clr.w trk start at trk 0
clr.w sect start at sector 0
lea buf,a0
tst.b hflag
bne wrt1
cmpi.w #$601a,(a0)
bne wrt1
add.l #28,a0
wrt1: move.l a0,bufp
*
wloop: tst.w count
beq exit
move.w sect,d1 check for end-of-track
cmp.w spt,d1
blt sok
clr.w sect advance to new track
move.w trk,d0
add.w #1,d0
move.w d0,trk
cmp.w off,d0
bge oflex
sok: move.w #settrk,d0 set the track
move.w trk,d1
trap #3
move.w sect,d1 set sector
move.w #setsec,d0
trap #3
move.w #isetdma,d0 set up dma address for write
move.l bufp,d1
trap #3
move.w #write,d0 and write
clr.w d1
trap #3
tst.w d0 check for write error
bne wrterx
add #1,sect increment sector number
sub #1,count
add.l #128,bufp
bra wloop
*
exit: move.w #flush,d0 exit location - flush bios buffers
trap #3
unlk a6
rts and exit to CCP
*
erxit: move.l #erstr,d1 miscellaneous errors
erx: move.w #prntstr,d0 print error message and exit
trap #2
bra exit
*
selerx: move.l #selstr,d1 disk select error
bra erx
wrterx: move.l #wrtstr,d1 disk write error
bra erx
bufoflx: move.l #bufofl,d1 buffer overflow
bra erx
oflex: move.l #trkofl,d1
bra erx
*
*
.bss
*
.even
*
buf: .ds.b bufsize+128
*
fcb: .ds.l 1 fcb address
spt: .ds.w 1 sectors per track
sect: .ds.w 1 current sector
trk: .ds.w 1 current track
dsk: .ds.w 1 selected disk
off: .ds.w 1 1st track of non-boot area
count: .ds.w 1
bufp: .ds.l 1
hflag: .ds.b 1
*
.data
*
erstr: .dc.b 'Invalid Command Line',13,10,'$'
selstr: .dc.b 'Select Error',13,10,'$'
wrtstr: .dc.b 'Write Error',13,10,'$'
opnfl: .dc.b 'Cannot Open Source File',13,10,'$'
bufofl: .dc.b 'Buffer Overflow',13,10,'$'
trkofl: .dc.b 'Too Much Data for System Tracks',13,10,'$'
*
*
.end

View File

@@ -0,0 +1,269 @@
/*----------------------------------------------------------------------*\
| serial.c v1.0 |
| SERIALIZATION PROGRAM FOR CP/M-68K |
| ================================== |
| |
| date: 1/3/83 |
| ---- |
| |
| last modified: 2/3/83 |
| ------------- |
| |
| description: |
| ----------- This program replaces up to 20 occurances |
| of "654321" in all files found in "SERIAL.DAT". |
| The string "654321" is replaced by a serial |
| number. Leading zeros will be filled in by |
| the program. The starting and ending serial |
| number's are read in from the command line. |
| The user is prompted for the serialization |
| drive. |
| |
| |
| COPYRIGHT (C) 1983 |
| DIGITAL RESEARCH |
| BOX 579 |
| PACIFIC GROVE, CA. 93950 |
| |
\*----------------------------------------------------------------------*/
#include "stdio.h" /* standard I/O library */
#define islower(c) ('a' <= (c) && (c) <= 'z')
#define toupper(c) (islower(c) ? ((c)-040) : (c))
#define RESET 13
#define SELECT 14
/********************************/
/* GLOBAL VARIABLES */
struct _serial /********************************/
{ /* */
BYTE filename[13]; /* file to serialize */
}; /* */
struct _serial serial[150]; /* array of structures */
/* */
BYTE enddata[] = "xxxxxxxxxxxx"; /* end of filenames marker */
BYTE marker[] = "654321"; /* place in file to sub serial #*/
BYTE snum[] = "000000"; /* serial number */
BYTE drive = 0; /* serialization drive */
BYTE chtab[] = "0123456789"; /* table of digits */
FILE *stream; /* pointer to a stream file */
/********************************/
/********************************/
/* FUNCTIONS */
/********************************/
FILE *fopen(); /* returns a stream I/O pointer */
FILE *fopenb(); /* returns a stream I/O pointer */
BYTE *trans(); /* returns a pointer to a string*/
LONG atol(); /* returns a long number */
LONG ftell(); /* returns a long number */
/********************************/
main(argc,argv)
WORD argc;
BYTE *argv[];
{
REG LONG start_num; /* starting serial number */
REG LONG final_num; /* final serial number */
REG LONG num; /* current serial number */
BYTE buffer[32]; /* read buffer */
BYTE boot; /* y or n to system tracks */
if(argc != 3)
{
printf("\nUsage: A>serial starting ending");
exit(0);
}
printf("Serial.68K V1.0");
init(); /* try to open data file */
boot = 'N'; /* no serializing of system trks*/
/* check range of serial number's */
if(atol(argv[1]) > 999999L || atol(argv[2]) > 999999L ||
atol(argv[1]) < 0L || atol(argv[2]) < 0L)
{
printf("\nERROR: Serial # out of range: [0-999999]");
exit(0);
}
printf("\nSerialization drive ? "); gets(buffer);
drive = toupper(buffer[0]);
/* verify to user the serial number range */
printf("\nSTARTING serial number is: %s",argv[1]);
printf("\nFINAL serial number is : %s",argv[2]);
if(boot == 'Y')
printf("\nSystem tracks will be serialized");
printf("\n\n");
/************************************************/
/* */
/* MAIN SERIALIZATION LOOP */
/* ----------------------- */
/* */
/************************************************/
for(num = atol(argv[1]); num <= atol(argv[2]); num++)
{
__BDOS(RESET,(long)0);
printf("\n\nInsert new diskette in drive %c and type RETURN",drive);
getchar();
printf("\nCURRENT serial number is: %LD\n",num);
if(boot == 'Y')
boottrk(num);
patch(num);
}
}
/************************/
VOID init() /* Open SERIAL.DAT */
/* Read SERIAL.DAT */
/************************/
{
BYTE buf[40];
REG UWORD j;
REG struct _serial *p;
if((stream = fopen("SERIAL.DAT","r")) == NULL)
{
printf("\nUnable to open SERIAL.DAT");
exit(0);
}
/* read in the data line by line */
/* and fill the structure serial */
fgets(buf,40,stream);
p = &serial;
do
{
j = 0;
while((p->filename[j] = buf[j++]) != '\n');
p->filename[j-1] = '\0';
p++;
fgets(buf,40,stream);
}
while(!(feof(stream)));
for(j = 0;j < 12;j++)
p->filename[j] = 'x';
p->filename[12] = '\0';
fclose(stream);
}
/************************/
VOID patch(num) /* Plug Serialization */
/* bytes into file */
/************************/
LONG num;
{
REG struct _serial *p;
REG UWORD i,j;
LONG offset[21];
REG BYTE *pp;
REG UWORD ch;
REG WORD fd;
__BDOS(SELECT,(long)drive-'A');
p = &serial;
while(strcmp(p,enddata))
{
printf("\nSerializing: %s ",p);
for(i = 1;i <= (12 - strlen(p));i++)
printf(" ");
if((stream = fopenb(p,"r")) == NULL)
printf("Unable to open file: %s",p);
else
{
for(j = 0;j < 21;j++)
offset[j] = -1L;
i = j = 0;
pp = marker;
rewind(stream);
while(1)
{
ch = fgetc(stream);
if(feof(stream))
break;
if(ch == *pp)
{
i++;
if(pp == marker)
offset[j] = ftell(stream);
pp++;
}
else
{
pp = marker;
offset[j] = -1L;
i = 0;
}
if(i == 6)
{
j++;
if(j == 20)
break;
i = 0;
pp = marker;
}
}
fclose(stream);
if(offset[0] == -1L)
printf("file cannot be serialized");
else
{
fd = openb(p, 2);
if ( fd == -1 ) printf("cannot write to file");
else
{
j = 0;
while(offset[j] != -1L)
{
lseek(fd, --offset[j++], 0);
write(fd, trans(num), 6);
}
printf("Serialization complete %d",j);
close(fd);
}
}
}
p++;
}
}
VOID boottrk(num)
LONG num;
{
printf("\nSerializing Boot tracks");
}
BYTE *trans(num)
LONG num;
{
REG BYTE *p;
LONG x;
p = snum;
x = 100000;
while(x)
{
*p++ = chtab[num/x];
num %= x;
x /= 10;
}
return(snum);
}