|
|
1.1 root 1: /*
2: Hatari
3:
1.1.1.2 root 4: GEMDos intercept routines. These are used mainly for Hard Drive redirection of high level file routines.
1.1 root 5:
1.1.1.2 root 6: Bugs/things to fix:
7: * RS232/Printing
8: * Figure out how to handle long file names and case conflicts,
9: (eg. FOO.BAR and foo.bar is the same file in TOS but not UNIX)
10: * rmdir routine, can't remove dir with files in it. (another tos/unix difference)
11: * Fix bugs, there are probably a few lurking around in here..
12:
13: */
1.1 root 14:
1.1.1.4 ! root 15: #include <sys/stat.h>
! 16: #include <time.h>
! 17: #include <dirent.h>
! 18: #include <ctype.h>
! 19: #include <unistd.h>
! 20:
1.1 root 21: #include "main.h"
22: #include "cart.h"
1.1.1.2 root 23: #include "tos.h"
1.1 root 24: #include "debug.h"
25: #include "decode.h"
26: #include "dialog.h"
27: #include "file.h"
28: #include "floppy.h"
1.1.1.3 root 29: #include "hdc.h"
1.1 root 30: #include "gemdos.h"
31: #include "m68000.h"
32: #include "memAlloc.h"
33: #include "memorySnapShot.h"
34: #include "misc.h"
35: #include "printer.h"
36: #include "rs232.h"
37: #include "stMemory.h"
38:
1.1.1.2 root 39: #include "uae-cpu/hatari-glue.h"
40:
41:
1.1.1.3 root 42: /* #define GEMDOS_VERBOSE */
1.1 root 43: #define ENABLE_SAVING /* Turn on saving stuff */
44:
45: #define INVALID_HANDLE_VALUE -1
46:
47: #ifndef MAX_PATH
48: #define MAX_PATH 256
49: #endif
50:
1.1.1.3 root 51:
1.1.1.2 root 52: /* structure with all the drive-specific data for our emulated drives */
53: EMULATEDDRIVE **emudrives = NULL;
54:
1.1 root 55: typedef struct
56: {
1.1.1.3 root 57: BOOL bUsed;
58: FILE *FileHandle;
1.1.1.2 root 59: char szActualName[MAX_PATH]; /* used by F_DATIME (0x57) */
1.1 root 60: } FILE_HANDLE;
61:
1.1.1.2 root 62: typedef struct
63: {
64: BOOL bUsed;
65: int nentries; /* number of entries in fs directory */
66: int centry; /* current entry # */
67: struct dirent **found; /* legal files */
68: char path[MAX_PATH]; /* sfirst path */
69: } INTERNAL_DTA;
70:
1.1 root 71: FILE_HANDLE FileHandles[MAX_FILE_HANDLES];
1.1.1.2 root 72: INTERNAL_DTA InternalDTAs[MAX_DTAS_FILES];
1.1 root 73: int DTAIndex; /* Circular index into above */
74: BOOL bInitGemDOS; /* Have we re-directed GemDOS vector to our own routines yet? */
75: DTA *pDTA; /* Our GEMDOS hard drive Disc Transfer Address structure */
76: unsigned short int CurrentDrive; /* Current drive (0=A,1=B,2=C etc...) */
77:
78: /* List of GEMDos functions... */
79: char *pszGemDOSNames[] = {
1.1.1.2 root 80: "Term", /*0x00*/
81: "Conin", /*0x01*/
82: "ConOut", /*0x02*/
83: "Auxiliary Input", /*0x03*/
84: "Auxiliary Output", /*0x04*/
85: "Printer Output", /*0x05*/
86: "RawConIO", /*0x06*/
87: "Direct Conin no echo", /*0x07*/
88: "Conin no echo", /*0x08*/
89: "Print line", /*0x09*/
90: "ReadLine", /*0x0a*/
91: "ConStat", /*0x0b*/
92: "", /*0x0c*/
93: "", /*0x0d*/
94: "SetDrv", /*0x0e*/
95: "", /*0x0f*/
96: "Conout Stat", /*0x10*/
97: "PrtOut Stat", /*0x11*/
98: "Auxin Stat", /*0x12*/
99: "AuxOut Stat", /*0x13*/
100: "", /*0x14*/
101: "", /*0x15*/
102: "", /*0x16*/
103: "", /*0x17*/
104: "", /*0x18*/
105: "Current Disk", /*0x19*/
106: "Set DTA", /*0x1a*/
1.1.1.3 root 107: "", /*0x1b*/
108: "", /*0x1c*/
109: "", /*0x1d*/
110: "", /*0x1e*/
111: "", /*0x1f*/
112: "Super", /*0x20*/
113: "", /*0x21*/
114: "", /*0x22*/
115: "", /*0x23*/
116: "", /*0x24*/
117: "", /*0x25*/
118: "", /*0x26*/
119: "", /*0x27*/
120: "", /*0x28*/
121: "", /*0x29*/
122: "Get Date", /*0x2a*/
123: "Set Date", /*0x2b*/
124: "Get Time", /*0x2c*/
125: "Set Time", /*0x2d*/
126: "", /*0x2e*/
127: "Get DTA", /*0x2f*/
1.1.1.2 root 128: "Get Version Number", /*0x30*/
129: "Keep Process", /*0x31*/
1.1.1.3 root 130: "", /*0x32*/
131: "", /*0x33*/
132: "", /*0x34*/
133: "", /*0x35*/
1.1.1.2 root 134: "Get Disk Free Space", /*0x36*/
135: "", /*0x37*/
136: "", /*0x38*/
137: "MkDir", /*0x39*/
138: "RmDir", /*0x3a*/
139: "ChDir", /*0x3b*/
140: "Create", /*0x3c*/
141: "Open", /*0x3d*/
142: "Close", /*0x3e*/
143: "Read", /*0x3f*/
144: "Write", /*0x40*/
145: "UnLink", /*0x41*/
146: "LSeek", /*0x42*/
147: "ChMod", /*0x43*/
148: "", /*0x44*/
149: "Dup", /*0x45*/
150: "Force", /*0x46*/
151: "GetDir", /*0x47*/
152: "Malloc", /*0x48*/
153: "MFree", /*0x49*/
154: "SetBlock", /*0x4a*/
155: "Exec", /*0x4b*/
156: "Term", /*0x4c*/
157: "", /*0x4d*/
158: "SFirst", /*0x4e*/
159: "SNext", /*0x4f*/
160: "", /*0x50*/
161: "", /*0x51*/
162: "", /*0x52*/
163: "", /*0x53*/
164: "", /*0x54*/
165: "", /*0x55*/
166: "Rename", /*0x56*/
167: "GSDTof" /*0x57*/
1.1 root 168: };
169:
1.1.1.2 root 170: unsigned char GemDOS_ConvertAttribute(mode_t mode);
171:
1.1.1.3 root 172:
173:
174:
1.1.1.2 root 175: /*-------------------------------------------------------*/
176: /*
177: Routines to convert time and date to MSDOS format.
178: Originally from the STonX emulator. (cheers!)
179: */
180: unsigned short time2dos (time_t t)
181: {
182: struct tm *x;
183: x = localtime (&t);
184: return (x->tm_sec>>1)|(x->tm_min<<5)|(x->tm_hour<<11);
185: }
1.1 root 186:
1.1.1.2 root 187: unsigned short date2dos (time_t t)
188: {
189: struct tm *x;
190: x = localtime (&t);
191: return x->tm_mday | ((x->tm_mon+1)<<5) | ( ((x->tm_year-80>0)?x->tm_year-80:0) << 9);
192: }
1.1 root 193:
1.1.1.3 root 194:
1.1.1.2 root 195: /*
196: Convert a string to uppercase
197: */
1.1 root 198: void strupr(char *string)
199: {
1.1.1.4 ! root 200: while(*string)
! 201: {
! 202: *string = toupper(*string);
! 203: string++;
! 204: }
1.1.1.2 root 205: }
206:
1.1.1.3 root 207:
1.1.1.2 root 208: /*-----------------------------------------------------------------------*/
209: /*
210: Populate a DATETIME structure with file info
211: */
212: BOOL GetFileInformation(char *name, DATETIME *DateTime)
213: {
214: struct stat filestat;
215: int n;
216: struct tm *x;
217:
218: n = stat(name, &filestat);
219: if( n != 0 ) return(FALSE);
220: x = localtime( &filestat.st_mtime );
221:
222: DateTime->word1 = 0;
223: DateTime->word2 = 0;
224:
225: DateTime->word1 |= (x->tm_mday & 0x1F); /* 5 bits */
226: DateTime->word1 |= (x->tm_mon & 0x0F)<<5; /* 4 bits */
227: DateTime->word1 |= (((x->tm_year-80>0)?x->tm_year-80:0) & 0x7F)<<9; /* 7 bits*/
228:
229: DateTime->word2 |= (x->tm_sec & 0x1F); /* 5 bits */
230: DateTime->word2 |= (x->tm_min & 0x3F)<<5; /* 6 bits */
231: DateTime->word2 |= (x->tm_hour & 0x1F)<<11; /* 5 bits */
232:
233: return(TRUE);
234: }
1.1.1.3 root 235:
236:
1.1.1.2 root 237: /*-----------------------------------------------------------------------*/
238: /*
239: Populate the DTA buffer with file info
240: */
241: int PopulateDTA(char *path, struct dirent *file)
242: {
243: char tempstr[MAX_PATH];
244: struct stat filestat;
245: int n;
246:
247: sprintf(tempstr, "%s/%s", path, file->d_name);
248: n = stat(tempstr, &filestat);
249: if(n != 0) return(FALSE); /* return on error */
250:
251: if(!pDTA) return(FALSE); /* no DTA pointer set */
252: strupr(file->d_name); /* convert to atari-style uppercase */
253: strncpy(pDTA->dta_name,file->d_name,TOS_NAMELEN); /* FIXME: better handling of long file names */
254: STMemory_WriteLong_PCSpace(pDTA->dta_size, (long)filestat.st_size);
255: STMemory_WriteWord_PCSpace(pDTA->dta_time, time2dos(filestat.st_mtime));
256: STMemory_WriteWord_PCSpace(pDTA->dta_date, date2dos(filestat.st_mtime));
257: pDTA->dta_attrib = GemDOS_ConvertAttribute(filestat.st_mode);
258:
1.1.1.4 ! root 259: return(TRUE);
1.1.1.2 root 260: }
261:
1.1.1.3 root 262:
1.1.1.2 root 263: /*-----------------------------------------------------------------------*/
264: /*
265: Clear a used DTA structure.
266: */
267: void ClearInternalDTA(){
268: int i;
269:
270: /* clear the old DTA structure */
271: if(InternalDTAs[DTAIndex].found != NULL){
272: for(i=0; i <InternalDTAs[DTAIndex].nentries; i++)
273: free(InternalDTAs[DTAIndex].found[i]);
274: free(InternalDTAs[DTAIndex].found);
275: }
276: InternalDTAs[DTAIndex].bUsed = FALSE;
277: }
278:
1.1.1.3 root 279:
1.1.1.2 root 280: /*-----------------------------------------------------------------------*/
281: /*
282: Match a file to a dir mask.
283: */
284: static int match (char *pat, char *name)
285: {
286: /* make uppercase copies */
287: char p0[MAX_PATH], n0[MAX_PATH];
288: strcpy(p0, pat);
289: strcpy(n0, name);
290: strupr(p0); strupr(n0);
291:
292: if(name[0] == '.') return(FALSE); /* no .* files */
293: if (strcmp(pat,"*.*")==0) return(TRUE);
294: else if (strcasecmp(pat,name)==0) return(TRUE);
295: else
296: {
297: char *p=p0,*n=n0;
298: for(;*n;)
299: {
300: if (*p=='*') {while (*n && *n != '.') n++;p++;}
301: else if (*p=='?' && *n) {n++;p++;}
302: else if (*p++ != *n++) return(FALSE);
303: }
304: if (*p==0)
305: {
306: return(TRUE);
307: }
308: }
309: return(FALSE);
310: }
311:
312: /*-----------------------------------------------------------------------*/
313: /*
1.1.1.4 ! root 314: Parse directory from sfirst mask
! 315: - e.g.: input: "hdemudir/auto/mask*.*" outputs: "hdemudir/auto"
1.1.1.2 root 316: */
317: void fsfirst_dirname(char *string, char *new){
318: int i=0;
319:
320: sprintf(new, string);
321: /* convert to front slashes. */
322: i=0;
323: while(new[i] != '\0'){
324: if(new[i] == '\\') new[i] = '/';
325: i++;
326: }
327: while(string[i] != '\0'){new[i] = string[i]; i++;} /* find end of string */
328: while(new[i] != '/') i--; /* find last slash */
329: new[i] = '\0';
1.1.1.3 root 330:
1.1 root 331: }
332:
1.1.1.2 root 333: /*-----------------------------------------------------------------------*/
334: /*
335: Parse directory mask, e.g. "*.*"
336: */
337: void fsfirst_dirmask(char *string, char *new){
338: int i=0, j=0;
339: while(string[i] != '\0')i++; /* go to end of string */
340: while(string[i] != '/') i--; /* find last slash */
341: i++;
342: while(string[i] != '\0')new[j++] = string[i++]; /* go to end of string */
343: new[j++] = '\0';
344: }
1.1 root 345:
1.1.1.2 root 346: /*-----------------------------------------------------------------------*/
1.1 root 347: /*
348: Initialize GemDOS/PC file system
349: */
350: void GemDOS_Init(void)
351: {
1.1.1.2 root 352: int i;
353: bInitGemDOS = FALSE;
354:
355: /* Clear handles structure */
1.1.1.3 root 356: Memory_Clear(FileHandles, sizeof(FILE_HANDLE)*MAX_FILE_HANDLES);
1.1.1.2 root 357: /* Clear DTAs */
1.1.1.3 root 358: for(i=0; i<MAX_DTAS_FILES; i++)
359: {
1.1.1.2 root 360: InternalDTAs[i].bUsed = FALSE;
361: InternalDTAs[i].nentries = 0;
362: InternalDTAs[i].found = NULL;
363: }
364: DTAIndex = 0;
1.1 root 365: }
366:
1.1.1.2 root 367: /*-----------------------------------------------------------------------*/
1.1 root 368: /*
369: Reset GemDOS file system
370: */
1.1.1.3 root 371: void GemDOS_Reset()
1.1 root 372: {
373: int i;
374:
1.1.1.2 root 375: /* Init file handles table */
1.1.1.3 root 376: for(i=0; i<MAX_FILE_HANDLES; i++)
377: {
1.1.1.2 root 378: /* Was file open? If so close it */
1.1 root 379: if (FileHandles[i].bUsed)
1.1.1.2 root 380: fclose(FileHandles[i].FileHandle);
1.1 root 381:
1.1.1.2 root 382: FileHandles[i].FileHandle = NULL;
1.1 root 383: FileHandles[i].bUsed = FALSE;
384: }
385:
1.1.1.3 root 386: for(i=0; i<MAX_DTAS_FILES; i++)
387: {
1.1.1.2 root 388: InternalDTAs[i].bUsed = FALSE;
389: InternalDTAs[i].nentries = 0;
390: InternalDTAs[i].found = NULL;
391: }
392:
393: /* Reset */
1.1 root 394: bInitGemDOS = FALSE;
395: CurrentDrive = nBootDrive;
396: pDTA = NULL;
397: DTAIndex = 0;
398: }
399:
1.1.1.3 root 400:
401: /*-----------------------------------------------------------------------*/
402: /*
403: Initialize a GEMDOS drive.
404: Only 1 emulated drive allowed, as of yet.
405: */
406: void GemDOS_InitDrives()
407: {
408: int i;
409:
410: /* intialize data for harddrive emulation: */
411: if(!GEMDOS_EMU_ON)
412: {
413: emudrives = malloc( MAX_HARDDRIVES*sizeof(EMULATEDDRIVE *) );
414: for(i=0; i<MAX_HARDDRIVES; i++)
415: emudrives[0] = malloc( sizeof(EMULATEDDRIVE) );
416: }
417:
418: for(i=0; i<MAX_HARDDRIVES; i++)
419: {
420: /* set emulation directory string */
421: strcpy(emudrives[i]->hd_emulation_dir, ConfigureParams.HardDisc.szHardDiscDirectories[i]);
422:
423: /* remove trailing slash, if any in the directory name */
424: File_CleanFileName(emudrives[i]->hd_emulation_dir);
425:
426: /* set drive to 2 + number of ACSI partitions */
427: emudrives[i]->hd_letter = 2 + nPartitions + i;
428:
429: ConfigureParams.HardDisc.nDriveList += 1;
430:
431: fprintf(stderr, "Hard drive emulation, %c: <-> %s\n",
432: emudrives[i]->hd_letter + 'A', emudrives[i]->hd_emulation_dir);
433: }
434: }
435:
436: /*-----------------------------------------------------------------------*/
437: /*
438: Un-init the GEMDOS drive
439: */
440: void GemDOS_UnInitDrives()
441: {
442: int i;
443:
444: GemDOS_Reset(); /* Close all open files on emulated drive*/
445:
446: if(GEMDOS_EMU_ON)
447: {
448: for(i=0; i<MAX_HARDDRIVES; i++)
449: {
450: free(emudrives[i]); /* Release memory */
451: ConfigureParams.HardDisc.nDriveList -= 1;
452: }
453:
454: free(emudrives);
455: emudrives = NULL;
456: }
457: }
458:
459:
1.1.1.2 root 460: /*-----------------------------------------------------------------------*/
1.1 root 461: /*
462: Save/Restore snapshot of local variables('MemorySnapShot_Store' handles type)
463: */
464: void GemDOS_MemorySnapShot_Capture(BOOL bSave)
465: {
466: unsigned int Addr;
467: int i;
468:
1.1.1.2 root 469: /* Save/Restore details */
1.1 root 470: MemorySnapShot_Store(&DTAIndex,sizeof(DTAIndex));
471: MemorySnapShot_Store(&bInitGemDOS,sizeof(bInitGemDOS));
472: if (bSave) {
473: Addr = (unsigned int)pDTA-(unsigned int)STRam;
474: MemorySnapShot_Store(&Addr,sizeof(Addr));
475: }
476: else {
477: MemorySnapShot_Store(&Addr,sizeof(Addr));
478: pDTA = (DTA *)((unsigned int)STRam+(unsigned int)Addr);
479: }
480: MemorySnapShot_Store(&CurrentDrive,sizeof(CurrentDrive));
1.1.1.2 root 481: /* Don't save file handles as files may have changed which makes
482: it impossible to get a valid handle back */
1.1 root 483: if (!bSave) {
1.1.1.2 root 484: /* Clear file handles */
1.1 root 485: for(i=0; i<MAX_FILE_HANDLES; i++) {
1.1.1.2 root 486: FileHandles[i].FileHandle = NULL;
1.1 root 487: FileHandles[i].bUsed = FALSE;
488: }
489: }
490: }
491:
1.1.1.2 root 492: /*-----------------------------------------------------------------------*/
1.1 root 493: /*
494: Return free PC file handle table index, or -1 if error
495: */
496: int GemDOS_FindFreeFileHandle(void)
497: {
498: int i;
499:
500: /* Scan our file list for free slot */
501: for(i=0; i<MAX_FILE_HANDLES; i++) {
502: if (!FileHandles[i].bUsed)
503: return(i);
504: }
505:
506: /* Cannot open any more files, return error */
507: return(-1);
508: }
509:
1.1.1.2 root 510: /*-----------------------------------------------------------------------*/
1.1 root 511: /*
512: Check ST handle is within our table range, return TRUE if not
513: */
514: BOOL GemDOS_IsInvalidFileHandle(int Handle)
515: {
516: BOOL bInvalidHandle=FALSE;
517:
518: /* Check handle was valid with our handle table */
519: if ( (Handle<0) || (Handle>=MAX_FILE_HANDLES) )
520: bInvalidHandle = TRUE;
521: else if (!FileHandles[Handle].bUsed)
522: bInvalidHandle = TRUE;
523:
524: return(bInvalidHandle);
525: }
526:
1.1.1.2 root 527: /*-----------------------------------------------------------------------*/
1.1 root 528: /*
529: Find drive letter from a filename, eg C,D... and return as drive ID(C:2, D:3...)
1.1.1.3 root 530: returns the current drive number if none is specified.
1.1 root 531: */
532: int GemDOS_FindDriveNumber(char *pszFileName)
533: {
534: /* Does have 'A:' or 'C:' etc.. at start of string? */
535: if ( (pszFileName[0]!='\0') && (pszFileName[1]==':') ) {
536: if ( (pszFileName[0]>='a') && (pszFileName[0]<='z') )
537: return(pszFileName[0]-'a');
538: else if ( (pszFileName[0]>='A') && (pszFileName[0]<='Z') )
539: return(pszFileName[0]-'A');
540: }
541:
542: return(CurrentDrive);
543: }
544:
1.1.1.2 root 545: /*-----------------------------------------------------------------------*/
1.1 root 546: /*
547: Return drive ID(C:2, D:3 etc...) or -1 if not one of our emulation hard-drives
548: */
549: int GemDOS_IsFileNameAHardDrive(char *pszFileName)
550: {
551: int DriveLetter;
552:
1.1.1.3 root 553: /* Do we even have a hard-drive? */
554: if(GEMDOS_EMU_ON)
555: {
556: DriveLetter = GemDOS_FindDriveNumber(pszFileName);
557: /* add support for multiple drives here.. */
558: if( DriveLetter == emudrives[0]->hd_letter )
559: return(DriveLetter);
560: }
561: /* Not a high-level redirected drive */
562: return(-1);
563:
564: /* this code is depreciated */
1.1 root 565: /* Do we even have a hard-drive? */
566: if (ConfigureParams.HardDisc.nDriveList!=DRIVELIST_NONE) {
1.1.1.2 root 567: /* Find drive letter(as number) */
1.1 root 568: DriveLetter = GemDOS_FindDriveNumber(pszFileName);
1.1.1.2 root 569: /* Does match one of our drives? */
1.1 root 570: if ( (DriveLetter>=2) && (DriveLetter<=DRIVELIST_TO_DRIVE_INDEX(ConfigureParams.HardDisc.nDriveList)) )
571: return(DriveLetter);
572: }
573:
1.1.1.2 root 574: /* No, let TOS handle it */
1.1 root 575: return(-1);
576: }
577:
1.1.1.2 root 578: /*-----------------------------------------------------------------------*/
1.1 root 579: /*
580: Use hard-drive directory, current ST directory and filename to create full path
581: */
582: void GemDOS_CreateHardDriveFileName(int Drive,char *pszFileName,char *pszDestName)
583: {
1.1.1.3 root 584: /* int DirIndex = Misc_LimitInt(Drive-2, 0,ConfigureParams.HardDisc.nDriveList-1); */
1.1.1.2 root 585: int i;
586:
1.1.1.3 root 587: if(pszFileName[0] == '\0') return; /* check for valid string */
588:
1.1.1.2 root 589: /* case full filename "C:\foo\bar" */
590: if(pszFileName[1] == ':') {
591: sprintf(pszDestName, "%s%s", emudrives[0]->hd_emulation_dir, File_RemoveFileNameDrive(pszFileName));
1.1.1.3 root 592: }
593: /* case referenced from root: "\foo\bar" */
1.1.1.2 root 594: else if(pszFileName[0] == '\\'){
595: sprintf(pszDestName, "%s%s", emudrives[0]->hd_emulation_dir, pszFileName);
596: }
1.1.1.3 root 597: /* case referenced from current directory */
1.1.1.2 root 598: else {
599: sprintf(pszDestName, "%s%s%s", emudrives[0]->hd_emulation_dir, emudrives[0]->fs_currpath, pszFileName);
600: }
601:
602: /* convert to front slashes. */
603: i=0;
604: while(pszDestName[i] != '\0'){
605: if(pszDestName[i] == '\\') pszDestName[i] = '/';
606: i++;
607: }
1.1 root 608:
609: }
610:
1.1.1.2 root 611: /*-----------------------------------------------------------------------*/
1.1 root 612: /*
613: Covert from FindFirstFile/FindNextFile attribute to GemDOS format
614: */
1.1.1.2 root 615: unsigned char GemDOS_ConvertAttribute(mode_t mode)
1.1 root 616: {
1.1.1.2 root 617: unsigned char Attrib=0;
618:
619: /* FIXME: More attributes */
620: if(S_ISDIR(mode)) Attrib |= GEMDOS_FILE_ATTRIB_SUBDIRECTORY;
621:
1.1 root 622: /* FIXME */
623: /*
624: // Look up attributes
625: if (dwFileAttributes&FILE_ATTRIBUTE_READONLY)
626: Attrib |= GEMDOS_FILE_ATTRIB_READONLY;
627: if (dwFileAttributes&FILE_ATTRIBUTE_HIDDEN)
628: Attrib |= GEMDOS_FILE_ATTRIB_HIDDEN;
629: if (dwFileAttributes&FILE_ATTRIBUTE_DIRECTORY)
630: Attrib |= GEMDOS_FILE_ATTRIB_SUBDIRECTORY;
631: */
632: return(Attrib);
633: }
634:
1.1.1.2 root 635: /*-----------------------------------------------------------------------*/
1.1 root 636: /*
637: GEMDOS Cauxin
638: Call 0x3
639: */
640: BOOL GemDOS_Cauxin(unsigned long Params)
641: {
642: unsigned char Char;
643:
1.1.1.2 root 644: /* Wait here until a character is ready */
1.1 root 645: while(!RS232_GetStatus());
646:
1.1.1.2 root 647: /* And read character */
1.1 root 648: RS232_ReadBytes(&Char,1);
649: Regs[REG_D0] = Char;
650:
651: return(TRUE);
652: }
653:
1.1.1.2 root 654: /*-----------------------------------------------------------------------*/
1.1 root 655: /*
656: GEMDOS Cauxout
657: Call 0x4
658: */
659: BOOL GemDOS_Cauxout(unsigned long Params)
660: {
661: unsigned char Char;
662:
1.1.1.2 root 663: /* Send character to RS232 */
1.1 root 664: Char = STMemory_ReadWord(Params+SIZE_WORD);
665: RS232_TransferBytesTo(&Char,1);
666:
667: return(TRUE);
668: }
669:
1.1.1.2 root 670: /*-----------------------------------------------------------------------*/
1.1 root 671: /*
672: GEMDOS Cprnout
673: Call 0x5
674: */
675: BOOL GemDOS_Cprnout(unsigned long Params)
676: {
677: unsigned char Char;
678:
1.1.1.2 root 679: /* Send character to printer(or file) */
1.1 root 680: Char = STMemory_ReadWord(Params+SIZE_WORD);
681: Printer_TransferByteTo(Char);
1.1.1.2 root 682: Regs[REG_D0] = -1; /* Printer OK */
1.1 root 683:
684: return(TRUE);
685: }
686:
1.1.1.2 root 687: /*-----------------------------------------------------------------------*/
1.1 root 688: /*
689: GEMDOS Set drive (0=A,1=B,2=C etc...)
690: Call 0xE
691: */
692: BOOL GemDOS_SetDrv(unsigned long Params)
693: {
1.1.1.2 root 694: /* Read details from stack for our own use */
1.1 root 695: CurrentDrive = STMemory_ReadWord(Params+SIZE_WORD);
696:
1.1.1.2 root 697: /* Still re-direct to TOS */
1.1 root 698: return(FALSE);
699: }
700:
1.1.1.2 root 701: /*-----------------------------------------------------------------------*/
1.1 root 702: /*
703: GEMDOS Cprnos
704: Call 0x11
705: */
706: BOOL GemDOS_Cprnos(unsigned long Params)
707: {
1.1.1.2 root 708: Regs[REG_D0] = -1; /* Printer OK */
1.1 root 709:
710: return(TRUE);
711: }
712:
1.1.1.2 root 713: /*-----------------------------------------------------------------------*/
1.1 root 714: /*
715: GEMDOS Cauxis
716: Call 0x12
717: */
718: BOOL GemDOS_Cauxis(unsigned long Params)
719: {
1.1.1.2 root 720: /* Read our RS232 state */
1.1 root 721: if (RS232_GetStatus())
1.1.1.2 root 722: Regs[REG_D0] = -1; /* Chars waiting */
1.1 root 723: else
724: Regs[REG_D0] = 0;
725:
726: return(TRUE);
727: }
728:
1.1.1.2 root 729: /*-----------------------------------------------------------------------*/
1.1 root 730: /*
731: GEMDOS Cauxos
732: Call 0x13
733: */
734: BOOL GemDOS_Cauxos(unsigned long Params)
735: {
1.1.1.2 root 736: Regs[REG_D0] = -1; /* Device ready */
1.1 root 737:
738: return(TRUE);
739: }
740:
1.1.1.2 root 741: /*-----------------------------------------------------------------------*/
1.1 root 742: /*
743: GEMDOS Set Disc Transfer Address (DTA)
744: Call 0x1A
745: */
746: BOOL GemDOS_SetDTA(unsigned long Params)
747: {
1.1.1.2 root 748: /* Look up on stack to find where DTA is! Store as PC pointer */
1.1 root 749: pDTA = (DTA *)STRAM_ADDR(STMemory_ReadLong(Params+SIZE_WORD));
750:
751: return(FALSE);
752: }
753:
1.1.1.2 root 754: /*-----------------------------------------------------------------------*/
755: /*
756: GEMDOS Dfree Free disc space.
757: Call 0x39
758: */
759: BOOL GemDOS_DFree(unsigned long Params)
760: {
761: int Drive;
762: unsigned long Address;
763:
764: Address = (unsigned long)STMemory_ReadLong(Params+SIZE_WORD);
765: Drive = STMemory_ReadWord(Params+SIZE_WORD+SIZE_LONG);
766: /* is it our drive? */
767: if((Drive == 0 && CurrentDrive >= 2) || Drive >= 3){
768: /* FIXME: Report actual free drive space */
769:
770: STMemory_WriteLong(Address, 10*2048); /* free clusters (mock 10 Mb) */
771: STMemory_WriteLong(Address+SIZE_LONG, 50*2048 ); /* total clusters (mock 50 Mb) */
772:
773: STMemory_WriteLong(Address+SIZE_LONG*2, 512 ); /* bytes per sector */
774: STMemory_WriteLong(Address+SIZE_LONG*3, 1 ); /* sectors per cluster */
775: return (TRUE);
776: } else return(FALSE); /* redirect to TOS */
777: }
778:
779: /*-----------------------------------------------------------------------*/
1.1 root 780: /*
781: GEMDOS MkDir
782: Call 0x39
783: */
784: BOOL GemDOS_MkDir(unsigned long Params)
785: {
786: char szDirPath[MAX_PATH];
787: char *pDirName;
788: int Drive;
789:
1.1.1.2 root 790: /* Find directory to make */
1.1 root 791: pDirName = (char *)STRAM_ADDR(STMemory_ReadLong(Params+SIZE_WORD));
1.1.1.2 root 792:
1.1 root 793: Drive = GemDOS_IsFileNameAHardDrive(pDirName);
1.1.1.2 root 794:
1.1 root 795: if (ISHARDDRIVE(Drive)) {
1.1.1.2 root 796: /* Copy old directory, as if calls fails keep this one */
1.1 root 797: GemDOS_CreateHardDriveFileName(Drive,pDirName,szDirPath);
798:
1.1.1.2 root 799: /* Attempt to make directory */
1.1 root 800: if ( mkdir(szDirPath, 0755)==0 )
801: Regs[REG_D0] = GEMDOS_EOK;
802: else
1.1.1.2 root 803: Regs[REG_D0] = GEMDOS_EACCDN; /* Access denied */
1.1 root 804:
805: return(TRUE);
806: }
807: return(FALSE);
808: }
809:
1.1.1.2 root 810: /*-----------------------------------------------------------------------*/
1.1 root 811: /*
812: GEMDOS RmDir
813: Call 0x3A
814: */
815: BOOL GemDOS_RmDir(unsigned long Params)
816: {
817: char szDirPath[MAX_PATH];
818: char *pDirName;
819: int Drive;
820:
1.1.1.2 root 821: /* Find directory to make */
1.1 root 822: pDirName = (char *)STRAM_ADDR(STMemory_ReadLong(Params+SIZE_WORD));
823: Drive = GemDOS_IsFileNameAHardDrive(pDirName);
824: if (ISHARDDRIVE(Drive)) {
1.1.1.2 root 825: /* Copy old directory, as if calls fails keep this one */
1.1 root 826: GemDOS_CreateHardDriveFileName(Drive,pDirName,szDirPath);
827:
1.1.1.2 root 828: /* Attempt to make directory */
1.1 root 829: if ( rmdir(szDirPath)==0 )
830: Regs[REG_D0] = GEMDOS_EOK;
831: else
1.1.1.2 root 832: Regs[REG_D0] = GEMDOS_EACCDN; /* Access denied */
1.1 root 833:
834: return(TRUE);
835: }
836: return(FALSE);
837: }
838:
1.1.1.2 root 839: /*-----------------------------------------------------------------------*/
1.1 root 840: /*
841: GEMDOS ChDir
842: Call 0x3B
843: */
844: BOOL GemDOS_ChDir(unsigned long Params)
845: {
846: char szDirPath[MAX_PATH];
847: char *pDirName;
848: int Drive;
1.1.1.2 root 849: int n;
1.1 root 850:
1.1.1.2 root 851: /* Find new directory */
1.1 root 852: pDirName = (char *)STRAM_ADDR(STMemory_ReadLong(Params+SIZE_WORD));
1.1.1.2 root 853:
1.1 root 854: Drive = GemDOS_IsFileNameAHardDrive(pDirName);
1.1.1.3 root 855:
1.1 root 856: if (ISHARDDRIVE(Drive)) {
857:
1.1.1.3 root 858: if(pDirName[1] == ':') pDirName += 2;
859:
860: /* FIXME: Klugdy code, check path exists, else error (GEMDOS_EPTHNF) */
861:
862: sprintf(szDirPath, "%s/", pDirName);
863:
864: /* front-slashify */
1.1.1.2 root 865: for(n=0;n<MAX_PATH;n++) if(szDirPath[n] == '\\')szDirPath[n] = '/';
1.1.1.3 root 866:
867: /* remove any trailing slashes */
868: if (szDirPath[strlen(szDirPath)-1]=='/' && szDirPath[strlen(szDirPath)-2]=='/')
869: szDirPath[strlen(szDirPath)-1] = '\0'; /* then remove it! */
870:
871:
872: strcpy(emudrives[0]->fs_currpath, szDirPath);
1.1.1.2 root 873: Regs[REG_D0] = GEMDOS_EOK;
1.1 root 874: return(TRUE);
875: }
1.1.1.2 root 876:
1.1 root 877: return(FALSE);
878: }
879:
1.1.1.2 root 880: /*-----------------------------------------------------------------------*/
1.1 root 881: /*
882: GEMDOS Create file
883: Call 0x3C
884: */
885: BOOL GemDOS_Create(unsigned long Params)
886: {
887: char szActualFileName[MAX_PATH];
888: char *pszFileName;
1.1.1.2 root 889: char *rwflags[] = { "w+", /* read / write (truncate if exists) */
890: "wb" /* write only */
891: };
1.1 root 892: int Drive,Index,Mode;
893:
1.1.1.2 root 894: /* Find filename */
1.1 root 895: pszFileName = (char *)STRAM_ADDR(STMemory_ReadLong(Params+SIZE_WORD));
896: Mode = STMemory_ReadWord(Params+SIZE_WORD+SIZE_LONG);
897: Drive = GemDOS_IsFileNameAHardDrive(pszFileName);
898: if (ISHARDDRIVE(Drive)) {
1.1.1.2 root 899: /* And convert to hard drive filename */
1.1 root 900: GemDOS_CreateHardDriveFileName(Drive,pszFileName,szActualFileName);
901:
1.1.1.2 root 902: /* Find slot to store file handle, as need to return WORD handle for ST */
1.1 root 903: Index = GemDOS_FindFreeFileHandle();
904: if (Index==-1) {
1.1.1.2 root 905: /* No free handles, return error code */
906: Regs[REG_D0] = GEMDOS_ENHNDL; /* No more handles */
1.1 root 907: return(TRUE);
908: }
909: else {
910: #ifdef ENABLE_SAVING
911:
1.1.1.2 root 912: FileHandles[Index].FileHandle = fopen(szActualFileName, rwflags[Mode&0x01]);
913:
914: if (FileHandles[Index].FileHandle != NULL) {
1.1 root 915: /* Tag handle table entry as used and return handle */
916: FileHandles[Index].bUsed = TRUE;
1.1.1.2 root 917: Regs[REG_D0] = Index+BASE_FILEHANDLE; /* Return valid ST file handle from range 6 to 45! (ours start from 0) */
1.1 root 918: return(TRUE);
919: }
920: else {
1.1.1.2 root 921: Regs[REG_D0] = GEMDOS_EFILNF; /* File not found */
1.1 root 922: return(TRUE);
923: }
924: #else
1.1.1.2 root 925: Regs[REG_D0] = GEMDOS_EFILNF; /* File not found */
1.1 root 926: return(TRUE);
927: #endif
928: }
929: }
930:
931: return(FALSE);
932: }
933:
1.1.1.2 root 934: /*-----------------------------------------------------------------------*/
1.1 root 935: /*
936: GEMDOS Open file
937: Call 0x3D
938: */
939: BOOL GemDOS_Open(unsigned long Params)
940: {
941: char szActualFileName[MAX_PATH];
942: char *pszFileName;
1.1.1.2 root 943: char *open_modes[] = { "rb", "wb", "r+" }; /* convert atari modes to stdio modes */
1.1 root 944: int Drive,Index,Mode;
945:
1.1.1.2 root 946: /* Find filename */
1.1 root 947: pszFileName = (char *)STRAM_ADDR(STMemory_ReadLong(Params+SIZE_WORD));
948: Mode = STMemory_ReadWord(Params+SIZE_WORD+SIZE_LONG);
949: Drive = GemDOS_IsFileNameAHardDrive(pszFileName);
1.1.1.2 root 950:
1.1 root 951: if (ISHARDDRIVE(Drive)) {
1.1.1.2 root 952: /* And convert to hard drive filename */
1.1 root 953: GemDOS_CreateHardDriveFileName(Drive,pszFileName,szActualFileName);
1.1.1.2 root 954: /* Find slot to store file handle, as need to return WORD handle for ST */
1.1 root 955: Index = GemDOS_FindFreeFileHandle();
1.1.1.2 root 956: if (Index == -1) {
957: /* No free handles, return error code */
958: Regs[REG_D0] = GEMDOS_ENHNDL; /* No more handles */
1.1 root 959: return(TRUE);
960: }
961:
1.1.1.2 root 962: /* Open file */
963: FileHandles[Index].FileHandle = fopen(szActualFileName, open_modes[Mode&0x03]);
1.1 root 964:
1.1.1.2 root 965: sprintf(FileHandles[Index].szActualName,"%s",szActualFileName);
966:
967: if (FileHandles[Index].FileHandle != NULL) {
968: /* Tag handle table entry as used and return handle */
969: FileHandles[Index].bUsed = TRUE;
970: Regs[REG_D0] = Index+BASE_FILEHANDLE; /* Return valid ST file handle from range 6 to 45! (ours start from 0) */
971: return(TRUE);
1.1 root 972: }
1.1.1.2 root 973: Regs[REG_D0] = GEMDOS_EFILNF; /* File not found/ error opening */
974: return(TRUE);
1.1 root 975: }
1.1.1.2 root 976:
1.1 root 977: return(FALSE);
978: }
979:
1.1.1.2 root 980: /*-----------------------------------------------------------------------*/
1.1 root 981: /*
982: GEMDOS Close file
983: Call 0x3E
984: */
985: BOOL GemDOS_Close(unsigned long Params)
986: {
987: int Handle;
988:
1.1.1.2 root 989: /* Find our handle - may belong to TOS */
1.1 root 990: Handle = STMemory_ReadWord(Params+SIZE_WORD)-BASE_FILEHANDLE;
991:
1.1.1.2 root 992: /* Check handle was valid */
1.1 root 993: if (GemDOS_IsInvalidFileHandle(Handle)) {
1.1.1.2 root 994: /* No assume was TOS */
1.1 root 995: return(FALSE);
996: }
997: else {
1.1.1.2 root 998: /* Close file and free up handle table */
999: fclose(FileHandles[Handle].FileHandle);
1.1 root 1000: FileHandles[Handle].bUsed = FALSE;
1.1.1.2 root 1001: /* Return no error */
1.1 root 1002: Regs[REG_D0] = GEMDOS_EOK;
1003: return(TRUE);
1004: }
1005: }
1006:
1.1.1.2 root 1007: /*-----------------------------------------------------------------------*/
1.1 root 1008: /*
1009: GEMDOS Read file
1010: Call 0x3F
1011: */
1012: BOOL GemDOS_Read(unsigned long Params)
1013: {
1014: char *pBuffer;
1.1.1.3 root 1015: unsigned long nBytesRead,Size,CurrentPos,FileSize;
1016: long nBytesLeft;
1.1 root 1017: int Handle;
1018:
1.1.1.2 root 1019: /* Read details from stack */
1.1 root 1020: Handle = STMemory_ReadWord(Params+SIZE_WORD)-BASE_FILEHANDLE;
1021: Size = STMemory_ReadLong(Params+SIZE_WORD+SIZE_WORD);
1022: pBuffer = (char *)STRAM_ADDR(STMemory_ReadLong(Params+SIZE_WORD+SIZE_WORD+SIZE_LONG));
1023:
1.1.1.2 root 1024: /* Check handle was valid */
1.1 root 1025: if (GemDOS_IsInvalidFileHandle(Handle)) {
1.1.1.2 root 1026: /* No - assume was TOS */
1.1 root 1027: return(FALSE);
1028: }
1029: else {
1030:
1.1.1.2 root 1031: /* To quick check to see where our file pointer is and how large the file is */
1032: CurrentPos = ftell(FileHandles[Handle].FileHandle);
1033: fseek(FileHandles[Handle].FileHandle, 0, SEEK_END);
1034: FileSize = ftell(FileHandles[Handle].FileHandle);
1035: fseek(FileHandles[Handle].FileHandle, CurrentPos, SEEK_SET);
1.1 root 1036:
1037: nBytesLeft = FileSize-CurrentPos;
1038:
1.1.1.2 root 1039: /* Check for End Of File */
1.1.1.3 root 1040: if (nBytesLeft == 0) {
1041: /* FIXME: should we return zero (bytes read) or an error? */
1042: Regs[REG_D0] = 0;
1.1 root 1043: return(TRUE);
1044: }
1045: else {
1.1.1.2 root 1046: /* Limit to size of file to prevent windows error */
1.1 root 1047: if (Size>FileSize)
1048: Size = FileSize;
1.1.1.2 root 1049: /* And read data in */
1050: nBytesRead = fread(pBuffer, 1, Size, FileHandles[Handle].FileHandle);
1.1 root 1051:
1.1.1.2 root 1052: /* Return number of bytes read */
1.1 root 1053: Regs[REG_D0] = nBytesRead;
1054:
1055: return(TRUE);
1056: }
1057: }
1058: }
1059:
1.1.1.2 root 1060: /*-----------------------------------------------------------------------*/
1.1 root 1061: /*
1062: GEMDOS Write file
1063: Call 0x40
1064: */
1065: BOOL GemDOS_Write(unsigned long Params)
1066: {
1067: char *pBuffer;
1068: unsigned long Size,nBytesWritten;
1069: int Handle;
1070:
1071: #ifdef ENABLE_SAVING
1.1.1.2 root 1072: /* Read details from stack */
1.1 root 1073: Handle = STMemory_ReadWord(Params+SIZE_WORD)-BASE_FILEHANDLE;
1074: Size = STMemory_ReadLong(Params+SIZE_WORD+SIZE_WORD);
1075: pBuffer = (char *)STRAM_ADDR(STMemory_ReadLong(Params+SIZE_WORD+SIZE_WORD+SIZE_LONG));
1076:
1.1.1.2 root 1077: /* Check handle was valid */
1.1 root 1078: if (GemDOS_IsInvalidFileHandle(Handle)) {
1.1.1.2 root 1079: /* No assume was TOS */
1.1 root 1080: return(FALSE);
1081: }
1082: else {
1083:
1.1.1.2 root 1084: nBytesWritten = fwrite(pBuffer, 1, Size, FileHandles[Handle].FileHandle);
1.1 root 1085: if (nBytesWritten>=0) {
1086:
1.1.1.2 root 1087: Regs[REG_D0] = nBytesWritten; /* OK */
1.1 root 1088: }
1089: else
1.1.1.2 root 1090: Regs[REG_D0] = GEMDOS_EACCDN; /* Access denied(ie read-only) */
1.1 root 1091:
1092: return(TRUE);
1093: }
1094: #endif
1095:
1096: return(FALSE);
1097: }
1098:
1.1.1.2 root 1099: /*-----------------------------------------------------------------------*/
1.1 root 1100: /*
1101: GEMDOS UnLink(Delete) file
1102: Call 0x41
1103: */
1104: BOOL GemDOS_UnLink(unsigned long Params)
1105: {
1106: #ifdef ENABLE_SAVING
1107: char szActualFileName[MAX_PATH];
1108: char *pszFileName;
1109: int Drive;
1110:
1.1.1.2 root 1111: /* Find filename */
1.1 root 1112: pszFileName = (char *)STRAM_ADDR(STMemory_ReadLong(Params+SIZE_WORD));
1113: Drive = GemDOS_IsFileNameAHardDrive(pszFileName);
1114: if (ISHARDDRIVE(Drive)) {
1.1.1.2 root 1115: /* And convert to hard drive filename */
1.1 root 1116: GemDOS_CreateHardDriveFileName(Drive,pszFileName,szActualFileName);
1117:
1.1.1.2 root 1118: /* Now delete file?? */
1.1 root 1119: if ( unlink(szActualFileName)==0 )
1.1.1.2 root 1120: Regs[REG_D0] = GEMDOS_EOK; /* OK */
1.1 root 1121: else
1.1.1.2 root 1122: Regs[REG_D0] = GEMDOS_EFILNF; /* File not found */
1.1 root 1123:
1124: return(TRUE);
1125: }
1126: #endif
1127:
1128: return(FALSE);
1129: }
1130:
1.1.1.2 root 1131: /*-----------------------------------------------------------------------*/
1.1 root 1132: /*
1133: GEMDOS File seek
1134: Call 0x42
1135: */
1136: BOOL GemDOS_LSeek(unsigned long Params)
1137: {
1138: long Offset;
1139: int Handle,Mode;
1140:
1.1.1.2 root 1141: /* Read details from stack */
1.1 root 1142: Offset = (long)STMemory_ReadLong(Params+SIZE_WORD);
1143: Handle = STMemory_ReadWord(Params+SIZE_WORD+SIZE_LONG)-BASE_FILEHANDLE;
1144: Mode = STMemory_ReadWord(Params+SIZE_WORD+SIZE_LONG+SIZE_WORD);
1145:
1.1.1.2 root 1146: /* Check handle was valid */
1.1 root 1147: if (GemDOS_IsInvalidFileHandle(Handle)) {
1.1.1.2 root 1148: /* No assume was TOS */
1.1 root 1149: return(FALSE);
1150: }
1151: else {
1.1.1.2 root 1152: /* Return offset from start of file */
1153: fseek(FileHandles[Handle].FileHandle, Offset, Mode);
1154: Regs[REG_D0] = ftell(FileHandles[Handle].FileHandle);
1.1 root 1155: return(TRUE);
1156: }
1157: }
1158:
1.1.1.2 root 1159: /*-----------------------------------------------------------------------*/
1160: /*
1161: GEMDOS Get Directory
1162: Call 0x47
1163: */
1164: int GemDOS_GetDir(unsigned long Params){
1165: unsigned long Address;
1166: unsigned short Drive;
1167:
1168: Address = (long)STMemory_ReadLong(Params+SIZE_WORD);
1169: Drive = STMemory_ReadWord(Params+SIZE_WORD+SIZE_LONG);
1170: /* is it our drive? */
1171: if((Drive == 0 && CurrentDrive >= 2) || Drive >= 3){
1172: STMemory_WriteByte(Address, '\0' );
1173: Regs[REG_D0] = GEMDOS_EOK; /* OK */
1174: return(TRUE);
1175: } else return(FALSE);
1176: }
1177:
1178: /*-----------------------------------------------------------------------*/
1.1 root 1179: /*
1180: PExec Load And Go - Redirect to cart' routine at address 0xFA1000
1181:
1182: If loading from hard-drive(ie drive ID 2 or more) set condition codes to run own GEMDos routines
1183: */
1.1.1.2 root 1184: int GemDOS_Pexec_LoadAndGo(unsigned long Params)
1.1 root 1185: {
1.1.1.3 root 1186: /* add multiple disk support here too */
1.1.1.2 root 1187: /* Hard-drive? */
1.1.1.3 root 1188: if( CurrentDrive == emudrives[0]->hd_letter )
1189: {
1190: /* If not using A: or B:, use my own routines to load */
1191: return(CALL_PEXEC_ROUTINE);
1192: }
1.1.1.2 root 1193: else return(FALSE);
1.1 root 1194: }
1195:
1.1.1.2 root 1196: /*-----------------------------------------------------------------------*/
1.1 root 1197: /*
1198: PExec Load But Don't Go - Redirect to cart' routine at address 0xFA1000
1199: */
1.1.1.2 root 1200: int GemDOS_Pexec_LoadDontGo(unsigned long Params)
1.1 root 1201: {
1.1.1.2 root 1202: /* Hard-drive? */
1.1.1.3 root 1203: if( CurrentDrive == emudrives[0]->hd_letter )
1204: {
1205: return(CALL_PEXEC_ROUTINE);
1206: } else return(FALSE);
1.1 root 1207: }
1208:
1.1.1.2 root 1209: /*-----------------------------------------------------------------------*/
1.1 root 1210: /*
1211: GEMDOS PExec handler
1212: Call 0x4B
1213: */
1.1.1.2 root 1214: int GemDOS_Pexec(unsigned long Params)
1.1 root 1215: {
1216: unsigned short int Mode;
1217:
1.1.1.2 root 1218: /* Find PExec mode */
1.1 root 1219: Mode = STMemory_ReadWord(Params+SIZE_WORD);
1220:
1.1.1.2 root 1221: /* Re-direct as needed */
1.1 root 1222: switch(Mode) {
1.1.1.2 root 1223: case 0: /* Load and go */
1224: return(GemDOS_Pexec_LoadAndGo(Params));
1225: case 3: /* Load, don't go */
1226: return(GemDOS_Pexec_LoadDontGo(Params));
1227: case 4: /* Just go */
1228: return(FALSE);
1229: case 5: /* Create basepage */
1230: return(FALSE);
1231: case 6:
1232: return(FALSE);
1.1 root 1233:
1.1.1.2 root 1234: default:
1235: return(FALSE);
1.1 root 1236: }
1237:
1.1.1.2 root 1238: /* Still re-direct to TOS */
1.1 root 1239: return(FALSE);
1240: }
1241:
1.1.1.4 ! root 1242:
! 1243: /*-----------------------------------------------------------------------*/
! 1244: /*
! 1245: GEMDOS Search Next
! 1246: Call 0x4F
! 1247: */
! 1248: BOOL GemDOS_SNext(unsigned long Params)
! 1249: {
! 1250: struct dirent **temp;
! 1251: int Index;
! 1252:
! 1253: /* Was DTA ours or TOS? */
! 1254: if (STMemory_ReadLong_PCSpace(pDTA->magic)==DTA_MAGIC_NUMBER) {
! 1255:
! 1256: /* Find index into our list of structures */
! 1257: Index = STMemory_ReadWord_PCSpace(pDTA->index)&(MAX_DTAS_FILES-1);
! 1258:
! 1259: if(InternalDTAs[Index].centry >= InternalDTAs[Index].nentries){
! 1260: Regs[REG_D0] = GEMDOS_ENMFIL; /* No more files */
! 1261: return(TRUE);
! 1262: }
! 1263:
! 1264: temp = InternalDTAs[Index].found;
! 1265: if(PopulateDTA(InternalDTAs[Index].path, temp[InternalDTAs[Index].centry++]) == FALSE){
! 1266: fprintf(stderr,"\tError setting DTA.\n");
! 1267: return(TRUE);
! 1268: }
! 1269:
! 1270: Regs[REG_D0] = GEMDOS_EOK;
! 1271: return(TRUE);
! 1272: }
! 1273:
! 1274: return(FALSE);
! 1275: }
! 1276:
! 1277:
1.1.1.2 root 1278: /*-----------------------------------------------------------------------*/
1.1 root 1279: /*
1280: GEMDOS Find first file
1281: Call 0x4E
1282: */
1283: BOOL GemDOS_SFirst(unsigned long Params)
1284: {
1285: char szActualFileName[MAX_PATH];
1.1.1.2 root 1286: char tempstr[MAX_PATH];
1.1 root 1287: char *pszFileName;
1.1.1.2 root 1288: struct dirent **files;
1.1 root 1289: unsigned short int Attr;
1290: int Drive;
1.1.1.2 root 1291: DIR *fsdir;
1292: int i,j,k;
1.1 root 1293:
1.1.1.2 root 1294: /* Find filename to search for */
1.1 root 1295: pszFileName = (char *)STRAM_ADDR(STMemory_ReadLong(Params+SIZE_WORD));
1296: Attr = STMemory_ReadWord(Params+SIZE_WORD+SIZE_LONG);
1297:
1298: Drive = GemDOS_IsFileNameAHardDrive(pszFileName);
1299: if (ISHARDDRIVE(Drive)) {
1300:
1.1.1.2 root 1301: /* And convert to hard drive filename */
1.1 root 1302: GemDOS_CreateHardDriveFileName(Drive,pszFileName,szActualFileName);
1.1.1.2 root 1303:
1304: /* Populate DTA, set index for our use */
1.1 root 1305: STMemory_WriteWord_PCSpace(pDTA->index,DTAIndex);
1.1.1.2 root 1306: STMemory_WriteLong_PCSpace(pDTA->magic,DTA_MAGIC_NUMBER); /* set our dta magic num */
1307:
1308: if(InternalDTAs[DTAIndex].bUsed == TRUE) ClearInternalDTA();
1309: InternalDTAs[DTAIndex].bUsed = TRUE;
1.1 root 1310:
1.1.1.2 root 1311: /* Were we looking for the volume label? */
1.1 root 1312: if (Attr&GEMDOS_FILE_ATTRIB_VOLUME_LABEL) {
1.1.1.2 root 1313: /* Volume name */
1314: strcpy(pDTA->dta_name,"EMULATED.001");
1315: Regs[REG_D0] = GEMDOS_EOK; /* Got volume */
1.1 root 1316: return(TRUE);
1317: }
1.1.1.2 root 1318:
1319: /* open directory */
1320: fsfirst_dirname(szActualFileName, InternalDTAs[DTAIndex].path);
1321: fsdir = opendir(InternalDTAs[DTAIndex].path);
1322:
1323: if( fsdir == NULL ){
1324: Regs[REG_D0] = GEMDOS_EPTHNF; /* Path not found */
1.1 root 1325: return(TRUE);
1326: }
1.1.1.2 root 1327: /* close directory */
1328: closedir( fsdir );
1329:
1330: InternalDTAs[DTAIndex].nentries = scandir(InternalDTAs[DTAIndex].path, &files, 0, alphasort);
1331: if( InternalDTAs[DTAIndex].nentries < 0 ){
1332: Regs[REG_D0] = GEMDOS_EFILNF; /* File (directory actually) not found */
1333: return(TRUE);
1334: }
1335:
1336: InternalDTAs[DTAIndex].centry = 0; /* current entry is 0 */
1337: fsfirst_dirmask(szActualFileName, tempstr); /* get directory mask */
1.1 root 1338:
1.1.1.2 root 1339: /* Create and populate a list of matching files. */
1.1 root 1340:
1.1.1.3 root 1341: j = 0; /* count number of entries matching mask */
1.1.1.2 root 1342: for(i=0;i<InternalDTAs[DTAIndex].nentries;i++)
1343: if(match(tempstr, files[i]->d_name)) j++;
1344:
1345: InternalDTAs[DTAIndex].found = (struct dirent **)malloc(sizeof(struct dirent *) * j);
1346:
1347: /* copy the dirent pointers for files matching the mask to our list */
1348: k = 0;
1349: for(i=0;i<InternalDTAs[DTAIndex].nentries;i++)
1350: if(match(tempstr, files[i]->d_name)){
1351: InternalDTAs[DTAIndex].found[k] = files[i];
1352: k++;
1353: }
1.1.1.3 root 1354:
1.1.1.2 root 1355: InternalDTAs[DTAIndex].nentries = j; /* set number of legal entries */
1.1 root 1356:
1.1.1.2 root 1357: if(InternalDTAs[DTAIndex].nentries == 0){
1358: /* No files of that match, return error code */
1359: Regs[REG_D0] = GEMDOS_EFILNF; /* File not found */
1360: return(TRUE);
1.1 root 1361: }
1.1.1.2 root 1362:
1363: /* Scan for first file (SNext uses no parameters) */
1.1.1.4 ! root 1364: GemDOS_SNext(0);
1.1.1.2 root 1365: /* increment DTA index */
1366: DTAIndex++;
1367: DTAIndex&=(MAX_DTAS_FILES-1);
1368:
1.1 root 1369: return(TRUE);
1370: }
1371: return(FALSE);
1372: }
1373:
1374:
1.1.1.2 root 1375: /*-----------------------------------------------------------------------*/
1.1 root 1376: /*
1377: GEMDOS Rename
1378: Call 0x56
1379: */
1380: BOOL GemDOS_Rename(unsigned long Params)
1381: {
1382: char *pszNewFileName,*pszOldFileName;
1383: char szNewActualFileName[MAX_PATH],szOldActualFileName[MAX_PATH];
1384: int NewDrive, OldDrive;
1385:
1.1.1.2 root 1386: /* Read details from stack */
1.1 root 1387: pszOldFileName = (char *)STRAM_ADDR(STMemory_ReadLong(Params+SIZE_WORD+SIZE_WORD));
1388: pszNewFileName = (char *)STRAM_ADDR(STMemory_ReadLong(Params+SIZE_WORD+SIZE_WORD+SIZE_LONG));
1389:
1390: NewDrive = GemDOS_IsFileNameAHardDrive(pszNewFileName);
1391: OldDrive = GemDOS_IsFileNameAHardDrive(pszOldFileName);
1392: if (ISHARDDRIVE(NewDrive) && ISHARDDRIVE(OldDrive)) {
1.1.1.2 root 1393: /* And convert to hard drive filenames */
1.1 root 1394: GemDOS_CreateHardDriveFileName(NewDrive,pszNewFileName,szNewActualFileName);
1395: GemDOS_CreateHardDriveFileName(OldDrive,pszOldFileName,szOldActualFileName);
1396:
1.1.1.2 root 1397: /* Rename files */
1.1 root 1398: if ( rename(szOldActualFileName,szNewActualFileName)==0 )
1399: Regs[REG_D0] = GEMDOS_EOK;
1400: else
1.1.1.2 root 1401: Regs[REG_D0] = GEMDOS_EACCDN; /* Access denied */
1.1 root 1402: return(TRUE);
1403: }
1404:
1405: return(FALSE);
1406: }
1407:
1.1.1.2 root 1408: /*-----------------------------------------------------------------------*/
1.1 root 1409: /*
1410: GEMDOS GSDToF
1411: Call 0x57
1412: */
1413: BOOL GemDOS_GSDToF(unsigned long Params)
1414: {
1415: DATETIME DateTime;
1.1.1.2 root 1416: unsigned long pBuffer;
1.1 root 1417: int Handle,Flag;
1418:
1.1.1.2 root 1419: /* Read details from stack */
1420: pBuffer = STMemory_ReadLong(Params+SIZE_WORD);
1.1 root 1421: Handle = STMemory_ReadWord(Params+SIZE_WORD+SIZE_LONG)-BASE_FILEHANDLE;
1422: Flag = STMemory_ReadWord(Params+SIZE_WORD+SIZE_WORD+SIZE_LONG);
1423:
1.1.1.2 root 1424: /* Check handle was valid */
1.1 root 1425: if (GemDOS_IsInvalidFileHandle(Handle)) {
1.1.1.2 root 1426: /* No assume was TOS */
1.1 root 1427: return(FALSE);
1428: }
1429:
1.1.1.2 root 1430: /* Set time/date stamp? Do nothing. */
1431: if( Flag == 1 ){
1432: Regs[REG_D0] = GEMDOS_EOK;
1433: return (TRUE);
1.1 root 1434: }
1.1.1.2 root 1435:
1436: Regs[REG_D0] = GEMDOS_ERROR; /* Invalid parameter */
1.1 root 1437:
1.1.1.2 root 1438: if (GetFileInformation(FileHandles[Handle].szActualName, &DateTime) == TRUE){
1439: STMemory_WriteWord(pBuffer, DateTime.word1);
1440: STMemory_WriteWord(pBuffer+2, DateTime.word2);
1441: Regs[REG_D0] = GEMDOS_EOK;
1.1 root 1442: }
1.1.1.2 root 1443: return (TRUE);
1.1 root 1444: }
1445:
1446: /*-----------------------------------------------------------------------*/
1447: /*
1448: Run GEMDos call, and re-direct if need to. Used to handle hard-disc emulation etc...
1449: This sets the condition codes(in SR), which are used in the 'cart.s' program to decide if we
1450: need to run old GEM vector, or PExec or nothing.
1451:
1452: This method keeps the stack and other states consistant with the original ST which is very important
1453: for the PExec call and maximum compatibility through-out
1454: */
1455: void GemDOS_OpCode(void)
1456: {
1457: unsigned short int GemDOSCall,CallingSReg;
1458: unsigned long Params;
1.1.1.2 root 1459: short RunOld;
1.1 root 1460:
1.1.1.2 root 1461:
1462: /* Read SReg from stack to see if parameters are on User or Super stack */
1463: MakeSR(); /* update value of SR */
1.1 root 1464: CallingSReg = STMemory_ReadWord(Regs[REG_A7]);
1465: if ((CallingSReg&SR_SUPERMODE)==0) /* Calling from user mode */
1.1.1.2 root 1466: Params = regs.usp;
1467: else {
1468: Params = Regs[REG_A7]+SIZE_WORD+SIZE_LONG; /* super stack */
1469: if( cpu_level>0 )
1470: Params += SIZE_WORD; /* Skip extra word whe CPU is >=68010 */
1471: }
1.1 root 1472:
1473: /* Default to run TOS GemDos (SR_NEG run Gemdos, SR_ZERO already done, SR_OVERFLOW run own 'Pexec' */
1.1.1.2 root 1474: RunOld = TRUE;
1.1 root 1475: SR &= SR_CLEAR_OVERFLOW;
1476: SR &= SR_CLEAR_ZERO;
1477: SR |= SR_NEG;
1478:
1479: /* Find pointer to call parameters */
1480: GemDOSCall = STMemory_ReadWord(Params);
1.1.1.2 root 1481:
1482: #ifdef GEMDOS_VERBOSE
1483: if(GemDOSCall <= 0x57)
1484: fprintf(stderr, "GemDOS 0x%X (%s)\n",GemDOSCall,pszGemDOSNames[GemDOSCall]);
1.1.1.3 root 1485: if(!GemDOSCall){
1486: fprintf(stderr, "Warning!!\n");
1487: DebugUI();
1488: }
1.1 root 1489: #endif
1490:
1491: /* Intercept call */
1492: switch(GemDOSCall) {
1.1.1.2 root 1493: /* case 0x3: */
1494: /* if (GemDOS_Cauxin(Params)) */
1495: /* RunOld = FALSE; */
1496: /* break; */
1497: /* case 0x4: */
1498: /* if (GemDOS_Cauxout(Params)) */
1499: /* RunOld = FALSE; */
1500: /* break; */
1501: /* case 0x5: */
1502: /* if (GemDOS_Cprnout(Params)) */
1503: /* RunOld = FALSE; */
1504: /* break; */
1505: case 0xe:
1506: if (GemDOS_SetDrv(Params))
1507: RunOld = FALSE;
1508: break;
1509: /* case 0x11: */
1510: /* if (GemDOS_Cprnos(Params)) */
1511: /* RunOld = FALSE; */
1512: /* break; */
1513: /* case 0x12: */
1514: /* if (GemDOS_Cauxis(Params)) */
1515: /* RunOld = FALSE; */
1516: /* break; */
1517: /* case 0x13: */
1518: /* if (GemDOS_Cauxos(Params)) */
1519: /* RunOld = FALSE; */
1520: /* break; */
1.1 root 1521: case 0x1a:
1522: if (GemDOS_SetDTA(Params))
1.1.1.2 root 1523: RunOld = FALSE;
1524: break;
1525: case 0x36:
1526: if (GemDOS_DFree(Params))
1527: RunOld = FALSE;
1.1 root 1528: break;
1529: case 0x39:
1530: if (GemDOS_MkDir(Params))
1.1.1.2 root 1531: RunOld = FALSE;
1.1 root 1532: break;
1533: case 0x3a:
1534: if (GemDOS_RmDir(Params))
1.1.1.2 root 1535: RunOld = FALSE;
1.1 root 1536: break;
1537: case 0x3b:
1538: if (GemDOS_ChDir(Params))
1.1.1.2 root 1539: RunOld = FALSE;
1.1 root 1540: break;
1541: case 0x3c:
1542: if (GemDOS_Create(Params))
1.1.1.2 root 1543: RunOld = FALSE;
1.1 root 1544: break;
1545: case 0x3d:
1546: if (GemDOS_Open(Params))
1.1.1.2 root 1547: RunOld = FALSE;
1.1 root 1548: break;
1549: case 0x3e:
1550: if (GemDOS_Close(Params))
1.1.1.2 root 1551: RunOld = FALSE;
1.1 root 1552: break;
1553: case 0x3f:
1554: if (GemDOS_Read(Params))
1.1.1.2 root 1555: RunOld = FALSE;
1.1 root 1556: break;
1557: case 0x40:
1558: if (GemDOS_Write(Params))
1.1.1.2 root 1559: RunOld = FALSE;
1.1 root 1560: break;
1561: case 0x41:
1562: if (GemDOS_UnLink(Params))
1.1.1.2 root 1563: RunOld = FALSE;
1.1 root 1564: break;
1565: case 0x42:
1566: if (GemDOS_LSeek(Params))
1.1.1.2 root 1567: RunOld = FALSE;
1568: break;
1569: case 0x47:
1570: if (GemDOS_GetDir(Params))
1571: RunOld = FALSE;
1.1 root 1572: break;
1573: case 0x4b:
1.1.1.2 root 1574: if(GemDOS_Pexec(Params) == CALL_PEXEC_ROUTINE);
1575: RunOld = CALL_PEXEC_ROUTINE;
1.1 root 1576: break;
1577: case 0x4e:
1578: if (GemDOS_SFirst(Params))
1.1.1.2 root 1579: RunOld = FALSE;
1.1 root 1580: break;
1581: case 0x4f:
1582: if (GemDOS_SNext(Params))
1.1.1.2 root 1583: RunOld = FALSE;
1.1 root 1584: break;
1.1.1.2 root 1585: case 0x56:
1586: if (GemDOS_Rename(Params))
1587: RunOld = FALSE;
1588: break;
1589: case 0x57:
1590: if (GemDOS_GSDToF(Params))
1591: RunOld = FALSE;
1592: break;
1593: }
1594:
1595: switch(RunOld){
1596: case FALSE: /* skip over branch to pexec to RTE */
1597: SR |= SR_ZERO;
1598: break;
1599: case CALL_PEXEC_ROUTINE: /* branch to pexec, then redirect to old gemdos. */
1600: SR |= SR_OVERFLOW;
1601: break;
1.1 root 1602: }
1603:
1.1.1.2 root 1604: MakeFromSR(); /* update the flags from the SR register */
1.1 root 1605: }
1606:
1.1.1.2 root 1607: /*-----------------------------------------------------------------------*/
1.1 root 1608: /*
1.1.1.2 root 1609: GemDOS_Boot - routine called on the first occurence of the gemdos opcode.
1.1.1.3 root 1610: (this should be in the cartridge bootrom)
1611: Sets up our gemdos handler (or, if we don't need one, just turn off keyclicks)
1.1.1.2 root 1612: */
1613:
1614: void GemDOS_Boot()
1615: {
1616:
1.1.1.3 root 1617: bInitGemDOS = TRUE;
1618: #ifdef GEMDOS_VERBOSE
1619: fprintf(stderr, "Gemdos_Boot()\n");
1620: #endif
1.1.1.2 root 1621: /* install our gemdos handler, if -e or --harddrive option used */
1.1.1.3 root 1622: if(GEMDOS_EMU_ON){
1623:
1.1.1.2 root 1624: /* Patch pexec code - coded value is 4, but must be 6 for TOS > 1.00 */
1625: if(TOSVersion > 0x0100)
1626: STMemory_WriteByte(CART_PEXEC_TOS, 0x06);
1627:
1628: /* Save old GEMDOS handler adress */
1629: STMemory_WriteLong(CART_OLDGEMDOS, STMemory_ReadLong(0x0084));
1630: /* Setup new GEMDOS handler, see cartimg.c */
1631: STMemory_WriteLong(0x0084, CART_GEMDOS);
1.1 root 1632: }
1633: }
1.1.1.2 root 1634:
1635: /*
1636: GemDOS_RunOldOpCode()
1637: Has been relocated to a routine in hatari-glue.c
1638: */
1639:
1640:
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.