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

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

unix.superglobalmegacorp.com

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