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