home *** CD-ROM | disk | FTP | other *** search
/ The Datafile PD-CD 4 / DATAFILE_PDCD4.iso / utilities / utilst / virtual / !Virtual / c / control next >
Encoding:
Text File  |  1993-07-05  |  32.5 KB  |  1,260 lines

  1. /* includes */
  2. #include "swis.h"
  3. #include "swiv.h"
  4. #include "wimp.h"
  5.  
  6. #include "virtual.h"
  7. #include "lib.h"
  8. #include "pager.h"
  9. #include "output.h"
  10. #include "asm.h"
  11. #include "poll.h"
  12.  
  13. #include "xswis.h"      /* Some RO3 swis */
  14.  
  15. /* constants */
  16. /*#define DEBUG*/
  17.  
  18. #define N_bit 0x80000000
  19. #define Z_bit 0x40000000
  20. #define C_bit 0x20000000
  21. #define V_bit 0x10000000
  22. #define PSW_bits 0xF0000000
  23.  
  24. static int * const swivec=(int*)8;
  25. static int ingos = 0;
  26. static int incallback = 0;
  27.  
  28. /* errors */
  29. #define ERR(x) ((struct Error *)(x))
  30. static char BadMemory[] = { "XXXXNo memory at this address" };
  31. static char Failed[] = { "XXXXMisc Virtual swi failed" };
  32. static char NotAllowed[] = { "XXXXThis swi not allowed under virtual" };
  33.  
  34. /* module wrapping */
  35.  struct Error *Cinit(private **p) /* */
  36. { /* called with C stack a 1K bit out of svcstack. */
  37.   struct Error *err;
  38.   if (!*p)
  39.     *p=alloc(sizeof(private));
  40.   (*p)->uses = 0;
  41.   (*p)->w = 0;
  42.   worksemaphore = 1;
  43.   err = swix(OS_CallEvery,IN(R0|R1|R2),15,&OurCallEvery,*p);
  44.   if (err)
  45.     free(*p),*p=0;
  46.   return err;
  47. }
  48.  
  49.  struct Error *Cfinish(private **p)
  50. { /* called with C stack a 1K bit out of svcstack. */
  51.   /* should check (*p)->uses */
  52.   return swix(OS_RemoveTickerEvent,IN(R0|R1),&OurCallEvery,*p);
  53. }
  54.  
  55.  struct Error *CDoPhysical(int task, int addr, int len, int k[3],private *priv) 
  56. { /* called with C stack a 1K bit out of svcstack. */
  57.   WKSP *w=priv->w;
  58.   RANGE r;
  59.   if (w->ourtask!=task)
  60.     return 0;
  61.   r = Locate(w,addr,addr+len);
  62.   k[0]=r.start; k[1]=r.end; k[2]=w->pagefile;  
  63.   return 0;
  64. }
  65.  
  66.  
  67. /* ******************** mode changers */
  68.  void ClaimVVecs(WKSP *w) 
  69. { int oldswi;
  70.   workptr=w;
  71.   swi(OS_ChangeEnvironment,IN(R0|R1)|OUT(R1),2,&VPrefetchAbort,&w->OldPrefetchAbort);
  72.   swi(OS_ChangeEnvironment,IN(R0|R1)|OUT(R1),3,&VDataAbort,&w->OldDataAbort);
  73.   swi(OS_ChangeEnvironment,IN(R0|R1|R2|R3)|OUT(R1|R2|R3),7,&VCallBack,w,&w->regs,
  74.                                    &w->OldCallBack,&w->OldCallBackR12,&w->OldCallBackRegs);
  75.   swi(OS_ChangeEnvironment,IN(R0|R1|R2|R3),6,&VError,&w->errnum,&w->errPC);
  76.   swi(OS_ChangeEnvironment,IN(R0|R1|R2),16,&VUpCall,w);
  77.   swi(OS_ChangeEnvironment,IN(R0|R1|R2),11,&VExit,w);
  78.   oldswi=*swivec;
  79.   if (oldswi>>24==0xEA)
  80.     ; /* B */
  81.   oldswi=8+(int)swivec+(oldswi<<8>>6);
  82.   w->OldSWIV=oldswi;
  83.   workOldSWIV=oldswi;
  84.   *swivec=(int)&VSWIV-8-(int)swivec>>2|0xEA000000;
  85. }
  86.  
  87.  void ReleaseVVecs(WKSP *w) 
  88. {
  89.   *swivec=w->OldSWIV-8-(int)swivec>>2|0xEA000000;
  90.   swi(OS_ChangeEnvironment,IN(R0|R1),2,w->OldPrefetchAbort);
  91.   swi(OS_ChangeEnvironment,IN(R0|R1),3,w->OldDataAbort);
  92.   swi(OS_ChangeEnvironment,IN(R0|R1|R2|R3),7,w->OldCallBack,w->OldCallBackR12,w->OldCallBackRegs);
  93.   swi(OS_ChangeEnvironment,IN(R0|R1|R2|R3),6,&NormError,w,&w->errPC);
  94.   swi(OS_ChangeEnvironment,IN(R0|R1|R2),16,&NormUpCall,w);
  95.   swi(OS_ChangeEnvironment,IN(R0|R1|R2),11,&NormExit,w);
  96. }
  97.  
  98.  void ClaimExtVecs( WKSP *w ) 
  99. { swi(OS_Claim,IN(R0|R1|R2),3,&ExtWriteC,w);
  100.   swi(OS_ChangeEnvironment,IN(R0|R1|R2|R3),6,&ExtError,w,&w->errPC);
  101.   swi(OS_ChangeEnvironment,IN(R0|R1|R2),16,&ExtUpCall,w);
  102.   swi(OS_ChangeEnvironment,IN(R0|R1|R2),11,&ExtExit,w);
  103. }
  104.  
  105.  void ReleaseExtVecs( WKSP *w ) 
  106. { swi(OS_Release,IN(R0|R1|R2),3,&ExtWriteC,w);
  107.   swi(OS_ChangeEnvironment,IN(R0|R1|R2|R3),6,&NormError,w,&w->errPC);
  108.   swi(OS_ChangeEnvironment,IN(R0|R1|R2),16,&NormUpCall,w);
  109.   swi(OS_ChangeEnvironment,IN(R0|R1|R2),11,&NormExit,w);
  110. }
  111.  
  112.  void Virtual(WKSP *w) 
  113. {
  114.   virtualmem(w);
  115.   ClaimVVecs(w);
  116. }
  117.  
  118.  void Normal(WKSP *w) 
  119. {
  120.   ReleaseVVecs(w);
  121.   normalmem(w);
  122. }
  123.  
  124.  void V2Ext( WKSP *w ) 
  125. {
  126.   ReleaseVVecs(w);
  127.   ClaimExtVecs(w);
  128. }
  129.  
  130.  void Ext2V( WKSP *w ) 
  131. {
  132.   ReleaseExtVecs(w);
  133.   ClaimVVecs(w);
  134. }
  135.  
  136.  void Ext2Norm( WKSP *w) 
  137. {
  138.   ReleaseExtVecs(w);
  139.   normalmem(w);
  140. }
  141.  
  142.  void Norm2Ext( WKSP *w) 
  143. {
  144.   virtualmem(w);
  145.   ClaimExtVecs(w);
  146. }
  147.  
  148.  
  149. /* ******************** Virtual mode handlers */
  150.  WKSP *CVWantAddr(WKSP *w, int start, int len) 
  151. {
  152.   if (len<0)
  153.     start += len, len= -len;
  154.   if (w->regs[15]&3)
  155.   { Normal(w);
  156.     printf("***** CWantAddr called from non-user mode. Disaster! *****\n");
  157.     RealDoOff(w);
  158.   }
  159.   if (!WriteRange(w,start,start+len))
  160.   { Normal(w);
  161.     printf("***** CWantAddr can't get desired area: %08x+%08x****\n",start,len);
  162.     RealDoOff(w);
  163.   }
  164.   return w;
  165. }
  166.  
  167.  void doeschand(WKSP *w,int n) 
  168. { w->EscapeCondition = n;
  169. #ifndef FIXED_SYSTEMCALL_VERSION_FO
  170.   if (w->Escape)
  171.   { Normal(w);
  172.     printf("(should call escape handler at %08x)",w->Escape);
  173.     Virtual(w);
  174.   }
  175. #else
  176.   if (w->Escape != -1) {
  177.     int result, * ruser = w->regs;
  178.     if (w->EscapeR12 != -1)
  179.         WriteRange(w, w->EscapeR12, w->EscapeR12+512);
  180.     ReadRange(w, w->Escape, w->Escape+8);
  181.     result = CallEscapeHandler(w->Escape, w->EscapeR12, (w->EscapeCondition == 2) ? 0x40 : 0);
  182.     if (result == 1) {
  183.         int j, * rcallback = (int *) w->CallBackBuf;
  184.         /* call back flag is set */
  185.         WriteRange(w, w->CallBackR12, w->CallBackR12 + 512);
  186.         WriteRange(w, w->CallBackBuf, w->CallBackBuf + 16 * 4);
  187.         ReadRange(w, w->CallBack, w->CallBack + 8);
  188.         for (j = 0; j < 16; j++)
  189.                 rcallback[j] = ruser[j];        /* save user registers into callback buffer */
  190.         ruser[12] = w->CallBackR12;
  191.         ruser[15] = w->CallBack;
  192.         incallback = 1;
  193.     }
  194.   }
  195. #endif
  196. }
  197.  
  198.  WKSP *CVCallBack(WKSP *w) 
  199. { Normal(w);
  200.   Poll(w);
  201.   Virtual(w);
  202.   if (1==w->EscapeCondition)
  203.     doeschand(w,2);
  204.   worksemaphore=1;      /* Ready to reenable when we exit */
  205.   return w;
  206. }
  207.  
  208.  WKSP *CVSWIV(WKSP *w,int instr) 
  209. {
  210.   int *r=w->regs;
  211.   char s[256];
  212.   struct Error *err=0;
  213.   int psw,i;
  214.   int swinum=instr&~(XOS_Bit|0xFF000000);
  215.   r[15]&=~V_bit;
  216. #if 0
  217.     Normal(w);
  218.     swi(OS_SWINumberToString,IN(R0|R1|R2),instr&0xFFFFFF,s,256);
  219.     printf("Swi %s PC=%08x ",s,r[15]);
  220.     for (i=0;i<=14;i++)
  221.       printf("R%d=%08x ",i,r[i]);
  222.     printf("...");
  223.     Virtual(w);
  224. #endif
  225.   switch(swinum) {
  226.   /* input/output */
  227.  
  228.    /*
  229.     * OS SWIs
  230.     */
  231.  
  232.    case OS_WriteC: 
  233.     outc(w,r[0]);
  234.     break;
  235.   
  236.    case OS_Write0: 
  237.     { char *p;
  238.       ReadRange(w,r[0],r[0]+1);
  239.       for (p=(char *)r[0];*p;p++)
  240.       { ReadPtr(w,(int)p);
  241.         outc(w,*p);
  242.       }
  243.       r[0]=(int)++p;
  244.     }
  245.     break;
  246.   
  247.    case OS_WriteS: 
  248.     { char *p=(char *)(r[15]&~0xfc000003);
  249.       char *q=p;
  250.       for (;*p;p++)
  251.       { ReadPtr(w,(int)p);
  252.         outc(w,*p);
  253.       }
  254.       r[15]+=(((p+1)-q)|3)+1;
  255.     }
  256.     break;
  257.   
  258.    case OS_WriteN: 
  259.     { int n;
  260.       for ( n=0; n<r[1]; n++ )
  261.       { ReadPtr(w,r[0]+n);
  262.         outc(w,((char *)r[0])[n]);
  263.       }
  264.     }
  265.     break;
  266.   
  267.    case OS_NewLine: 
  268.     outc(w,'\r'); outc(w,'\n');
  269.     break;
  270.   
  271.    case OS_ReadC: 
  272.     r[0]=getc(w);
  273.     if (-1==r[0])
  274.     { r[0] = 27;
  275.       r[15]|=C_bit;
  276.     }
  277.     else
  278.       r[15]&=~C_bit;
  279.     if (1==w->EscapeCondition)
  280.       doeschand(w,2);
  281.     break;
  282.   
  283.    case OS_ReadLine: 
  284.     { char buf[256];
  285.       int n=0,c;
  286.       r[15]&=~C_bit;
  287.       for (;;)
  288.       { c=getc(w);
  289.         switch (c)
  290.         {
  291.            case 13: case 10: 
  292.             buf[n]=13;
  293.             break;
  294.           
  295.            case 27: case -1: 
  296.             r[15]|=C_bit;
  297.             break;
  298.           
  299.            case 127: case 8: 
  300.             if (n>0)
  301.             { outc(w,127); n--; }
  302.             else
  303.               outc(w,7);
  304.             continue;
  305.           
  306.            case 21: 
  307.             while (n>0)
  308.             { outc(w,127); n--; }
  309.             continue;
  310.           
  311.            default: 
  312.             if (r[2]<=c && c<=r[3])
  313.             { if (n<r[1]-1 && n<255)
  314.               { buf[n++]=c;
  315.                 outc(w,c);
  316.               }
  317.               else
  318.                 outc(w,7);
  319.             }
  320.             else
  321.               outc(w,7);
  322.             continue;
  323.           
  324.         }
  325.         outc(w,'\r'); outc(w,'\n');
  326.         break;
  327.       }
  328.       WriteRange(w,r[0],r[0]+n+1);
  329.       memcpy((void *)r[0],buf,n+1);
  330.       r[1]=n;
  331.     }
  332.     if (1==w->EscapeCondition)
  333.       doeschand(w,2);
  334.     break;
  335.  
  336.    case OS_Byte: 
  337.     switch (r[0])
  338.     { default: goto uk;
  339.       case 0:           /* display os version */
  340.         Normal(w);
  341.         err = swix(OS_Byte,IN(R0|R1)|OUT(R1),0,r[1],&r[1]);
  342.         Virtual(w);
  343.         break;
  344.       case 2:           /* switch input streams */
  345. #ifdef DEBUG
  346.         Normal(w);
  347.         printf("(FX 2,%d)",r[1]);
  348.         Virtual(w);
  349. #endif
  350.         break;
  351.       case 3:           /* switch output streams */
  352. #ifdef DEBUG
  353.         Normal(w);
  354.         printf("(FX 3,%d)",r[1]);
  355.         Virtual(w);
  356. #endif
  357.         break;
  358.       case 15:          /* clear input or all buffers */
  359.         break;
  360.       case 21:          /* clear specific buffer */
  361.         break;
  362.       case 124:         /* clear esc cond immed */
  363.         w->EscapeCondition = 0;
  364.         break;
  365.       case 125:         /* cause esc cond */
  366.         doeschand(w,2);
  367.         break;
  368.       case 126:         /* acknowledge escape cond */
  369.         r[1]=w->EscapeCondition?0xff:0;
  370.         if (w->EscapeCondition)
  371.           doeschand(w,0);
  372.         break;
  373.       case 160:
  374.       case 161:
  375.         err = swix(OS_Byte,IN(R0|R1|R2)|OUT(R0|R1|R2),r[0],r[1],r[2],&r[0],&r[1],&r[2]);
  376.         break;
  377.       case 0xDA:        /* Read/write bytes in VDU queue */
  378.         r[1]=0;
  379.         break;
  380.       case 0xDC:        /* Read/write escape character */
  381.         { int old = w->EscapeChar;
  382.           w->EscapeChar = (w->EscapeChar&r[2])^r[1];
  383.           r[1] = old;
  384.           break;
  385.         }
  386.       case 0xE5:      /* Read/write escape char enable */
  387.         { int old = w->EscapeCharEnable;
  388.           w->EscapeCharEnable = (w->EscapeCharEnable&r[2])^r[1];
  389.           r[1] = old;
  390.           break;
  391.         }
  392.     }
  393.     break;
  394.   
  395.    case OS_SerialOp: 
  396.     err = ERR(&NotAllowed);
  397.     break;
  398.   
  399.    case OS_Word: 
  400.     switch (r[0])
  401.     { default: goto uk;
  402.       case 1: case 2: case 3: case 4: case 14:
  403.         WriteRange(w, r[1],r[1]+256);
  404.         err = swix(OS_Word,IN(R0|R1),r[0],r[1]);
  405.         break;
  406.     }
  407.     break;
  408.   
  409.    case OS_ReadUnsigned: 
  410.     ReadRange(w,r[1],r[1]+256);
  411.     err = swix(OS_ReadUnsigned,IN(R0|R1|R2)|OUT(R1|R2),r[0],r[1],r[2],&r[1],&r[2]);
  412.     break;
  413.   
  414.    case OS_EnterOS: 
  415. #ifdef DEBUG
  416.     Normal(w);
  417.     printf("***OS_EnterOS (ignored) from %08x ****\n",r[15]);
  418.     Virtual(w);
  419. #endif
  420. #ifdef FIXED_SYSTEMCALL_VERSION_FO
  421.     if (ingos || incallback) {
  422.       r[15] = r[15] | 0x03;             /* allow SVC mode here! */
  423.       if (incallback) incallback = 0;
  424.     }
  425. #endif
  426.     break;
  427.   
  428.    case OS_IntOff: 
  429. #ifdef DEBUG
  430.     Normal(w);
  431.     printf("***OS_IntOff (ignored) from %08x ****\n",r[15]);
  432.     Virtual(w);
  433. #endif
  434.     break;
  435.   
  436.    case OS_IntOn: 
  437. #ifdef DEBUG
  438.     Normal(w);
  439.     printf("***OS_IntOn (ignored) from %08x ****\n",r[15]);
  440.     Virtual(w);
  441. #endif
  442.     break;
  443.   
  444.    case OS_Exit: 
  445. #ifdef DEBUG
  446.     Normal(w);
  447.     printf("***OS_Exit from %08x ****\n",r[15]);
  448.     Virtual(w);
  449. #endif
  450.     if (-1==w->Exit)
  451.     { Normal(w);
  452.       RealDoOff(w);
  453.     }
  454. #ifdef FIXED_SYSTEMCALL_VERSION_FO
  455. /*
  456.  *  The return value Sys$ReturnCode has to be set here
  457.  *  Normally OS_Exit does this, but is never called here.
  458.  */
  459.     if (r[1] == 0x58454241) { /* ABEX */
  460.        int val = r[2];
  461.        Normal(w);
  462.        err = swix(OS_SetVarVal, IN(R0|R1|R2|R3|R4),"Sys$ReturnCode", &val, 4, 0, 1);
  463.        Virtual(w);
  464.     }
  465.     ReadRange(w,w->ExitR12, w->ExitR12+512);
  466. #endif
  467.     r[15] = w->Exit;
  468.     r[12] = w->ExitR12;
  469.     break;
  470.   
  471.    case OS_GenerateError: 
  472.     { char buf[264];
  473.       Normal(w);
  474.       FromMem(w,r[0],buf,sizeof(buf));
  475.       printf("***GenerateError: PC=%08x %d %s\n",r[15],((int *)buf)[0],buf+4);
  476.       Virtual(w);
  477.     }
  478.     getc(w);
  479.     err = (void *)r[0];
  480.     break;
  481.   
  482.    case OS_ChangeEnvironment: 
  483.     switch (r[0])
  484.     { int t;
  485.   #define ifswap(x,y) ((x)?((t)=(x),(x)=(y),(y)=(t)):((x)=(y)))
  486.       default: goto uk;
  487.       case 0: ifswap(r[1],w->MemoryLimit); break;
  488.       case 1: ifswap(r[1],w->UndefinedInstruction); break;
  489.       case 2: ifswap(r[1],w->PrefetchAbort); break;
  490.       case 3: ifswap(r[1],w->DataAbort); break;
  491.       case 4: ifswap(r[1],w->AddressException); break;
  492.       case 5: ifswap(r[1],w->OtherExceptions); break;
  493.       case 6: ifswap(r[1],w->Error); ifswap(r[2],w->ErrorR0); ifswap(r[3],w->ErrorBuf); break;
  494.       case 7: ifswap(r[1],w->CallBack); ifswap(r[2],w->CallBackR12); ifswap(r[3],w->CallBackBuf); break;
  495.       case 8: ifswap(r[1],w->BreakPoint); ifswap(r[2],w->BreakPointR12); ifswap(r[3],w->BreakPointBuf); break;
  496.       case 9: ifswap(r[1],w->Escape); ifswap(r[2],w->EscapeR12); break;
  497.       case 10: ifswap(r[1],w->Event); ifswap(r[2],w->EventR12); break;
  498.       case 11: ifswap(r[1],w->Exit); ifswap(r[2],w->ExitR12); break;
  499.       case 12: ifswap(r[1],w->UnusedSWI); ifswap(r[2],w->UnusedSWIR12); break;
  500.       case 13: ifswap(r[1],w->ExceptionRegs); break;
  501.       case 14: ifswap(r[1],w->ApplicationSpace); break;
  502.       case 15: ifswap(r[1],w->CurrentlyActiveObject); break;
  503.       case 16: ifswap(r[1],w->UpCall); ifswap(r[2],w->UpCallR12); break;
  504.     }
  505.     break;
  506.   
  507.    case OS_SetEnv: 
  508.     { int t;
  509.       ifswap(r[0],w->Exit);
  510.       ifswap(r[1],w->MemoryLimit);
  511.       ifswap(r[2],w->ApplicationSpace);
  512.       ifswap(r[4],w->UndefinedInstruction);
  513.       ifswap(r[5],w->PrefetchAbort);
  514.       ifswap(r[6],w->DataAbort);
  515.       ifswap(r[7],w->AddressException);
  516.     }
  517.     break;
  518.  
  519. #ifdef FIXED_SYSTEMCALL_VERSION_FO
  520. /*
  521.  * Simple additions.
  522.  */
  523.    case OS_Control: {
  524.       int t;
  525.       ifswap(r[0],w->Error); ifswap(r[1],w->ErrorBuf);
  526.       ifswap(r[2],w->Escape);
  527.       ifswap(r[3],w->Event);
  528.     }
  529.     break;
  530.  
  531.    case OS_ReadVduVariables: {
  532.       int i = 0, value;
  533.       Normal(w);
  534.       while (FromMem(w, r[0] + i, &value, 4), value != -1) i += 4;
  535.       Virtual(w);
  536.       ReadRange(w, r[0], r[0] + i);
  537.       WriteRange(w, r[1], r[1] + i);
  538.       err = swix(OS_ReadVduVariables, IN(R0|R1), r[0], r[1]);
  539.     }
  540.     break;
  541.  
  542. #endif
  543.   
  544.    case OS_GetEnv: 
  545.     r[0]=(int)&w->command;
  546.     r[1]=w->MemoryLimit;
  547.     r[2]=(int)&w->starttime;
  548.     break;
  549.   
  550.    case OS_ReadVarVal: 
  551.     ReadRange(w,r[0],r[0]+256);
  552.     if (r[2]>=0)
  553.       WriteRange(w,r[1],r[1]+r[2]);
  554.     err = swix(OS_ReadVarVal,IN(R0|R1|R2|R3|R4)|OUT(R2|R3|R4),r[0],r[1],r[2],r[3],r[4],&r[2],&r[3],&r[4]);
  555.     break;
  556.  
  557. #ifdef FIXED_SYSTEMCALL_VERSION_FO
  558. /*
  559.  * Simple addition.
  560.  */
  561.    case OS_SetVarVal:
  562.     ReadRange(w, r[0], r[0] + 256);
  563.     if (r[2] > 0)
  564.       ReadRange(w, r[1], r[1] + r[2]);
  565.     if (r[3] > 0)
  566.       ReadRange(w, r[3], r[3] + 256);
  567.     err = swix(OS_SetVarVal,IN(R0|R1|R2|R3|R4)|OUT(R3|R4),r[0],r[1],r[2],r[3],r[4],&r[3],&r[4]);
  568.     break;
  569. #endif
  570.   
  571.    case OS_Module: 
  572.     switch (r[0])
  573.     { default: goto uk;
  574.       case 6:
  575.         Normal(w);
  576.         err = swix(OS_Module,IN(R0|R3)|OUT(R2),r[0],r[3],&r[2]);
  577.         Virtual(w);
  578.         break;
  579.       case 7:
  580.         Normal(w);
  581.         err = swix(OS_Module,IN(R0|R2),r[0],r[2]);
  582.         Virtual(w);
  583.         break;
  584.       case 18:
  585.         ReadRange(w,r[1],r[1]+256);
  586.         err = swix(OS_Module,IN(R0|R1)|OUT(R1|R2|R3|R4|R5),
  587.                         r[0],r[1],&r[1],&r[2],&r[3],&r[4],&r[5]);
  588.         break;
  589.     }
  590.     break;
  591.  
  592. #ifdef FIXED_SYSTEMCALL_VERSION_FO
  593.    case OS_ConvertHex8:
  594.     WriteRange(w,r[1],r[1]+r[2]);
  595.     err = swix(OS_ConvertHex8,IN(R0|R1|R2)|OUT(R0|R1|R2),r[0],r[1],r[2],&r[0],&r[1],&r[2]);
  596.     break;
  597. #endif
  598.  
  599.    case OS_CLI: 
  600.     { char buf[256];
  601.       Normal(w);
  602.       FromMem(w,r[0],buf,sizeof(buf));
  603. #ifdef FIXED_SYSTEMCALL_VERSION_FO
  604.       if ((buf[0]|0x20)=='g' && (buf[1]|0x20)=='o' && (buf[2]|0x20)=='s' && buf[3]<=' ')
  605.          ingos = 1;
  606.       else
  607.          ingos = 0;
  608. /*
  609.  * Before loading a new programme into memory the old and new pages
  610.  * should be on the same addresses.
  611.  */
  612.       FixMemoryPages(w);
  613. #endif
  614.       err=swix(OS_CLI,IN(R0),buf);
  615.       Virtual(w);
  616.     }
  617.     break;
  618.  
  619.    case OS_Mouse:  
  620.      Normal(w);
  621.      err = swix(OS_Mouse,OUT(R0|R1|R2|R3),&r[0],&r[1],&r[2],&r[3]);
  622.      Virtual(w);
  623.      break;
  624.  
  625.    case OS_ReadMonotonicTime:  
  626.      Normal(w);
  627.      err = swix(OS_ReadMonotonicTime,OUT(R0),&r[0]);
  628.      Virtual(w);
  629.      break;
  630.  
  631.    case OS_SWINumberFromString: 
  632.     { char buf[256];
  633.       Normal(w);
  634.       FromMem(w,r[1],buf,sizeof(buf));
  635.       err=swix(OS_SWINumberFromString,IN(R1)|OUT(R0),&buf,&r[0]);
  636.       Virtual(w);
  637.     }
  638.     break;
  639.  
  640.    /* Filesystem SWIs */
  641.    case OS_Find: 
  642.     if (!r[0])
  643.     { Normal(w);
  644.       err = swix(OS_Find,IN(R0|R1)|OUT(PSW),r[0],r[1],&psw);
  645.       Virtual(w);
  646.     }
  647.     else
  648.     { char name[256];
  649.       char path[256];
  650.       Normal(w);
  651.       FromMem(w,r[1],name,sizeof(name));
  652.       if ((r[0]&3)==1 || (r[0]&3)==2)
  653.         FromMem(w,r[2],path,sizeof(path));
  654.       err = swix(OS_Find,IN(R0|R1|R2)|OUT(PSW|R0),r[0],name,path,&psw,&r[0]);
  655.       Virtual(w);
  656.     }
  657.     break;
  658.   
  659.    case OS_BGet: case OS_BPut: case OS_Args: 
  660.     Normal(w);
  661.     err=swix(swinum,IN(R0|R1|R2)|OUT(PSW|R0|R1|R2),r[0],r[1],r[2],&psw,&r[0],&r[1],&r[2]);
  662.     r[15]=r[15]&~PSW_bits|PSW&PSW_bits;
  663.     Virtual(w);
  664.     break;
  665.   
  666.    case OS_GBPB: 
  667.     Normal(w);
  668.     if (1<=r[0] && r[0]<=4)
  669.     { /* read/write variety */
  670.       while (r[3]>0)
  671.       { RANGE k = Physical(w,r[2],r[2]+r[3]);
  672.         int p = k.start;
  673.         int l = k.end-k.start;
  674.         int q,m;
  675.         err=swix(OS_GBPB,IN(R0|R1|R2|R3|R4)|OUT(PSW|R2|R3|R4),r[0],r[1],p,l,r[4],&psw,&q,&m,&r[4]);
  676.         r[2]+=q-p;
  677.         r[3]-=l-m;
  678.         if (err || m)
  679.           break;
  680.     } }
  681.     else if (5<=r[0] && r[0]<=8)
  682.     { char buf[2048];
  683.       FromMem(w,r[2],buf,sizeof(buf));
  684.       err=swix(OS_GBPB,IN(R0|R1|R2|R3|R4)|OUT(PSW|R3|R4),r[0],buf,r[2],r[3],r[4],&psw,&r[3],&r[4]);
  685.       ToMem(w,buf,r[2],sizeof(buf));
  686.     }
  687.     else if (9<=r[0] && r[0]<=12)
  688.     { char dirname[256];
  689.       char wild[256];
  690.       RANGE k;
  691.       FromMem(w,r[1],&dirname,sizeof(dirname));
  692.       if (r[6])
  693.         FromMem(w,r[6],&wild,sizeof(wild));
  694.       k = Physical(w,r[2],r[2]+r[5]);
  695.       err=swix(OS_GBPB,IN(R0|R1|R2|R3|R4|R5|R6)|OUT(PSW|R3|R4),
  696.         r[0],dirname,k.start,r[3],r[4],k.end-k.start,r[6]?wild:0,
  697.         &psw,&r[3],&r[4]);
  698.     }
  699.     else
  700.     { Virtual(w);
  701.       goto uk;
  702.     }
  703.     r[15]=r[15]&~PSW_bits|PSW&PSW_bits;
  704.     Virtual(w);
  705.     break;
  706.   
  707.    case OS_File: 
  708.     Normal(w);
  709.     switch(r[0])
  710.     { default: Virtual(w); goto uk;
  711.       case 5: case 13: case 15: case 17:        /* read cat info */
  712.       case 20: case 21: case 22: case 23:
  713.       { int h;
  714.         char path[256];
  715.         char name[256];
  716.         FromMem(w,r[1],name,sizeof(name));
  717.         if (r[0]==13 || r[0]==15 || r[0]==21 || r[0]==22)
  718.           FromMem(w,r[4],path,sizeof(path));
  719.         err = swix(OS_File,IN(R0|R1|R4)|OUT(R0|R2|R3|R4|R5|R6),r[0],name,path,
  720.                                         &r[0],&r[2],&r[3],&r[4],&r[5],&h);
  721.         if (20<=r[0] && r[0]<=23)
  722.           r[6]=h;
  723.         break;
  724.       }
  725.       case 1: case 2: case 3: case 4: case 9: case 18:  /* Write cat info */
  726.       case 6:           /* Delete */
  727.       case 7: case 11:  /* Create */
  728.       case 8:           /* Create directory */
  729.       { char name[256];
  730.         FromMem(w,r[1],name,sizeof(name));
  731.         err = swix(OS_File,IN(R0|R1|R2|R3|R4|R5)|OUT(R0|R2|R3|R4|R5),r[0],name,r[2],r[3],r[4],r[5],
  732.                                         &r[0],&r[2],&r[3],&r[4],&r[5]);
  733.         break;
  734.       }
  735.       case 12: case 14: case 16: case 255:      /* load */
  736.       { int h;
  737.         char path[256];
  738.         char name[256];
  739.         RANGE k;
  740.         int l,m,q;
  741.         int p=(r[3]&0xFF)?-1:r[2];
  742.         int t = r[0]==255?0:r[0]==12?1:r[0]==14?2:r[0]==16?3:0;
  743.         FromMem(w,r[1],name,sizeof(name));
  744.         if (t==1 || t==2)
  745.           FromMem(w,r[4],path,sizeof(path));
  746.         err = swix(OS_File,IN(R0|R1|R4)|OUT(R0|R2|R3|R4|R5),"\x05\x0D\x0F\x11"[t],name,path,
  747.                                         &r[0],&r[2],&r[3],&r[4],&r[5]);
  748.         if (err)
  749.           break;
  750.         err = swix(OS_Find,IN(R0|R1|R2)|OUT(R0),0x4C+t,name,path,&h);
  751.         if (err)
  752.           break;
  753.         if (p==-1)
  754.           p = r[2];
  755.         l = r[4];
  756.         while (l>0)
  757.         { k = Physical(w,p,p+l);
  758.           if (!k.start)
  759.           { err=ERR(&BadMemory);
  760.             break;
  761.           }
  762.           err = swix(OS_GBPB,IN(R0|R1|R2|R3)|OUT(R2|R3),4,h,k.start,k.end-k.start,&q,&m);
  763.           if (err)
  764.             break;
  765.           if (q!=k.end || m)
  766.           { err = ERR(&Failed);
  767.             break;
  768.           }
  769.           p+=k.end-k.start;
  770.           l-=k.end-k.start;
  771.         }
  772.         if (!err)
  773.           err = swix(OS_Find,IN(R0|R1),0,h);
  774.         else
  775.           (void)swix(OS_Find,IN(R0|R1),0,h);
  776.       }
  777.     }
  778.     Virtual(w);
  779.     break;
  780.   
  781.    case OS_FSControl: 
  782.     Normal(w);
  783.     switch (r[0])
  784.     { default: Virtual(w); goto uk;
  785.       case 27:          /* Wipe objects */
  786.       { char name[256];
  787.         FromMem(w,r[1],name,sizeof(name));
  788.         err = swix(OS_FSControl,IN(R0|R1|R2|R3|R4|R5|R6|R7),r[0],name,r[2],r[3],r[4],r[5],r[6],r[7]);
  789.         break;
  790.       }
  791.     }
  792.     Virtual(w);
  793.     break;
  794.   
  795.     /*
  796.      * RISCOS extension module SWIs
  797.      */
  798.      
  799. #ifndef SharedCLibrary_LibInitAPCS_R
  800. #define SharedCLibrary_LibInitAPCS_R 0x80681
  801. #endif
  802.    case SharedCLibrary_LibInitAPCS_R: 
  803.     ReadRange(w,r[0],r[0]+256);
  804.     WriteRange(w,r[1],r[1]+32768);
  805.     err = swix(SharedCLibrary_LibInitAPCS_R,IN(R0|R1|R2|R3|R4|R5|R6)|OUT(R0|R1|R2|R6),
  806.         r[0],r[1],r[2],r[3],r[4],r[5],r[6],&r[0],&r[1],&r[2],&r[6]);
  807.     break;
  808.   
  809.    case DDEUtils_SetCLSize: 
  810.     Normal(w);
  811.     free(w->DDECL);
  812.     w->DDECLSize = r[0];
  813.     w->DDECL = alloc(r[0]);
  814.     Virtual(w);
  815.     break;
  816.   
  817.    case DDEUtils_SetCL: 
  818.     Normal(w);
  819.     FromMem(w,r[0],w->DDECL,w->DDECLSize);
  820.     Virtual(w);
  821.     break;
  822.   
  823.    case DDEUtils_GetCLSize: 
  824.     r[0] = w->DDECLSize;
  825.     break;
  826.   
  827. #ifndef DDEUtils_GetCL
  828. #define DDEUtils_GetCL 0x42584
  829. #endif
  830.    case DDEUtils_GetCL: 
  831.     Normal(w);
  832.     ToMem(w,w->DDECL,r[0],w->DDECLSize);
  833.     Virtual(w);
  834.     break;
  835.   
  836.    case DDEUtils_ThrowbackStart: 
  837.     Normal(w);
  838.     err = swix(DDEUtils_ThrowbackStart,0);
  839.     Virtual(w);
  840.     break;
  841.   
  842.    case DDEUtils_ThrowbackSend: 
  843.     { char file[256];
  844.       char msg[256];
  845.       Normal(w);
  846.       FromMem(w,r[2],&file,sizeof(file));
  847.       if (r[0])
  848.         FromMem(w,r[5],&msg,sizeof(msg));
  849.       err = swix(DDEUtils_ThrowbackSend,IN(R0|R2|R3|R4|R5),r[0],file,r[3],r[4],msg);
  850.       Virtual(w);
  851.       break;
  852.     }
  853.   
  854.    case DDEUtils_ThrowbackEnd: 
  855.     Normal(w);
  856.     err = swix(DDEUtils_ThrowbackEnd,0);
  857.     Virtual(w);
  858.     break;
  859.   
  860.    case MessageTrans_Lookup: case MessageTrans_ErrorLookup:
  861.     ReadRange(w,r[1],r[1]+256);
  862.     if (r[2])
  863.       WriteRange(w,r[2],r[2]+r[3]);
  864.     err = swix(swinum,IN(R0|R1|R2|R3|R4|R5|R6|R7)|OUT(R0|R2|R3),
  865.         r[0],r[1],r[2],r[3],r[4],r[5],r[6],r[7],&r[0],&r[2],&r[3]);
  866.     break;
  867.   
  868.    case Wimp_ReadSysInfo: 
  869.     err = swix(Wimp_ReadSysInfo,IN(R0)|OUT(R0),r[0],&r[0]);
  870.     break;
  871.   
  872.    case FPEmulator_Version: 
  873.     err = swix(FPEmulator_Version,OUT(R0),&r[0]);
  874.     break;
  875.   
  876.    case Territory_ReadCurrentTimeZone: 
  877.     err = swix(Territory_ReadCurrentTimeZone,OUT(R0|R1),&r[0],&r[1]);
  878.     break;
  879.   
  880.    case Territory_ReadTimeZones: 
  881.     err = swix(Territory_ReadTimeZones,IN(R0)|OUT(R0|R1|R2|R3),r[0],&r[0],&r[1],&r[2],&r[3]);
  882.     break;
  883.   
  884.    case Territory_ConvertTimeToOrdinals: 
  885.     ReadRange(w,r[1],r[1]+5);
  886.     WriteRange(w,r[2],r[2]+32);
  887.     err = swix(Territory_ConvertTimeToOrdinals,IN(R0|R1|R2),r[0],r[1],r[2]);
  888.     break;
  889.  
  890.    case Wimp_SlotSize: 
  891. #ifndef FIXED_SYSTEMCALL_VERSION_FO
  892. /*
  893.  * When this SWI is allowed, the wimpslot will be expanded to the
  894.  * maximum value, or sometimes to a wrong value.
  895.  * In the first case there is no space left for Edit's taskwindow,
  896.  * so Virtual will stop. 
  897.  * I think a programme running under Virtual must not cange its
  898.  * 'Wimp_Slot'. The user can make any changes to the WimpSlot by
  899.  * dragging a bar in the Tasks window.
  900.  *
  901.  * When a task wants to enlarge the wimpslot, ie make the 'DiskSlot'
  902.  * bigger, will this be allowed.
  903.  *
  904.  * So this code is not compiled
  905.  */
  906.     swi(Wimp_SlotSize,IN(R0|R1),OUT(R1|R2),-1,r[1],&r[1],&r[2]);
  907.     if (r[0]!=-1)
  908.     { w->ApplicationSpace = r[0];
  909.       w->MemoryLimit = r[0];
  910.     }
  911.     r[0]=w->ApplicationSpace;
  912.     break;
  913. #else
  914. /*
  915.  * So here's my new code
  916.  */
  917.     if (r[0] != -1) {
  918.       if (r[0] > w->ApplicationSpace - K32) {           /* task asks for wimpslot extension */
  919.         int i, OldAppSpace = w->ApplicationSpace;
  920.         w->ApplicationSpace = ADDR(PLACE(r[0] + K32 + K32));
  921.         if (w->ApplicationSpace > M24)
  922.           w->ApplicationSpace = M24;
  923.         w->MemoryLimit = w->ApplicationSpace;
  924.         for (i = PLACE(OldAppSpace); i < PLACE(w->ApplicationSpace); i++) {
  925.           w->ourmem[i] = TAGLOC(ZERO, 0);
  926.         }
  927.       }
  928.     }
  929.     r[0] = w->ApplicationSpace - K32;
  930.     break;
  931. #endif
  932.   
  933.   /* BASICTrans swis */
  934.   case BASICTrans_HELP:
  935.   case BASICTrans_Message:
  936.   case BASICTrans_Error:
  937.     V2Ext(w);
  938.     err=swix(instr&0xFDFFFF,IN(R0|R1|R2|R3|R4|R5|R6|R7|R8|R9)|
  939.                            OUT(R0|R1|R2|R3|R4|R5|R6|R7|R8|R9),
  940.          r[0], r[1], r[2], r[3], r[4], r[5], r[6], r[7], r[8], r[9],
  941.         &r[0],&r[1],&r[2],&r[3],&r[4],&r[5],&r[6],&r[7],&r[8],&r[9]);
  942.     Ext2V(w);
  943.     break;
  944.  
  945.   case TaskWindow_TaskInfo:  
  946.      Normal(w);
  947.      if (r[0] == 0)
  948.        r[0] = 1;
  949.      else
  950.        err = swix(TaskWindow_TaskInfo,IN(R0)|OUT(R0),r[0],&r[0]);
  951.      Virtual(w);
  952.      break;
  953.  
  954.    /*
  955.     * Default (unrecognized SWIs) handling
  956.     */
  957.   
  958.    default: 
  959.     if (swinum>=0x100 && swinum<0x200)
  960.     { outc(w,(char)swinum);
  961.       break;
  962.     }
  963.   uk:
  964.     Normal(w);
  965.     swi(OS_SWINumberToString,IN(R0|R1|R2),instr&0xFFFFFF,s,256);
  966.     printf("UKSwi %s PC=%08x ",s,r[15]);
  967.     for (i=0;i<=8;i++)
  968.       printf("R%d=%08x ",i,r[i]);
  969.     printf("Allow(Yn)?\n");
  970.     Virtual(w);
  971.   lp:
  972.     switch (getc(w))
  973.     { case -1:
  974.         w->EscapeCondition = 0;
  975.         /* FALL THROUGH */
  976.       default:
  977.         goto lp;
  978.       case 'n': case'N':
  979.         err = ERR(&NotAllowed);
  980.         break;
  981.       case 'y': case 'Y': case 13:
  982.         V2Ext(w);
  983.         err=swix(instr&0xFDFFFF,IN(R0|R1|R2|R3|R4|R5|R6|R7|R8|R9)|
  984.                                OUT(PSW|R0|R1|R2|R3|R4|R5|R6|R7|R8|R9),
  985.              r[0], r[1], r[2], r[3], r[4], r[5], r[6], r[7], r[8], r[9],
  986.        &psw,&r[0],&r[1],&r[2],&r[3],&r[4],&r[5],&r[6],&r[7],&r[8],&r[9]);
  987.         r[15]=r[15]&~PSW_bits|PSW&PSW_bits;
  988.         Ext2V(w);
  989.         break;
  990.     }
  991.     break;
  992.   
  993.   }
  994. #if 0
  995.     Normal(w);
  996.     for (i=0;i<=15;i++)
  997.       printf("R%d=%08x ",i,r[i]);
  998.     if (err)
  999.       printf("**** ERROR **** %d %s",err->num,err->msg);
  1000.     printf("\n");
  1001.     if (r[15]&0x0c000003)
  1002.     { printf("***Bad PC***\n");
  1003.       RealDoOff(w);
  1004.     }
  1005.     Virtual(w);
  1006. #endif
  1007.   if (!err)
  1008.     return w;
  1009.   if (instr&XOS_Bit) /* X form */
  1010.   { r[0]=(int)err;
  1011.     r[15]|=V_bit;
  1012.     return w;
  1013.   }
  1014.   if (-1==w->Error)
  1015.   { Normal(w);
  1016.     printf("***Error:%s",err->msg);
  1017.     RealDoOff(w);
  1018.   }
  1019.   WriteRange(w,w->ErrorBuf,w->ErrorBuf+264);
  1020.   ((int*)w->ErrorBuf)[0] = r[15];
  1021.   ((int*)w->ErrorBuf)[1] = err->num;
  1022.   strcpy( (char *)&((int*)w->ErrorBuf)[2], err->msg );
  1023.   r[0] = w->ErrorR0;
  1024.   r[15] = w->Error & ~3;
  1025.   return w;
  1026. }
  1027.  
  1028.  int CVUpCall( int r0, int r1, int r2, WKSP *w) 
  1029. { /* Called with sp a 1K chunk out of svcstack */
  1030.   switch(r0)
  1031.   { case 256:
  1032.       r0 = 0; /* Not quite sure what on earth is going on here, but better stop it! */
  1033.       break;
  1034.     default:
  1035.       break;
  1036.   }
  1037.     return r0;
  1038. }
  1039.  
  1040.  
  1041. /* ******************** Ext mode handlers */
  1042.  int CExtWriteC(int c, WKSP *w) 
  1043. { /* called with stack a 1K bit out of svcstack */
  1044.   w->outbuf[w->outcount++]=c;
  1045.   if (w->outcount>=OUTMAX-2)
  1046.   { Ext2Norm(w);
  1047.     printflush(w);
  1048.     FindPages(w);
  1049.     Norm2Ext(w);
  1050.   }
  1051.   return 0x80000000;     /* VC CC */
  1052. }
  1053.  
  1054.  int CExtUpCall(int r0,int r1,int r2,WKSP *w) 
  1055. { /* Called with sp a 1K chunk out of svcstack */
  1056.   switch(r0)
  1057.   { case 256:
  1058.       r0 = 0;
  1059.       break;
  1060.     default:
  1061.       break;
  1062.   }
  1063.   return r0;
  1064. }
  1065.  
  1066.  int CExtError(WKSP *w) 
  1067. { /* Called in user, ext mode */
  1068.   printf("ExtError PC=%08x errnum %d errmess %s****\n",w->errPC,w->errnum,w->errmess);
  1069.   Ext2V(w);
  1070.   return (int)&w->errnum;
  1071. }
  1072.  
  1073.  void CExtExit(WKSP *w) 
  1074. { /* Called in user, ext mode */
  1075.   Ext2V(w);
  1076. }
  1077.  
  1078.  
  1079. /* ******************** Normal mode handlers */
  1080.  void __main(private *p,char *cmd) 
  1081. { /* This is called in user mode, with its stack at the top of the WimpSlot */
  1082.   wimp_eventdata b;
  1083.   struct Error *e;
  1084.   char *buf[64];
  1085.   int version,ourtask,outtask,txt,i;
  1086.   WKSP *w;
  1087.   strcpy(b.msg.data.chars+8,cmd);
  1088.   swi(OS_ReadArgs,IN(R0|R1|R2|R3),
  1089.         ",wimpslot/K,name/K,pagefile/K,ctrl/S,display/S,quit/S,task,txt", cmd, buf, sizeof(buf));
  1090.   if (!buf[0])
  1091.     return;
  1092.   swi(Wimp_Initialise,IN(R0|R1|R2)|OUT(R0|R1),200,0x4b534154,
  1093.                 buf[2]?buf[2]:"Virtual",&version,&ourtask);
  1094.   if (!buf[7] || !buf[8])
  1095.   { memcpy(b.msg.data.chars,"virtual ",8);
  1096.     b.msg.hdr.action = 0x808c5; /* TaskWindow_NewTask; */
  1097.     b.msg.hdr.your_ref = 0;
  1098.     b.msg.hdr.size = (21+(strlen(b.msg.data.chars)|3));
  1099.     swi(Wimp_SendMessage,IN(R0|R1|R2),17,&b.msg,0);
  1100.     swi(OS_Exit,0);
  1101.   }
  1102.   outtask = xtoi(buf[7]);
  1103.   txt = xtoi(buf[8]);
  1104.  
  1105.   b.msg.hdr.action = /*TaskWindow_Ego*/ 0x808c2;
  1106.   b.msg.hdr.your_ref = 0;
  1107.   b.msg.data.words[0]=txt;
  1108.   b.msg.hdr.size = 24;
  1109.   swi(Wimp_SendMessage,IN(R0|R1|R2),17,&b.msg,outtask);
  1110.  
  1111.   w = alloc(sizeof(WKSP));
  1112.   p->w = w;
  1113.   p->uses++;
  1114.   w->private = p;
  1115.   w->outtask = outtask;
  1116.   w->ourtask = ourtask;
  1117.   w->outcount = 0;
  1118.   w->incount = 0;
  1119.   w->instart = 0;
  1120.   w->EscapeCondition = 0;
  1121.   w->EscapeChar = 27;
  1122. #ifdef FIXED_SYSTEMCALL_VERSION_FO
  1123.   w->EscapeCharEnable = 0;
  1124. #endif
  1125.   w->moreavailable = 0;
  1126.   strcpy(w->pagefilename,buf[3]?buf[3]:"<Swap$Path>pagefile0");
  1127.   strcpy(w->command,buf[0]?buf[0]:"GOS");
  1128.   w->ApplicationSpace=buf[1]?sizetoi(buf[1])+K32:M24;
  1129.   if (w->ApplicationSpace>M24)
  1130.     w->ApplicationSpace=M24;
  1131.   w->UpCall = w->Error = w->Exit = w->Escape = w->UndefinedInstruction = w->PrefetchAbort = w->DataAbort = w->AddressException = -1;
  1132.   w->DDECLSize = 0;
  1133.   w->DDECL = 0;
  1134.   i=0;
  1135.   while (0!=(e=swix(OS_Find,IN(R0|R1)|OUT(R0),0x80,w->pagefilename,&w->pagefile)) && i<10)
  1136.     w->pagefilename[strlen(w->pagefilename)-1]++,i++;
  1137.   if (e)
  1138.   { swi(Wimp_ReportError,IN(R0|R1|R2),e,2,"Virtual");
  1139.     swi(OS_Exit,0);
  1140.   }
  1141.   svcmode();
  1142.   swi(OS_Claim,IN(R0|R1|R2),3,&NormWriteC,w);
  1143. #if 0
  1144.   printf("cmd=%s\n",w->command);
  1145.   printf("wimpslot=%08x\n",w->ApplcationSpace);
  1146.   printf("name=%s\n",buf[2]);
  1147.   printf("pagefile=%s\n",w->pagefilename);
  1148.   printf("ctrl=%08x\n",(int)buf[4]);
  1149.   printf("display=%08x\n",(int)buf[5]);
  1150.   printf("quit=%08x\n",(int)buf[6]);
  1151.   printf("task=%08x\n",outtask);
  1152.   printf("txt=%08x\n",txt);
  1153. #endif
  1154.   swi(OS_ChangeEnvironment,IN(R0|R1|R2|R3)|OUT(R1|R2|R3),6,&NormError,w,&w->errPC,
  1155.                         &w->OldError,&w->OldErrorR0,&w->OldErrorBuf);
  1156.   swi(OS_ChangeEnvironment,IN(R0|R1|R2)|OUT(R1|R2),16,&NormUpCall,w,&w->OldUpCall,&w->OldUpCallR12);
  1157.   swi(OS_ChangeEnvironment,IN(R0|R1|R2)|OUT(R1|R2),11,&NormExit,w,&w->OldExit,&w->OldExitR12);
  1158.  
  1159.   Initourmem(w);
  1160.   SetWimpMemMap(w);
  1161.   SetVirtualSlot(w,w->ApplicationSpace-K32);
  1162.   w->MemoryLimit = w->ApplicationSpace;
  1163. #if 0
  1164.   printf("Going virtual\n");
  1165. #endif
  1166.   Virtual(w);
  1167.   usermode();
  1168.   worksemaphore = 0;    /* Enable interupts */
  1169. #ifdef DEBUG
  1170.   swi(OS_Write0,IN(R0),"This is virtual: OS_CLI ");
  1171.   swi(OS_Write0,IN(R0),w->command);
  1172.   swi(OS_NewLine,0);
  1173. #endif
  1174.   swi(OS_CLI,IN(R0),w->command);
  1175.   swi(OS_Exit,0);
  1176. }
  1177.  
  1178.  void RealDoOff(WKSP *w) 
  1179. {
  1180.   private *priv=w->private;
  1181.   wimp_eventdata b;
  1182. #ifdef DEBUG
  1183.   printf("RealDoOff\n");
  1184. #endif
  1185.   swi(OS_Release,IN(R0|R1|R2),3,&NormWriteC,w);
  1186.   printflush(w);
  1187.   swi(OS_ChangeEnvironment,IN(R0|R1|R2),6,w->OldError,w->OldErrorR0,w->OldErrorBuf);
  1188.   swi(OS_ChangeEnvironment,IN(R0|R1|R2),11,w->OldExit,w->OldExitR12);
  1189.   swi(OS_ChangeEnvironment,IN(R0|R1|R2),16,w->OldUpCall,w->OldUpCallR12);
  1190.   Finishourmem(w);
  1191.   usermode();
  1192.   b.msg.hdr.action = /*TaskWindow_Morio*/ 0x808c3;
  1193.   b.msg.hdr.your_ref = 0;
  1194.   b.msg.hdr.size = 20;
  1195.   swi(Wimp_SendMessage,IN(R0|R1|R2),17,&b.msg,w->outtask);
  1196.  
  1197.   swi(Wimp_CloseDown, 0);
  1198.   swix(OS_Find,IN(R0|R1),0,w->pagefile);
  1199.   swix(OS_File,IN(R0|R1),6,w->pagefilename);
  1200.   free((char *)w->stacktop-STACKSIZE);
  1201.   free(w->DDECL);
  1202.   free(w);
  1203.   priv->uses--;
  1204.   priv->w = 0;
  1205.   swi(OS_Exit,0);
  1206. }
  1207.  
  1208.  int CNormError( WKSP *w )
  1209. { printf("NormError: PC=%08x errnum %d errmess %s\n",w->errPC,w->errnum,w->errmess);
  1210.   swi(OS_Release,IN(R0|R1|R2),3,&NormWriteC,w);
  1211.   swi(Wimp_ReportError,IN(R0|R1|R2),&w->errnum,2,"Virtual");
  1212.   swi(OS_Claim,IN(R0|R1|R2),3,&NormWriteC,w);
  1213.   RealDoOff(w);
  1214.   return 0;
  1215. }
  1216.  
  1217.  void CNormExit(WKSP *w)
  1218. { printf("NormExit\n");
  1219.   RealDoOff(w);
  1220. }
  1221.  
  1222.  int CNormWriteC(int c, WKSP *w) 
  1223. { /* called with stack a 1K bit out of svcstack */
  1224.   w->outbuf[w->outcount++]=c;
  1225.   if (w->outcount>=OUTMAX-2)
  1226.   { printflush(w);
  1227.     FindPages(w);
  1228.   }
  1229.   return 0x80000000;     /* VC CC */
  1230. }
  1231.  
  1232.  int CNormUpCall(int r0,int r1,int r2,WKSP *w) 
  1233. { /* Called with sp a 1K chunk out of svcstack */
  1234.   switch(r0)
  1235.   { case 256:
  1236.       { char *cmd, *tptr;
  1237.  
  1238. #ifndef FIXED_SYSTEMCALL_VERSION_FO
  1239. /*
  1240.  * These lines are one of the main reasons of the bug. They are bad!
  1241.  */
  1242.         w->UpCall = w->Error = w->Exit = w->Escape = w->UndefinedInstruction = w->PrefetchAbort = w->DataAbort = w->AddressException = -1;
  1243.         SetWimpMemMap(w);
  1244.         SetVirtualSlot(w,w->ApplicationSpace-K32);
  1245. #endif
  1246.         Virtual(w);
  1247.         swi(OS_GetEnv,OUT(R0|R2),&cmd,&tptr);
  1248.         strcpy(w->command,cmd);
  1249.         memcpy(w->starttime,tptr,5);
  1250.         worksemaphore = 0;    /* Enable interupts */
  1251.         break;
  1252.       }
  1253.     default:
  1254.       break;
  1255.   }
  1256.   return r0;
  1257. }
  1258.  
  1259.  
  1260.