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