/* $Revision Header *** Header built automatically - do not edit! *********** * * (C) Copyright 1990/91 by Peter Vorwerk * * Name .....: ATCopy.c * Created ..: Sunday 09-Sep-90 15:12 * Revision .: 22 * * Date Author Comment * ========= ======== ==================== * 29-Apr-91 Peter Vorwerk Recompiled with 5.0d * 05-Feb-91 Peter Vorwerk Now will find XT's * --------- ------------- ------- 2.2 ----------- * 12-Jan-91 Peter Vorwerk New Intro * 12-Jan-91 Peter Vorwerk Bugfixing for SideCar's * 10-Jan-91 Peter Vorwerk New FileRequester * 08-Jan-91 Peter Vorwerk Bugfixing Conversion of char's * 07-Jan-91 Peter Vorwerk Speed up OPT B option * --------- ------------- ------- 2.1 ------------ * 01-Jan-91 Peter Vorwerk Two versions * 29-Dec-90 Peter Vorwerk Bugfixing (File size) * --------- ------------- ------- 2.0 ------------ * 11-Nov-90 Peter Vorwerk Bugfixing (FileRequester) * 29-Oct-90 Peter Vorwerk PC Namenkonventionen (2.0) * 27-Oct-90 Peter Vorwerk Bugfixing * 27-Oct-90 Peter Vorwerk PC part resident * 22-Oct-90 Peter Vorwerk Bugfixing * 22-Oct-90 Peter Vorwerk Multi buffers (PD <-> SHARE) * 19-Oct-90 Peter Vorwerk 8 small (128) buffers * 18-Oct-90 Peter Vorwerk Bugfixing * 17-Oct-90 Peter Vorwerk Double Buffer * 15-Oct-90 Peter Vorwerk Bugfixing * 10-Oct-90 Peter Vorwerk Allocates JanusRAM * 21-Sep-90 Peter Vorwerk Full WB Support * 15-Sep-90 Peter Vorwerk Suports conversion * 14-Sep-90 Peter Vorwerk Bugfixing * 13-Sep-90 Peter Vorwerk Now suports joker * 13-Sep-90 Peter Vorwerk Multi File no Wildcards * 10-Sep-90 Peter Vorwerk Stop at Timeout * 10-Sep-90 Peter Vorwerk Bugs fixed * 09-Sep-90 Peter Vorwerk Eine Datei keine Konversion * 09-Sep-90 Peter Vorwerk Created this file! * * $Revision Header ********************************************************/ #define REVISION 22 #define VERSION 2 #include #include /* Include-Files laden */ #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include char *Copy = "ATCopy2.22 (c) 29.04.1991 by Peter Vorwerk"; extern char *scdir(char *); #ifdef TEST long cumsec = 0,cummic = 0,sec1,sec2,mic1,mic2; #endif #define NUMBUF 24 #define DATA_LEN 129+1+1 /* 129 = 128 + 1 = Bufferlänge plus eins für überlange Blocke */ /* 1 für akktuelle Blocklänge (neu ab V2.1) */ /* 1 für Flag je Block */ #define BLOCK_LEN 129+1 /* 129 = 128 + 1 = Bufferlänge plus eins für überlange Blocke */ /* 1 für akktuelle Blocklänge (neu ab V2.1) */ #define B 'B' #define NC 'N' #define CR 'C' #define NONE '\0' /* Offset's für Parameter RAM (16K) */ /* Diese Werte gelten sowohl für die PC- als auch für die AT-Karte. */ #define FileFlag0 BASIS #define FileData0 BASIS + NUMBUF #define FILENAME 0x10 #define NEWDATA 0x20 #define LASTDATA 0x30 #define CLOSEFILE 0x40 #define EMERGENCY 0x50 #define SLEEP 0x60 /* Wird NOCH nicht benötigt, da das Programm auf dem PC/AT noch nicht resident mitläuft. Erst ab V2.0. */ #ifndef MAXTIME #define MAXTIME 20 #endif #define AT 1 #define XT 2 #define SideCar 3 struct AlertMessage { SHORT LeftEdge; BYTE TopEdge; char AlertText[50]; BYTE Flag; }; struct Library *IconBase = NULL; struct Library *JanusBase = NULL; struct Library *KD_FReqBase = NULL; UBYTE *Flag = NULL; UBYTE *Data = NULL; FILE *fh = NULL; UBYTE directory[128]; UBYTE filename[32]; UBYTE pattern[32]; struct ExtraData extras; extern struct AlertMessage TimeOut[]; #define TIMEOUT 80L extern struct AlertMessage NoLib[]; #define NOLIB 80L char tabelle[128] = { /* 0x80 */ 0x7f,0x7f,0x7f,0x7f,0x7f,0x7f,0x7f,0x7f, /* 0x88 */ 0x7f,0x7f,0x7f,0x7f,0x7f,0x7f,0x7f,0x7f, /* 0x90 */ 0x7f,0x7f,0x7f,0x7f,0x7f,0x7f,0x7f,0x7f, /* 0x98 */ 0x7f,0x7f,0x7f,0x7f,0x7f,0x7f,0x7f,0x7f, /* 0xa0 */ 0x7f,0xad,0x9b,0x9c,0x7f,0x9d,0x7f,0x7f, /* 0xa8 */ 0x7f,0x7f,0xa6,0xae,0xaa,0x7f,0x7f,0xfe, /* 0xb0 */ 0xf8,0xf1,0xfd,0x7f,0x7f,0xe6,0x7f,0xf9, /* 0xb8 */ 0x7f,0x7f,0xa7,0xaf,0xac,0xab,0x7f,0xa8, /* 0xc0 */ 0x7f,0x7f,0x7f,0x7f,0x8e,0x8f,0x92,0x80, /* 0xc8 */ 0x7f,0x90,0x7f,0x7f,0x7f,0x7f,0x7f,0x7f, /* 0xd0 */ 0x7f,0xa5,0x7f,0x7f,0x7f,0x7f,0x99,0x7f, /* 0xd8 */ 0x7f,0x7f,0x7f,0x7f,0x9a,0x7f,0x7f,0xe1, /* 0xe0 */ 0x85,0xa0,0x83,0x7f,0x84,0x86,0x91,0x87, /* 0xe8 */ 0x8a,0x82,0x88,0x89,0x8d,0xa1,0x8c,0x8b, /* 0xf0 */ 0xeb,0xa4,0x95,0xa2,0x93,0x7f,0x94,0xf6, /* 0xf8 */ 0xed,0x97,0xa3,0x96,0x81,0x7f,0x7f,0x98 }; /* In BASIS wird die BasisAdresse der PC/AT eingetragen. */ APTR BASIS = NULL; char ATCP[16]; extern struct NewWindow NewWindowStructure1; extern struct IntuiText IText9; void Version(void) { SPrintf(ATCP,"ATCopy V%ld.%ld",VERSION,REVISION); NewWindowStructure1.Title = (UBYTE *) ATCP; IText9.IText = (UBYTE *) ATCP; } void CheckForPC(void) { /* Ermitteln, ob und wenn ja ab welcher Adresse die PC/AT Karte ansprechbar ist. */ if ((BASIS = AllocJanusMem(DATA_LEN * NUMBUF,MEMF_PARAMETER | MEM_BYTEACCESS)) == NULL) { DisplayAlert(RECOVERY_ALERT,(char *) &NoLib,NOLIB); exit(20); } } int CheckPC(unsigned char *ptr) { ptr += 0x7fff7; /* Modus Register der XT/AT Karte siehe 'Amiga SYSTEM-Handbuch' */ if (*ptr >= 0xe0 || *ptr == 0) { return(SideCar); } /* Beim SideCar ist dieses Register mit DIP-Schltern aufgebaut. Daher die merkwürdige Abfrage. */ if (*ptr < 128) { return(AT); } return(XT); } void WakeUpPC(void) { unsigned char *ptr,*key,*intr; int i; UWORD *offset; long stsecs,stmics,ensecs,enmics; /* Auslösen eines (Software-) Interupts auf dem PC/AT um das schlafende Programm zu wecken! */ /* Zur Zeit ( noch ? ) nicht so möglich! Es wird entweder das Programm AT.exe oder das Programm XT.exe auf dem PC aufgerufen. Dazu werden die Zeichen A (X), T und {CR} direkt zum PC gesendet. Simulierte Tastatur. */ /* Die Keyboard Addresse ist als positiver Offset 0x72 in der Janus.library abgelegt. */ /* Achtung! Im 'Amiga SYSTEM-Handbuch wird die feste Addresse 0x7ffff als Keyboard Addresse genannt. Bei meinem Amiga 2000 mit AT Karte stimmte dies, jedoch nicht beim SideCar. Die Offset Struktur wurde experimentell ( teilweiser Speicherdump vom Programm PCWINDOW ) ermittelt. Zum Glück stimmte wenigstens die Adresse des Interrupts, so konnte ich im Speicher nach dem Auftreten dieser Kombination suchen und die nähere Umgebung disassemblieren. */ key = (unsigned char *) JanusBase; key += 0x72; offset = (UWORD *) key; ptr = (unsigned char *) GetJanusStart(); key = ptr + 0x7e000; key += *offset; intr = ptr + 0x7fffb; /* Addresse aus 'Amiga SYSTEM-Handbuch' */ *key = '\034'; /* {CR} */ *intr = '\377'; /* 0xff */ Delay(1); i = CheckPC(ptr); if (i == AT) { *key = '\036'; /* 'A' */ } else { *key = '\055'; /* 'X' */ } *intr = '\377'; /* 0xff */ Delay(1); *key = '\024'; /* 'T' */ *intr = '\377'; /* 0xff */ Delay(1); *key = '\034'; /* {CR} */ *intr = '\377'; /* 0xff */ /* Bei diesen Codes handelt es sich natürlich um die Roh-Codes der PC-Tastatur ! */ /* Siehe Handbücher zu Turbo Pascal o.ä. */ ptr = (unsigned char *) BASIS; *ptr++ = '\011'; /* Länge des Strings "ATCopy2.1" octal ! */ strcpy((char *) ptr,"ATCopy2.1"); /* Kein Änderung im Protokoll => 2.1 und 2.2 können gemischt werden. Aber nicht 2.0 mit 2.x !!! */ /* Die Startaddresse des angeforderten Buffers wird mit dem Text markiert und danach vom PC aus gesucht. Siehe PCCOPY.PAS */ ptr--; CurrentTime(&stsecs,&stmics); while(*ptr != 0) { Chk_Abort(); CurrentTime(&ensecs,&enmics); /* Wenn der XT/AT nich innerhalb von 20 Sekunden antworted das Programm abbrechen. */ if (ensecs - stsecs > MAXTIME * 2) { DisplayAlert(RECOVERY_ALERT,(char *) &TimeOut,TIMEOUT); FreeTrackedItem(GetTracker(TRAK_FREQ)); FreeJanusMem(BASIS,DATA_LEN * NUMBUF); exit(20); } } Flag = (UBYTE *) FileFlag0; for(i = 0; i < NUMBUF; i++) { *Flag++ = 0; } /* Alle Buffer sind leer und können benutzt werden. */ } void _abort(void) { #ifdef TEST Printf("\nInsgesamt %ld µsec gewarted.\n",cumsec*1000000+cummic); #endif #ifdef DEBUG Printf("\nLast Flag = <%lx>\n",*Flag); #endif *Flag = EMERGENCY; FreeTrackedItem(GetTracker(TRAK_FREQ)); FreeJanusMem(BASIS,DATA_LEN * NUMBUF); if (fh) fclose(fh); /* Da hier Programmende kann entfallen. */ exit(20); } void timeout(void) { long stsecs,stmics,ensecs,enmics; /* Prüfen, ob der Kanal frei ist und ggf. darauf warten. Dauert es allerdings länger als 10 Sekunden => Abbruch. */ #ifdef TEST CurrentTime(&sec1,&mic1); #endif CurrentTime(&stsecs,&stmics); while(*Flag != 0) { Delay(1); Chk_Abort(); CurrentTime(&ensecs,&enmics); if (ensecs - stsecs > MAXTIME) { #ifdef TEST CurrentTime(&sec2,&mic2); cumsec += sec2-sec1; cummic += mic2-mic1; Printf("\nInsgesamt %ld µsec gewarted.\n",cumsec*1000000+cummic); #endif #ifdef DEBUG Printf("\nLast Flag = <%lx>\n",*Flag); #endif *Flag = EMERGENCY; DisplayAlert(RECOVERY_ALERT,(char *) &TimeOut,TIMEOUT); FreeTrackedItem(GetTracker(TRAK_FREQ)); FreeJanusMem(BASIS,DATA_LEN * NUMBUF); if (fh) fclose(fh); /* Da hier Progende kann fh = NULL; entfallen. */ exit(20); } } #ifdef TEST CurrentTime(&sec2,&mic2); cumsec += sec2-sec1; cummic += mic2-mic1; #endif } extern int Konvert(int wert, char opt, int *flag); extern int transfer(UBYTE * data, char opt); int copyfile2(char *str, char *PC, char opt) { register int c; static int last = 0; int flag2 = FALSE; register char *filename; register UBYTE *data; char *s,buffer[80],buffer2[60]; if (*str == '\0') { return(FALSE); } if (strlen(PC) > 0) { s = &PC[strlen(PC)-1]; if (*s != ':' && *s != '\\') { /* Der PC-Pfad muß mit ':' oder '\\' enden. */ s++; *s++ = '\\'; *s = '\0'; } } filename = BaseName(str); s = buffer2; do { *s = *filename; if (*s == '\0') break; /* Nicht alle Zeichen sind beim PC für Dateinamen erlaubt. */ if (*s < '\041' || *s == '\\' || *s == '[' || *s == ']' || *s == '|' || *s > '\177') { filename++; s--; continue; } if (*s == '.') { filename = strrchr(filename,'.'); } /* Suchen des letzten '.' nur eine Extension ist beim PC/AT möglich. */ filename++; } while(*s++ != '\0'); if (buffer2[0] == '.' || buffer2[0] == '\0') { return(TRUE); } /* Der Name darf nicht leer "" sein oder nur aus einer Extension bestehen. */ if ((fh = fopen(str,"r")) == NULL) { return(FALSE); } /* File läst sich auf der Amigaseite nicht öffnen. => Programm abbrechen. */ strcpy(buffer,PC); strcat(buffer,buffer2); timeout(); data = Data; c = strlen(buffer); *data++ = c; filename = buffer; while(*filename != '\0') { *data++ = *filename++; } /* Dateiname übertragen. Längenbyte gefolgt vom Text ; PASCAL-Format. */ *Flag = FILENAME; if (*Flag != FILENAME && *Flag != 0) *Flag = EMERGENCY; /* Wenn direkt nach dem Schreibzugriff NICHT der Wert im Speicher steht ist ein Fehler aufgetreten. Sollte NIE vorkommem. => Programm abbrechen. */ do { Flag++; Data += BLOCK_LEN; last++; /* Umschalten auf den nächsten Buffer. Ringpuffer */ if (last == NUMBUF) { last = 0; Flag = (UBYTE *) FileFlag0; Data = (UBYTE *) FileData0; } } while(transfer(Data,opt)); Flag++; Data += BLOCK_LEN; last++; if (last == NUMBUF) { last = 0; Flag = (UBYTE *) FileFlag0; Data = (UBYTE *) FileData0; } fclose(fh); fh = NULL; /* FileHandle löschen damit bei einem Fehler nicht die Datei noch einmal geschlossen wird. Der GURU läst grüßen! */ return(TRUE); } extern char Intro(char **pc,char *opt); int copyfile(char *str, char *PC, char *Option) { int flag; char buffer[162],opt; struct FileList *ext; if (PC == NULL || *PC == '\0') PC = "\0 default PC-path"; if (Option == NULL) Option = "\0 Option"; /* Hier die gewünschte 'Default' Option eintragen. */ opt = Intro(&PC,Option); if (opt == 255 || opt == -1) return(FALSE); *Option = opt; /* Per Requester ausgewählte Option speichern. */ if (str == NULL || *str == '\0') { /* Wenn kein Dateiname per CLI oder WB übergeben wurde diesen per Requester anfordern. */ filename[0] = 0; extras.oktext = (UBYTE *) "Copy"; extras.canceltext = (UBYTE *) "No Way!"; if (FReq(NULL, (UBYTE *) ATCP,filename,directory,pattern, FR_CANCELTEXT | FR_EXTENDEDSELECT | FR_OKTEXT | FR_AUTOPOSITION | FR_AUTOSIZE | FR_NOINFO | FR_SCREENFONT ,&extras)) { flag = FALSE; if (extras.ExtendedList) { /* Wenn Extendet Select, siehe KR_FREQ.DOC, gewählt wurde NUR diese auswerten. */ ext = extras.ExtendedList; for (; ext; ext = ext->next) { strcpy(buffer,(char *) directory); strcat(buffer,(char *) ext->FileName); flag = copyfile2(buffer,PC,opt); } FreeMem(extras.ExtendedList,extras.ExtendedList->private); extras.ExtendedList = NULL; } else { /* Ansonsten den Dateinamen lesen. */ strcpy(buffer,(char *) directory); strcat(buffer,(char *) filename); flag = copyfile2(buffer,PC,opt); } } else { /* Keine Auswahl bzw. CAncel gewählt => ENDE! */ return(FALSE); } } else { /* Dateinamen per CLI oder WB vorgegeben. */ flag = copyfile2(str,PC,opt); } return(flag); } void main(int argc, char *argv[]) { register char **demo; register char *s; int wbmax,i; struct DiskObject *Do; struct WBStartup *Wbs; struct Process *proc = (struct Process *)FindTask(NULL); struct FileLock *origlock; Version(); directory[0] = filename[0] = pattern[0] = 0; /* Lib's öffnen. */ if (!(JanusBase = ArpOpenLibrary("janus.library",0L))) { DisplayAlert(RECOVERY_ALERT,(char *) &NoLib,NOLIB); exit(10); } if (!(KD_FReqBase = ArpOpenLibrary(KLIBNAME,KLIBVERSION))) { Puts("KD_FREQ.LIBRARY fehlt!\n"); exit(10); } CheckForPC(); /* Ermitteln der Basisadresse. */ WakeUpPC(); /* AT.EXE oder XT.EXE aufrufen. */ Flag = (UBYTE *) FileFlag0; Data = (UBYTE *) FileData0; if (argc > 0) { demo = (char **) argv[1]; if (demo != NULL) { if (*demo != NULL) { while(*demo != NULL) { /* Wenn Jokerzeichen im Argument sind, diese Auswerten mit scdir(). */ while(s = scdir(*demo)) { /* S ist aufgelöster Name, der zum Joker paßt. */ copyfile(s,argv[2],argv[3]); } demo++; } } else { do ; while(copyfile(NULL,argv[2],argv[3])); } } else { do ; while(copyfile(NULL,argv[2],argv[3])); } } else /* WB Aufruf */ { origlock = (struct FileLock *) CurrentDir(DupLock((BPTR) proc->pr_CurrentDir)); Wbs = (struct WBStartup *) argv; if (!(IconBase = ArpOpenLibrary("icon.library",0L))) { exit(10); } if (Wbs->sm_ArgList[0].wa_Lock) { struct FileLock *savelock = (struct FileLock *) CurrentDir(Wbs->sm_ArgList[0].wa_Lock); if (Do = (struct DiskObject *) GetDiskObject(Wbs->sm_ArgList[0].wa_Name)) { FreeDiskObject(Do); } CurrentDir((BPTR) savelock); } if ((wbmax = Wbs->sm_NumArgs - 1) == 0) { do ; while(copyfile(NULL,NULL,NULL)); /* Ganz ohne Parameter zB WorkBench */ } else { for(i = 0; i < wbmax; i++) { UnLock(CurrentDir(DupLock((BPTR) Wbs->sm_ArgList[i+1].wa_Lock))); if (Do = (struct DiskObject *) GetDiskObject(Wbs->sm_ArgList[i+1].wa_Name)) { FreeDiskObject(Do); } copyfile(Wbs->sm_ArgList[i+1].wa_Name,NULL,NULL); } } origlock = (struct FileLock *) CurrentDir((BPTR) origlock); } timeout(); *Flag = EMERGENCY; timeout(); /* Warten bis XT/AT fertig ist. Dann Speicher freigeben! */ #ifdef TEST Printf("\nInsgesamt %ld µsec gewarted.\n",cumsec*1000000+cummic); #endif FreeTrackedItem(GetTracker(TRAK_FREQ)); FreeJanusMem(BASIS,DATA_LEN * NUMBUF); } /* Das war's. */