Annotation of hatari/src/gemdos.c, revision 1.1

1.1     ! root        1: /*
        !             2:   Hatari
        !             3: 
        !             4:   GEMDos intercept routines. These are used mainly for Hard Drive redirection of high level
        !             5:   file routines.
        !             6: */
        !             7: 
        !             8: #include <sys/types.h>
        !             9: #include <sys/stat.h>
        !            10: #include <fcntl.h>
        !            11: 
        !            12: #include "main.h"
        !            13: #include "cart.h"
        !            14: #include "debug.h"
        !            15: #include "decode.h"
        !            16: #include "dialog.h"
        !            17: #include "file.h"
        !            18: #include "floppy.h"
        !            19: #include "gemdos.h"
        !            20: #include "m68000.h"
        !            21: #include "memAlloc.h"
        !            22: #include "memorySnapShot.h"
        !            23: #include "misc.h"
        !            24: #include "printer.h"
        !            25: #include "rs232.h"
        !            26: #include "statusBar.h"
        !            27: #include "stMemory.h"
        !            28: #include "view.h"
        !            29: 
        !            30: #define ENABLE_SAVING             /* Turn on saving stuff */
        !            31: 
        !            32: #define INVALID_HANDLE_VALUE -1
        !            33: 
        !            34: #ifndef MAX_PATH
        !            35: #define MAX_PATH 256
        !            36: #endif
        !            37: 
        !            38: typedef struct 
        !            39: {
        !            40:  BOOL bUsed;
        !            41:  int FileHandle;
        !            42: } FILE_HANDLE;
        !            43: 
        !            44: FILE_HANDLE  FileHandles[MAX_FILE_HANDLES];
        !            45: //INTERNAL_DTA InternalDTAs[MAX_DTAS_FILES];
        !            46: int DTAIndex;                                 /* Circular index into above */
        !            47: BOOL bInitGemDOS;                             /* Have we re-directed GemDOS vector to our own routines yet? */
        !            48: DTA *pDTA;                                    /* Our GEMDOS hard drive Disc Transfer Address structure */
        !            49: unsigned short int CurrentDrive;              /* Current drive (0=A,1=B,2=C etc...) */
        !            50: 
        !            51: #ifdef DEBUG_TO_FILE
        !            52: /* List of GEMDos functions... */
        !            53: char *pszGemDOSNames[] = {
        !            54:   "Term",                 //0x00
        !            55:   "Conin",                //0x01
        !            56:   "ConOut",               //0x02
        !            57:   "Auxiliary Input",      //0x03
        !            58:   "Auxiliary Output",     //0x04
        !            59:   "Printer Output",       //0x05
        !            60:   "RawConIO",             //0x06
        !            61:   "Direct Conin no echo", //0x07
        !            62:   "Conin no echo",        //0x08
        !            63:   "Print line",           //0x09
        !            64:   "ReadLine",             //0x0a
        !            65:   "ConStat",              //0x0b
        !            66:   "",                     //0x0c
        !            67:   "",                     //0x0d
        !            68:   "SetDrv",               //0x0e
        !            69:   "",                     //0x0f
        !            70:   "Conout Stat",          //0x10
        !            71:   "PrtOut Stat",          //0x11
        !            72:   "Auxin Stat",           //0x12
        !            73:   "AuxOut Stat",          //0x13
        !            74:   "",                     //0x14
        !            75:   "",                     //0x15
        !            76:   "",                     //0x16
        !            77:   "",                     //0x17
        !            78:   "",                     //0x18
        !            79:   "Current Disk",         //0x19
        !            80:   "Set DTA",              //0x1a
        !            81:   "",        //0x1b
        !            82:   "",        //0x1c
        !            83:   "",        //0x1d
        !            84:   "",        //0x1e
        !            85:   "",        //0x1f
        !            86:   "Super",   //0x20
        !            87:   "",        //0x21
        !            88:   "",        //0x22
        !            89:   "",        //0x23
        !            90:   "",        //0x24
        !            91:   "",        //0x25
        !            92:   "",        //0x26
        !            93:   "",        //0x27
        !            94:   "",        //0x28
        !            95:   "",        //0x29
        !            96:   "Get Date",      //0x2a
        !            97:   "Set Date",      //0x2b
        !            98:   "Get Time",      //0x2c
        !            99:   "Set Time",      //0x2d
        !           100:   "",              //0x2e
        !           101:   "Get DTA",       //0x2f
        !           102:   "Get Version Number",   //0x30
        !           103:   "Keep Process",         //0x31
        !           104:   "",        //0x32
        !           105:   "",        //0x33
        !           106:   "",        //0x34
        !           107:   "",        //0x35
        !           108:   "Get Disk Free Space",  //0x36
        !           109:   "",           //0x37
        !           110:   "",           //0x38
        !           111:   "MkDir",      //0x39
        !           112:   "RmDir",      //0x3a
        !           113:   "ChDir",      //0x3b
        !           114:   "Create",     //0x3c
        !           115:   "Open",       //0x3d
        !           116:   "Close",      //0x3e
        !           117:   "Read",       //0x3f
        !           118:   "Write",      //0x40
        !           119:   "UnLink",     //0x41
        !           120:   "LSeek",      //0x42
        !           121:   "ChMod",      //0x43
        !           122:   "",           //0x44
        !           123:   "Dup",        //0x45
        !           124:   "Force",      //0x46
        !           125:   "GetDir",     //0x47
        !           126:   "Malloc",     //0x48
        !           127:   "MFree",      //0x49
        !           128:   "SetBlock",   //0x4a
        !           129:   "Exec",       //0x4b
        !           130:   "Term",       //0x4c
        !           131:   "",           //0x4d
        !           132:   "SFirst",     //0x4e
        !           133:   "SNext",      //0x4f
        !           134:   "",           //0x50
        !           135:   "",           //0x51
        !           136:   "",           //0x52
        !           137:   "",           //0x53
        !           138:   "",           //0x54
        !           139:   "",           //0x55
        !           140:   "Rename",     //0x56
        !           141:   "GSDTof"      //0x57
        !           142: };
        !           143: #endif
        !           144: 
        !           145: 
        !           146: 
        !           147: /* Convert a string to uppercase */
        !           148: void strupr(char *string)
        !           149: {
        !           150:  int i;
        !           151:  for(i=0; i<strlen(string); i++)
        !           152:    string[i] = toupper(string[i]);
        !           153: }
        !           154: 
        !           155: 
        !           156: //-----------------------------------------------------------------------
        !           157: /*
        !           158:   Initialize GemDOS/PC file system
        !           159: */
        !           160: void GemDOS_Init(void)
        !           161: {
        !           162:   // Clear handles structure
        !           163:   Memory_Clear(FileHandles,sizeof(FILE_HANDLE)*MAX_FILE_HANDLES);
        !           164: }
        !           165: 
        !           166: //-----------------------------------------------------------------------
        !           167: /*
        !           168:   Reset GemDOS file system
        !           169: */
        !           170: void GemDOS_Reset(void)
        !           171: {
        !           172:   int i;
        !           173: 
        !           174:   // Init file handles table
        !           175:   for(i=0; i<MAX_FILE_HANDLES; i++) {
        !           176:     // Was file open? If so close it
        !           177:     if (FileHandles[i].bUsed)
        !           178:       close(FileHandles[i].FileHandle);
        !           179: 
        !           180:     FileHandles[i].FileHandle = INVALID_HANDLE_VALUE;
        !           181:     FileHandles[i].bUsed = FALSE;
        !           182:   }
        !           183: 
        !           184:   // Reset
        !           185:   bInitGemDOS = FALSE;
        !           186:   CurrentDrive = nBootDrive;
        !           187:   pDTA = NULL;
        !           188:   DTAIndex = 0;
        !           189: }
        !           190: 
        !           191: //-----------------------------------------------------------------------
        !           192: /*
        !           193:   Save/Restore snapshot of local variables('MemorySnapShot_Store' handles type)
        !           194: */
        !           195: void GemDOS_MemorySnapShot_Capture(BOOL bSave)
        !           196: {
        !           197:   unsigned int Addr;
        !           198:   int i;
        !           199: 
        !           200:   // Save/Restore details
        !           201:   MemorySnapShot_Store(&DTAIndex,sizeof(DTAIndex));
        !           202:   MemorySnapShot_Store(&bInitGemDOS,sizeof(bInitGemDOS));
        !           203:   if (bSave) {
        !           204:     Addr = (unsigned int)pDTA-(unsigned int)STRam;
        !           205:     MemorySnapShot_Store(&Addr,sizeof(Addr));
        !           206:   }
        !           207:   else {
        !           208:     MemorySnapShot_Store(&Addr,sizeof(Addr));
        !           209:     pDTA = (DTA *)((unsigned int)STRam+(unsigned int)Addr);
        !           210:   }
        !           211:   MemorySnapShot_Store(&CurrentDrive,sizeof(CurrentDrive));
        !           212:   // Don't save file handles as files may have changed which makes
        !           213:   // it impossible to get a valid handle back
        !           214:   if (!bSave) {
        !           215:     // Clear file handles
        !           216:     for(i=0; i<MAX_FILE_HANDLES; i++) {
        !           217:       FileHandles[i].FileHandle = INVALID_HANDLE_VALUE;
        !           218:       FileHandles[i].bUsed = FALSE;
        !           219:     }
        !           220:     // And DTAs
        !           221: /*FIXME*/
        !           222: /*    for(i=0; i<MAX_DTAS_FILES; i++) {
        !           223:       InternalDTAs[i].FileHandle = INVALID_HANDLE_VALUE;
        !           224:       memset(&InternalDTAs[i].FindFileData,0x0,sizeof(WIN32_FIND_DATA));
        !           225:     }
        !           226: */
        !           227:   }
        !           228: }
        !           229: 
        !           230: //-----------------------------------------------------------------------
        !           231: /*
        !           232:   Return free PC file handle table index, or -1 if error
        !           233: */
        !           234: int GemDOS_FindFreeFileHandle(void)
        !           235: {
        !           236:   int i;
        !           237: 
        !           238:   /* Scan our file list for free slot */
        !           239:   for(i=0; i<MAX_FILE_HANDLES; i++) {
        !           240:     if (!FileHandles[i].bUsed)
        !           241:       return(i);
        !           242:   }
        !           243: 
        !           244:   /* Cannot open any more files, return error */
        !           245:   return(-1);
        !           246: }
        !           247: 
        !           248: //-----------------------------------------------------------------------
        !           249: /*
        !           250:   Check ST handle is within our table range, return TRUE if not
        !           251: */
        !           252: BOOL GemDOS_IsInvalidFileHandle(int Handle)
        !           253: {
        !           254:   BOOL bInvalidHandle=FALSE;
        !           255: 
        !           256:   /* Check handle was valid with our handle table */
        !           257:   if ( (Handle<0) || (Handle>=MAX_FILE_HANDLES) )
        !           258:     bInvalidHandle = TRUE;
        !           259:   else if (!FileHandles[Handle].bUsed)
        !           260:     bInvalidHandle = TRUE;
        !           261: 
        !           262:   return(bInvalidHandle);
        !           263: }
        !           264: 
        !           265: //-----------------------------------------------------------------------
        !           266: /*
        !           267:   Find drive letter from a filename, eg C,D... and return as drive ID(C:2, D:3...)
        !           268: */
        !           269: int GemDOS_FindDriveNumber(char *pszFileName)
        !           270: {
        !           271:   /* Does have 'A:' or 'C:' etc.. at start of string? */
        !           272:   if ( (pszFileName[0]!='\0') && (pszFileName[1]==':') ) {
        !           273:     if ( (pszFileName[0]>='a') && (pszFileName[0]<='z') )
        !           274:       return(pszFileName[0]-'a');
        !           275:     else if ( (pszFileName[0]>='A') && (pszFileName[0]<='Z') )
        !           276:       return(pszFileName[0]-'A');
        !           277:   }
        !           278: 
        !           279:   return(CurrentDrive);
        !           280: }
        !           281: 
        !           282: //-----------------------------------------------------------------------
        !           283: /*
        !           284:   Return drive ID(C:2, D:3 etc...) or -1 if not one of our emulation hard-drives
        !           285: */
        !           286: int GemDOS_IsFileNameAHardDrive(char *pszFileName)
        !           287: {
        !           288:   int DriveLetter;
        !           289: 
        !           290:   /* Do we even have a hard-drive? */
        !           291:   if (ConfigureParams.HardDisc.nDriveList!=DRIVELIST_NONE) {
        !           292:     // Find drive letter(as number)
        !           293:     DriveLetter = GemDOS_FindDriveNumber(pszFileName);
        !           294:     // Does match one of our drives?
        !           295:     if ( (DriveLetter>=2) && (DriveLetter<=DRIVELIST_TO_DRIVE_INDEX(ConfigureParams.HardDisc.nDriveList)) )
        !           296:       return(DriveLetter);
        !           297:   }
        !           298: 
        !           299:   // No, let TOS handle it
        !           300:   return(-1);
        !           301: }
        !           302: 
        !           303: //-----------------------------------------------------------------------
        !           304: /*
        !           305:   Use hard-drive directory, current ST directory and filename to create full path
        !           306: */
        !           307: void GemDOS_CreateHardDriveFileName(int Drive,char *pszFileName,char *pszDestName)
        !           308: {
        !           309:   int DirIndex = Misc_LimitInt(Drive-2, 0,ConfigureParams.HardDisc.nDriveList-1);
        !           310: //  debug << "::" << pszFileName << endl;
        !           311:   /* Combine names */
        !           312:   if (File_IsRootFileName(pszFileName))
        !           313:     sprintf(pszDestName,"%s%s",ConfigureParams.HardDisc.szHardDiscDirectories[DirIndex],File_RemoveFileNameDrive(pszFileName));
        !           314:   else {
        !           315:     if (File_DoesFileNameEndWithSlash(szCurrentDir))
        !           316:       sprintf(pszDestName,"%s%s%s",ConfigureParams.HardDisc.szHardDiscDirectories[DirIndex],File_RemoveFileNameDrive(szCurrentDir),File_RemoveFileNameDrive(pszFileName));
        !           317:     else
        !           318:       sprintf(pszDestName,"%s%s/%s",ConfigureParams.HardDisc.szHardDiscDirectories[DirIndex],File_RemoveFileNameDrive(szCurrentDir),File_RemoveFileNameDrive(pszFileName));
        !           319:   }
        !           320:   // Remove any '/'s at end of filenames
        !           321:   File_RemoveFileNameTrailingSlashes(pszDestName);
        !           322: 
        !           323:   // And make all upper case, as original ST
        !           324:   strupr(pszDestName);
        !           325: //  debug << "\t" << pszDestName << endl;
        !           326: }
        !           327: 
        !           328: //-----------------------------------------------------------------------
        !           329: /*
        !           330:   Covert from FindFirstFile/FindNextFile attribute to GemDOS format
        !           331: */
        !           332: char GemDOS_ConvertAttribute(int dwFileAttributes)
        !           333: {
        !           334:   char Attrib=0;
        !           335: /* FIXME */
        !           336: /*
        !           337:   // Look up attributes
        !           338:   if (dwFileAttributes&FILE_ATTRIBUTE_READONLY)
        !           339:     Attrib |= GEMDOS_FILE_ATTRIB_READONLY;
        !           340:   if (dwFileAttributes&FILE_ATTRIBUTE_HIDDEN)
        !           341:     Attrib |= GEMDOS_FILE_ATTRIB_HIDDEN;
        !           342:   if (dwFileAttributes&FILE_ATTRIBUTE_DIRECTORY)
        !           343:     Attrib |= GEMDOS_FILE_ATTRIB_SUBDIRECTORY;
        !           344: */
        !           345:   return(Attrib);
        !           346: }
        !           347: 
        !           348: //-----------------------------------------------------------------------
        !           349: /*
        !           350:   GEMDOS Cauxin
        !           351:   Call 0x3
        !           352: */
        !           353: BOOL GemDOS_Cauxin(unsigned long Params)
        !           354: {
        !           355:   unsigned char Char;
        !           356: 
        !           357:   // Wait here until a character is ready
        !           358:   while(!RS232_GetStatus());
        !           359: 
        !           360:   // And read character
        !           361:   RS232_ReadBytes(&Char,1);
        !           362:   Regs[REG_D0] = Char;
        !           363: 
        !           364:   return(TRUE);
        !           365: }
        !           366: 
        !           367: //-----------------------------------------------------------------------
        !           368: /*
        !           369:   GEMDOS Cauxout
        !           370:   Call 0x4
        !           371: */
        !           372: BOOL GemDOS_Cauxout(unsigned long Params)
        !           373: {
        !           374:   unsigned char Char;
        !           375: 
        !           376:   // Send character to RS232
        !           377:   Char = STMemory_ReadWord(Params+SIZE_WORD);
        !           378:   RS232_TransferBytesTo(&Char,1);
        !           379: 
        !           380:   return(TRUE);
        !           381: }
        !           382: 
        !           383: //-----------------------------------------------------------------------
        !           384: /*
        !           385:   GEMDOS Cprnout
        !           386:   Call 0x5
        !           387: */
        !           388: BOOL GemDOS_Cprnout(unsigned long Params)
        !           389: {
        !           390:   unsigned char Char;
        !           391: 
        !           392:   // Send character to printer(or file)
        !           393:   Char = STMemory_ReadWord(Params+SIZE_WORD);
        !           394:   Printer_TransferByteTo(Char);
        !           395:   Regs[REG_D0] = -1;                // Printer OK
        !           396: 
        !           397:   return(TRUE);
        !           398: }
        !           399: 
        !           400: //-----------------------------------------------------------------------
        !           401: /*
        !           402:   GEMDOS Set drive (0=A,1=B,2=C etc...)
        !           403:   Call 0xE
        !           404: */
        !           405: BOOL GemDOS_SetDrv(unsigned long Params)
        !           406: {
        !           407:   // Read details from stack for our own use
        !           408:   CurrentDrive = STMemory_ReadWord(Params+SIZE_WORD);
        !           409: //  debug << "CurrentDrive: " << CurrentDrive << endl;
        !           410: 
        !           411:   // Still re-direct to TOS
        !           412:   return(FALSE);
        !           413: }
        !           414: 
        !           415: //-----------------------------------------------------------------------
        !           416: /*
        !           417:   GEMDOS Cprnos
        !           418:   Call 0x11
        !           419: */
        !           420: BOOL GemDOS_Cprnos(unsigned long Params)
        !           421: {
        !           422:   Regs[REG_D0] = -1;                // Printer OK
        !           423: 
        !           424:   return(TRUE);
        !           425: }
        !           426: 
        !           427: //-----------------------------------------------------------------------
        !           428: /*
        !           429:   GEMDOS Cauxis
        !           430:   Call 0x12
        !           431: */
        !           432: BOOL GemDOS_Cauxis(unsigned long Params)
        !           433: {
        !           434:   // Read our RS232 state
        !           435:   if (RS232_GetStatus())
        !           436:     Regs[REG_D0] = -1;              // Chars waiting
        !           437:   else
        !           438:     Regs[REG_D0] = 0;
        !           439: 
        !           440:   return(TRUE);
        !           441: }
        !           442: 
        !           443: //-----------------------------------------------------------------------
        !           444: /*
        !           445:   GEMDOS Cauxos
        !           446:   Call 0x13
        !           447: */
        !           448: BOOL GemDOS_Cauxos(unsigned long Params)
        !           449: {
        !           450:   Regs[REG_D0] = -1;                // Device ready
        !           451: 
        !           452:   return(TRUE);
        !           453: }
        !           454: 
        !           455: //-----------------------------------------------------------------------
        !           456: /*
        !           457:   GEMDOS Set Disc Transfer Address (DTA)
        !           458:   Call 0x1A
        !           459: */
        !           460: BOOL GemDOS_SetDTA(unsigned long Params)
        !           461: {
        !           462:   // Look up on stack to find where DTA is! Store as PC pointer
        !           463:   pDTA = (DTA *)STRAM_ADDR(STMemory_ReadLong(Params+SIZE_WORD));
        !           464:   
        !           465: //  char szString[256];
        !           466: //  sprintf(szString,"0x%X",STMemory_ReadLong(Params+SIZE_WORD));
        !           467: //  debug << " to " << szString << endl;
        !           468: 
        !           469:   // Still re-direct to TOS
        !           470:   return(FALSE);
        !           471: }
        !           472: 
        !           473: //-----------------------------------------------------------------------
        !           474: /*
        !           475:   GEMDOS MkDir
        !           476:   Call 0x39
        !           477: */
        !           478: BOOL GemDOS_MkDir(unsigned long Params)
        !           479: {  
        !           480:   char szDirPath[MAX_PATH];
        !           481:   char *pDirName;
        !           482:   int Drive;
        !           483: 
        !           484:   // Find directory to make
        !           485:   pDirName = (char *)STRAM_ADDR(STMemory_ReadLong(Params+SIZE_WORD));
        !           486: //  debug << pDirName << endl;
        !           487:   Drive = GemDOS_IsFileNameAHardDrive(pDirName);
        !           488: //  debug << Drive << endl;
        !           489:   if (ISHARDDRIVE(Drive)) {
        !           490:     // Copy old directory, as if calls fails keep this one
        !           491:     GemDOS_CreateHardDriveFileName(Drive,pDirName,szDirPath);
        !           492: 
        !           493:     // Attempt to make directory
        !           494:     if ( mkdir(szDirPath, 0755)==0 )
        !           495:       Regs[REG_D0] = GEMDOS_EOK;
        !           496:     else
        !           497:       Regs[REG_D0] = GEMDOS_EACCDN;        // Access denied
        !           498: 
        !           499:     return(TRUE);
        !           500:   }
        !           501:   return(FALSE);
        !           502: }
        !           503: 
        !           504: //-----------------------------------------------------------------------
        !           505: /*
        !           506:   GEMDOS RmDir
        !           507:   Call 0x3A
        !           508: */
        !           509: BOOL GemDOS_RmDir(unsigned long Params)
        !           510: {  
        !           511:   char szDirPath[MAX_PATH];
        !           512:   char *pDirName;
        !           513:   int Drive;
        !           514: 
        !           515:   // Find directory to make
        !           516:   pDirName = (char *)STRAM_ADDR(STMemory_ReadLong(Params+SIZE_WORD));
        !           517:   Drive = GemDOS_IsFileNameAHardDrive(pDirName);
        !           518:   if (ISHARDDRIVE(Drive)) {
        !           519:     // Copy old directory, as if calls fails keep this one
        !           520:     GemDOS_CreateHardDriveFileName(Drive,pDirName,szDirPath);
        !           521: 
        !           522:     // Attempt to make directory
        !           523:     if ( rmdir(szDirPath)==0 )
        !           524:       Regs[REG_D0] = GEMDOS_EOK;
        !           525:     else
        !           526:       Regs[REG_D0] = GEMDOS_EACCDN;        // Access denied
        !           527: 
        !           528:     return(TRUE);
        !           529:   }
        !           530:   return(FALSE);
        !           531: }
        !           532: 
        !           533: //-----------------------------------------------------------------------
        !           534: /*
        !           535:   GEMDOS ChDir
        !           536:   Call 0x3B
        !           537: */
        !           538: BOOL GemDOS_ChDir(unsigned long Params)
        !           539: {  
        !           540:   char szDirPath[MAX_PATH];
        !           541:   char *pDirName;
        !           542:   int Drive;
        !           543: 
        !           544:   // Find new directory
        !           545:   pDirName = (char *)STRAM_ADDR(STMemory_ReadLong(Params+SIZE_WORD));
        !           546: //  debug << pDirName << endl;
        !           547:   Drive = GemDOS_IsFileNameAHardDrive(pDirName);
        !           548:   if (ISHARDDRIVE(Drive)) {
        !           549:     // Check path exists, else error
        !           550:     GemDOS_CreateHardDriveFileName(Drive,"",szDirPath);
        !           551: 
        !           552:     if ( chdir(szDirPath)==0 ) {
        !           553:       strcpy(szCurrentDir,pDirName);
        !           554:       Regs[REG_D0] = GEMDOS_EOK;
        !           555:     }
        !           556:     else
        !           557:       Regs[REG_D0] = GEMDOS_EPTHNF;        // Path not found
        !           558: 
        !           559:     return(TRUE);
        !           560:   }
        !           561: 
        !           562:   return(FALSE);
        !           563: }
        !           564: 
        !           565: //-----------------------------------------------------------------------
        !           566: /*
        !           567:   GEMDOS Create file
        !           568:   Call 0x3C
        !           569: */
        !           570: BOOL GemDOS_Create(unsigned long Params)
        !           571: {
        !           572:   char szActualFileName[MAX_PATH];
        !           573:   char *pszFileName;
        !           574:   unsigned int Access;
        !           575:   int Drive,Index,Mode;
        !           576: 
        !           577:   // Find filename
        !           578:   pszFileName = (char *)STRAM_ADDR(STMemory_ReadLong(Params+SIZE_WORD));
        !           579:   Mode = STMemory_ReadWord(Params+SIZE_WORD+SIZE_LONG);
        !           580:   Drive = GemDOS_IsFileNameAHardDrive(pszFileName);
        !           581:   if (ISHARDDRIVE(Drive)) {
        !           582:     // And convert to hard drive filename
        !           583:     GemDOS_CreateHardDriveFileName(Drive,pszFileName,szActualFileName);
        !           584: 
        !           585:     // Find slot to store file handle, as need to return WORD handle for ST (NOTE PC's Window handles are all LONGS)
        !           586:     Index = GemDOS_FindFreeFileHandle();
        !           587:     if (Index==-1) {
        !           588:       // No free handles, return error code
        !           589:       Regs[REG_D0] = GEMDOS_ENHNDL;       // No more handles
        !           590:       return(TRUE);
        !           591:     }
        !           592:     else {
        !           593: #ifdef ENABLE_SAVING
        !           594:       // Select mode
        !           595:       switch(Mode&0x01) {                 // Top bits used in some TOSes
        !           596:         case 0:                           // Read/Write
        !           597: //FIXME          Access = GENERIC_READ|GENERIC_WRITE;
        !           598:           break;
        !           599:         case 1:                           // Write only
        !           600: //FIXME          Access = GENERIC_WRITE;
        !           601:           break;
        !           602:       }
        !           603: 
        !           604: //FIXME      FileHandles[Index].FileHandle = CreateFile(szActualFileName,Access,0,NULL,CREATE_ALWAYS,FILE_ATTRIBUTE_NORMAL,NULL);
        !           605:       if (FileHandles[Index].FileHandle!=INVALID_HANDLE_VALUE) {
        !           606:         /* Tag handle table entry as used and return handle */
        !           607:         FileHandles[Index].bUsed = TRUE;
        !           608:         Regs[REG_D0] = Index+BASE_FILEHANDLE;  // Return valid ST file handle from range 6 to 45! (ours start from 0)
        !           609: 
        !           610:         return(TRUE);
        !           611:       }
        !           612:       else {
        !           613:         Regs[REG_D0] = GEMDOS_EFILNF;     // File not found
        !           614:         return(TRUE);
        !           615:       }
        !           616: #else
        !           617:       Regs[REG_D0] = GEMDOS_EFILNF;       // File not found
        !           618:       return(TRUE);
        !           619: #endif
        !           620:     }
        !           621:   }
        !           622: 
        !           623:   return(FALSE);
        !           624: }
        !           625: 
        !           626: //-----------------------------------------------------------------------
        !           627: /*
        !           628:   GEMDOS Open file
        !           629:   Call 0x3D
        !           630: */
        !           631: BOOL GemDOS_Open(unsigned long Params)
        !           632: {
        !           633:   char szActualFileName[MAX_PATH];
        !           634:   char *pszFileName;
        !           635:   unsigned int Access;
        !           636:   int Drive,Index,Mode;
        !           637: 
        !           638:   // Find filename
        !           639:   pszFileName = (char *)STRAM_ADDR(STMemory_ReadLong(Params+SIZE_WORD));
        !           640:   Mode = STMemory_ReadWord(Params+SIZE_WORD+SIZE_LONG);
        !           641:   Drive = GemDOS_IsFileNameAHardDrive(pszFileName);
        !           642: //  Debug_File("Open %s\n",pszFileName);
        !           643:   if (ISHARDDRIVE(Drive)) {
        !           644:     // And convert to hard drive filename
        !           645:     GemDOS_CreateHardDriveFileName(Drive,pszFileName,szActualFileName);
        !           646: 
        !           647:     // Find slot to store file handle, as need to return WORD handle for ST (NOTE PC's Window handles are all LONGS)
        !           648:     Index = GemDOS_FindFreeFileHandle();
        !           649:     if (Index==-1) {
        !           650:       // No free handles, return error code
        !           651:       Regs[REG_D0] = GEMDOS_ENHNDL;       // No more handles
        !           652:       return(TRUE);
        !           653:     }
        !           654:     else {
        !           655:       // Select mode
        !           656:       switch(Mode&0x03) {                 // Top bits used in some TOSes
        !           657:         case 0:                           // Read only
        !           658: //FIXME          Access = GENERIC_READ;
        !           659:           break;
        !           660:         case 1:                           // Write only
        !           661: //FIXME          Access = GENERIC_WRITE;
        !           662:           break;
        !           663:         case 2:                           // Read/Write
        !           664: //FIXME          Access = GENERIC_READ|GENERIC_WRITE;
        !           665:           break;
        !           666:       }
        !           667: 
        !           668:       // Open file
        !           669: //FIXME      FileHandles[Index].FileHandle = CreateFile(szActualFileName,Access,0,NULL,OPEN_EXISTING,FILE_ATTRIBUTE_NORMAL,NULL);
        !           670:       if (FileHandles[Index].FileHandle!=INVALID_HANDLE_VALUE) {
        !           671:         // Tag handle table entry as used and return handle
        !           672:         FileHandles[Index].bUsed = TRUE;
        !           673:         Regs[REG_D0] = Index+BASE_FILEHANDLE;  // Return valid ST file handle from range 6 to 45! (ours start from 0)
        !           674: 
        !           675:         return(TRUE);
        !           676:       }
        !           677:       else {
        !           678:         Regs[REG_D0] = GEMDOS_EFILNF;     // File not found
        !           679:         return(TRUE);
        !           680:       }
        !           681:     }
        !           682:   }
        !           683: 
        !           684:   return(FALSE);
        !           685: }
        !           686: 
        !           687: //-----------------------------------------------------------------------
        !           688: /*
        !           689:   GEMDOS Close file
        !           690:   Call 0x3E  
        !           691: */
        !           692: BOOL GemDOS_Close(unsigned long Params)
        !           693: {
        !           694:   int Handle;
        !           695: 
        !           696:   // Find our handle - may belong to TOS
        !           697:   Handle = STMemory_ReadWord(Params+SIZE_WORD)-BASE_FILEHANDLE;
        !           698: 
        !           699:   // Check handle was valid
        !           700:   if (GemDOS_IsInvalidFileHandle(Handle)) {
        !           701:     // No assume was TOS
        !           702:     return(FALSE);
        !           703:   }
        !           704:   else {
        !           705:     // Close file and free up handle table
        !           706:     close(FileHandles[Handle].FileHandle);
        !           707:     FileHandles[Handle].bUsed = FALSE;
        !           708:     // Return no error
        !           709:     Regs[REG_D0] = GEMDOS_EOK;
        !           710:     return(TRUE);
        !           711:   }
        !           712: }
        !           713: 
        !           714: //-----------------------------------------------------------------------
        !           715: /*
        !           716:   GEMDOS Read file
        !           717:   Call 0x3F
        !           718: */
        !           719: BOOL GemDOS_Read(unsigned long Params)
        !           720: {
        !           721:   char *pBuffer;
        !           722:   unsigned long nBytesRead,Size,CurrentPos,FileSize,nBytesLeft;
        !           723:   int Handle;
        !           724: 
        !           725:   // Read details from stack
        !           726:   Handle = STMemory_ReadWord(Params+SIZE_WORD)-BASE_FILEHANDLE;
        !           727:   Size = STMemory_ReadLong(Params+SIZE_WORD+SIZE_WORD);
        !           728:   pBuffer = (char *)STRAM_ADDR(STMemory_ReadLong(Params+SIZE_WORD+SIZE_WORD+SIZE_LONG));
        !           729: 
        !           730:   // Check handle was valid
        !           731:   if (GemDOS_IsInvalidFileHandle(Handle)) {
        !           732:     // No assume was TOS
        !           733:     return(FALSE);
        !           734:   }
        !           735:   else {
        !           736:     StatusBar_SetIcon(STATUS_ICON_HARDDRIVE,ICONSTATE_UPDATE);
        !           737: 
        !           738:     // To quick check to see where our file pointer is and how large the file is
        !           739:     CurrentPos = lseek(FileHandles[Handle].FileHandle, 0, SEEK_CUR);
        !           740:     FileSize = lseek(FileHandles[Handle].FileHandle, 0, SEEK_END);
        !           741:     lseek(FileHandles[Handle].FileHandle, CurrentPos, SEEK_SET);
        !           742: 
        !           743:     nBytesLeft = FileSize-CurrentPos;
        !           744: 
        !           745:     // Check for End Of File
        !           746:     if (nBytesLeft<0) {
        !           747:       Regs[REG_D0] = GEMDOS_ERROR;
        !           748: 
        !           749:       return(TRUE);
        !           750:     }
        !           751:     else {
        !           752:       // Limit to size of file to prevent windows error
        !           753:       if (Size>FileSize)
        !           754:         Size = FileSize;
        !           755:       // And read data in
        !           756:       nBytesRead = read(FileHandles[Handle].FileHandle, pBuffer, Size);
        !           757: //???      FlushFileBuffers(FileHandles[Handle].FileHandle);
        !           758: 
        !           759:       // Return number of bytes read
        !           760:       Regs[REG_D0] = nBytesRead;
        !           761: 
        !           762:       return(TRUE);
        !           763:     }
        !           764:   }
        !           765: }
        !           766: 
        !           767: //-----------------------------------------------------------------------
        !           768: /*
        !           769:   GEMDOS Write file
        !           770:   Call 0x40
        !           771: */
        !           772: BOOL GemDOS_Write(unsigned long Params)
        !           773: {
        !           774:   char *pBuffer;
        !           775:   unsigned long Size,nBytesWritten;
        !           776:   int Handle;
        !           777: 
        !           778: #ifdef ENABLE_SAVING
        !           779:   // Read details from stack
        !           780:   Handle = STMemory_ReadWord(Params+SIZE_WORD)-BASE_FILEHANDLE;
        !           781:   Size = STMemory_ReadLong(Params+SIZE_WORD+SIZE_WORD);
        !           782:   pBuffer = (char *)STRAM_ADDR(STMemory_ReadLong(Params+SIZE_WORD+SIZE_WORD+SIZE_LONG));
        !           783: 
        !           784:   // Check handle was valid
        !           785:   if (GemDOS_IsInvalidFileHandle(Handle)) {
        !           786:     // No assume was TOS
        !           787:     return(FALSE);
        !           788:   }
        !           789:   else {
        !           790:     StatusBar_SetIcon(STATUS_ICON_HARDDRIVE,ICONSTATE_UPDATE);
        !           791: 
        !           792:     nBytesWritten = write(FileHandles[Handle].FileHandle, pBuffer, Size);
        !           793:     if (nBytesWritten>=0) {
        !           794: //???      FlushFileBuffers(FileHandles[Handle].FileHandle);
        !           795: 
        !           796:       Regs[REG_D0] = nBytesWritten;      // OK
        !           797:     }
        !           798:     else
        !           799:       Regs[REG_D0] = GEMDOS_EACCDN;      // Access denied(ie read-only)
        !           800: 
        !           801:     return(TRUE);
        !           802:   }
        !           803: #endif
        !           804: 
        !           805:   return(FALSE);
        !           806: }
        !           807: 
        !           808: //-----------------------------------------------------------------------
        !           809: /*
        !           810:   GEMDOS UnLink(Delete) file
        !           811:   Call 0x41
        !           812: */
        !           813: BOOL GemDOS_UnLink(unsigned long Params)
        !           814: {
        !           815: #ifdef ENABLE_SAVING
        !           816:   char szActualFileName[MAX_PATH];
        !           817:   char *pszFileName;
        !           818:   int Drive;
        !           819: 
        !           820:   // Find filename
        !           821:   pszFileName = (char *)STRAM_ADDR(STMemory_ReadLong(Params+SIZE_WORD));
        !           822:   Drive = GemDOS_IsFileNameAHardDrive(pszFileName);
        !           823:   if (ISHARDDRIVE(Drive)) {
        !           824:     // And convert to hard drive filename
        !           825:     GemDOS_CreateHardDriveFileName(Drive,pszFileName,szActualFileName);
        !           826: 
        !           827:     // Now delete file??
        !           828:     if ( unlink(szActualFileName)==0 )
        !           829:       Regs[REG_D0] = GEMDOS_EOK;          // OK
        !           830:     else
        !           831:       Regs[REG_D0] = GEMDOS_EFILNF;       // File not found
        !           832: 
        !           833:     return(TRUE);
        !           834:   }
        !           835: #endif
        !           836: 
        !           837:   return(FALSE);
        !           838: }
        !           839: 
        !           840: //-----------------------------------------------------------------------
        !           841: /*
        !           842:   GEMDOS File seek
        !           843:   Call 0x42
        !           844: */
        !           845: BOOL GemDOS_LSeek(unsigned long Params)
        !           846: {
        !           847:   long Offset;
        !           848:   int Handle,Mode;
        !           849: 
        !           850:   // Read details from stack
        !           851:   Offset = (long)STMemory_ReadLong(Params+SIZE_WORD);
        !           852:   Handle = STMemory_ReadWord(Params+SIZE_WORD+SIZE_LONG)-BASE_FILEHANDLE;
        !           853:   Mode = STMemory_ReadWord(Params+SIZE_WORD+SIZE_LONG+SIZE_WORD);
        !           854: 
        !           855:   // Check handle was valid
        !           856:   if (GemDOS_IsInvalidFileHandle(Handle)) {
        !           857:     // No assume was TOS
        !           858:     return(FALSE);
        !           859:   }
        !           860:   else {
        !           861:     // Return offset from start of file
        !           862:     Regs[REG_D0] = lseek(FileHandles[Handle].FileHandle, Offset, Mode);
        !           863:     return(TRUE);
        !           864:   }
        !           865: }
        !           866: 
        !           867: //-----------------------------------------------------------------------
        !           868: /*
        !           869:   PExec Load And Go - Redirect to cart' routine at address 0xFA1000
        !           870: 
        !           871:   If loading from hard-drive(ie drive ID 2 or more) set condition codes to run own GEMDos routines
        !           872: */
        !           873: void GemDOS_Pexec_LoadAndGo(unsigned long Params)
        !           874: {
        !           875:   // Hard-drive?
        !           876:   if (CurrentDrive>=2)                // If not using A: or B:, use my own routines to load
        !           877:     SR = (SR&0xff00) | SR_OVERFLOW;
        !           878: }
        !           879: 
        !           880: //-----------------------------------------------------------------------
        !           881: /*
        !           882:   PExec Load But Don't Go - Redirect to cart' routine at address 0xFA1000
        !           883: */
        !           884: void GemDOS_Pexec_LoadDontGo(unsigned long Params)
        !           885: {
        !           886:   // Hard-drive?
        !           887:   if (CurrentDrive>=2)
        !           888:     SR = (SR&0xff00) | SR_OVERFLOW;
        !           889: }
        !           890: 
        !           891: //-----------------------------------------------------------------------
        !           892: /*
        !           893:   GEMDOS PExec handler
        !           894:   Call 0x4B
        !           895: */
        !           896: BOOL GemDOS_Pexec(unsigned long Params)
        !           897: {
        !           898:   unsigned short int Mode;
        !           899: 
        !           900:   // Find PExec mode
        !           901:   Mode = STMemory_ReadWord(Params+SIZE_WORD);
        !           902: //  Debug_File("Pexec %d (Drv:%d)\n",Mode,CurrentDrive);
        !           903: 
        !           904:   // Re-direct as needed
        !           905:   switch(Mode) {
        !           906:     case 0:      // Load and go
        !           907:       GemDOS_Pexec_LoadAndGo(Params);
        !           908:       return(FALSE);
        !           909:     case 3:      // Load, don't go
        !           910:       GemDOS_Pexec_LoadDontGo(Params);
        !           911:       return(FALSE);
        !           912:     case 4:      // Just go
        !           913:       return(FALSE);
        !           914:     case 5:      // Create basepage
        !           915:       return(FALSE);
        !           916:     case 6:
        !           917:       return(FALSE);
        !           918: 
        !           919:     default:
        !           920:       return(FALSE);
        !           921:   }
        !           922: 
        !           923:   // Still re-direct to TOS
        !           924:   return(FALSE);
        !           925: }
        !           926: 
        !           927: //-----------------------------------------------------------------------
        !           928: /*
        !           929:   GEMDOS Find first file
        !           930:   Call 0x4E
        !           931: */
        !           932: BOOL GemDOS_SFirst(unsigned long Params)
        !           933: {
        !           934:   int FatDate, FatTime;
        !           935:   char szActualFileName[MAX_PATH];
        !           936:   char *pszFileName;
        !           937:   unsigned short int Attr;
        !           938:   int Drive;
        !           939: 
        !           940:   // Find filename to search for
        !           941:   pszFileName = (char *)STRAM_ADDR(STMemory_ReadLong(Params+SIZE_WORD));
        !           942:   Attr = STMemory_ReadWord(Params+SIZE_WORD+SIZE_LONG);
        !           943: //  debug << "SFirst: " << pszFileName << endl;
        !           944: //  M68000_OutputHistory();
        !           945: 
        !           946:   Drive = GemDOS_IsFileNameAHardDrive(pszFileName);
        !           947:   if (ISHARDDRIVE(Drive)) {
        !           948:     StatusBar_SetIcon(STATUS_ICON_HARDDRIVE,ICONSTATE_UPDATE);
        !           949: 
        !           950:     // And convert to hard drive filename
        !           951:     GemDOS_CreateHardDriveFileName(Drive,pszFileName,szActualFileName);
        !           952: 
        !           953:     // Populate DTA, set index for our use
        !           954:     STMemory_WriteWord_PCSpace(pDTA->index,DTAIndex);
        !           955:     STMemory_WriteLong_PCSpace(pDTA->magic,DTA_MAGIC_NUMBER);
        !           956:     strcpy(pDTA->dta_pat,"");
        !           957:     pDTA->dta_sattrib = 0;
        !           958:     pDTA->dta_attrib = 0;
        !           959: 
        !           960:     // Were we looking for the volume label? Read directly from drive
        !           961:     if (Attr&GEMDOS_FILE_ATTRIB_VOLUME_LABEL) {
        !           962:       // Default and find drive from filename
        !           963:       strcpy(pDTA->dta_name,"");
        !           964:       File_GetFileNameDrive(pszFileName);
        !           965: //FIXME      if (GetVolumeInformation(pszFileName,pDTA->dta_name,TOS_NAMELEN,NULL,NULL,NULL,NULL,0))
        !           966: //        strupr(pDTA->dta_name);
        !           967:       Regs[REG_D0] = GEMDOS_EOK;          // Got volume
        !           968:       return(TRUE);
        !           969:     }
        !           970: 
        !           971:     // Scan for first file
        !           972: /* FIXME */
        !           973: /*
        !           974:     InternalDTAs[DTAIndex].FileHandle = FindFirstFile(szActualFileName,&InternalDTAs[DTAIndex].FindFileData);
        !           975:     if (InternalDTAs[DTAIndex].FileHandle==INVALID_HANDLE_VALUE) {
        !           976:       // No files of that match, return error code
        !           977:       Regs[REG_D0] = GEMDOS_EFILNF;        // File not found
        !           978:       return(TRUE);
        !           979:     }
        !           980:     else {
        !           981:       // Repeat find until have useable filename! The PC returns '.' and '..' - ignore '.'!
        !           982:       while( !stricmp(InternalDTAs[DTAIndex].FindFileData.cFileName,".") ) {
        !           983:         if (FindNextFile(InternalDTAs[DTAIndex].FileHandle,&InternalDTAs[DTAIndex].FindFileData)==0) {
        !           984:           // If this is all there is, then error
        !           985:           Regs[REG_D0] = GEMDOS_ENMFIL;    // No more files
        !           986:           return(TRUE);
        !           987:         }
        !           988:       }
        !           989: 
        !           990:       // And make all upper case, as original ST
        !           991:       strupr(InternalDTAs[DTAIndex].FindFileData.cFileName);
        !           992:       strcpy(pDTA->dta_name,InternalDTAs[DTAIndex].FindFileData.cFileName);
        !           993: 
        !           994:       // Fill remaining details, as PC
        !           995: //FIXME      STMemory_WriteLong_PCSpace(pDTA->dta_size,InternalDTAs[DTAIndex].FindFileData.nFileSizeLow);
        !           996: //FIXME      Misc_TimeDataToDos(&InternalDTAs[DTAIndex].FindFileData.ftLastWriteTime,&FatDate,&FatTime);
        !           997:       STMemory_WriteWord_PCSpace(pDTA->dta_time,FatTime);
        !           998:       STMemory_WriteWord_PCSpace(pDTA->dta_date,FatDate);
        !           999: //FIXME      pDTA->dta_attrib = GemDOS_ConvertAttribute(InternalDTAs[DTAIndex].FindFileData.dwFileAttributes);
        !          1000: 
        !          1001:       Regs[REG_D0] = GEMDOS_EOK;
        !          1002: 
        !          1003:       DTAIndex++;
        !          1004:       DTAIndex&=(MAX_DTAS_FILES-1);
        !          1005:     }
        !          1006:     return(TRUE);
        !          1007: */
        !          1008:   }
        !          1009:   return(FALSE);
        !          1010: }
        !          1011: 
        !          1012: //-----------------------------------------------------------------------
        !          1013: /*
        !          1014:   GEMDOS Search Next
        !          1015:   Call 0x4F
        !          1016: */
        !          1017: BOOL GemDOS_SNext(unsigned long Params)
        !          1018: {
        !          1019:   int FatDate, FatTime;
        !          1020:   int DTAIndex;
        !          1021: 
        !          1022:   // Was DTA ours or TOS?
        !          1023:   if (STMemory_ReadLong_PCSpace(pDTA->magic)==DTA_MAGIC_NUMBER) {
        !          1024:     StatusBar_SetIcon(STATUS_ICON_HARDDRIVE,ICONSTATE_UPDATE);
        !          1025: 
        !          1026:     // Find index into our list of structures
        !          1027:     DTAIndex = STMemory_ReadWord_PCSpace(pDTA->index)&(MAX_DTAS_FILES-1);
        !          1028: /*FIXME
        !          1029:     if (FindNextFile(InternalDTAs[DTAIndex].FileHandle,&InternalDTAs[DTAIndex].FindFileData)==0) {
        !          1030:       Regs[REG_D0] = GEMDOS_ENMFIL;        // No more files
        !          1031:       return(TRUE);
        !          1032:     }
        !          1033:     // Find next file on hard drive
        !          1034:     else {
        !          1035:       // And make all upper case, as original ST
        !          1036:       strupr(InternalDTAs[DTAIndex].FindFileData.cFileName);
        !          1037:       strcpy(pDTA->dta_name,InternalDTAs[DTAIndex].FindFileData.cFileName);
        !          1038:       // Fill remaining details, as PC
        !          1039:       STMemory_WriteLong_PCSpace(pDTA->dta_size,InternalDTAs[DTAIndex].FindFileData.nFileSizeLow);
        !          1040:       Misc_TimeDataToDos(&InternalDTAs[DTAIndex].FindFileData.ftLastWriteTime,&FatDate,&FatTime);
        !          1041:       STMemory_WriteWord_PCSpace(pDTA->dta_time,FatTime);
        !          1042:       STMemory_WriteWord_PCSpace(pDTA->dta_date,FatDate);
        !          1043:       pDTA->dta_attrib = GemDOS_ConvertAttribute(InternalDTAs[DTAIndex].FindFileData.dwFileAttributes);
        !          1044:   
        !          1045:       Regs[REG_D0] = GEMDOS_EOK;
        !          1046:       return(TRUE);
        !          1047:     }
        !          1048: */
        !          1049:   }
        !          1050: 
        !          1051:   return(FALSE);
        !          1052: }
        !          1053: 
        !          1054: //-----------------------------------------------------------------------
        !          1055: /*
        !          1056:   GEMDOS Rename
        !          1057:   Call 0x56
        !          1058: */
        !          1059: BOOL GemDOS_Rename(unsigned long Params)
        !          1060: {
        !          1061:   char *pszNewFileName,*pszOldFileName;
        !          1062:   char szNewActualFileName[MAX_PATH],szOldActualFileName[MAX_PATH];
        !          1063:   int NewDrive, OldDrive;
        !          1064: 
        !          1065:   // Read details from stack
        !          1066:   pszOldFileName = (char *)STRAM_ADDR(STMemory_ReadLong(Params+SIZE_WORD+SIZE_WORD));
        !          1067:   pszNewFileName = (char *)STRAM_ADDR(STMemory_ReadLong(Params+SIZE_WORD+SIZE_WORD+SIZE_LONG));
        !          1068: 
        !          1069:   NewDrive = GemDOS_IsFileNameAHardDrive(pszNewFileName);
        !          1070:   OldDrive = GemDOS_IsFileNameAHardDrive(pszOldFileName);
        !          1071:   if (ISHARDDRIVE(NewDrive) && ISHARDDRIVE(OldDrive)) {
        !          1072:     // And convert to hard drive filenames
        !          1073:     GemDOS_CreateHardDriveFileName(NewDrive,pszNewFileName,szNewActualFileName);
        !          1074:     GemDOS_CreateHardDriveFileName(OldDrive,pszOldFileName,szOldActualFileName);
        !          1075: 
        !          1076:     // Rename files
        !          1077:     if ( rename(szOldActualFileName,szNewActualFileName)==0 )
        !          1078:       Regs[REG_D0] = GEMDOS_EOK;
        !          1079:     else
        !          1080:       Regs[REG_D0] = GEMDOS_EACCDN;        // Access denied
        !          1081:     return(TRUE);
        !          1082:   }
        !          1083: 
        !          1084:   return(FALSE);
        !          1085: }
        !          1086: 
        !          1087: //-----------------------------------------------------------------------
        !          1088: /*
        !          1089:   GEMDOS GSDToF
        !          1090:   Call 0x57
        !          1091: */
        !          1092: BOOL GemDOS_GSDToF(unsigned long Params)
        !          1093: {
        !          1094: /*FIXME*/
        !          1095: /*
        !          1096:   BY_HANDLE_FILE_INFORMATION FileInfo;
        !          1097:   WORD FatDate,FatTime;
        !          1098:   DATETIME DateTime;
        !          1099:   char *pBuffer;
        !          1100:   int Handle,Flag;
        !          1101: 
        !          1102:   // Read details from stack
        !          1103:   pBuffer = (char *)STRAM_ADDR(STMemory_ReadLong(Params+SIZE_WORD));
        !          1104:   Handle = STMemory_ReadWord(Params+SIZE_WORD+SIZE_LONG)-BASE_FILEHANDLE;
        !          1105:   Flag = STMemory_ReadWord(Params+SIZE_WORD+SIZE_WORD+SIZE_LONG);
        !          1106: 
        !          1107:   // Check handle was valid
        !          1108:   if (GemDOS_IsInvalidFileHandle(Handle)) {
        !          1109:     // No assume was TOS
        !          1110:     return(FALSE);
        !          1111:   }
        !          1112:   else {
        !          1113:     Regs[REG_D0] = GEMDOS_ERROR;  // Invalid parameter
        !          1114: 
        !          1115:     if (Flag==0) {    // Read time
        !          1116:       if (GetFileInformationByHandle(FileHandles[Handle].FileHandle,&FileInfo)) {
        !          1117:         if (FileTimeToDosDateTime(&FileInfo.ftCreationTime,&FatDate,&FatTime)) {
        !          1118:           DateTime.hour = FatTime>>11;
        !          1119:           DateTime.minute = FatTime>>5;
        !          1120:           DateTime.second = FatTime;
        !          1121:           DateTime.year = FatDate>>9;
        !          1122:           DateTime.month = FatDate>>5;
        !          1123:           DateTime.day = FatDate;
        !          1124: 
        !          1125:           Regs[REG_D0] = GEMDOS_EOK;
        !          1126:         }
        !          1127:       }
        !          1128:     }
        !          1129:     else if (Flag==1) {
        !          1130:       Regs[REG_D0] = GEMDOS_EOK;
        !          1131:     }
        !          1132:     
        !          1133:      return(TRUE);
        !          1134:   }
        !          1135: */
        !          1136:   return(FALSE);
        !          1137: }
        !          1138: 
        !          1139: //-----------------------------------------------------------------------
        !          1140: /*
        !          1141:   This is called when we get a GemDOS exception. We then re-direct vector to our
        !          1142:   own routine. This forces execution through TOS which sets up the stack etc... and
        !          1143:   then calls our own routine in the cart' space which has the illegal instruction
        !          1144:   'GEMDOS_OPCODE'.
        !          1145: */
        !          1146: BOOL GemDOS(void)
        !          1147: {
        !          1148:   unsigned long OldGemDOSVector;
        !          1149: 
        !          1150:   // Init Gemdos if not already
        !          1151:   if (!bInitGemDOS) {
        !          1152:     OldGemDOSVector = STMemory_ReadLong(0x84);
        !          1153:     STMemory_WriteLong(CART_OLDGEMDOS,OldGemDOSVector);  // Store original gemdos handler
        !          1154:     STMemory_WriteLong(0x84,CART_GEMDOS);                // And redirect to new one (see cart.s)
        !          1155: 
        !          1156:     bInitGemDOS = TRUE;
        !          1157:   }
        !          1158: 
        !          1159:   // Now execute as normal, we may intercept it again later (see cart.s)
        !          1160:   return(FALSE);
        !          1161: }
        !          1162: 
        !          1163: 
        !          1164: /*-----------------------------------------------------------------------*/
        !          1165: /*
        !          1166:   Run GEMDos call, and re-direct if need to. Used to handle hard-disc emulation etc...
        !          1167:   This sets the condition codes(in SR), which are used in the 'cart.s' program to decide if we
        !          1168:   need to run old GEM vector, or PExec or nothing.
        !          1169: 
        !          1170:   This method keeps the stack and other states consistant with the original ST which is very important
        !          1171:   for the PExec call and maximum compatibility through-out
        !          1172: */
        !          1173: void GemDOS_OpCode(void)
        !          1174: {
        !          1175:   unsigned short int GemDOSCall,CallingSReg;
        !          1176:   unsigned long Params;
        !          1177: 
        !          1178:   /* Read SReg from stack to see if parameters are on User or Super stack (We enter here ALWAYS in super mode) */
        !          1179:   CallingSReg = STMemory_ReadWord(Regs[REG_A7]);
        !          1180:   if ((CallingSReg&SR_SUPERMODE)==0)      /* Calling from user mode */
        !          1181:     Params = Regs[REG_A8];
        !          1182:   else              /* Calling from super mode */
        !          1183:     Params = Regs[REG_A7]+SIZE_WORD+SIZE_LONG;
        !          1184: 
        !          1185:   /* Default to run TOS GemDos (SR_NEG run Gemdos, SR_ZERO already done, SR_OVERFLOW run own 'Pexec' */
        !          1186:   SR &= SR_CLEAR_OVERFLOW;
        !          1187:   SR &= SR_CLEAR_ZERO;
        !          1188:   SR |= SR_NEG;
        !          1189: 
        !          1190:   /* Find pointer to call parameters */
        !          1191:   GemDOSCall = STMemory_ReadWord(Params);
        !          1192: #ifdef DEBUG_TO_FILE
        !          1193:   Debug_File("GemDOS 0x%X (%s)\n",GemDOSCall,pszGemDOSNames[GemDOSCall]);
        !          1194: #endif
        !          1195: 
        !          1196:   /* Intercept call */
        !          1197:   switch(GemDOSCall) {
        !          1198:     case 0x3:
        !          1199:       if (GemDOS_Cauxin(Params))
        !          1200:         SR |= SR_ZERO;
        !          1201:       break;
        !          1202:     case 0x4:
        !          1203:       if (GemDOS_Cauxout(Params))
        !          1204:         SR |= SR_ZERO;
        !          1205:       break;
        !          1206:     case 0x5:
        !          1207:       if (GemDOS_Cprnout(Params))
        !          1208:         SR |= SR_ZERO;
        !          1209:       break;
        !          1210:     case 0xe:
        !          1211:       if (GemDOS_SetDrv(Params))
        !          1212:         SR |= SR_ZERO;
        !          1213:       break;      
        !          1214:     case 0x11:
        !          1215:       if (GemDOS_Cprnos(Params))
        !          1216:         SR |= SR_ZERO;
        !          1217:       break;
        !          1218:     case 0x12:
        !          1219:       if (GemDOS_Cauxis(Params))
        !          1220:         SR |= SR_ZERO;
        !          1221:       break;
        !          1222:     case 0x13:
        !          1223:       if (GemDOS_Cauxos(Params))
        !          1224:         SR |= SR_ZERO;
        !          1225:       break;
        !          1226:     case 0x1a:
        !          1227:       if (GemDOS_SetDTA(Params))
        !          1228:         SR |= SR_ZERO;
        !          1229:       break;
        !          1230:     case 0x39:
        !          1231:       if (GemDOS_MkDir(Params))
        !          1232:         SR |= SR_ZERO;
        !          1233:       break;
        !          1234:     case 0x3a:
        !          1235:       if (GemDOS_RmDir(Params))
        !          1236:         SR |= SR_ZERO;
        !          1237:       break;
        !          1238:     case 0x3b:
        !          1239:       if (GemDOS_ChDir(Params))
        !          1240:         SR |= SR_ZERO;
        !          1241:       break;
        !          1242:     case 0x3c:
        !          1243:       if (GemDOS_Create(Params))
        !          1244:         SR |= SR_ZERO;
        !          1245:       break;
        !          1246:     case 0x3d:
        !          1247:       if (GemDOS_Open(Params))
        !          1248:         SR |= SR_ZERO;
        !          1249:       break;
        !          1250:     case 0x3e:
        !          1251:       if (GemDOS_Close(Params))
        !          1252:         SR |= SR_ZERO;
        !          1253:       break;
        !          1254:     case 0x3f:
        !          1255:       if (GemDOS_Read(Params))
        !          1256:         SR |= SR_ZERO;
        !          1257:       break;
        !          1258:     case 0x40:
        !          1259:       if (GemDOS_Write(Params))
        !          1260:         SR |= SR_ZERO;
        !          1261:       break;
        !          1262:     case 0x41:
        !          1263:       if (GemDOS_UnLink(Params))
        !          1264:         SR |= SR_ZERO;
        !          1265:       break;
        !          1266:     case 0x42:
        !          1267:       if (GemDOS_LSeek(Params))
        !          1268:         SR |= SR_ZERO;
        !          1269:       break;
        !          1270:     case 0x4b:
        !          1271:       if (GemDOS_Pexec(Params))
        !          1272:         SR |= SR_ZERO;
        !          1273:       break;
        !          1274:     case 0x4e:
        !          1275:       if (GemDOS_SFirst(Params))
        !          1276:         SR |= SR_ZERO;
        !          1277:       break;
        !          1278:     case 0x4f:
        !          1279:       if (GemDOS_SNext(Params))
        !          1280:         SR |= SR_ZERO;
        !          1281:       break;
        !          1282:     case 0x56:
        !          1283:       if (GemDOS_Rename(Params))
        !          1284:         SR |= SR_ZERO;
        !          1285:       break;
        !          1286:     case 0x57:
        !          1287:       if (GemDOS_GSDToF(Params))
        !          1288:         SR |= SR_ZERO;
        !          1289:       break;
        !          1290:   }
        !          1291: 
        !          1292:   /* Write back to emulation condition codes, used for code re-direction */
        !          1293:   EmuCCode = SR<<4;
        !          1294: }
        !          1295: 
        !          1296: 
        !          1297: //-----------------------------------------------------------------------
        !          1298: /*
        !          1299:   Re-direct execution to old GEM calls, used in 'cart.s'
        !          1300: */
        !          1301: void GemDOS_RunOldOpCode(void)
        !          1302: {
        !          1303:   /* Set 'PC' to that of old GemDOS routines (see 'old_gemdos' in cart.s) */
        !          1304:   m68k_setpc( STMemory_ReadLong(0xfa1004) );    /* Address of 'old_gemdos' in cart.s */
        !          1305: /*  __asm {
        !          1306:     mov    ecx,[STRAM_OFFSET+0xfa1004]    // Address of 'old_gemdos' in cart.s
        !          1307:     bswap  ecx
        !          1308:     and    ecx,0x00ffffff
        !          1309:     mov    esi,ecx
        !          1310:     add    esi,STRAM_OFFSET      // New PC
        !          1311:     RET
        !          1312:   }
        !          1313: */
        !          1314: }

unix.superglobalmegacorp.com

This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.