summaryrefslogtreecommitdiff
path: root/emulators/stonx/files/patch-gemdos.c
diff options
context:
space:
mode:
authorDirk Meyer <dinoex@FreeBSD.org>2025-04-12 17:03:37 +0200
committerDirk Meyer <dinoex@FreeBSD.org>2025-04-12 17:03:37 +0200
commit0d3ad926cfcd8bb9d4c66052368f7c929495bdd7 (patch)
treee59ac8b3f623340f9afa86e24e7438a959153f28 /emulators/stonx/files/patch-gemdos.c
parentmail/thunderbird: update to 137.0.2 (rc1) (diff)
emulators/stonx: Build with free EmuTOS
support localized ROMS add printer support preserve stonxrc on updates fix sound
Diffstat (limited to 'emulators/stonx/files/patch-gemdos.c')
-rw-r--r--emulators/stonx/files/patch-gemdos.c566
1 files changed, 566 insertions, 0 deletions
diff --git a/emulators/stonx/files/patch-gemdos.c b/emulators/stonx/files/patch-gemdos.c
new file mode 100644
index 000000000000..c0d8b8796bed
--- /dev/null
+++ b/emulators/stonx/files/patch-gemdos.c
@@ -0,0 +1,566 @@
+--- gemdos.c.orig 2003-12-19 20:56:06 UTC
++++ gemdos.c
+@@ -10,6 +10,7 @@
+ #include <stdlib.h>
+ #include <string.h>
+ #include <time.h>
++#include <utime.h>
+ #include <unistd.h>
+ #include <ctype.h>
+ #include <errno.h>
+@@ -83,6 +84,9 @@ typedef struct
+ {
+ UL bp;
+ int f,redirected;
++#if LPPIPES
++ FILE *lpp; /* special pipe descriptor for PRN:/AUX: device handling */
++#endif
+ } FINFO;
+
+ #define MAXDRIVES 26
+@@ -93,13 +97,24 @@ char curpath[MAXDRIVES][500];
+ UL gemdos_drives = 0;
+ UW curdrv=0;
+ char curpath[MAXDRIVES][500];
++#if LPPIPES
++char *prnpipe = NULL;
++char *auxpipe = NULL;
++#define MAXFILES 128 /* try to conform with default GEMDOS limits */
++#define H_OFFSET 6 /* and behaviour */
++#define MAXDIRS 256 /* At least, _I_ need this */
++#else
++/* FIXME: don't no the intension of those strange values
++ * stonx used here. These parameters need further discussion.
++ * see above attempt to fix them */
+ #define MAXFILES 100
+ #define H_OFFSET 80 /* < 100 because of problems with PC/TC's assembler */
++#define MAXDIRS 40
++#endif
+ /* FIXME: There should be one handle-pool only! */
+ static FINFO file[MAXFILES];
+ static int redirect_stdh[6][MAXFILES];
+ void *act_pd;
+-#define MAXDIRS 40
+
+ DIR *fsdir[MAXDIRS];
+ char curspath[MAXDIRS][500];
+@@ -282,8 +297,9 @@ void Dsetdrv (UW drv)
+
+ void Dsetdrv (UW drv)
+ {
++ DBG("Dsetdrv(%c), db: 0x%x = ",'A'+drv, drive_bits);
+ curdrv = drv;
+-#if 0
++#if 1
+ if (BIT(drv,drive_bits) == 0)
+ {
+ DREG(0) = TOS_EDRIVE;
+@@ -296,17 +312,20 @@ void Dsetdrv (UW drv)
+ SET_Z();
+ }
+ #endif
++ DBG("%d (curdrv: %d)\n", DREG(1), curdrv);
+ }
+
+ void Dgetdrv (void)
+ {
+ DREG(0) = curdrv;
++ DBG("Dgetdrv() = %d\n", curdrv);
+ SET_Z();
+ }
+
+ void Fsetdta (UL dtaptr)
+ {
+ UL bp = LM_UL(act_pd);
++ DBG("Process %lx DTA = %lx\n", (long)bp, (long)dtaptr);
+ #if 0
+ SM_UL(MEM(bp+32),dtaptr);
+ SET_Z();
+@@ -333,6 +352,7 @@ void fname2unix (char *stpath, char *unixpath)
+ n++;
+ }
+ *unixpath=0;
++ DBG("Converted <%s> to <%s>\n", a, b);
+ }
+
+ static char lastpath[500];
+@@ -344,6 +364,7 @@ int st2unixpath (char *stpath, char *unixpath)
+ drv = (stpath[1] == ':' ? toupper(stpath[0])-'A' : curdrv);
+ if (((gemdos_drives>>drv)&1) == 0)
+ {
++ DBG("ERROR in st2unixpath <%s>\n", stpath);
+ *unixpath=0;
+ return 0;
+ }
+@@ -359,6 +380,7 @@ int st2unixpath (char *stpath, char *unixpath)
+ }
+ fname2unix(lastpath,path);
+ sprintf(unixpath,"%s%s",root[drv],path);
++ DBG("st2unixpath(%s) = <%s>\n", stpath, unixpath);
+ return 1;
+ }
+
+@@ -382,27 +404,50 @@ int unix2fname (char *unixname, char *stname)
+ p++;
+ }
+ *stname=0;
++ DBG("ufile: <%s> stfile: <%s>\n", unixname, q);
+ return 1;
+ }
+
+ static int match (char *pat, char *name)
+ {
+- if (strcmp(pat,"*.*")==0) return 1;
+- else if (strcasecmp(pat,name)==0) return 1;
++ DBG("Match(<%s>, <%s>) ", pat, name);
++ if (strcmp(pat,"*.*")==0)
++ {
++ DBG("OK\n");
++ return 1;
++ }
++ else if (strcasecmp(pat,name)==0)
++ {
++ DBG("OK\n");
++ return 1;
++ }
+ else
+ {
+ char *p=pat,*n=name;
+ for(;*n;)
+ {
+- if (*p=='*') {while (*n && *n != '.') n++;p++;}
+- else if (*p=='?' && *n) {n++;p++;}
+- else if (*p++ != *n++) return 0;
++ if (*p=='*') {
++ while (*n && *n != '.')
++ n++; /* skip to extension */
++ p++; /* step over '*' */
++ }
++ else if (*p=='?' && *n) {
++ n++; p++; /* single match */
++ }
++ else if (toupper(*p++) != *n++) {
++ /* FIXME: TOS always uses uppercase letters */
++ /* does mint behave different? hpj */
++ DBG("Failed\n");
++ return 0;
++ }
+ }
+ if (*p==0)
+ {
++ DBG("OK\n");
+ return 1;
+ }
+ }
++ DBG("Failed\n");
+ return 0;
+ }
+
+@@ -411,6 +456,7 @@ void compress_path (char *path)
+ char *lastdir=NULL, lastchar=0, *d, *p=path;
+ char *dirstack[MAXDIRS];
+ int a=0, i;
++ DBG("Before path compression: <%s>\n", p);
+ d = path;
+ while (*p)
+ {
+@@ -441,6 +487,7 @@ void compress_path (char *path)
+ }
+ if (d != path && *(d-1) == '\\') d--;
+ *d=0;
++ DBG("Result of path compression: %s\n", path);
+ }
+
+ int xopendir (char *p, int doopen)
+@@ -496,7 +543,19 @@ UW date2dos (time_t t)
+ return x->tm_mday|((x->tm_mon+1)<<5)|(MAX(x->tm_year-80,0)<<9);
+ }
+
++time_t dos2time (UW time, UW date)
++{
++ struct tm brokentime;
+
++ brokentime.tm_sec = (time & 0x001f) << 1;
++ brokentime.tm_min = (time & 0x07e0) >> 5;
++ brokentime.tm_hour = (time & 0xf800) >> 11;
++ brokentime.tm_mday = (date & 0x001f);
++ brokentime.tm_mon = (date & 0x01e0) >> 5;
++ brokentime.tm_year = ((date & 0xfe00) >> 9) + 80;
++ return mktime(&brokentime);
++}
++
+ void Fsnext (void)
+ {
+ UL bp;
+@@ -522,6 +581,7 @@ void Fsnext (void)
+ bp = LM_UL(act_pd);
+ dta = (DTA *)MEM(LM_UL(MEM(bp+32)));
+ attribs = LM_UB(&(dta->dta_sattrib));
++ DBG("Fsnext(%s)\n", dta->dta_pat);
+
+ repeat:
+ SM_UL((UL *)&(dta -> magic),EVALID);
+@@ -530,6 +590,7 @@ void Fsnext (void)
+ rr = (LM_W((W *)&(dta->index)));
+ if (rr < 0) {
+ if (rr == -1) {
++ DBG("(no more files)\n");
+ DREG(0) = TOS_ENMFIL;
+ SET_Z();
+ return;
+@@ -548,6 +609,7 @@ void Fsnext (void)
+ e = xreaddir (rr);
+ if (e == NULL)
+ {
++ DBG("(no more files)\n");
+ DREG(0) = TOS_ENMFIL;
+ SET_Z();
+ xclosedir(LM_UW((UW *)&(dta->index)));
+@@ -558,6 +620,7 @@ void Fsnext (void)
+ SM_UL((UL *)&(dta->magic),SVALID);
+ strcpy(dta->dta_name, stname);
+ sprintf (uname, "%s/%s", curspath[rr], e->d_name);
++ DBG("stat(%s)\n", uname);
+ if (STATFUNC (uname, &s) < 0)
+ goto repeat;
+ da = (s.st_mode & S_IFDIR)?0x10:0; /* FIXME */
+@@ -600,7 +663,7 @@ void Dsetpath (char *pname)
+ return;
+ }
+ if (pname[1] == ':') strcpy(pname,&pname[2]); /* for Dsetdrv(C:\FOO) */
+- if (pname[0] == '\\') strcpy(curpath[drv],pname);
++ if (!pname[0] || (pname[0] == '\\')) strcpy(curpath[drv],pname);
+ else
+ {
+ strcat(curpath[drv],"\\");
+@@ -609,6 +672,8 @@ void Dsetpath (char *pname)
+ #if 1
+ compress_path(curpath[drv]);
+ #endif
++ DBG("Dsetpath(%s) -> %s on drive %d <%s>\n",
++ pname, curpath[drv], curdrv, upath);
+ /* FIXME */
+ DREG(0)=0;
+ SET_Z();
+@@ -626,6 +691,7 @@ void Fsfirst (char *fspec, UW attribs)
+ cursdrv=999;
+ return;
+ }
++ DBG("Fsfirst(%s,%x) on drive %d\n", fspec, attribs, curdrv);
+ if (fspec[1]==':') cursdrv=toupper(fspec[0])-'A';
+ else cursdrv=curdrv;
+ bp = LM_UL(act_pd);
+@@ -657,6 +723,7 @@ void Fsfirst (char *fspec, UW attribs)
+ !strchr (dta -> dta_pat, '*')) {
+ r = xopendir (upath, 0);
+ } else {
++ DBG("Opendir(%s)\n", upath);
+ r = xopendir (upath, 1);
+ if (r < 0)
+ {
+@@ -690,13 +757,17 @@ void Fopen (char *fname, UW mode)
+ UL bp;
+ int f;
+ char upath[500];
++ struct stat s;
++
+ if (!st2unixpath(fname, upath))
+ {
+ DBG("Fopen(%s,%x) drive %d not done\n",fname,mode,curdrv);
++ DREG(0) = TOS_EFILNF;
++ SET_Z();
+ return;
+ }
+ bp = LM_UL(act_pd);
+- DBG("Fopen(%s,%x) on drive %d -> %s\n",fname,mode,curdrv,upath);
++ DBG("Fopen(\"%s\",%x) on drive %d -> %s\n",fname,mode,curdrv,upath);
+ for (i=0; i<MAXFILES && file[i].bp != 0; i++)
+ if (i >= MAXFILES)
+ {
+@@ -713,6 +784,13 @@ void Fopen (char *fname, UW mode)
+ SET_Z();
+ return;
+ }
++ fstat(f,&s);
++ if (S_ISDIR(s.st_mode)) {
++ DBG("Fopen: %s is a directory\n",fname);
++ DREG(0) = TOS_EFILNF;
++ SET_Z();
++ return;
++ }
+ file[i].bp = bp;
+ file[i].f = f;
+ file[i].redirected = 0;
+@@ -738,6 +816,15 @@ void Fread (W handle, UL count, char *buf)
+ SET_Z();
+ return;
+ }
++#if LPPIPES
++ /* ignore reading on a lppipe */
++ if (file[i].lpp)
++ {
++ DREG(0) = 0;
++ SET_Z();
++ return;
++ }
++#endif
+ if (count > 0x1fffffff) count = 0x1fffffff;
+ rd = FREAD_CHUNK;
+ for(;count > 0;)
+@@ -775,7 +862,16 @@ void Fclose (W handle)
+ SET_Z();
+ return;
+ }
+- close(file[i].f);
++#if LPPIPES
++ /* close lp pipe */
++ if (file[i].lpp)
++ {
++ pclose(file[i].lpp);
++ file[i].lpp = NULL;
++ }
++ else
++#endif
++ close(file[i].f);
+ file[i].bp = 0;
+ file[i].f = -1;
+ /* handle end of redirection (see Fforce) */
+@@ -787,16 +883,66 @@ void Fcreate (char *fname, UW attribs)
+
+ void Fcreate (char *fname, UW attribs)
+ {
+- int i;
+- UL bp;
+- int f;
++ int i=0;
++ int f=0;
++ UL bp=LM_UL(act_pd);
+ char upath[500];
++
++#if LPPIPES
++ /* check for a pipe command */
++ if (prnpipe && !strcasecmp(fname, "PRN:"))
++ f = 'p';
++
++ if (auxpipe && !strcasecmp(fname, "AUX:"))
++ f = 'a';
++
++ if (f)
++ {
++ /* create new pipe */
++ for (i=0; i<MAXFILES && file[i].bp != 0; i++)
++ ;
++ if (i >= MAXFILES)
++ {
++ DREG(0) = TOS_ENMFIL;
++ SET_Z();
++ return;
++ }
++
++ if (f == 'a')
++ {
++ file[i].lpp = popen(auxpipe, "w");
++ DBG("Fcreate(%s) -> %s = %d ", fname, auxpipe, i+H_OFFSET);
++ } else if (f == 'p') {
++ file[i].lpp = popen(prnpipe, "w");
++ DBG("Fcreate(%s) -> %s = %d ", fname, prnpipe, i+H_OFFSET);
++ }
++
++ if (file[i].lpp)
++ {
++ file[i].bp = bp;
++ file[i].f = i;
++ file[i].redirected = 0;
++ DREG(0) = i+H_OFFSET;
++ SET_Z();
++ DBG("OK\n");
++ }
++ else
++ {
++ DREG(0) = TOS_EACCDN;
++ SET_Z();
++ DBG("Failed\n");
++ }
++ return;
++ }
++#endif
++
+ if (!st2unixpath(fname, upath))
+ {
+ DBG("Fcreate(%s,%x) drive %d not done\n",fname,attribs,curdrv);
++ DREG(0) = TOS_EPTHNF;
++ SET_Z();
+ return;
+ }
+- bp = LM_UL(act_pd);
+ DBG("Fcreate(%s,%x) on drive %d -> %s\n",fname,attribs,curdrv,upath);
+ if (attribs == FA_LABEL) {
+ DBG("\tDrivelabels cannot be created!\n");
+@@ -813,7 +959,7 @@ void Fcreate (char *fname, UW attribs)
+ return;
+ }
+
+- f = creat(upath,DEFAULT_MODE);
++ f = open(upath,O_CREAT|O_RDWR|O_TRUNC,DEFAULT_MODE);
+ if (f < 0)
+ {
+ DBG("creat(): %s\n",strerror(errno));
+@@ -843,7 +989,12 @@ void Fwrite (W handle, UL count, char *buf)
+ SET_Z();
+ return;
+ }
+- r = write (file[i].f, buf, (size_t) count);
++#if LPPIPES
++ if (file[i].lpp)
++ r = fwrite(buf, 1, (size_t) count, file[i].lpp);
++ else
++#endif
++ r = write (file[i].f, buf, (size_t) count);
+ if ( r < 0 )
+ r = unix2toserrno( errno, TOS_EACCDN );
+ DBG("\tReturnvalue for handle %d = %d\n",i+H_OFFSET,r);
+@@ -856,6 +1007,7 @@ void Fdelete (char *fname)
+ {
+ char upath[500];
+ if (!st2unixpath(fname,upath)) return;
++ DBG("Fdelete(%s) on drive %d <%s> = ",fname,curdrv,upath);
+ if (unlink(upath) < 0)
+ {
+ DREG(0) = unix2toserrno( errno, TOS_EACCDN );
+@@ -864,13 +1016,14 @@ void Fdelete (char *fname)
+ }
+ DREG(0)=0;
+ SET_Z();
+- return;
++ DBG("%d\n", DREG(0));
+ }
+
+ void Dcreate (char *pname)
+ {
+ char upath[500];
+ if (!st2unixpath(pname,upath)) return;
++ DBG("Dcreate(%s) on drive %d <%s> = ",pname,curdrv,upath);
+ if (mkdir(upath,DEFAULT_DIRMODE) < 0)
+ {
+ DREG(0) = unix2toserrno(errno,TOS_EACCDN);
+@@ -879,12 +1032,14 @@ void Dcreate (char *pname)
+ }
+ DREG(0)=0;
+ SET_Z();
++ DBG("%d\n", DREG(0));
+ }
+
+ void Ddelete (char *pname)
+ {
+ char upath[500];
+ if (!st2unixpath(pname,upath)) return;
++ DBG("Ddelete(%s) on drive %d <%s> = ",pname,curdrv,upath);
+ if (rmdir(upath) < 0)
+ {
+ DREG(0) = unix2toserrno(errno,TOS_EACCDN);
+@@ -893,22 +1048,26 @@ void Ddelete (char *pname)
+ }
+ DREG(0)=0;
+ SET_Z();
++ DBG("%d\n", DREG(0));
+ }
+
+ void Dgetpath (char *buf, UW drv)
+ {
+ /* FIXME */
++ DBG("Dgetpath(%d) = ",drv);
+ if (drv == 0)
+ drv=curdrv;
+ else
+ --drv;
+ if (!((gemdos_drives >> drv)&1))
+ {
++ DBG("(tos)\n");
+ return;
+ }
+ DREG(0) = 0;
+ sprintf(buf,"%s",curpath[drv]);
+ SET_Z();
++ DBG("%s\n",curpath[drv]);
+ }
+
+ void Pexec (UW mode, char *file, char *cmdlin, char *env)
+@@ -957,13 +1116,25 @@ void Fseek (L offset, W handle, UW mode)
+ SET_Z();
+ return;
+ }
++#if LPPIPES
++ /* do not allow seeking on lp pipe */
++ if (file[i].lpp)
++ {
++ DREG(0) = TOS_EACCDN;
++ SET_Z();
++ return;
++ }
++#endif
++
+ dpos=lseek(file[i].f,0,SEEK_CUR);
+ dlen=lseek(file[i].f,0,SEEK_END);
++ DBG("Fseek: file length is %ld\n",dlen);
+ (void)lseek(file[i].f,dpos,SEEK_SET);
+ dpos=lseek(file[i].f,offset,mode);
+ if (dpos > dlen) DREG(0)=-64; /* ERANGE */
+ else DREG(0)=dpos;
+ SET_Z();
++ DBG("Fseek(%d,%d,%d) = %d\n", offset, handle, mode, DREG(0));
+ return;
+ }
+
+@@ -987,6 +1158,11 @@ void Fdatime (UW *t, UW *d, W handle, UW wflag)
+ {
+ struct stat s;
+ int i=handle-H_OFFSET;
++ time_t time;
++ char link[500], f[500];
++ int len;
++ struct utimbuf ut;
++ DBG("Fdatime(%x,%i,%d)\n",t,handle,wflag);
+ if (i<0) return;
+ if (file[i].bp != LM_UL(act_pd) || file[i].f < 0)
+ {
+@@ -997,14 +1173,28 @@ void Fdatime (UW *t, UW *d, W handle, UW wflag)
+ if (wflag == 0)
+ {
+ fstat (file[i].f, &s);
+- SM_UW(t,s.st_mtime);
+- SM_UW(d,s.st_mtime);
++ SM_UW(t,time2dos(s.st_mtime));
++ SM_UW(d,date2dos(s.st_mtime));
+ DREG(0) = 0;
+ SET_Z();
+ return;
+ }
+ else if (wflag == 1)
+ {
++ sprintf (link,"/proc/%d/fd/%d",getpid(),file[i].f); /* needs /proc-based OS (Linux) */
++ len = readlink (link,f,499);
++ if (len > 0)
++ {
++ f[len] = 0;
++ time = dos2time(LM_UW(t),LM_UW(d));
++ ut.actime = time;
++ ut.modtime = time;
++ utime(f,&ut);
++ }
++ else
++ {
++ DBG("Fdatime: could not read link \"%s\": %s\n",link,strerror(errno));
++ }
+ DREG(0) = 0;
+ SET_Z();
+ return;
+@@ -1300,6 +1490,9 @@ void init_gemdos (void)
+ file[i].bp = 0;
+ file[i].f = -1;
+ file[i].redirected = 0;
++#if LPPIPES
++ file[i].lpp = NULL;
++#endif
+ }
+ for (i=0; i<6; i++ )
+ redirect_stdh[i][0] = -1;