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