Annotation of frontvm/hardware/hostcall.c, revision 1.1.1.2

1.1       root        1: /*
                      2:   Hatari - gemdos.c
                      3: 
                      4:   This file is distributed under the GNU Public License, version 2 or at
                      5:   your option any later version. Read the file gpl.txt for details.
                      6: 
                      7:   GEMDOS intercept routines.
                      8:   These are used mainly for hard drive redirection of high level file routines.
                      9: 
                     10:   Now case is handled by using glob. See the function
                     11:   GemDOS_CreateHardDriveFileName for that. It also knows about symlinks.
                     12:   A filename is recognized on its eight first characters, do don't try to
                     13:   push this too far, or you'll get weirdness ! (But I can even run programs
                     14:   directly from a mounted cd in lower cases, so I guess it's working well !).
                     15: */
                     16: 
                     17: #include <sys/stat.h>
                     18: #include <time.h>
                     19: #include <dirent.h>
                     20: #include <ctype.h>
                     21: #include <unistd.h>
                     22: #include <glob.h>
                     23: #include <SDL/SDL.h>
                     24: #include <SDL/SDL_endian.h>
                     25: 
                     26: #include "main.h"
                     27: #include "configuration.h"
                     28: #include "file.h"
1.1.1.2 ! root       29: #include "../m68000.h"
1.1       root       30: #include "hostcall.h"
                     31: #include "memAlloc.h"
                     32: #include "misc.h"
                     33: #include "screen.h"
                     34: #include "audio.h"
                     35: #include "input.h"
1.1.1.2 ! root       36: #include "keymap.h"
        !            37: #include "shortcut.h"
1.1       root       38: #include "fe2.h"
                     39: 
                     40: //#define GEMDOS_VERBOSE
                     41: // uncomment the following line to debug filename lookups on hd
                     42: // #define FILE_DEBUG 1
                     43: 
                     44: #define ENABLE_SAVING             /* Turn on saving stuff */
                     45: 
                     46: #define INVALID_HANDLE_VALUE -1
                     47: 
                     48: #ifndef MAX_PATH
                     49: #define MAX_PATH 256
                     50: #endif
                     51: 
                     52: /* GLOB_ONLYDIR is a GNU extension for the glob() function and not defined
                     53:  * on some systems. We should probably use something different for this
                     54:  * case, but at the moment it we simply define it as 0... */
                     55: #ifndef GLOB_ONLYDIR
                     56: #warning GLOB_ONLYDIR was not defined.
                     57: #define GLOB_ONLYDIR 0
                     58: #endif
                     59: 
                     60: 
                     61: /* structure with all the drive-specific data for our emulated drives */
                     62: EMULATEDDRIVE emudrive;
                     63: 
                     64: typedef struct
                     65: {
                     66:   BOOL bUsed;
                     67:   FILE *FileHandle;
                     68:   char szActualName[MAX_PATH];   /* used by F_DATIME (0x57) */
                     69: } FILE_HANDLE;
                     70: 
                     71: typedef struct
                     72: {
                     73:   BOOL bUsed;
                     74:   int  nentries;                   /* number of entries in fs directory */
                     75:   int  centry;                     /* current entry # */
                     76:   struct dirent **found;           /* legal files */
                     77:   char path[MAX_PATH];             /* sfirst path */
                     78: } INTERNAL_DTA;
                     79: 
                     80: FILE_HANDLE  FileHandles[MAX_FILE_HANDLES];
                     81: INTERNAL_DTA InternalDTAs[MAX_DTAS_FILES];
                     82: int DTAIndex;                                 /* Circular index into above */
                     83: DTA *pDTA;                                    /* Our GEMDOS hard drive Disc Transfer Address structure */
                     84: unsigned char GemDOS_ConvertAttribute(mode_t mode);
                     85: 
1.1.1.2 ! root       86: /* to write shit with endian corrrection */
        !            87: static inline u32 do_get_mem_long(u32 *a)
        !            88: {
        !            89: #ifdef __i386__
        !            90:        u32 val = *a;
        !            91:        __asm__ ("bswap %0\n":"=r"(val):"0"(val));
        !            92:        return val;
        !            93: #elif LITTLE_ENDIAN
        !            94:     u8 *b = (u8 *)a;
        !            95:     return (*b << 24) | (*(b+1) << 16) | (*(b+2) << 8) | (*(b+3));
        !            96: #else
        !            97:     return *a;
        !            98: #endif
        !            99: }
        !           100: 
        !           101: static inline u16 do_get_mem_word(u16 *a)
        !           102: {
        !           103: #ifdef __i386__
        !           104:        u16 val = *a;
        !           105:        __asm__ ("xchgb %b0,%h0" : "=q" (val) :  "0" (val));
        !           106:        return val;
        !           107: #elif LITTLE_ENDIAN
        !           108:     u8 *b = (u8 *)a;
        !           109:     return (*b << 8) | (*(b+1));
        !           110: #else
        !           111:     return *a;
        !           112: #endif
        !           113: }
        !           114: 
        !           115: static inline u8 do_get_mem_byte(u8 *a)
        !           116: {
        !           117:     return *a;
        !           118: }
        !           119: 
        !           120: static inline void do_put_mem_long(u32 *a, u32 v)
        !           121: {
        !           122: #ifdef __i386__
        !           123:        __asm__ ("bswap %0\n":"=r"(v):"0"(v));
        !           124:        *a = v;
        !           125: #elif LITTLE_ENDIAN
        !           126:     u8 *b = (u8 *)a;
        !           127:     
        !           128:     *b = v >> 24;
        !           129:     *(b+1) = v >> 16;    
        !           130:     *(b+2) = v >> 8;
        !           131:     *(b+3) = v;
        !           132: #else
        !           133:     *a = v;
        !           134: #endif
        !           135: }
        !           136: 
        !           137: static inline void do_put_mem_word(u16 *a, u16 v)
        !           138: {
        !           139: #ifdef __i386__
        !           140:        __asm__ ("xchgb %b0,%h0" : "=q" (v) :  "0" (v));
        !           141:        *a = v;
        !           142: #elif LITTLE_ENDIAN
        !           143:     u8 *b = (u8 *)a;
        !           144:     
        !           145:     *b = v >> 8;
        !           146:     *(b+1) = v;
        !           147: #else
        !           148:     *a = v;
        !           149: #endif
        !           150: }
        !           151: 
        !           152: static inline void do_put_mem_byte(u8 *a, u8 v)
        !           153: {
        !           154:     *a = v;
        !           155: }
1.1       root      156: 
                    157: /*-------------------------------------------------------*/
                    158: /*
                    159:   Routines to convert time and date to MSDOS format.
                    160:   Originally from the STonX emulator. (cheers!)
                    161: */
                    162: unsigned short time2dos (time_t t)
                    163: {
                    164:        struct tm *x;
                    165:        x = localtime (&t);
                    166:        return (x->tm_sec>>1)|(x->tm_min<<5)|(x->tm_hour<<11);
                    167: }
                    168: 
                    169: unsigned short date2dos (time_t t)
                    170: {
                    171:        struct tm *x;
                    172:        x = localtime (&t);
                    173:        return x->tm_mday | ((x->tm_mon+1)<<5) | ( ((x->tm_year-80>0)?x->tm_year-80:0) << 9);
                    174: }
                    175: 
                    176: 
                    177: /*-----------------------------------------------------------------------*/
                    178: /*
                    179:   Populate a DATETIME structure with file info
                    180: */
                    181: BOOL GetFileInformation(char *name, DATETIME *DateTime)
                    182: {
                    183:   struct stat filestat;
                    184:   int n;
                    185:   struct tm *x;
                    186: 
                    187:   n = stat(name, &filestat);
                    188:   if( n != 0 ) return(FALSE);
                    189:   x = localtime( &filestat.st_mtime );
                    190: 
                    191:   DateTime->word1 = 0;
                    192:   DateTime->word2 = 0;
                    193: 
                    194:   DateTime->word1 |= (x->tm_mday & 0x1F);         /* 5 bits */
                    195:   DateTime->word1 |= (x->tm_mon & 0x0F)<<5;       /* 4 bits */
                    196:   DateTime->word1 |= (((x->tm_year-80>0)?x->tm_year-80:0) & 0x7F)<<9;      /* 7 bits*/
                    197: 
                    198:   DateTime->word2 |= (x->tm_sec & 0x1F);          /* 5 bits */
                    199:   DateTime->word2 |= (x->tm_min & 0x3F)<<5;       /* 6 bits */
                    200:   DateTime->word2 |= (x->tm_hour & 0x1F)<<11;     /* 5 bits */
                    201: 
                    202:   return(TRUE);
                    203: }
                    204: 
                    205: 
                    206: /*-----------------------------------------------------------------------*/
                    207: /*
                    208:   Populate the DTA buffer with file info
                    209: */
                    210: int PopulateDTA(char *path, struct dirent *file)
                    211: {
                    212:   char tempstr[MAX_PATH];
                    213:   struct stat filestat;
                    214:   int n;
                    215: 
                    216:   sprintf(tempstr, "%s/%s", path, file->d_name);
                    217:   n = stat(tempstr, &filestat);
                    218:   if(n != 0) return(FALSE); /* return on error */
                    219: 
                    220:   if(!pDTA) return(FALSE); /* no DTA pointer set */
                    221:   Misc_strupr(file->d_name);    /* convert to atari-style uppercase */
                    222:   strncpy(pDTA->dta_name,file->d_name,TOS_NAMELEN); /* FIXME: better handling of long file names */
1.1.1.2 ! root      223:   do_put_mem_long ((u32*)pDTA->dta_size, (long)filestat.st_size);
        !           224:   do_put_mem_word ((u16*)pDTA->dta_time, time2dos(filestat.st_mtime));
        !           225:   do_put_mem_word ((u16*)pDTA->dta_date, date2dos(filestat.st_mtime));
1.1       root      226:   pDTA->dta_attrib = GemDOS_ConvertAttribute(filestat.st_mode);
                    227: 
                    228:   return(TRUE);
                    229: }
                    230: 
                    231: 
                    232: /*-----------------------------------------------------------------------*/
                    233: /*
                    234:   Clear a used DTA structure.
                    235: */
                    236: void ClearInternalDTA(){
                    237:   int i;
                    238: 
                    239:   /* clear the old DTA structure */
                    240:   if(InternalDTAs[DTAIndex].found != NULL){
                    241:     for(i=0; i <InternalDTAs[DTAIndex].nentries; i++)
                    242:       free(InternalDTAs[DTAIndex].found[i]);
                    243:     free(InternalDTAs[DTAIndex].found);
                    244:   }
                    245:   InternalDTAs[DTAIndex].bUsed = FALSE;
                    246: }
                    247: 
                    248: 
                    249: /*-----------------------------------------------------------------------*/
                    250: /*
                    251:   Match a file to a dir mask.
                    252: */
                    253: static int match (char *pat, char *name)
                    254: {
                    255:   /* make uppercase copies */
                    256:   char p0[MAX_PATH], n0[MAX_PATH];
                    257:   strcpy(p0, pat);
                    258:   strcpy(n0, name);
                    259:   Misc_strupr(p0);
                    260:   Misc_strupr(n0);
                    261: 
                    262:   if(name[0] == '.') return(FALSE);                   /* no .* files */
                    263:   if (strcmp(pat,"*.*")==0) return(TRUE);
                    264:   else if (strcasecmp(pat,name)==0) return(TRUE);
                    265:   else
                    266:     {
                    267:       char *p=p0,*n=n0;
                    268:       for(;*n;)
                    269:        {
                    270:          if (*p=='*') {while (*n && *n != '.') n++;p++;}
                    271:          else if (*p=='?' && *n) {n++;p++;}
                    272:          else if (*p++ != *n++) return(FALSE);
                    273:        }
                    274:       if (*p==0)
                    275:        {
                    276:          return(TRUE);
                    277:        }
                    278:     }
                    279:   return(FALSE);
                    280: }
                    281: 
                    282: /*-----------------------------------------------------------------------*/
                    283: /*
                    284:   Parse directory from sfirst mask
                    285:   - e.g.: input:  "hdemudir/auto/mask*.*" outputs: "hdemudir/auto"
                    286: */
                    287: void fsfirst_dirname(char *string, char *new){
                    288:   int i=0;
                    289: 
                    290:   sprintf(new, string);
                    291:   /* convert to front slashes. */
                    292:   i=0;
                    293:   while(new[i] != '\0'){
                    294:     if(new[i] == '\\') new[i] = '/';
                    295:     i++;
                    296:   }
                    297:   while(string[i] != '\0'){new[i] = string[i]; i++;} /* find end of string */
                    298:   while(new[i] != '/') i--; /* find last slash */
                    299:   new[i] = '\0';
                    300: 
                    301: }
                    302: 
                    303: /*-----------------------------------------------------------------------*/
                    304: /*
                    305:   Parse directory mask, e.g. "*.*"
                    306: */
                    307: void fsfirst_dirmask(char *string, char *new){
                    308:   int i=0, j=0;
                    309:   while(string[i] != '\0')i++;   /* go to end of string */
                    310:   while(string[i] != '/') i--;   /* find last slash */
                    311:   i++;
                    312:   while(string[i] != '\0')new[j++] = string[i++]; /* go to end of string */
                    313:   new[j++] = '\0';
                    314: }
                    315: 
                    316: /*-----------------------------------------------------------------------*/
                    317: /*
                    318:   Initialize GemDOS/PC file system
                    319: */
                    320: void GemDOS_Init(void)
                    321: {
                    322:   int i;
                    323: 
                    324:   /* Clear handles structure */
                    325:   Memory_Clear(FileHandles, sizeof(FILE_HANDLE)*MAX_FILE_HANDLES);
                    326:   /* Clear DTAs */
                    327:   for(i=0; i<MAX_DTAS_FILES; i++)
                    328:   {
                    329:     InternalDTAs[i].bUsed = FALSE;
                    330:     InternalDTAs[i].nentries = 0;
                    331:     InternalDTAs[i].found = NULL;
                    332:   }
                    333:   DTAIndex = 0;
                    334: }
                    335: 
                    336: /*-----------------------------------------------------------------------*/
                    337: /*
                    338:   Reset GemDOS file system
                    339: */
                    340: void GemDOS_Reset()
                    341: {
                    342:   int i;
                    343: 
                    344:   /* Init file handles table */
                    345:   for(i=0; i<MAX_FILE_HANDLES; i++)
                    346:   {
                    347:     /* Was file open? If so close it */
                    348:     if (FileHandles[i].bUsed)
                    349:       fclose(FileHandles[i].FileHandle);
                    350: 
                    351:     FileHandles[i].FileHandle = NULL;
                    352:     FileHandles[i].bUsed = FALSE;
                    353:   }
                    354: 
                    355:   for(i=0; i<MAX_DTAS_FILES; i++)
                    356:   {
                    357:     InternalDTAs[i].bUsed = FALSE;
                    358:     InternalDTAs[i].nentries = 0;
                    359:     InternalDTAs[i].found = NULL;
                    360:   }
                    361: 
                    362:   /* Reset */
                    363:   pDTA = NULL;
                    364:   DTAIndex = 0;
                    365: }
                    366: 
                    367: 
                    368: /*-----------------------------------------------------------------------*/
                    369: /*
                    370:   Initialize a GEMDOS drive.
                    371:   Only 1 emulated drive allowed, as of yet.
                    372: */
                    373: void GemDOS_InitDrives()
                    374: {
                    375:     /* set emulation directory string */
                    376:     strcpy(emudrive.hd_emulation_dir, "./");
                    377: 
                    378:     /* remove trailing slash, if any in the directory name */
                    379:     File_CleanFileName(emudrive.hd_emulation_dir);
                    380: 
                    381:     emudrive.hd_letter = 2;
                    382: }
                    383: 
                    384: 
                    385: /*-----------------------------------------------------------------------*/
                    386: /*
                    387:   Un-init the GEMDOS drive
                    388: */
                    389: void GemDOS_UnInitDrives()
                    390: {
                    391:   GemDOS_Reset();        /* Close all open files on emulated drive*/
                    392: }
                    393: 
                    394: 
                    395: /*-----------------------------------------------------------------------*/
                    396: /*
                    397:   Return free PC file handle table index, or -1 if error
                    398: */
                    399: int GemDOS_FindFreeFileHandle(void)
                    400: {
                    401:   int i;
                    402: 
                    403:   /* Scan our file list for free slot */
                    404:   for(i=0; i<MAX_FILE_HANDLES; i++) {
                    405:     if (!FileHandles[i].bUsed)
                    406:       return(i);
                    407:   }
                    408: 
                    409:   /* Cannot open any more files, return error */
                    410:   return(-1);
                    411: }
                    412: 
                    413: /*-----------------------------------------------------------------------*/
                    414: /*
                    415:   Check ST handle is within our table range, return TRUE if not
                    416: */
                    417: BOOL GemDOS_IsInvalidFileHandle(int Handle)
                    418: {
                    419:   BOOL bInvalidHandle=FALSE;
                    420: 
                    421:   /* Check handle was valid with our handle table */
                    422:   if ( (Handle<0) || (Handle>=MAX_FILE_HANDLES) )
                    423:     bInvalidHandle = TRUE;
                    424:   else if (!FileHandles[Handle].bUsed)
                    425:     bInvalidHandle = TRUE;
                    426: 
                    427:   return(bInvalidHandle);
                    428: }
                    429: 
                    430: int baselen(char *s) {
                    431:   /* Returns the length of the basename of the file passed in parameter
                    432:      (ie the file without extension) */
                    433:   char *ext = strchr(s,'.');
                    434:   if (ext) return ext-s;
                    435:   return strlen(s);
                    436: }
                    437: 
                    438: /*-----------------------------------------------------------------------*/
                    439: /*
                    440:   Use hard-drive directory, current ST directory and filename to create full path
                    441: */
                    442: void GemDOS_CreateHardDriveFileName(int Drive,char *pszFileName,char *pszDestName)
                    443: {
                    444:   /*  int DirIndex = Misc_LimitInt(Drive-2, 0,ConfigureParams.HardDisc.nDriveList-1); */
                    445:   char *s,*start;
                    446: 
                    447:   if(pszFileName[0] == '\0') return; /* check for valid string */
                    448: 
                    449:   /* case full filename "C:\foo\bar" */
                    450:   s=pszDestName; start=NULL;
                    451: 
                    452:   if(pszFileName[1] == ':') {
                    453:     sprintf(pszDestName, "%s%s", emudrive.hd_emulation_dir, File_RemoveFileNameDrive(pszFileName));
                    454:   }
                    455:   /* case referenced from root:  "\foo\bar" */
                    456:   else if(pszFileName[0] == '\\'){
                    457:     sprintf(pszDestName, "%s%s", emudrive.hd_emulation_dir, pszFileName);
                    458:   }
                    459:   /* case referenced from current directory */
                    460:   else {
                    461:     sprintf(pszDestName, "%s%s",  emudrive.fs_currpath, pszFileName);
                    462:     start = pszDestName + strlen(emudrive.fs_currpath)-1;
                    463:   }
                    464: 
                    465:   /* convert to front slashes. */
                    466:   while((s = strchr(s+1,'\\'))) {
                    467:     if (!start) {
                    468:       start = s;
                    469:       continue;
                    470:     }
                    471:     {
                    472:       glob_t globbuf;
                    473:       char old1,old2,dest[256];
                    474:       int len,j,found,base_len;
                    475: 
                    476:       *start++ = '/';
                    477:       old1 = *start; *start++ = '*';
                    478:       old2 = *start; *start = 0;
                    479:       glob(pszDestName,GLOB_ONLYDIR,NULL,&globbuf);
                    480:       *start-- = old2; *start = old1;
                    481:       *s = 0;
                    482:       len = strlen(pszDestName);
                    483:       base_len = baselen(start);
                    484:       found = 0;
                    485:       for (j=0; j<globbuf.gl_pathc; j++) {
                    486:        /* If we search for a file of at least 8 characters, then it might
                    487:           be a longer filename since the ST can access only the first 8
                    488:           characters. If not, then it's a precise match (with case). */
                    489:        if (!(base_len < 8 ? strcasecmp(globbuf.gl_pathv[j],pszDestName) :
                    490:              strncasecmp(globbuf.gl_pathv[j],pszDestName,len))) {
                    491:          /* we found a matching name... */
                    492:          sprintf(dest,"%s%c%s",globbuf.gl_pathv[j],'/',s+1);
                    493:          strcpy(pszDestName,dest);
                    494:          j = globbuf.gl_pathc;
                    495:          found = 1;
                    496:        }
                    497:       }
                    498:       globfree(&globbuf);
                    499:       if (!found) {
                    500:        /* didn't find it. Let's try normal files (it might be a symlink) */
                    501:        *start++ = '*';
                    502:        *start = 0;
                    503:        glob(pszDestName,0,NULL,&globbuf);
                    504:        *start-- = old2; *start = old1;
                    505:        for (j=0; j<globbuf.gl_pathc; j++) {
                    506:          if (!strncasecmp(globbuf.gl_pathv[j],pszDestName,len)) {
                    507:            /* we found a matching name... */
                    508:            sprintf(dest,"%s%c%s",globbuf.gl_pathv[j],'/',s+1);
                    509:            strcpy(pszDestName,dest);
                    510:            j = globbuf.gl_pathc;
                    511:            found = 1;
                    512:          }
                    513:        }
                    514:        globfree(&globbuf);
                    515:        if (!found) {           /* really nothing ! */
                    516:          *s = '/';
                    517:          fprintf(stderr,"no path for %s\n",pszDestName);
                    518:        }
                    519:       }
                    520:     }
                    521:     start = s;
                    522:   }
                    523: 
                    524:   if (!start) start = strrchr(pszDestName,'/'); // path already converted ?
                    525: 
                    526:   if (start) {
                    527:     *start++ = '/';     /* in case there was only 1 anti slash */
                    528:     if (*start && !strchr(start,'?') && !strchr(start,'*')) {
                    529:       /* We have a complete name after the path, not a wildcard */
                    530:       glob_t globbuf;
                    531:       char old1,old2;
                    532:       int len,j,found,base_len;
                    533: 
                    534:       old1 = *start; *start++ = '*';
                    535:       old2 = *start; *start = 0;
                    536:       glob(pszDestName,0,NULL,&globbuf);
                    537:       *start-- = old2; *start = old1;
                    538:       len = strlen(pszDestName);
                    539:       base_len = baselen(start);
                    540:       found = 0;
                    541:       for (j=0; j<globbuf.gl_pathc; j++) {
                    542:        /* If we search for a file of at least 8 characters, then it might
                    543:           be a longer filename since the ST can access only the first 8
                    544:           characters. If not, then it's a precise match (with case). */
                    545:        if (!(base_len < 8 ? strcasecmp(globbuf.gl_pathv[j],pszDestName) :
                    546:              strncasecmp(globbuf.gl_pathv[j],pszDestName,len))) {
                    547:          /* we found a matching name... */
                    548:          strcpy(pszDestName,globbuf.gl_pathv[j]);
                    549:          j = globbuf.gl_pathc;
                    550:          found = 1;
                    551:        }
                    552:       }
                    553: #if FILE_DEBUG
                    554:       if (!found) {
                    555:        /* It's often normal, the gem uses this to test for existence */
                    556:        /* of desktop.inf or newdesk.inf for example. */
                    557:        fprintf(stderr,"didn't find filename %s\n",pszDestName);
                    558:       }
                    559: #endif
                    560:       globfree(&globbuf);
                    561:     }
                    562:   }
                    563: 
                    564: #if FILE_DEBUG
                    565:  fprintf(stderr,"conv %s -> %s\n",pszFileName,pszDestName);
                    566: #endif
                    567: }
                    568: 
                    569: /*-----------------------------------------------------------------------*/
                    570: /*
                    571:   Covert from FindFirstFile/FindNextFile attribute to GemDOS format
                    572: */
                    573: unsigned char GemDOS_ConvertAttribute(mode_t mode)
                    574: {
                    575:   unsigned char Attrib=0;
                    576: 
                    577:   /* FIXME: More attributes */
                    578:   if(S_ISDIR(mode)) Attrib |= GEMDOS_FILE_ATTRIB_SUBDIRECTORY;
                    579: 
                    580: /* FIXME */
                    581: /*
                    582:   // Look up attributes
                    583:   if (dwFileAttributes&FILE_ATTRIBUTE_READONLY)
                    584:     Attrib |= GEMDOS_FILE_ATTRIB_READONLY;
                    585:   if (dwFileAttributes&FILE_ATTRIBUTE_HIDDEN)
                    586:     Attrib |= GEMDOS_FILE_ATTRIB_HIDDEN;
                    587:   if (dwFileAttributes&FILE_ATTRIBUTE_DIRECTORY)
                    588:     Attrib |= GEMDOS_FILE_ATTRIB_SUBDIRECTORY;
                    589: */
                    590:   return(Attrib);
                    591: }
                    592: 
                    593: 
                    594: /*-----------------------------------------------------------------------*/
                    595: /*
                    596:   GEMDOS Set Disc Transfer Address (DTA)
                    597:   Call 0x1A
                    598: */
1.1.1.2 ! root      599: void GemDOS_SetDTA()
1.1       root      600: {
1.1.1.2 ! root      601:        unsigned long Params;
        !           602:        
        !           603:        Params = GetReg (REG_A7);
        !           604:        Params -= SIZE_WORD;
        !           605:        
1.1       root      606:   /* Look up on stack to find where DTA is! Store as PC pointer */
                    607:   pDTA = (DTA *)STRAM_ADDR(STMemory_ReadLong(Params+SIZE_WORD));
                    608: }
                    609: 
                    610: /*-----------------------------------------------------------------------*/
                    611: /*
                    612:   GEMDOS Create file
                    613:   Call 0x3C
                    614: */
1.1.1.2 ! root      615: void GemDOS_Create()
1.1       root      616: {
                    617:   char szActualFileName[MAX_PATH];
                    618:   char *pszFileName;
                    619:   char *rwflags[] = { "w+", /* read / write (truncate if exists) */
                    620:                      "wb"  /* write only */
                    621:   };
                    622:   int Drive,Index,Mode;
1.1.1.2 ! root      623:        unsigned long Params;
        !           624:        
        !           625:        Params = GetReg (REG_A7);
        !           626:        Params -= SIZE_WORD;
        !           627:        
1.1       root      628: 
                    629:   /* Find filename */
                    630:   pszFileName = (char *)STRAM_ADDR(STMemory_ReadLong(Params+SIZE_WORD));
                    631:   Mode = STMemory_ReadWord(Params+SIZE_WORD+SIZE_LONG);
                    632:   Drive = 2;
                    633:     /* And convert to hard drive filename */
                    634:     GemDOS_CreateHardDriveFileName(Drive,pszFileName,szActualFileName);
                    635: 
                    636:     /* Find slot to store file handle, as need to return WORD handle for ST */
                    637:     Index = GemDOS_FindFreeFileHandle();
                    638:     if (Index==-1) {
                    639:       /* No free handles, return error code */
1.1.1.2 ! root      640:       SetReg (REG_D0, GEMDOS_ENHNDL);       /* No more handles */
1.1       root      641:       return;
                    642:     }
                    643:     else {
                    644: #ifdef ENABLE_SAVING
                    645: 
                    646:       FileHandles[Index].FileHandle = fopen(szActualFileName, rwflags[Mode&0x01]);
                    647: 
                    648:       if (FileHandles[Index].FileHandle != NULL) {
                    649:         /* Tag handle table entry as used and return handle */
                    650:         FileHandles[Index].bUsed = TRUE;
1.1.1.2 ! root      651:         SetReg (REG_D0, Index+BASE_FILEHANDLE);  /* Return valid ST file handle from range 6 to 45! (ours start from 0) */
1.1       root      652:         return;
                    653:       }
                    654:       else {
1.1.1.2 ! root      655:         SetReg (REG_D0, GEMDOS_EFILNF);     /* File not found */
1.1       root      656:         return;
                    657:       }
                    658: #else
1.1.1.2 ! root      659:       SetReg (REG_D0, GEMDOS_EFILNF);       /* File not found */
1.1       root      660:       return;
                    661: #endif
                    662:     }
                    663: }
                    664: 
                    665: /*-----------------------------------------------------------------------*/
                    666: /*
                    667:   GEMDOS Open file
                    668:   Call 0x3D
                    669: */
1.1.1.2 ! root      670: void GemDOS_Open()
1.1       root      671: {
                    672:   char szActualFileName[MAX_PATH];
                    673:   char *pszFileName;
                    674:   char *open_modes[] = { "rb", "wb", "r+" };  /* convert atari modes to stdio modes */
                    675:   int Drive,Index,Mode;
1.1.1.2 ! root      676:        unsigned long Params;
        !           677:        
        !           678:        Params = GetReg (REG_A7);
        !           679:        Params -= SIZE_WORD;
        !           680:        
1.1       root      681: 
                    682:   /* Find filename */
                    683:   pszFileName = (char *)STRAM_ADDR(STMemory_ReadLong(Params+SIZE_WORD));
                    684:   Mode = STMemory_ReadWord(Params+SIZE_WORD+SIZE_LONG);
                    685:   Drive = 2;
                    686: 
                    687:     /* And convert to hard drive filename */
                    688:     GemDOS_CreateHardDriveFileName(Drive,pszFileName,szActualFileName);
                    689:     /* Find slot to store file handle, as need to return WORD handle for ST  */
                    690:     Index = GemDOS_FindFreeFileHandle();
                    691:     if (Index == -1) {
                    692:       /* No free handles, return error code */
1.1.1.2 ! root      693:       SetReg (REG_D0, GEMDOS_ENHNDL);       /* No more handles */
1.1       root      694:       return;
                    695:     }
                    696: 
                    697:     /* Open file */
                    698:     FileHandles[Index].FileHandle =  fopen(szActualFileName, open_modes[Mode&0x03]);
                    699: 
                    700:     sprintf(FileHandles[Index].szActualName,"%s",szActualFileName);
                    701: 
                    702:     if (FileHandles[Index].FileHandle != NULL) {
                    703:       /* Tag handle table entry as used and return handle */
                    704:       FileHandles[Index].bUsed = TRUE;
1.1.1.2 ! root      705:       SetReg (REG_D0, Index+BASE_FILEHANDLE);  /* Return valid ST file handle from range 6 to 45! (ours start from 0) */
1.1       root      706:       return;
                    707:     }
1.1.1.2 ! root      708:     SetReg (REG_D0, GEMDOS_EFILNF);     /* File not found/ error opening */
1.1       root      709:     return;
                    710: }
                    711: 
                    712: /*-----------------------------------------------------------------------*/
                    713: /*
                    714:   GEMDOS Close file
                    715:   Call 0x3E
                    716: */
1.1.1.2 ! root      717: void GemDOS_Close()
1.1       root      718: {
                    719:   int Handle;
1.1.1.2 ! root      720:        unsigned long Params;
        !           721:        
        !           722:        Params = GetReg (REG_A7);
        !           723:        Params -= SIZE_WORD;
        !           724:        
1.1       root      725: 
                    726:   /* Find our handle - may belong to TOS */
                    727:   Handle = STMemory_ReadWord(Params+SIZE_WORD)-BASE_FILEHANDLE;
                    728: 
                    729:   /* Check handle was valid */
                    730:   if (GemDOS_IsInvalidFileHandle(Handle)) {
                    731:     /* No assume was TOS */
                    732:     return;
                    733:   }
                    734:   else {
                    735:     /* Close file and free up handle table */
                    736:     fclose(FileHandles[Handle].FileHandle);
                    737:     FileHandles[Handle].bUsed = FALSE;
                    738:     /* Return no error */
1.1.1.2 ! root      739:     SetReg (REG_D0, GEMDOS_EOK);
1.1       root      740:     return;
                    741:   }
                    742: }
                    743: 
                    744: /*-----------------------------------------------------------------------*/
                    745: /*
                    746:   GEMDOS Read file
                    747:   Call 0x3F
                    748: */
1.1.1.2 ! root      749: void GemDOS_Read()
1.1       root      750: {
                    751:   char *pBuffer;
                    752:   unsigned long nBytesRead,Size,CurrentPos,FileSize;
                    753:   long nBytesLeft;
                    754:   int Handle;
1.1.1.2 ! root      755:        unsigned long Params;
        !           756:        
        !           757:        Params = GetReg (REG_A7);
        !           758:        Params -= SIZE_WORD;
        !           759:        
1.1       root      760: 
                    761:   /* Read details from stack */
                    762:   Handle = STMemory_ReadWord(Params+SIZE_WORD)-BASE_FILEHANDLE;
                    763:   Size = STMemory_ReadLong(Params+SIZE_WORD+SIZE_WORD);
                    764:   pBuffer = (char *)STRAM_ADDR(STMemory_ReadLong(Params+SIZE_WORD+SIZE_WORD+SIZE_LONG));
                    765: 
                    766:   /* Check handle was valid */
                    767:   if (GemDOS_IsInvalidFileHandle(Handle)) {
                    768:     /* No -  assume was TOS */
                    769:     return;
                    770:   }
                    771:   else {
                    772: 
                    773:     /* To quick check to see where our file pointer is and how large the file is */
                    774:     CurrentPos = ftell(FileHandles[Handle].FileHandle);
                    775:     fseek(FileHandles[Handle].FileHandle, 0, SEEK_END);
                    776:     FileSize = ftell(FileHandles[Handle].FileHandle);
                    777:     fseek(FileHandles[Handle].FileHandle, CurrentPos, SEEK_SET);
                    778: 
                    779:     nBytesLeft = FileSize-CurrentPos;
                    780: 
                    781:     /* Check for End Of File */
                    782:     if (nBytesLeft == 0) {
                    783:       /* FIXME: should we return zero (bytes read) or an error? */
1.1.1.2 ! root      784:        SetReg (REG_D0, 0);
1.1       root      785:       return;
                    786:     }
                    787:     else {
                    788:       /* Limit to size of file to prevent windows error */
                    789:       if (Size>FileSize)
                    790:         Size = FileSize;
                    791:       /* And read data in */
                    792:       nBytesRead = fread(pBuffer, 1, Size, FileHandles[Handle].FileHandle);
                    793: 
                    794:       /* Return number of bytes read */
1.1.1.2 ! root      795:       SetReg (REG_D0, nBytesRead);
1.1       root      796: 
                    797:       return;
                    798:     }
                    799:   }
                    800: }
                    801: 
                    802: /*-----------------------------------------------------------------------*/
                    803: /*
                    804:   GEMDOS Write file
                    805:   Call 0x40
                    806: */
1.1.1.2 ! root      807: void GemDOS_Write()
1.1       root      808: {
                    809:   char *pBuffer;
                    810:   unsigned long Size,nBytesWritten;
                    811:   int Handle;
1.1.1.2 ! root      812:        unsigned long Params;
        !           813:        
        !           814:        Params = GetReg (REG_A7);
        !           815:        Params -= SIZE_WORD;
        !           816:        
1.1       root      817: 
                    818: #ifdef ENABLE_SAVING
                    819:   /* Read details from stack */
                    820:   Handle = STMemory_ReadWord(Params+SIZE_WORD)-BASE_FILEHANDLE;
                    821:   Size = STMemory_ReadLong(Params+SIZE_WORD+SIZE_WORD);
                    822:   pBuffer = (char *)STRAM_ADDR(STMemory_ReadLong(Params+SIZE_WORD+SIZE_WORD+SIZE_LONG));
                    823: 
                    824:   /* Check handle was valid */
                    825:   if (GemDOS_IsInvalidFileHandle(Handle)) {
                    826:     /* No assume was TOS */
                    827:     return;
                    828:   }
                    829:   else {
                    830: 
                    831:     nBytesWritten = fwrite(pBuffer, 1, Size, FileHandles[Handle].FileHandle);
                    832:     if (nBytesWritten>=0) {
                    833: 
1.1.1.2 ! root      834:       SetReg (REG_D0, nBytesWritten);      /* OK */
1.1       root      835:     }
                    836:     else
1.1.1.2 ! root      837:       SetReg (REG_D0, GEMDOS_EACCDN);      /* Access denied(ie read-only) */
1.1       root      838: 
                    839:     return;
                    840:   }
                    841: #endif
                    842: 
                    843:   return;
                    844: }
                    845: 
                    846: /*-----------------------------------------------------------------------*/
                    847: /*
                    848:   GEMDOS UnLink(Delete) file
                    849:   Call 0x41
                    850: */
1.1.1.2 ! root      851: void GemDOS_UnLink()
1.1       root      852: {
                    853: #ifdef ENABLE_SAVING
                    854:   char szActualFileName[MAX_PATH];
                    855:   char *pszFileName;
                    856:   int Drive;
1.1.1.2 ! root      857:        unsigned long Params;
        !           858:        
        !           859:        Params = GetReg (REG_A7);
        !           860:        Params -= SIZE_WORD;
        !           861:        
1.1       root      862: 
                    863:   /* Find filename */
                    864:   pszFileName = (char *)STRAM_ADDR(STMemory_ReadLong(Params+SIZE_WORD));
                    865:   Drive = 2;
                    866:     /* And convert to hard drive filename */
                    867:     GemDOS_CreateHardDriveFileName(Drive,pszFileName,szActualFileName);
                    868: 
                    869:     /* Now delete file?? */
                    870:     if ( unlink(szActualFileName)==0 )
1.1.1.2 ! root      871:       SetReg (REG_D0, GEMDOS_EOK);          /* OK */
1.1       root      872:     else
1.1.1.2 ! root      873:       SetReg (REG_D0, GEMDOS_EFILNF);       /* File not found */
1.1       root      874: 
                    875:     return;
                    876: #endif
                    877: 
                    878: }
                    879: 
                    880: /*-----------------------------------------------------------------------*/
                    881: /*
                    882:   GEMDOS Search Next
                    883:   Call 0x4F
                    884: */
1.1.1.2 ! root      885: void GemDOS_SNext()
1.1       root      886: {
                    887:   struct dirent **temp;
                    888:   int Index;
1.1.1.2 ! root      889:        unsigned long Params;
        !           890:        
        !           891:        Params = GetReg (REG_A7);
        !           892:        Params -= SIZE_WORD;
        !           893:        
1.1       root      894: 
                    895:   /* Was DTA ours or TOS? */
1.1.1.2 ! root      896:   if (do_get_mem_long ((u32*)pDTA->magic)==DTA_MAGIC_NUMBER) {
1.1       root      897: 
                    898:     /* Find index into our list of structures */
1.1.1.2 ! root      899:     Index = do_get_mem_word ((u16*)pDTA->index)&(MAX_DTAS_FILES-1);
1.1       root      900: 
                    901:     if(InternalDTAs[Index].centry >= InternalDTAs[Index].nentries){
1.1.1.2 ! root      902:       SetReg (REG_D0, GEMDOS_ENMFIL);    /* No more files */
1.1       root      903:       return;
                    904:     }
                    905: 
                    906:     temp = InternalDTAs[Index].found;
                    907:     if(PopulateDTA(InternalDTAs[Index].path, temp[InternalDTAs[Index].centry++]) == FALSE){
                    908:       fprintf(stderr,"\tError setting DTA.\n");
                    909:       return;
                    910:     }
                    911: 
1.1.1.2 ! root      912:     SetReg (REG_D0, GEMDOS_EOK);
1.1       root      913:     return;
                    914:   }
                    915: 
                    916:   return;
                    917: }
                    918: 
                    919: 
                    920: /*-----------------------------------------------------------------------*/
                    921: /*
                    922:   GEMDOS Find first file
                    923:   Call 0x4E
                    924: */
1.1.1.2 ! root      925: void GemDOS_SFirst()
1.1       root      926: {
                    927:   char szActualFileName[MAX_PATH];
                    928:   char tempstr[MAX_PATH];
                    929:   char *pszFileName;
                    930:   struct dirent **files;
                    931:   unsigned short int Attr;
                    932:   int Drive;
                    933:   DIR *fsdir;
                    934:   int i,j,k;
1.1.1.2 ! root      935:        unsigned long Params;
        !           936:        
        !           937:        Params = GetReg (REG_A7);
        !           938:        Params -= SIZE_WORD;
        !           939:        
1.1       root      940: 
                    941:   /* Find filename to search for */
                    942:   pszFileName = (char *)STRAM_ADDR(STMemory_ReadLong(Params+SIZE_WORD));
                    943:   Attr = STMemory_ReadWord(Params+SIZE_WORD+SIZE_LONG);
                    944: 
                    945:   Drive = 2;
                    946: 
                    947:     /* And convert to hard drive filename */
                    948:     GemDOS_CreateHardDriveFileName(Drive,pszFileName,szActualFileName);
                    949: 
                    950:     /* Populate DTA, set index for our use */
1.1.1.2 ! root      951:     do_put_mem_word ((u16*)pDTA->index,DTAIndex);
        !           952:     do_put_mem_long ((u32*)pDTA->magic,DTA_MAGIC_NUMBER); /* set our dta magic num */
1.1       root      953: 
                    954:     if(InternalDTAs[DTAIndex].bUsed == TRUE) ClearInternalDTA();
                    955:     InternalDTAs[DTAIndex].bUsed = TRUE;
                    956: 
                    957:     /* Were we looking for the volume label? */
                    958:     if (Attr&GEMDOS_FILE_ATTRIB_VOLUME_LABEL) {
                    959:       /* Volume name */
                    960:       strcpy(pDTA->dta_name,"EMULATED.001");
1.1.1.2 ! root      961:       SetReg (REG_D0, GEMDOS_EOK);          /* Got volume */
1.1       root      962:       return;
                    963:     }
                    964: 
                    965:     /* open directory */
                    966:     fsfirst_dirname(szActualFileName, InternalDTAs[DTAIndex].path);
                    967:     fsdir = opendir(InternalDTAs[DTAIndex].path);
                    968: 
                    969:     if( fsdir == NULL ){
1.1.1.2 ! root      970:       SetReg (REG_D0, GEMDOS_EPTHNF);        /* Path not found */
1.1       root      971:       return;
                    972:     }
                    973:     /* close directory */
                    974:     closedir( fsdir );
                    975: 
                    976:     InternalDTAs[DTAIndex].nentries = scandir(InternalDTAs[DTAIndex].path, &files, 0, alphasort);
                    977:     if( InternalDTAs[DTAIndex].nentries < 0 ){
1.1.1.2 ! root      978:       SetReg (REG_D0, GEMDOS_EFILNF);        /* File (directory actually) not found */
1.1       root      979:       return;
                    980:     }
                    981: 
                    982:     InternalDTAs[DTAIndex].centry = 0;        /* current entry is 0 */
                    983:     fsfirst_dirmask(szActualFileName, tempstr); /* get directory mask */
                    984: 
                    985:     /* Create and populate a list of matching files. */
                    986: 
                    987:     j = 0;                     /* count number of entries matching mask */
                    988:     for(i=0;i<InternalDTAs[DTAIndex].nentries;i++)
                    989:       if(match(tempstr, files[i]->d_name)) j++;
                    990: 
                    991:     if (j==0) {
                    992:       return;
                    993:     }
                    994: 
                    995:     InternalDTAs[DTAIndex].found = (struct dirent **)malloc(sizeof(struct dirent *) * j);
                    996: 
                    997:     /* copy the dirent pointers for files matching the mask to our list */
                    998:     k = 0;
                    999:     for(i=0;i<InternalDTAs[DTAIndex].nentries;i++)
                   1000:       if(match(tempstr, files[i]->d_name)){
                   1001:        InternalDTAs[DTAIndex].found[k] = files[i];
                   1002:        k++;
                   1003:       }
                   1004: 
                   1005:     InternalDTAs[DTAIndex].nentries = j; /* set number of legal entries */
                   1006: 
                   1007:     if(InternalDTAs[DTAIndex].nentries == 0){
                   1008:       /* No files of that match, return error code */
1.1.1.2 ! root     1009:       SetReg (REG_D0, GEMDOS_EFILNF);        /* File not found */
1.1       root     1010:       return;
                   1011:     }
                   1012: 
                   1013:     /* Scan for first file (SNext uses no parameters) */
                   1014:     GemDOS_SNext(0);
                   1015:     /* increment DTA index */
                   1016:     DTAIndex++;
                   1017:     DTAIndex&=(MAX_DTAS_FILES-1);
                   1018: 
                   1019:     return;
                   1020: }
                   1021: 
                   1022: 
1.1.1.2 ! root     1023: void Call_Memset ()
1.1       root     1024: {
                   1025:        int adr, count;
1.1.1.2 ! root     1026:        unsigned long Params;
        !          1027:        
        !          1028:        Params = GetReg (REG_A7);
        !          1029:        Params -= SIZE_WORD;
        !          1030:        
1.1       root     1031:        count = STMemory_ReadLong (Params+SIZE_WORD);
                   1032:        adr = STMemory_ReadLong (Params+SIZE_WORD+SIZE_LONG);
                   1033:        memset (STRam+adr, 0, count);
                   1034: }
                   1035: 
1.1.1.2 ! root     1036: void Call_MemsetBlue ()
1.1       root     1037: {
                   1038:        int adr, count;
1.1.1.2 ! root     1039:        unsigned long Params;
        !          1040:        
        !          1041:        Params = GetReg (REG_A7);
        !          1042:        Params -= SIZE_WORD;
        !          1043:        
1.1       root     1044:        count = STMemory_ReadLong (Params+SIZE_WORD);
                   1045:        adr = STMemory_ReadLong (Params+SIZE_WORD+SIZE_LONG);
                   1046:        memset (STRam+adr, 0xe, count);
                   1047: }
                   1048: 
1.1.1.2 ! root     1049: void Call_Memcpy ()
1.1       root     1050: {
                   1051:        int dest, src, count;
1.1.1.2 ! root     1052:        unsigned long Params;
        !          1053:        
        !          1054:        Params = GetReg (REG_A7);
        !          1055:        Params -= SIZE_WORD;
        !          1056:        
1.1       root     1057: 
                   1058:        dest = STMemory_ReadLong (Params + SIZE_WORD);
                   1059:        src = STMemory_ReadLong (Params + SIZE_WORD + SIZE_LONG);
                   1060:        count = STMemory_ReadLong (Params + SIZE_WORD + 2*SIZE_LONG);
                   1061: 
                   1062:        memcpy (STRam+dest, STRam+src, count);
                   1063: }
                   1064: 
                   1065: static const char mouse_bmp[256] = {
                   1066:  0, 0,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,
                   1067:  0,15, 0,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,
                   1068:  0,15,15, 0,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,
                   1069:  0,15,15,15, 0,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,
                   1070:  0,15,15,15,15, 0,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,
                   1071:  0,15,15,15,15,15, 0,-1,-1,-1,-1,-1,-1,-1,-1,-1,
                   1072:  0,15,15,15,15, 0,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,
                   1073:  0,15,15,15,15, 0,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,
                   1074:  0,15, 0,15,15,15, 0,-1,-1,-1,-1,-1,-1,-1,-1,-1,
                   1075:  0, 0,-1, 0,15,15, 0,-1,-1,-1,-1,-1,-1,-1,-1,-1,
                   1076: -1,-1,-1, 0,15,15,15, 0,-1,-1,-1,-1,-1,-1,-1,-1,
                   1077: -1,-1,-1,-1, 0,15,15, 0,-1,-1,-1,-1,-1,-1,-1,-1,
                   1078: -1,-1,-1,-1, 0,15,15,15, 0,-1,-1,-1,-1,-1,-1,-1,
                   1079: -1,-1,-1,-1,-1, 0,15, 0,-1,-1,-1,-1,-1,-1,-1,-1,
                   1080: -1,-1,-1,-1,-1,-1, 0,-1,-1,-1,-1,-1,-1,-1,-1,-1,
                   1081: -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1
                   1082: };
                   1083: 
                   1084: Uint8 under_mouse[256];
                   1085: 
1.1.1.2 ! root     1086: void Call_BlitCursor ()
1.1       root     1087: {
                   1088:        int x, y, adr, org_x, org_y;
                   1089:        Uint8 *pixbase, *pix;
                   1090:        const char *bmp;
                   1091:        Uint8 *save;
1.1.1.2 ! root     1092:        unsigned long Params;
        !          1093:        
        !          1094:        Params = GetReg (REG_A7);
        !          1095:        Params -= SIZE_WORD;
        !          1096:        
1.1       root     1097:        org_x = STMemory_ReadLong (Params+SIZE_WORD);
                   1098:        org_y = STMemory_ReadLong (Params+SIZE_WORD+SIZE_LONG);
                   1099:        adr = STMemory_ReadLong (Params+SIZE_WORD+2*SIZE_LONG);
                   1100: 
                   1101:        pixbase = STRam + adr + (org_y*SCREENBYTES_LINE) + org_x;
                   1102:        bmp = mouse_bmp;
                   1103:        save = under_mouse;
                   1104: 
                   1105:        for (y=0; y<16; y++) {
                   1106:                if (y + org_y > SCREEN_HEIGHT_HBL) break;
                   1107:                pix = pixbase;
                   1108:                pixbase += SCREENBYTES_LINE;
                   1109:                for (x=0; x<16; x++, pix++, bmp++, save++) {
                   1110:                        if (x+org_x >= SCREENBYTES_LINE) continue;
                   1111:                        *save = *pix;
                   1112:                        if (*bmp != -1) *pix = *bmp;
                   1113:                }
                   1114:        }
                   1115: }
                   1116: 
1.1.1.2 ! root     1117: void Call_RestoreUnderCursor ()
1.1       root     1118: {
                   1119:        int x, y, adr, org_x, org_y;
                   1120:        Uint8 *pixbase, *pix;
                   1121:        char *bmp;
1.1.1.2 ! root     1122:        unsigned long Params;
        !          1123:        
        !          1124:        Params = GetReg (REG_A7);
        !          1125:        Params -= SIZE_WORD;
        !          1126:        
1.1       root     1127:        org_x = STMemory_ReadLong (Params+SIZE_WORD);
                   1128:        org_y = STMemory_ReadLong (Params+SIZE_WORD+SIZE_LONG);
                   1129:        adr = STMemory_ReadLong (Params+SIZE_WORD+2*SIZE_LONG);
                   1130: 
                   1131:        pixbase = STRam + adr + (org_y*SCREENBYTES_LINE) + org_x;
                   1132:        bmp = under_mouse;
                   1133: 
                   1134:        for (y=0; y<16; y++) {
                   1135:                if (y + org_y > SCREEN_HEIGHT_HBL) break;
                   1136:                pix = pixbase;
                   1137:                pixbase += SCREENBYTES_LINE;
                   1138:                for (x=0; x<16; x++, pix++, bmp++) {
                   1139:                        if (x+org_x >= SCREENBYTES_LINE) continue;
                   1140:                        if (*bmp != -1) *pix = *bmp;
                   1141:                }
                   1142:        }
                   1143: }
                   1144: 
1.1.1.2 ! root     1145: void Call_PutPix ()
1.1       root     1146: {
                   1147:        int col, org_x, scr;
                   1148:        char *pix;
1.1.1.2 ! root     1149:        unsigned long Params;
        !          1150:        
        !          1151:        Params = GetReg (REG_A7);
        !          1152:        Params -= SIZE_WORD;
        !          1153:        
1.1       root     1154:        col = STMemory_ReadWord (Params+SIZE_WORD)>>2;
1.1.1.2 ! root     1155:        org_x = (unsigned short) GetReg (REG_D4);
        !          1156:        scr = GetReg (REG_A3);
1.1       root     1157: 
                   1158:        /* hack to fix screen line. frontier's logic still thinks
                   1159:         * there are 160 bytes per line */
                   1160:        /* which screen buffer it is based on */
                   1161:        if (scr & 0x100000) {
                   1162:                scr -= 0x100000;
                   1163:                scr *= 2;
                   1164:                scr += 0x100000;
                   1165:        } else {
                   1166:                scr -= 0xf0000;
                   1167:                scr *= 2;
                   1168:                scr += 0xf0000;
                   1169:        }
                   1170:        pix = (char *)STRam + scr + org_x;
                   1171:        *pix = col;
                   1172:        return;
                   1173: }
                   1174: 
1.1.1.2 ! root     1175: void Call_FillLine ()
1.1       root     1176: {
                   1177:        int org_x,len,scr,col;
                   1178:        char *pix;
1.1.1.2 ! root     1179:        unsigned long Params;
        !          1180:        
        !          1181:        Params = GetReg (REG_A7);
        !          1182:        Params -= SIZE_WORD;
        !          1183:        
1.1       root     1184: 
                   1185:        col = STMemory_ReadWord (Params+SIZE_WORD)>>2;
1.1.1.2 ! root     1186:        org_x = (unsigned short) GetReg (REG_D4);
        !          1187:        len = (~GetReg (REG_D5)) & 0xffff;
        !          1188:        scr = GetReg (REG_A3);
1.1       root     1189:        
                   1190:        /* hack to fix screen line. frontier's logic still thinks
                   1191:         * there are 160 bytes per line */
                   1192:        /* which screen buffer it is based on */
                   1193:        if (scr & 0x100000) {
                   1194:                scr -= 0x100000;
                   1195:                scr *= 2;
                   1196:                scr += 0x100000;
                   1197:        } else {
                   1198:                scr -= 0xf0000;
                   1199:                scr *= 2;
                   1200:                scr += 0xf0000;
                   1201:        }
                   1202:        pix = (char *)STRam + scr;
                   1203:        org_x = SCREENBYTES_LINE;
                   1204:        while (org_x--) {
                   1205:                *pix = col;
                   1206:                pix++;
                   1207:        }
                   1208: }
                   1209: 
                   1210: /*
                   1211:  * This is used by the scanner code to draw object stalks
                   1212:  * which are below the plane of the scanner.
                   1213:  * The mask d7 indicates which pixels in the plane to set,
                   1214:  * and they are set if their current colour is zero.
                   1215:  *
                   1216:  * This implementation isn't the way the function is really
                   1217:  * supposed to be implemented (colour and draw mask was
                   1218:  * combined in d6 but the colour mask is wrong now for
                   1219:  * non-planar screen).
                   1220:  */
1.1.1.2 ! root     1221: void Call_BackHLine ()
1.1       root     1222: {
                   1223:        int i,scr,col,bitfield;
                   1224:        char *pix;
1.1.1.2 ! root     1225:        unsigned long Params;
        !          1226:        
        !          1227:        Params = GetReg (REG_A7);
        !          1228:        Params -= SIZE_WORD;
        !          1229:        
1.1       root     1230: 
                   1231:        col = STMemory_ReadWord (Params+SIZE_WORD)>>2;
1.1.1.2 ! root     1232:        scr = GetReg (REG_A3);
        !          1233:        bitfield = (unsigned short) GetReg (REG_D7);
1.1       root     1234:        
                   1235:        /* hack to fix screen line. frontier's logic still thinks
                   1236:         * there are 160 bytes per line */
                   1237:        /* which screen buffer it is based on */
                   1238:        if (scr & 0x100000) {
                   1239:                scr -= 0x100000;
                   1240:                scr *= 2;
                   1241:                scr += 0x100000;
                   1242:        } else {
                   1243:                scr -= 0xf0000;
                   1244:                scr *= 2;
                   1245:                scr += 0xf0000;
                   1246:        }
                   1247:        pix = STRam + scr;
                   1248:        for (i=15; i>=0; i--) {
                   1249:                if ((bitfield & (1<<i)) && (*pix == 0)) *pix = col;
                   1250:                pix++;
                   1251:        }
                   1252: }
                   1253: 
1.1.1.2 ! root     1254: void Call_OldHLine ()
1.1       root     1255: {
                   1256:        int org_x,len,scr,col;
                   1257:        char *pix;
1.1.1.2 ! root     1258:        unsigned long Params;
        !          1259:        
        !          1260:        Params = GetReg (REG_A7);
        !          1261:        Params -= SIZE_WORD;
        !          1262:        
1.1       root     1263: 
                   1264:        col = STMemory_ReadWord (Params+SIZE_WORD)>>2;
                   1265:        //printf ("col=%d, d4=%d, (idx) d5=%d, (scr_line) a3=%p\n", col, Regs[REG_D4]&0xffff, Regs[REG_D5]&0xffff, (void*)Regs[REG_A3]);
1.1.1.2 ! root     1266:        org_x = (unsigned short) GetReg (REG_D4);
        !          1267:        len = (unsigned short) GetReg (REG_D5);
        !          1268:        scr = GetReg (REG_A3);
1.1       root     1269:        
                   1270:        /* hack to fix screen line. frontier's logic still thinks
                   1271:         * there are 160 bytes per line */
                   1272:        /* which screen buffer it is based on */
                   1273:        if (scr & 0x100000) {
                   1274:                scr -= 0x100000;
                   1275:                scr *= 2;
                   1276:                scr += 0x100000;
                   1277:        } else {
                   1278:                scr -= 0xf0000;
                   1279:                scr *= 2;
                   1280:                scr += 0xf0000;
                   1281:        }
                   1282:        len = len/2;
                   1283:        /* horizontal line */
                   1284:        pix = STRam + scr + org_x;
                   1285:        while (len--) {
                   1286:                *pix = col;
                   1287:                pix++;
                   1288:        }
                   1289: }
                   1290: 
1.1.1.2 ! root     1291: void Call_HLine ()
1.1       root     1292: {
                   1293:        int org_x,len,scr,col;
                   1294:        char *pix;
                   1295: 
1.1.1.2 ! root     1296:        col = (GetReg(REG_D1) & 0xffff)>>2;
        !          1297:        org_x = GetReg(REG_D4) & 0xffff;
        !          1298:        len = GetReg(REG_D5) & 0xffff;
        !          1299:        scr = GetReg(REG_A3);
1.1       root     1300:        
                   1301:        /* horizontal line */
                   1302:        pix = STRam + scr + org_x;
                   1303:        while (len--) {
                   1304:                *pix = col;
                   1305:                pix++;
                   1306:        }
                   1307: }
                   1308: 
                   1309: /*
                   1310:  * Blits frontier format 4-plane thingy
                   1311:  */
1.1.1.2 ! root     1312: void Call_BlitBmp ()
1.1       root     1313: {
                   1314:        int width, height, org_x, org_y, bmp, scr;
                   1315:        char *bmp_pix, *scr_pix, *ybase;
                   1316:        int xpoo, i, ypoo, plane_incr;
                   1317:        
                   1318:        short word0, word1, word2, word3;
1.1.1.2 ! root     1319:        unsigned long Params;
        !          1320:        
        !          1321:        Params = GetReg (REG_A7);
        !          1322:        Params -= SIZE_WORD;
        !          1323:        
        !          1324: 
1.1       root     1325:        
                   1326:        width = STMemory_ReadWord (Params+SIZE_WORD);
                   1327:        height = STMemory_ReadWord (Params+SIZE_WORD*2);
                   1328:        org_x = STMemory_ReadWord (Params+SIZE_WORD*3);
                   1329:        org_y = STMemory_ReadWord (Params+SIZE_WORD*4);
                   1330:        bmp = STMemory_ReadLong (Params+SIZE_WORD*5);
                   1331:        scr = STMemory_ReadLong (Params+SIZE_WORD*5 + SIZE_LONG);
                   1332: 
                   1333:        /* width is in words (width/16) */
                   1334:        //printf ("Blit %dx%d to %d,%d, bmp 0x%x, scr 0x%x.\n", width, height, org_x, org_y, bmp, scr);
                   1335:        bmp_pix = STRam + bmp + 4;
                   1336:        ybase = STRam + scr + (org_y*SCREENBYTES_LINE) + org_x;
                   1337: 
                   1338:        /* These checks were in the original blit routine */
                   1339:        if (org_x < 0) return;
                   1340:        if (org_y < 0) return;
                   1341:        if (height > 200) return;
                   1342:        if (width > 320) return;
                   1343:        
                   1344:        plane_incr = 2*height*width;
                   1345:        
                   1346:        ypoo = height;
                   1347:        while (ypoo--) {
                   1348:                scr_pix = (char *)ybase;
                   1349:                ybase += SCREENBYTES_LINE;
                   1350:                for (xpoo = width; xpoo; xpoo--) {
                   1351:                        word0 = SDL_SwapBE16 (*((short*)bmp_pix));
                   1352:                        bmp_pix += plane_incr;
                   1353:                        word1 = SDL_SwapBE16 (*((short*)bmp_pix));
                   1354:                        bmp_pix += plane_incr;
                   1355:                        word2 = SDL_SwapBE16 (*((short*)bmp_pix));
                   1356:                        bmp_pix += plane_incr;
                   1357:                        word3 = SDL_SwapBE16 (*((short*)bmp_pix));
                   1358:                        
                   1359:                        for (i=0; i<16; i++) {
                   1360:                                *scr_pix = (word0 >> (15-i))&0x1;
                   1361:                                *scr_pix |= ((word1 >> (15-i))&0x1)<<1;
                   1362:                                *scr_pix |= ((word2 >> (15-i))&0x1)<<2;
                   1363:                                *scr_pix |= ((word3 >> (15-i))&0x1)<<3;
                   1364:                                scr_pix++;
                   1365:                        }
                   1366:                        bmp_pix -= 3*plane_incr;
                   1367:                        bmp_pix += 2;
                   1368:                }
                   1369:        }
                   1370: }
                   1371: 
                   1372: #define SCR_W  320
                   1373: 
1.1.1.2 ! root     1374: void Call_DrawStrShadowed ()
1.1       root     1375: {
                   1376:        unsigned char *str;
                   1377:        
1.1.1.2 ! root     1378:        str = GetReg (REG_A0) + STRam;
1.1       root     1379: 
1.1.1.2 ! root     1380:        SetReg (REG_D1, DrawStr (
        !          1381:                        GetReg (REG_D1), GetReg (REG_D2),
        !          1382:                        GetReg (REG_D0), str, TRUE));
1.1       root     1383: }
                   1384: 
1.1.1.2 ! root     1385: void Call_DrawStr ()
1.1       root     1386: {
                   1387:        unsigned char *str;
                   1388:        
1.1.1.2 ! root     1389:        str = GetReg (REG_A0) + STRam;
1.1       root     1390: 
1.1.1.2 ! root     1391:        SetReg (REG_D1, DrawStr (
        !          1392:                        GetReg (REG_D1), GetReg (REG_D2),
        !          1393:                        GetReg (REG_D0), str, FALSE));
1.1       root     1394: }
                   1395: 
1.1.1.2 ! root     1396: void Call_SetMainPalette ()
1.1       root     1397: {
                   1398:        Uint32 pal_ptr;
                   1399:        int i;
1.1.1.2 ! root     1400:        unsigned long Params;
        !          1401: 
        !          1402:        Params = GetReg (REG_A7);
        !          1403:        Params -= SIZE_WORD;
        !          1404:        
1.1       root     1405:        
                   1406:        pal_ptr = STMemory_ReadLong (Params+SIZE_WORD);
                   1407:        
                   1408:        for (i=0; i<16; i++) {
                   1409:                MainPalette[i] = STMemory_ReadWord (pal_ptr);
                   1410:                //printf ("%hx ", MainPalette[i]);
                   1411:                pal_ptr+=2;
                   1412:        }
                   1413:        //printf ("\n");
                   1414: }
                   1415: 
1.1.1.2 ! root     1416: void Call_SetCtrlPalette ()
1.1       root     1417: {
                   1418:        Uint32 pal_ptr;
                   1419:        int i;
1.1.1.2 ! root     1420:        unsigned long Params;
        !          1421:        
        !          1422:        Params = GetReg (REG_A7);
        !          1423:        Params -= SIZE_WORD;
        !          1424:        
1.1       root     1425:        
                   1426:        pal_ptr = STMemory_ReadLong (Params+SIZE_WORD);
                   1427:        
                   1428:        for (i=0; i<16; i++) {
                   1429:                CtrlPalette[i] = STMemory_ReadWord (pal_ptr);
                   1430:                pal_ptr+=2;
                   1431:        }
                   1432: }
                   1433: 
                   1434: int len_working_ext_pal;
                   1435: unsigned short working_ext_pal[240];
                   1436: 
1.1.1.2 ! root     1437: void Call_InformScreens ()
1.1       root     1438: {
1.1.1.2 ! root     1439:        unsigned long Params;
        !          1440:        
        !          1441:        Params = GetReg (REG_A7);
        !          1442:        Params -= SIZE_WORD;
        !          1443:        
1.1       root     1444:        physcreen2 = STMemory_ReadLong (Params+SIZE_WORD);
                   1445:        logscreen2 = STMemory_ReadLong (Params+SIZE_WORD+SIZE_LONG);
                   1446:        physcreen = STMemory_ReadLong (Params+SIZE_WORD+2*SIZE_LONG);
                   1447:        logscreen = STMemory_ReadLong (Params+SIZE_WORD+3*SIZE_LONG);
                   1448: }
                   1449: 
                   1450: /* also copies the extended palette into main palette */
1.1.1.2 ! root     1451: void Call_SetScreenBase ()
1.1       root     1452: {
                   1453:        int i;
1.1.1.2 ! root     1454:        unsigned long Params;
        !          1455:        
        !          1456:        Params = GetReg (REG_A7);
        !          1457:        Params -= SIZE_WORD;
        !          1458:        
1.1       root     1459:        VideoBase = STMemory_ReadLong (Params+SIZE_WORD);
                   1460:        VideoRaster = STRam + VideoBase;
                   1461: 
                   1462:        for (i=0; i<len_working_ext_pal; i++) {
                   1463:                MainPalette[16+i] = working_ext_pal[i];
                   1464:        }
                   1465:        len_main_palette = 16 + len_working_ext_pal;
                   1466: }
                   1467: 
1.1.1.2 ! root     1468: void Call_MakeExtPalette ()
1.1       root     1469: {
                   1470:        int col_list, len, col_idx, col_val, i;
1.1.1.2 ! root     1471:        unsigned long Params;
        !          1472:        
        !          1473:        Params = GetReg (REG_A7);
        !          1474:        Params -= SIZE_WORD;
        !          1475:        
1.1       root     1476: 
                   1477:        col_list = STMemory_ReadLong (Params+SIZE_WORD);
                   1478: 
                   1479:        len = STMemory_ReadWord (col_list) >> 2;
                   1480:        len_working_ext_pal = len;
                   1481:        col_list+=2;
                   1482:        //printf ("%d colours.\n", len+2);
                   1483:        for (i=0; i<len; i++) {
                   1484:                col_val = STMemory_ReadWord (col_list);
                   1485:                working_ext_pal[i] = col_val;
                   1486:                col_list += 2;
                   1487:                col_idx = STMemory_ReadWord (col_list);
                   1488:                /* offset dynamic colours into extended palette
                   1489:                 * range (colours 16+) */
                   1490:                col_idx += 16<<2;
                   1491:                STMemory_WriteWord (col_list, col_idx);
                   1492:                col_list += 2;
                   1493:        }
                   1494: }
1.1.1.2 ! root     1495: void Call_DumpRegs ()
        !          1496: {
        !          1497:        int i;
        !          1498:        printf ("D: ");
        !          1499:        for (i=0; i<8; i++) {
        !          1500:                printf ("$%x ", GetReg (i));
        !          1501:        } printf ("\n");
        !          1502:        printf ("A: ");
        !          1503:        for (i=0; i<8; i++) {
        !          1504:                printf ("$%x ", GetReg (i+8));
        !          1505:        } printf ("\n");
        !          1506: }
        !          1507: 
1.1       root     1508: 
1.1.1.2 ! root     1509: void Call_DumpDebug ()
1.1       root     1510: {
1.1.1.2 ! root     1511:        int i, j;
        !          1512: 
        !          1513:        printf ("Debug info. PC @ 68k line %d.\n", line_no);
        !          1514:        
        !          1515:        Call_DumpRegs ();
        !          1516:        
        !          1517:        printf ("Stack:");
        !          1518:        j = GetReg (15);
        !          1519:        for (i=0; i<8; i++) {
        !          1520:                j+=4;
        !          1521:                printf (" $%x", STMemory_ReadLong (j));
        !          1522:        }
        !          1523:        putchar ('\n');
1.1       root     1524: }
                   1525: 
1.1.1.2 ! root     1526: void Call_NotifyOfScrFlip ()
1.1       root     1527: {
                   1528:        bScreenContentsChanged = TRUE;
                   1529: }
                   1530: 
                   1531: /* mouse pos in d3,d4 */
1.1.1.2 ! root     1532: void Call_NotifyMousePos ()
1.1       root     1533: {
                   1534: #if 0
                   1535:        int x, y;
                   1536:        
1.1.1.2 ! root     1537:        x = GetReg (REG_D3) & 0xffff;
        !          1538:        y = GetReg (REG_D4) & 0xffff;
1.1       root     1539: 
                   1540:        x *= ScreenDraw.MouseScale;
                   1541:        y *= ScreenDraw.MouseScale;
                   1542:        
                   1543:        SDL_EventState (SDL_MOUSEMOTION, SDL_DISABLE);
                   1544:        SDL_WarpMouse (x, y);
                   1545:        SDL_EventState (SDL_MOUSEMOTION, SDL_ENABLE);
                   1546:        SDL_ShowCursor (SDL_ENABLE);    
                   1547: #endif /* 0 */
                   1548: }
                   1549: 
1.1.1.2 ! root     1550: void Call_DrawQuad ()
1.1       root     1551: {
1.1.1.2 ! root     1552:        int high, equal, i, j;
1.1       root     1553:        struct Point pts[4];
                   1554: 
1.1.1.2 ! root     1555:        pts[0].x = GetReg(REG_D0);
        !          1556:        pts[0].y = GetReg(REG_D1);
        !          1557:        pts[1].x = GetReg(REG_D2);
        !          1558:        pts[1].y = GetReg(REG_D3);
        !          1559:        pts[2].x = GetReg(REG_D4);
        !          1560:        pts[2].y = GetReg(REG_D5);
        !          1561:        pts[3].x = GetReg(REG_D6);
        !          1562:        pts[3].y = GetReg(REG_D7);
1.1       root     1563:        
                   1564:        /* the two points with highest y actually seem to be
                   1565:         * drawn only to y-1 by the frontier routines. weird. */
                   1566:        for (i=0; i<4; i++) {
                   1567:                high = 0;
1.1.1.2 ! root     1568:                equal = -1;
1.1       root     1569:                for (j=0; j<4; j++) {
1.1.1.2 ! root     1570:                        if (i == j) continue;
1.1       root     1571:                        if (pts[i].y > pts[j].y) high++;
1.1.1.2 ! root     1572:                        if (pts[i].y == pts[j].y) equal = j;
        !          1573:                }
        !          1574:                if ((high == 2) && (equal != -1)) {
        !          1575:                        pts[equal].y--;
        !          1576:                        pts[i].y--;
        !          1577:                        break;
1.1       root     1578:                }
                   1579:        }
1.1.1.2 ! root     1580:        DrawPoly (pts, 4, GetReg (REG_A0)/4);
        !          1581: 
        !          1582:        /*char *poop;
        !          1583:        for (i=0; i<4; i++) {
        !          1584:                poop = LOGSCREEN2 + (SCREENBYTES_LINE*(int)pts[i].y) + (int)pts[i].x;
        !          1585:                *poop = 0;
        !          1586:        }*/
        !          1587: }
        !          1588: 
        !          1589: void Call_DrawTriangle ()
        !          1590: {
        !          1591:        DrawTriangle ((short)GetReg (REG_D0), (short)GetReg (REG_D1),
        !          1592:                        (short)GetReg (REG_D2), (short)GetReg (REG_D3),
        !          1593:                        (short)GetReg (REG_D4), (short)GetReg (REG_D5),
        !          1594:                        ((short)GetReg (REG_A0))/4);
1.1       root     1595: }
                   1596: 
1.1.1.2 ! root     1597: static void Call_Idle ()
1.1       root     1598: {
1.1.1.2 ! root     1599:        usleep (0);
1.1       root     1600: }
                   1601: 
1.1.1.2 ! root     1602: void Call_HostUpdate ()
1.1       root     1603: {
1.1.1.2 ! root     1604:        /* Clear any key presses which are due to be de-bounced (held for one ST frame) */
        !          1605:        Keymap_DebounceAllKeys();
        !          1606:        /* Check 'Function' keys, so if press F12 we update screen correctly to Window! */
        !          1607:        ShortCut_CheckKeys();
        !          1608:        /* And handle any messages, check for quit message */
        !          1609:        Main_EventHandler();         /* Process messages, set 'bQuitProgram' if user tries to quit */
        !          1610:        /* Pass NULL interrupt function to quit cleanly */
        !          1611:        //if (bQuitProgram) Int_AddAbsoluteInterrupt(4, 0L);
        !          1612: }
1.1       root     1613: 
1.1.1.2 ! root     1614: /* d0.b = exception number, a0 = handler. */
        !          1615: static void SetExceptionHandler ()
        !          1616: {
        !          1617:        /* only 32 handlers */
        !          1618:        exception_handlers[GetReg(0) & 31] = GetReg (8);
        !          1619: }
1.1       root     1620: 
1.1.1.2 ! root     1621: int DumpMess (int pos, int line)
        !          1622: {
        !          1623:        if (GetXFlag ()) putchar ('X');
        !          1624:        if (GetZFlag ()) putchar ('Z');
        !          1625:        if (GetNFlag ()) putchar ('N');
        !          1626:        if (GetVFlag ()) putchar ('V');
        !          1627:        if (GetCFlag ()) putchar ('C');
        !          1628:        return 0;
        !          1629:        printf (" $%x $%x $%x $%x $%x $%x $%x $%x*$%x $%x $%x $%x $%x $%x $%x $%x:%d\n",
        !          1630:                        GetReg (0),
        !          1631:                        GetReg (1),
        !          1632:                        GetReg (2),
        !          1633:                        GetReg (3),
        !          1634:                        GetReg (4),
        !          1635:                        GetReg (5),
        !          1636:                        GetReg (6),
        !          1637:                        GetReg (7),
        !          1638:                        GetReg (8),
        !          1639:                        GetReg (9),
        !          1640:                        GetReg (10),
        !          1641:                        GetReg (11),
        !          1642:                        GetReg (12),
        !          1643:                        GetReg (13),
        !          1644:                        GetReg (14),
        !          1645:                        GetReg (15),line_no);
        !          1646: }
        !          1647: static int _X, _Z, _N, _V, _C;
        !          1648: static int PrevRegs[16];
        !          1649: 
        !          1650: int changed ()
        !          1651: {
        !          1652:        int i;
        !          1653:        if (GetXFlag () != _X) return 1;
        !          1654:        if (GetZFlag () != _Z) return 1;
        !          1655:        if (GetNFlag () != _N) return 1;
        !          1656:        if (GetVFlag () != _V) return 1;
        !          1657:        if (GetCFlag () != _C) return 1;
        !          1658:        for (i=0; i<16; i++) {
        !          1659:                if (PrevRegs[i] != GetReg (i)) return 1;
1.1       root     1660:        }
1.1.1.2 ! root     1661:        return 0;
        !          1662: }
1.1       root     1663: 
1.1.1.2 ! root     1664: void DumpRegsChanged ()
        !          1665: {
        !          1666:        int i;
        !          1667: 
        !          1668:        //if (!changed ()) return;
        !          1669: 
        !          1670:        _X = GetXFlag ();
        !          1671:        _Z = GetZFlag ();
        !          1672:        _V = GetVFlag ();
        !          1673:        _N = GetNFlag ();
        !          1674:        _C = GetCFlag ();
        !          1675:        
        !          1676:        if (_X) putchar ('X');
        !          1677:        if (_Z) putchar ('Z');
        !          1678:        if (_N) putchar ('N');
        !          1679:        if (_V) putchar ('V');
        !          1680:        if (_C) putchar ('C');
        !          1681:        
        !          1682:        for (i=0; i<16; i++) {
        !          1683:                if (PrevRegs[i] != GetReg (i)) {
        !          1684:                        printf (" %c%d:%x->%x", (i<8?'d':'a'), (i<8?i:i-8), PrevRegs[i], GetReg (i));
        !          1685:                        PrevRegs[i] = GetReg (i);
1.1       root     1686:                }
1.1.1.2 ! root     1687:        }
        !          1688:        printf (" @%d\n", line_no);
1.1       root     1689: }
                   1690: 
                   1691: 
1.1.1.2 ! root     1692: HOSTCALL hcalls [] = {
        !          1693:        &SetExceptionHandler,
1.1       root     1694:        &Call_Memset,           /* 0x1 */
                   1695:        &Call_MemsetBlue,               /* 0x2 */
                   1696:        &Call_BlitCursor,               /* 0x3 */
                   1697:        &Call_RestoreUnderCursor,       /* 0x4 */
                   1698:        &Call_BlitBmp,          /* 0x5 */
                   1699:        &Call_OldHLine,         /* 0x6 */
1.1.1.2 ! root     1700:        &Call_HostUpdate,               /* 0x7 */
1.1       root     1701:        &Call_Memcpy,           /* 0x8 */
                   1702:        &Call_PutPix,           /* 0x9 */
                   1703:        &Call_BackHLine,                /* 0xa */
                   1704:        &Call_FillLine,         /* 0xb */
                   1705:        &Call_SetMainPalette,   /* 0xc */
                   1706:        &Call_SetCtrlPalette,   /* 0xd */
                   1707:        &Call_SetScreenBase,            /* 0xe */
                   1708:        &Screen_Draw,                   /* 0xf */
                   1709:        &Call_DumpRegs,         /* 0x10 */
                   1710:        &Call_MakeExtPalette,   /* 0x11 */
                   1711:        &Call_PlaySFX,                  /* 0x12 */
                   1712:        &Call_GetMouseInput,            /* 0x13 */
                   1713:        &Call_GetKeyboardEvent,         /* 0x14 */
1.1.1.2 ! root     1714:        NULL,                   /* 0x15 */
1.1       root     1715:        &Call_HLine,                    /* 0x16 */
                   1716:        &Call_NotifyOfScrFlip,          /* 0x17 */
                   1717:        &Call_NotifyMousePos,           /* 0x18 */
                   1718:        &Call_InformScreens,            /* 0x19 */
                   1719:        &GemDOS_SetDTA,
                   1720:        &Call_DrawStrShadowed,          /* 0x1b */
                   1721:        &Call_DrawStr,                  /* 0x1c */
                   1722:        &Call_DrawTriangle,             /* 0x1d */
                   1723:        &Call_DrawQuad,                 /* 0x1e */
1.1.1.2 ! root     1724:        &Call_Idle,                     /* 0x1f */
        !          1725:        &Call_DumpDebug,                /* 0x20 */
1.1       root     1726:        NULL,
                   1727:        NULL,
                   1728:        NULL,
                   1729:        NULL,
                   1730:        NULL,
                   1731:        NULL,
                   1732:        NULL,
                   1733:        NULL,
                   1734:        NULL,
                   1735:        NULL,
                   1736:        NULL,
                   1737:        NULL,
                   1738:        NULL,
                   1739:        NULL,
                   1740:        NULL,
                   1741:        NULL,                           /* 0x30 */
                   1742:        NULL,
                   1743:        NULL,
                   1744:        NULL,
                   1745:        NULL,
                   1746:        NULL,
                   1747:        NULL,
                   1748:        NULL,
                   1749:        NULL,
                   1750:        NULL,
                   1751:        NULL,
                   1752:        NULL,
                   1753:        &GemDOS_Create,
                   1754:        &GemDOS_Open,
                   1755:        &GemDOS_Close,
                   1756:        &GemDOS_Read,
                   1757:        &GemDOS_Write,                  /* 0x40 */
                   1758:        &GemDOS_UnLink,
                   1759:        NULL,
                   1760:        NULL,
                   1761:        NULL,
                   1762:        NULL,
                   1763:        NULL,
                   1764:        NULL,
                   1765:        NULL,
                   1766:        NULL,
                   1767:        NULL,
                   1768:        NULL,
                   1769:        NULL,
                   1770:        NULL,
                   1771:        &GemDOS_SFirst,
                   1772:        &GemDOS_SNext,
                   1773:        NULL,                           /* 0x50 */
                   1774: };

unix.superglobalmegacorp.com

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