//­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­ // // Soucecode: TrackMaster // // © by BrainTrace Design / Carsten Schlote, Egelseeweg 52, // 6302 Lich 1 // // Date Author Comment // ========= ========= ======================== // 26-Sep-91 Schlote Offset & Directory Offset / Rev. Specialmdir // 12-Sep-91 Schlote & MB Relocator & Link feature // 10-Aug-91 Schlote Large-Size Dirtable // 25-Jul-91 Schlote Added lzh-coding of data // 22-Jul-91 Schlote Created this file! // //­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­ #include "tm.h" #define BLKLENGTH( real ) ((real & 0xffffe00)+0x200) #define COMPBLKLEN( real ) ( BLKLENGTH( real + ENCODEEXTRA( real ) ) ) #define MAXENTRIES (4*64) /* Maximale Anzahl von Files */ #define DIRBLOCK (2*512) /* Offset to DirBlock */ //­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­ // The following stuff defines some code & data into glues.a extern LONG __asm BBChkSum( register __a0 LONG * bootblock ); extern LONG __chip BootBlock[]; extern LONG __chip LoaderOffset, __chip LoaderLength; extern LONG __chip NumFiles; //­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­ OPAIR __chip dirfeld[MAXENTRIES]; // Dieses Feld enthält die Offsets/Längen für Trackdisk.device // Wird während des Schreibens erstellt. TEXT filefeld[MAXENTRIES][30]; /* Filename */ LONG realfilelen[MAXENTRIES]; /* Die echte Filelänge in Bytes !! */ BOOL compressfile[MAXENTRIES]; /* Dieses File comprimieren ? */ BOOL relocatefile[MAXENTRIES]; /* File relocieren und wohin */ ULONG reloaddrfile[MAXENTRIES]; LONG newoffset[MAXENTRIES]; /* Neuer BlockOffset o. -1 */ LONG numfiles; /* Wieviele Files zu Zeit */ LONG curroffset; /* Actueller Blockoffset */ TEXT *hunkfmt = "HunkWizard -a%lx -o%s %s\n"; //­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­ ULONG dospacket(struct MsgPort *aprt,LONG typ, LONG arg1,LONG arg2,LONG arg3,LONG arg4,LONG arg5,LONG arg6,LONG arg7) { struct StandardPacket *sp; struct MsgPort* rp; ULONG ret; if ( (rp = CreatePort(NULL,0))==NULL ) { return(-1); }else{ if ( (sp = AllocMem(sizeof(struct StandardPacket),MEMF_PUBLIC|MEMF_CLEAR))==0) { DeletePort(rp); return(-1); }else{ sp->sp_Msg.mn_Node.ln_Name = (char*)&(sp->sp_Pkt); sp->sp_Pkt.dp_Link = &(sp->sp_Msg); sp->sp_Pkt.dp_Port = rp; sp->sp_Pkt.dp_Type = typ; sp->sp_Pkt.dp_Arg1 = arg1; sp->sp_Pkt.dp_Arg2 = arg2; sp->sp_Pkt.dp_Arg3 = arg3; sp->sp_Pkt.dp_Arg4 = arg4; sp->sp_Pkt.dp_Arg5 = arg5; sp->sp_Pkt.dp_Arg6 = arg6; sp->sp_Pkt.dp_Arg7 = arg7; PutMsg(aprt, &sp->sp_Msg); WaitPort(rp); GetMsg(rp); ret = sp->sp_Pkt.dp_Res1; FreeMem( sp, sizeof(struct StandardPacket)); DeletePort(rp); } } return(ret); } void inhibitdrive(WORD drnum, BOOL state) { TEXT*tp; struct MsgPort *mp; switch( drnum ) { case 0 : tp = "df0:"; break; case 1 : tp = "df1:"; break; case 2 : tp = "df2:"; break; case 3 : tp = "df3:"; break; } mp = DeviceProc( tp ); if ( mp ) { dospacket( mp, ACTION_INHIBIT,state,0,0,0,0,0,0); } } //­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­ LONG calcrating( struct LhBuffer *lh ) { LONG ret; ret = ( (lh->lh_SrcSize - lh->lh_DstSize) * 100 ) / lh->lh_SrcSize; return( ret ); } //­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­ BOOL CheckDisk( struct IOStdReq* ior) { BOOL err = FALSE; ior->io_Command = TD_CHANGESTATE; DoIO( ior ); if ( ior->io_Actual != FALSE ) { printf("Insert a blank,formatted disk in drive before !\n"); err = TRUE; } else { ior->io_Command = TD_PROTSTATUS; err = DoIO( ior ); if ( ior->io_Actual != FALSE ) { printf("Disk in selected drive is write-protected !\n"); err = TRUE; } } return( err ); } //­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­ struct Library *LhBase; struct LhBuffer *lhbuffer; void openlibs(void) { if ( !(LhBase = OpenLibrary( LH_NAME, LH_VERSION ) )) { printf("\nI can't find the %s\nCompression disabled.\n",LH_NAME); }else{ if ( !(lhbuffer = CreateBuffer(FALSE))) { printf("Unable to allocate auxilary buffers for compression.\n" "Terminating.\n"); exit( RETURN_FAIL ); } } } void closelibs(void) { if ( lhbuffer ) { DeleteBuffer(lhbuffer); lhbuffer = NULL; } if ( LhBase ) { CloseLibrary( LhBase ); LhBase = NULL; } } //­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­ void Usage(TEXT*pn) { printf( "Usage: %s scriptfile <0..3>\n\n" "This tool was designed to copy some workfiles to a non-dos disk\n" "using trackdisk.device.\n" "'scriptfile' is a file, which contains the names of the file to\n" "store. See TrackMaster Docfile for more information\n\n",pn); } //­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­ int main(int argc,char *argv[]) { struct MsgPort *myport; /* Mein MessagePort */ struct IOStdReq *myio; /* Mein Standard IO Block */ LONG unitnum; /* Nummer des Disklaufwerkes */ struct FileInfoBlock *fib; /* Für Filelängen etc */ BPTR lock; FILE *fp; TEXT buffer[256]; /* Eingabepuffer für Zeile */ BYTE *filebuff; /* DateiPuffer */ BYTE *compbuff; /* Compress Dest-Buffer */ LONG i,j; /* Laufvariable */ BOOL breakloop = FALSE; /* Falls ein Fehler auftritt */ BOOL firstline = FALSE; /* schon erste Zeile bearbeit.*/ BOOL compresson = FALSE; /* Default is aus !!! */ BOOL relocateon = FALSE; /* " */ ULONG relocateaddr; BOOL specialon = FALSE; /* Special command */ TEXT specialcom[80]; BOOL patchdir = FALSE; /* Skip some leading files on */ LONG patchfrom; /* disk, yet. */ printf("\nTrackMaster V1.7 Freeware ©1990 Carsten Schlote\n" " BrainTrace Design Software\n\n"); //­­­­­­­ Startup-Stuff for lhlib ­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­ onexit( closelibs ); openlibs(); //­­­­­­­ Argumente auswerten ­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­ if ( argc != 3 ) { Usage(argv[0]); exit(RETURN_ERROR); }else{ if ( sscanf( argv[2],"%ld\n", &unitnum )!=1 ) { printf("The drive number is invalid !\n\n"); breakloop = TRUE; }else{ if ( (fp = fopen( argv[1],"r" ))==NULL ) { printf("Can't open scriptfile\n\n"); breakloop = TRUE; }else{ if ( !(fib = AllocMem( sizeof(*fib),MEMF_PUBLIC ))) { printf("Can't allocate FIB.\n\n"); breakloop = TRUE; }else{ numfiles = 0; //­­­­Scriptzeile lesen und auswerten­­­­­­­­­­­­­­­­­­­­­­­­­­­ while ( !breakloop && (fgets( buffer,256,fp ) != NULL) ) { if ( buffer[0]=='\n' ) continue; /* Commentar */ if (newoffset[numfiles]<=0) newoffset[ numfiles ] = -1; /* No new offset, yet */ //­­­­Commandosequence auswerten­­­­­­­­­­­­­­­­­­­­­­­­­­­­­ if ( buffer[0]=='#' ) { if ( buffer[1]=='\n' ) continue; /* Commentar */ switch ( toupper( buffer[1] ) ) { case '@' : if ( patchdir || firstline ) { printf("*** #@ may be used only once and the beginning of the script.\n"); breakloop = TRUE; }else{ if ( sscanf( &buffer[3],"%ld",&patchfrom ) != 1 ) { printf("*** Dir Entry Number wrong or non-decimal.\n"); breakloop = TRUE; } patchdir = TRUE; numfiles = patchfrom; } break; case 'O' : if ( sscanf( &buffer[3],"%ld",&newoffset[numfiles] ) != 1 ) { printf("*** Offset Number wrong or non-decimal.\n"); breakloop = TRUE; } break; case 'C' : if ( LhBase ) compresson = ( buffer[2]=='1' )?TRUE:FALSE; break; case 'R' : relocateon = (buffer[2]== '1')?TRUE:FALSE; if ( buffer[2] == '1' ) { if ( sscanf( &buffer[3],"%lx", &relocateaddr ) != 1 ) { printf("*** Hexaddr for relocate is wrong\n"); breakloop = TRUE; } } break; case 'S' : specialon = (buffer[2]== '1')?TRUE:FALSE; strcpy( specialcom ,&buffer[3] ); break; case 'L' : { TEXT tempfname[30]; TEXT linkfiles[30*30] = "\0"; TEXT doscom[256]; if ( sscanf( &buffer[2],"%d %s",&i,tempfname ) != 2 ) { printf("*** Link parameters wrong or missing.\n"); breakloop = TRUE; } if ( i <= 30 && i > 1 ) { while ( i > 0 ) { if ( fgets( buffer,256,fp ) != NULL ) { if ( buffer[0] == '\n' ) continue; strcat( linkfiles, buffer ); linkfiles[ strlen(linkfiles)-1 ] = ' '; } --i; } sprintf(doscom,"Join %s to %s", linkfiles, tempfname ); if ( Execute( doscom, NULL,NULL ) == FALSE ) { printf("*** Linkage failed.\n"); breakloop=TRUE; continue; } strcpy(buffer, tempfname ); goto getlinkfilename; }else{ printf("*** Too many/less files for link option.\n"); breakloop = TRUE; } } break; } continue; } buffer[ strlen( buffer ) -1 ] = 0; getlinkfilename: //­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­ if ( relocateon & specialon ) { printf("Script options conflict\n"); breakloop = TRUE; continue; } //­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­ if ( specialon ) { TEXT tempfname[30], doscom[256], *p; TEXT speccom[160]; strcpy( speccom, specialcom ); strcpy( tempfname, buffer ); strcat( tempfname, ".rel" ); while ( p = strchr( speccom, '@' ) ) { p[0] = '%'; switch ( p[1] ) { case 's' : sprintf( doscom, speccom, buffer ); strcpy( speccom, doscom ); break; case 'd' : p[1] = 's'; sprintf( doscom, speccom, tempfname); strcpy( speccom, doscom ); break; } } strcpy( doscom, speccom ); printf("%s",doscom ); if ( Execute( doscom, NULL,NULL ) == FALSE ) { printf("Can't start requested command or prg failed.\n"); breakloop = TRUE; continue; } strcpy( buffer, tempfname ); } //­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­ if ( relocateon ) { TEXT tempfname[30]; TEXT doscom[256]; strcpy( tempfname, buffer ); strcat( tempfname, ".rel" ); sprintf( doscom, hunkfmt, relocateaddr, tempfname,buffer ); if ( Execute( doscom, NULL,NULL ) == FALSE ) { printf("Can't start hunkwizard or prg failed.\n"); breakloop = TRUE; continue; } strcpy( buffer, tempfname ); } //­­­­File locken und auswerten­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­ if ( sscanf( buffer,"%30s\n",filefeld[numfiles]) != 1 ) { printf("Error in scriptfile.\n"); breakloop = TRUE; } else { if ( (lock=Lock(filefeld[numfiles],ACCESS_READ))==0 ) { printf("Can't find file %s.\n\n",filefeld[numfiles]); breakloop = TRUE; }else{ if ( Examine( lock, fib ) == FALSE ) { printf("Can't examine file %s.\n\n",filefeld[numfiles]); breakloop = TRUE; }else{ realfilelen[numfiles]=fib->fib_Size; compressfile[numfiles] = (numfiles==0)?FALSE:compresson; relocatefile[numfiles] = relocateon; reloaddrfile[numfiles] = relocateaddr; } UnLock(lock); } } if ( ++numfiles >= MAXENTRIES-1 ) { // Wegen filenamesfile => - 1 ! printf("Table overflow. Too many files in script !\n"); breakloop=TRUE; } firstline = TRUE; } FreeMem(fib,sizeof(fib)); } fclose(fp); /* scriptfile schließen */ } } } if ( breakloop ) exit( RETURN_FAIL ); //­­­­ Filenamen abspeichern ­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­ { LONG fnamelen = numfiles * 30; BPTR fh; if ( fh = Open( "tm.dir", MODE_NEWFILE ) ) { if ( Write( fh, filefeld, fnamelen ) != fnamelen ) exit(RETURN_FAIL); Close(fh); } else { exit( RETURN_FAIL ); } strcpy( filefeld[numfiles], "tm.dir" ); realfilelen[numfiles]= fnamelen; compressfile[numfiles] = TRUE; relocatefile[numfiles] = FALSE; reloaddrfile[numfiles] = NULL; newoffset[numfiles] = -1; ++numfiles; } //­­­­­­­ Daten lesen und schreiben ­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­ #define TDCOM( com, data, offset, len ) { myio->io_Command = com; myio->io_Data = data; myio->io_Offset = offset; myio->io_Length = len; DoIO(myio); } #define TDCOMX( com, data, offset, len ) { TDCOM( com,data, offset,len); if (myio->io_Error) { printf("*** IO-Error %ld. Terminating.\n",myio->io_Error); goto error; } } if(numfiles==0) { printf("Nothing to write !?\n\n"); exit(RETURN_WARN); } if ( (myport = CreatePort( NULL,0 ))==NULL ) { printf("Can't create port.\n\n"); exit(RETURN_ERROR); }else{ if ( (myio = CreateStdIO( myport ))==NULL ) { printf("Can't create std io.\n\n"); exit(RETURN_ERROR); }else{ if ( OpenDevice( TD_NAME, unitnum, myio, 0 )!=0 ) { printf("Can't open %s unit %ld.\n\n",TD_NAME,unitnum); exit(RETURN_ERROR); }else{ inhibitdrive( unitnum, TRUE ); printf("Please insert disk in Drive df%ld: and hit return.",unitnum); Read( Input(), buffer, sizeof(buffer) ); if ( (i = CheckDisk( myio )) ) { printf("*** IO-Error %ld. Terminating.\n",i); goto nodisk; } //­­­­Files lesen, bearbeiten und schreiben ­­­­­­­­­­­­­­­­­­­­­­­ curroffset = DIRBLOCK + BLKLENGTH( (numfiles*8) ); printf("---------------------------------------------------------------------\n"); for ( i= (patchdir)?patchfrom:0 ; i 0 && !olddirfeld[j].offset && !olddirfeld[j].length ; --j ) ; TDCOMX( CMD_READ, packedfiles, olddirfeld[j].offset, olddirfeld[j].length ); if ( lp[0] == 'PACK' ) { lhbuffer->lh_Src = &lp[3]; lhbuffer->lh_SrcSize = lp[1]; lhbuffer->lh_Dst = oldfilefeld; lhbuffer->lh_DstSize = lp[2]; LhDecode( lhbuffer ); }else memcpy( oldfilefeld, packedfiles, sizeof(packedfiles) ); } if ( newoffset[i] != -1 ) { if ( newoffset[i]*512 < curroffset ) { printf("*** Warning : Seeking to lower disk offset.\n"); } curroffset = newoffset[i] * 512; printf("Seek to Diskblock %ld and continue writing.\n",newoffset[i] ); } if ( curroffset < (DIRBLOCK + BLKLENGTH( (numfiles*8) )) || curroffset > ( 160*11*512 ) ) { printf("*** Seek offset invalid.\n\n"); break; } if( !(filebuff = AllocMem( BLKLENGTH(realfilelen[i]), MEMF_CHIP|MEMF_PUBLIC|MEMF_CLEAR ))) { printf("*** Can't allocate buffer for file %s.\n\n",filefeld[i]); breakloop = TRUE; }else{ if( !(lock = Open( filefeld[i], MODE_OLDFILE ))) { printf("*** Can't open file %s.\n\n",filefeld[i]); breakloop = TRUE; } else { if ( Read(lock, filebuff, realfilelen[i]) != realfilelen[i] ) { printf("*** Can't open file %s.\n\n",filefeld[i]); breakloop = TRUE; }else{ if ( compressfile[i] ) { if ( !(compbuff = AllocMem( COMPBLKLEN( realfilelen[i] ), MEMF_CHIP|MEMF_CLEAR|MEMF_PUBLIC ))) { printf("*** Can't allocate compression buffer.\nTerminate.\n"); breakloop = TRUE; }else{ if ( i == numfiles-1 && patchdir ) { for ( j=0; jlh_Src = filebuff; lhbuffer->lh_SrcSize = realfilelen[i]; lhbuffer->lh_Dst = compbuff + ( 3*4 ); printf(" Compress data - stand by."); if ( LhEncode( lhbuffer )==0 ) { printf("\r*** Compression failed.\nTerminating.\n"); breakloop = TRUE; }else{ if ( lhbuffer->lh_DstSize >= lhbuffer->lh_SrcSize ) { printf("\r*** uncompressable data. Check file %s\nTerminate.\n",filefeld[i] ); breakloop = TRUE; }else{ { LONG * tp; tp = (LONG*)(compbuff); tp[0] = 'PACK' ; tp[1] = lhbuffer->lh_SrcSize; tp[2] = lhbuffer->lh_DstSize; } dirfeld[i].offset = curroffset; dirfeld[i].length = BLKLENGTH( lhbuffer->lh_DstSize ); printf("\r%3ld. Offset: %6ld(%4ld) Length: %6ld(%4ld) Rate:%ld%% File: %s\n", i, dirfeld[i].offset,dirfeld[i].offset/512, dirfeld[i].length,dirfeld[i].length/512,calcrating( lhbuffer ),filefeld[i] ); TDCOMX( CMD_WRITE, compbuff, dirfeld[i].offset, dirfeld[i].length); curroffset += dirfeld[i].length; } } FreeMem( compbuff, COMPBLKLEN(realfilelen[i]) ); } }else{ dirfeld[i].offset = curroffset; dirfeld[i].length = BLKLENGTH( realfilelen[i] ); printf("%3ld. Offset: %6ld(%4ld) Length: %6ld(%4ld) File: %s\n", i, dirfeld[i].offset,dirfeld[i].offset/512, dirfeld[i].length,dirfeld[i].length/512,filefeld[i] ); TDCOMX( CMD_WRITE, filebuff, dirfeld[i].offset, dirfeld[i].length); curroffset += dirfeld[i].length; } Close(lock); } } FreeMem(filebuff, BLKLENGTH( realfilelen[i] ) ); } if ( breakloop ) break; } printf("---------------------------------------------------------------------\n"); printf("Writing %ld direntrie(s) to offset %ld(%ld).\n",numfiles,DIRBLOCK,DIRBLOCK/512); TDCOMX( CMD_WRITE, dirfeld, DIRBLOCK, BLKLENGTH( (numfiles*8) ) ); printf("---------------------------------------------------------------------\n"); printf("Writing BootLoader for first, unpacked & pc-relative program !\n"); LoaderOffset = dirfeld[0].offset; LoaderLength = dirfeld[0].length; NumFiles = numfiles; BBChkSum( BootBlock ); TDCOMX( CMD_WRITE, BootBlock, 0, 1024 ); error: printf("---------------------------------------------------------------------\n"); TDCOM( CMD_UPDATE, 0,0,0 ); TDCOM( TD_MOTOR, 0,0,0 ); // Motor aus printf("Please remove disk from Drive df%ld: and hit return.",unitnum); Read( Input(), buffer, sizeof(buffer) ); nodisk: inhibitdrive( unitnum, FALSE ); printf("%s",(breakloop==FALSE)?"All done.\n":"Operation failed !\n"); CloseDevice( myio ); } DeleteStdIO( myio ); } DeletePort( myport ); } //­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­ closelibs(); //­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­­ return( breakloop?RETURN_FAIL:RETURN_OK ); }