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