diff options
author | Dirk Meyer <dinoex@FreeBSD.org> | 2025-04-12 17:03:37 +0200 |
---|---|---|
committer | Dirk Meyer <dinoex@FreeBSD.org> | 2025-04-12 17:03:37 +0200 |
commit | 0d3ad926cfcd8bb9d4c66052368f7c929495bdd7 (patch) | |
tree | e59ac8b3f623340f9afa86e24e7438a959153f28 /emulators/stonx/files/patch-gemdos.c | |
parent | mail/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.c | 566 |
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; |