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