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