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