home *** CD-ROM | disk | FTP | other *** search
/ Fujiology Archive / fujiology_archive_v1_0.iso / !FALCON / !BONUS / UTILITY / FS.ZIP / FALCSCR5 / FS.C next >
C/C++ Source or Header  |  1997-06-16  |  19KB  |  533 lines

  1. /************************************************************************/
  2. /*                                                                        */
  3. /* FalconScreen                                                            */
  4. /* ============                                                            */
  5. /*                                                                        */
  6. /* Copyright 1993 by Markus Gutschke.                                    */
  7. /* This program is postcardware. You are encouraged to distribute it    */
  8. /* freely as long as you do not charge anybody for it, but if you keep    */
  9. /* a copy, you have to send me a postcard:                                */
  10. /*        Markus Gutschke                                                    */
  11. /*        Papenbusch 31                                                    */
  12. /*        4400 M"unster                                                    */
  13. /*        W-Germany                                                        */
  14. /* Note! This program may not be distributed with so-called PD-            */
  15. /* collections or on cover-disks!                                        */
  16. /* If you encounter any bugs (there are probably a lot!), have comments    */
  17. /* or suggestions or just found some useful settings for the video        */
  18. /* registers, please send e-mail to:                                    */
  19. /*        srb242@math.uni-muenster.de                                        */
  20. /* or:    Markus.Gutschke@uni-muenster.de                                    */
  21. /*                                                                        */
  22. /* The current version of this program will only affect the 640x480x1bit*/
  23. /* mode (if "MONO" is defined) and the 640x480x4bit mode (TT-MEDIUM) on    */
  24. /* an SVGA monitor. It will replace one of these modes with a user        */
  25. /* selectable higher resolution. Currently 832x624 (for mono) and        */
  26. /* 928x704 (for 16 colors) are the highest possible settings.            */
  27. /*                                                                        */
  28. /* This program relies on several undocumented features of the            */
  29. /* Falcon030, thus I am unable to guarantee, that it will work on any    */
  30. /* computer other than my own. This program will most certainly damage    */
  31. /* any monitor, that does not support SVGA video modes! Even SVGA        */
  32. /* monitors might be damaged/destroyed, since this program is pushing    */
  33. /* the signal timing very hard. If you feel at all uncomfortable with    */
  34. /* the possibility of damaging your hardware, do not run this program!    */
  35. /*                                                                        */
  36. /* Since I am releasing this program free of charge, I am unable to        */
  37. /* give any support or guarantee for this program!                        */
  38. /*                                                                        */
  39. /* This program will compile with TurboC and PureC. You will probably    */
  40. /* have to make changes, if you want to compile it with any other        */
  41. /* system. If you added conditional preprocessor directives that allow    */
  42. /* you to compile this program both with TC/PC and with your system        */
  43. /* please let me know.                                                    */
  44. /* The assembler interface relies on the TC/PC parameter passing scheme.*/
  45. /* Scalar values will be passed in D0 through D2, addresses will be        */
  46. /* passed in A0 and A1; all parameters that cannot be passed by            */
  47. /* registers, will be passed on the stack. Return values will be either    */
  48. /* in D0 (scalar values) or in A0 (pointers). D3-D7/A2-A7 remain        */
  49. /* unaffected throughout a function call.                                */
  50. /*                                                                        */
  51. /************************************************************************/
  52.  
  53. #define        BETA                    /* This is a beta release of FS        */
  54. #define        MONO                    /* Add experimental code for mono-    */
  55.                                     /* chrome mode!                        */
  56. #undef        OLDVALUES                /* Use improved parameter sets!        */
  57. #define        PRGNAME        "FS.PRG"    /* Program name for patching params.*/
  58. #define        ID            '\344FSC'    /* XBRA Id                            */
  59.  
  60. #define        MINN        1            /* min-/maximum legal values for N    */
  61. #define        MAXN        ((int)(sizeof(table)/sizeof(struct TABLE)-1))
  62.  
  63. /* Several negative LineA variables need patching                        */
  64.  
  65. #define        VGemX        (((int *)linea)[-0x015A])
  66. #define        VGemY        (((int *)linea)[-0x0159])
  67. #define        VCelHT        (((int *)linea)[-0x0017])
  68. #define        VCelMX        (((int *)linea)[-0x0016])
  69. #define        VCelMY        (((int *)linea)[-0x0015])
  70. #define        VCelWR        (((int *)linea)[-0x0014])
  71. #define        VXMax        (((int *)linea)[-0x0006])
  72. #define        VYMax        (((int *)linea)[-0x0002])
  73. #define        VBytesLin    (((int *)linea)[-0x0001])
  74. #define        VPlanes        (((int *)linea)[ 0x0000])
  75. #define        VWrap        (((int *)linea)[ 0x0001])
  76.  
  77. /* List of undocumented video registers (c.f. VIDEO.PRG)                */
  78.  
  79. #define        RShift        (*(int *)0xFFFF8260l)
  80. #define        RSpShift    (*(int *)0xFFFF8266l)
  81. #define        RWrap        (*(int *)0xFFFF8210l)
  82. #define        RCO            (*(int *)0xFFFF82C0l)
  83. #define        RMode        (*(int *)0xFFFF82C2l)
  84. #define        RHHT        (*(int *)0xFFFF8282l)
  85. #define        RHBB        (*(int *)0xFFFF8284l)
  86. #define        RHBE        (*(int *)0xFFFF8286l)
  87. #define        RHDB        (*(int *)0xFFFF8288l)
  88. #define        RHDE        (*(int *)0xFFFF828Al)
  89. #define        RHSS        (*(int *)0xFFFF828Cl)
  90. #define        RHFS        (*(int *)0xFFFF828El)
  91. #define        RHEE        (*(int *)0xFFFF8290l)
  92. #define        RVFT        (*(int *)0xFFFF82A2l)
  93. #define        RVBB        (*(int *)0xFFFF82A4l)
  94. #define        RVBE        (*(int *)0xFFFF82A6l)
  95. #define        RVDB        (*(int *)0xFFFF82A8l)
  96. #define        RVDE        (*(int *)0xFFFF82AAl)
  97. #define        RVSS        (*(int *)0xFFFF82ACl)
  98.  
  99. /* Bindings for system calls are provided by the assembler modul        */
  100.  
  101. void    *LineA0(void);
  102. int        Kbshift(int);
  103. void    *Physbase(void);
  104. void    Setscreen(void *,void *,int,int);
  105. int        Vsetmode(int);
  106. int        Montype(void);
  107. void    VsetRGB(int,int,long *);
  108. void    VgetRGB(int,int,long *);
  109. void    Pterm0(void);
  110. int        Cnecin(void);
  111. void    Cconws(char *);
  112. int        Cconis(void);
  113. void    *Srealloc(unsigned long);
  114. long    Super(void *);
  115. int        Fopen(char *,int);
  116. void    Fclose(int);
  117. long    Fread(int,long,void *);
  118. long    Fwrite(int,long,void *);
  119. long    Fseek(long,int,int);
  120. void    *Malloc(long amount);
  121. void    Mfree(void *addr);
  122.  
  123. /* Copyright message                                                    */
  124.  
  125. void showlogo(int x,int y,unsigned short *scr,
  126.               int width,int height,int planes);
  127. void hidelogo(void);
  128.  
  129. static char copyright[] =
  130.     "\x1BpFalconScreen (c) 1993 by M. Gutschke\x1Bq\r\n"
  131.     "This program is postcardware!\r\n"
  132.     "If you like it, send a postcard to:\r\n"
  133.     "   Markus Gutschke\r\n"
  134.     "   Papenbusch 31\r\n"
  135.     "   4400 M\x81nster\r\n"
  136.     "   W-Germany\r\n"
  137. #ifdef    BETA
  138.     "Warning! This is a beta-Release!\r\n"
  139. #endif
  140.     "This program might damage your F030\r\n"
  141.     "and/or your monitor!\r\n";
  142.  
  143. /* Preset values                                                        */
  144.  
  145. struct settings {                    /* This preinitialized structure    */
  146.     long    magic;                    /* can be patched by the program!    */
  147.     int        size;
  148.     int        mask;                    /* It contains the user's prefered    */
  149.     int        value;                    /* resolution.                        */
  150.     int        planes;
  151.     int        n;
  152.     int        width,height;
  153. } settings = {ID,(int)sizeof(struct settings),0,0,0,MINN-1,0,0};
  154.  
  155. /* Precomputed parameter sets:                                            */
  156.  
  157. static struct TABLE {
  158.     int        width,height,frq,planes;
  159.     int        Shift,SpShift,Wrap,CO,Mode,HHT,HBB,HBE,HDB;
  160.     int        HDE,HSS,HFS,HEE,VFT,VBB,VBE,VDB,VDE,VSS,mask,value;
  161. } table[] = {
  162. #ifdef    MONO
  163.     640,480,80, 1,0,0x400, 40,0x182,8,0x0c6,0x8d,0x15,0x273,0x50,0x96,0,0,
  164.                             0x3e7,0x3e3,0x23,0x23,0x3eb,0x3e4,0x18F,0x008,
  165.     672,512,72, 1,0,0x400, 42,0x182,8,0x0ce,0x8d,0x0d,0x273,0x50,0x96,0,0,
  166.                             0x427,0x423,0x23,0x23,0x42b,0x424,0x18F,0x008,
  167.     704,528,67, 1,0,0x400, 44,0x182,8,0x0d6,0x8d,0x05,0x273,0x50,0x96,0,0,
  168.                             0x447,0x443,0x23,0x23,0x44b,0x444,0x18F,0x008,
  169.     736,560,59, 1,0,0x400, 46,0x182,8,0x0e6,0x8d,0x05,0x283,0x50,0x96,0,0,
  170.                             0x487,0x483,0x23,0x23,0x48b,0x484,0x18F,0x008,
  171.     768,576,54, 1,0,0x400, 48,0x182,8,0x0f6,0x8d,0x05,0x293,0x50,0x96,0,0,
  172.                             0x4a7,0x4a3,0x23,0x23,0x4ab,0x4a4,0x18F,0x008,
  173.     800,608,48, 1,0,0x400, 50,0x182,8,0x106,0x8d,0x05,0x2a3,0x50,0x96,0,0,
  174.                             0x4e7,0x4e3,0x23,0x23,0x4eb,0x4e4,0x18F,0x008,
  175.     832,624,44, 1,0,0x400, 52,0x182,8,0x116,0x8d,0x05,0x2b3,0x50,0x96,0,0,
  176.                             0x507,0x503,0x23,0x23,0x50b,0x504,0x18F,0x008,
  177. #endif
  178.  
  179. #if 0
  180.     640,480,78, 2,1,0x000, 80,0x182,8,0x017,0x12,0x01,0x20e,0x0d,0x11,0,0,
  181.                             0x3e7,0x3e3,0x23,0x23,0x3eb,0x3e4,0x18F,0x009,
  182. #endif
  183.  
  184.     640,480,62, 4,0,0x000,160,0x186,8,0x0c6,0x8d,0x15,0x2a3,0x7c,0x96,0,0,
  185.                             0x3e7,0x3e3,0x23,0x23,0x3eb,0x3e4,0x18F,0x00A,
  186.     672,512,72, 4,0,0x000,168,0x182,8,0x0ce,0x8d,0x0d,0x2a3,0x7c,0x96,0,0,
  187.                             0x427,0x423,0x23,0x23,0x42b,0x424,0x18F,0x00A,
  188.     704,528,67, 4,0,0x000,176,0x182,8,0x0d6,0x8d,0x05,0x2a3,0x7c,0x96,0,0,
  189.                             0x447,0x443,0x23,0x23,0x44b,0x444,0x18F,0x00A,
  190. #ifdef    OLDVALUES
  191.     736,560,58, 4,0,0x000,184,0x182,8,0x0ea,0xa2,0x1e,0x2d0,0x91,0xb8,0,0,
  192.                             0x487,0x483,0x23,0x23,0x48b,0x484,0x18F,0x00A,
  193.     768,576,55, 4,0,0x000,192,0x182,8,0x0f2,0xa2,0x16,0x2d0,0x91,0xb8,0,0,
  194.                             0x4a7,0x4a3,0x23,0x23,0x4ab,0x4a4,0x18F,0x00A,
  195.     800,608,50, 4,0,0x000,200,0x182,8,0x0fa,0xa2,0x0e,0x2d0,0x91,0xb8,0,0,
  196.                             0x4e7,0x4e3,0x23,0x23,0x4eb,0x4e4,0x18F,0x00A,
  197.     832,624,48, 4,0,0x000,208,0x182,8,0x102,0xa2,0x06,0x2d0,0x91,0xb8,0,0,
  198.                             0x507,0x503,0x23,0x23,0x50b,0x504,0x18F,0x00A
  199. #else
  200.     /* Harald, thank you for finding these improved values!                */
  201.     736,560,61, 4,0,0x000,184,0x182,8,0x0df,0xb8,0x29,0x2d0,0xa8,0xb7,0,0,
  202.                             0x487,0x483,0x23,0x23,0x48b,0x484,0x18F,0x00A,
  203.     768,576,57, 4,0,0x000,192,0x182,8,0x0e7,0xb8,0x21,0x2d0,0xa8,0xb7,0,0,
  204.                             0x4a7,0x4a3,0x23,0x23,0x4ab,0x4a4,0x18F,0x00A,
  205.     800,608,52, 4,0,0x000,200,0x182,8,0x0ef,0xb8,0x19,0x2d0,0xa8,0xb7,0,0,
  206.                             0x4e7,0x4e3,0x23,0x23,0x4eb,0x4e4,0x18F,0x00A,
  207.     832,624,50, 4,0,0x000,208,0x182,8,0x0f7,0xb8,0x11,0x2d0,0xa8,0xb7,0,0,
  208.                             0x507,0x503,0x23,0x23,0x50b,0x504,0x18F,0x00A,
  209.     864,656,46, 4,0,0x000,216,0x182,8,0x0ff,0xb8,0x09,0x2d0,0xa8,0xb7,0,0,
  210.                             0x547,0x543,0x23,0x23,0x54b,0x544,0x18F,0x00A,
  211.     896,672,45, 4,0,0x000,224,0x182,8,0x0ff,0xb8,0x01,0x2d0,0xa8,0xb7,0,0,
  212.                             0x567,0x563,0x23,0x23,0x56b,0x564,0x18F,0x00A,
  213.     928,704,40, 4,0,0x000,232,0x182,8,0x10f,0xb8,0x01,0x2e0,0xa8,0xb7,0,0,
  214.                             0x5a7,0x5a3,0x23,0x23,0x5ab,0x5a4,0x18F,0x00A
  215. #endif
  216. };
  217.  
  218. /* Convert a number to a string without exceeding the string size        */
  219.  
  220. static char *tonum(int i,char *s,int *n)
  221. {
  222.     /* recursion is needed to output digits in the right order!            */
  223.     if (i > 10) s = tonum(i/10,s,n);
  224.     if (*n > 1) {
  225.         (*n)--;
  226.         *s++ = i%10+'0'; }
  227.     *s = '\000';
  228.     return(s);
  229. }
  230.  
  231. /* Create a string that describes a screen resolution                    */
  232.  
  233. static void makeresstr(int w,int h,int p,int f,char *s,int n)
  234. {
  235.     char    *ptr1 = "bit (";
  236.     char    *ptr2 = "Hz)           ";
  237.  
  238.     /* -> "NNNxNNNxNbit (NNHz)      "                                    */
  239.     s = tonum(w,s,&n);
  240.     if (n <= 1) goto eos; else { n--; *s++ = 'x'; }
  241.     s = tonum(h,s,&n);
  242.     if (n <= 1) goto eos; else { n--; *s++ = 'x'; }
  243.     s = tonum(p,s,&n);
  244.     while (*ptr1 && n-- > 1)
  245.         *s++ = *ptr1++;
  246.     if (n <= 1) goto eos;
  247.     s = tonum(f,s,&n);
  248.     while (*ptr2 && n-- > 1)
  249.         *s++ = *ptr2++;
  250. eos:
  251.     *s ='\000';
  252.     return;
  253. }
  254.  
  255. /* Initialize video registers                                            */
  256.  
  257. static void setvideo(void)
  258. {
  259. /*    RShift        = table[settings.n].Shift;        */    /***/
  260. /*    RSpShift    = table[settings.n].SpShift;    */    /***/
  261.     RWrap        = table[settings.n].Wrap;
  262.     RCO            = table[settings.n].CO;
  263. /*    RMode        = table[settings.n].Mode;        */    /***/
  264.     RHHT        = table[settings.n].HHT;
  265.     RHBB        = table[settings.n].HBB;
  266.     RHBE        = table[settings.n].HBE;
  267.     RHDB        = table[settings.n].HDB;
  268.     RHDE        = table[settings.n].HDE;
  269.     RHSS        = table[settings.n].HSS;
  270.     RHFS        = table[settings.n].HFS;
  271.     RHEE        = table[settings.n].HEE;
  272.     RVFT        = table[settings.n].VFT;
  273.     RVBB        = table[settings.n].VBB;
  274.     RVBE        = table[settings.n].VBE;
  275.     RVDB        = table[settings.n].VDB;
  276.     RVDE        = table[settings.n].VDE;
  277.     RVSS        = table[settings.n].VSS;
  278.     return;
  279. }
  280.  
  281. /* Patch (negative) line-A variables                                    */
  282.  
  283. static void patchos(void)
  284. {
  285.     void    *linea = LineA0();
  286.  
  287.     VPlanes     = settings.planes;    /* Patch a couple of LineA variables*/
  288.     VWrap        = (settings.width>>3)*settings.planes;
  289.     VGemX        = settings.width-1;    /* VGemX and VGemY are undocumented!*/
  290.     VGemY        = settings.height-1;
  291.     VCelMX        = (settings.width>>3)-1;
  292.     VCelMY        = settings.height/VCelHT-1;
  293.     VCelWR        = (settings.width>>3)*settings.planes*VCelHT;
  294.     VXMax        = settings.width;
  295.     VYMax        = settings.height;
  296.     VBytesLin    = (settings.width>>3)*settings.planes;
  297.     return;
  298. }
  299.  
  300. /* Reallocate new screen memory                                            */
  301.  
  302. static void realloc(void)
  303. {
  304.     long    scrsize,hz200;
  305.     void    *scraddr;
  306.  
  307.     scrsize = ((long)settings.width*(long)settings.height*
  308.               (long)settings.planes)>>3;
  309.     scraddr = Srealloc(scrsize);    /* Reallocate screen memory            */
  310.     Setscreen(scraddr,scraddr,-1,-1);/* Set new screen address            */
  311.     showlogo(48,48,scraddr,settings.width,settings.height,settings.planes);
  312.     for (hz200 = *(long *)0x4BA+130;/* wait 0.65 seconds                */
  313.          *(long *)0x4BA < hz200;);
  314.     hidelogo();
  315.     return;
  316. }
  317.  
  318. /* Initialize a new video mode                                            */
  319.  
  320. void init(int dorealloc)
  321. {
  322.     Cconws("\x1B""H");
  323.     patchos();
  324.     setvideo();
  325.     if (dorealloc)
  326.         realloc();
  327.     Cconws("\x1B""E");
  328.     return;
  329. }
  330.  
  331. /* Handle extended setscreen modes                                        */
  332.  
  333. long    setscreen(long rc,void *log,void *phys,int rez,int mode)
  334. {
  335.     if (rez == 3 && (mode & settings.mask) == settings.value)
  336.         init(!log && !phys);
  337.     return(rc);
  338. }
  339.  
  340. /* Replace 640x480x4bit with new video mode                                */
  341.  
  342. long    vsetmode(long rc,int mode)
  343. {
  344.     if ((mode & settings.mask) == settings.value)
  345.         init(0);
  346.     return(rc);
  347. }
  348.  
  349. /* Return new screen size                                                */
  350.  
  351. long    vgetsize(long rc,int mode)
  352. {
  353.     if ((mode & settings.mask) == settings.value)
  354.         return(((long)settings.width*(long)settings.height*
  355.                 (long)settings.planes)>>3);
  356.     return(rc);
  357. }
  358.  
  359. /* Get/set an entry from the system cookie jar                            */
  360.  
  361. static long    docookie(long cookie,long value)
  362. {
  363.     long    stack;
  364.     long    *cookiejar;
  365.  
  366.     stack = Super(0l);
  367.     cookiejar = *(long **)0x5a0;
  368.     if (cookiejar) {
  369.         while (*cookiejar && *cookiejar != cookie) cookiejar += 2;
  370.         if (*cookiejar == 0 && value != 0 &&
  371.             cookiejar - *(long **)0x5a0 < 2*cookiejar[1]) {
  372.             cookiejar[3] = cookiejar[1];
  373.             cookiejar[2] = 0;
  374.             cookiejar[1] = value;
  375.             cookiejar[0] = cookie; } }
  376.     Super((void *)stack);
  377.     return (cookiejar && *cookiejar == cookie ? cookiejar[1] : 0);
  378. }
  379.  
  380. /* Change preferences                                                    */
  381.  
  382. static void setup(void)
  383. {
  384.     char    s[22];
  385.     int        handle,oldn,mode,oldmode,frq;
  386.     long    scrsize,offset,stack;
  387.     unsigned long hz200,vbl;
  388.     void    *oldscr,*newscr;
  389.     struct {long magic;int size;} header;
  390.  
  391.     while (Cconis()) Cnecin();
  392.     if (settings.n < MINN || settings.n > MAXN)
  393.         settings.n = MINN-1;        /* FS is inactive                    */
  394.     Cconws("Press <SHIFT> for testing!\r\n");
  395.     oldn = settings.n;
  396.     for (;;) {
  397.         Cconws("\x1BY\x2C Current resolution: ");
  398.         settings.width = table[settings.n].width;
  399.         settings.height= table[settings.n].height;
  400.         settings.mask  = table[settings.n].mask;
  401.         settings.value = table[settings.n].value;
  402.         settings.planes= table[settings.n].planes;
  403.         makeresstr(settings.width,settings.height,
  404.                    settings.planes,table[settings.n].frq,s,21);
  405.         Cconws(s);
  406.         Cconws("(+/-)");
  407.         scrsize = ((long)settings.width*(long)settings.height*
  408.                    (long)settings.planes)>>3;
  409.         newscr = Malloc(scrsize);
  410.         oldscr = Physbase();
  411.         for (mode = oldmode = Vsetmode(-1);!Cconis() || !mode;)
  412.             if ((Kbshift(-1) & 3) && !Cconis()) {
  413.                 if (mode && newscr) {
  414.                     mode = 0;
  415.                     Setscreen(newscr,newscr,3,0x0010|settings.value);
  416.                     stack = Super(0L);
  417.                     setvideo();
  418.                     showlogo(48,48,newscr,settings.width,
  419.                              settings.height,settings.planes);
  420.                                      /* measure refresh rate, while user */
  421.                                      /* views the screen                    */
  422.                     vbl = *(unsigned long *)0x462;
  423.                     hz200 = *(unsigned long *)0x4ba;
  424.                     Super((void *)stack); } }
  425.             else
  426.                 if (!mode) {
  427.                     stack = Super(0L);
  428.                     hz200 = *(unsigned long *)0x4ba - hz200;
  429.                     vbl = *(unsigned long *)0x462 - vbl;
  430.                     Super((void *)stack);
  431.                                     /* calculate "real" refresh rate    */
  432.                     frq = (int)((vbl*2000L+5)/hz200)/10;
  433.                     mode = oldmode;
  434.                     hidelogo();
  435.                     Setscreen(newscr,newscr,3,oldmode);
  436.                     Setscreen(oldscr,oldscr,-1,-1);
  437.                                     /* check for plausibility            */
  438.                     if ((frq - table[settings.n].frq) > -20 &&
  439.                         (frq - table[settings.n].frq) <  20 &&
  440.                         vbl > 20) {
  441.                         table[settings.n].frq = frq;
  442.                         makeresstr(settings.width,settings.height,
  443.                                    settings.planes,frq,s,21);
  444.                         Cconws("\x1BY\x2C Current resolution: ");
  445.                         Cconws(s);
  446.                         Cconws("(+/-)"); } }
  447.         Mfree(newscr);
  448.         switch ((char)Cnecin()) {    /* In/decrease resolution            */
  449.             case '+':
  450.                 if (settings.n < MAXN) settings.n++;
  451.                 break;
  452.             case '-':
  453.                 if (settings.n >= MINN) settings.n--;
  454.                 break;
  455.             default:
  456.                 goto eol; } }
  457. eol:                                /* Patch the executeable file        */
  458.     Cconws("\x1BY\x2C \x1BK");
  459.     if (oldn != settings.n) {
  460.         Cconws("S(ave settings, C(ontinue...\r\n");
  461.         if (((char)Cnecin() & 0xDF) == 'S') {
  462.             if ((handle = (int)Fopen(PRGNAME,2)) < 0 &&
  463.                 (handle = (int)Fopen("AUTO\\"PRGNAME,2)) < 0) {
  464.                 Cconws("Cannot open FS.PRG!\r\n");
  465.                 Cnecin();
  466.                 goto ferr; }
  467.             Fseek(0x1E,handle,0);    /* Find patch area and check for    */
  468.             Fread(handle,4,&offset);/* magic first!                        */
  469.             Fseek(0x1C+offset,handle,0);
  470.             Fread(handle,6,&header);
  471.             if (header.magic != ID || header.size != sizeof(settings)) {
  472.                 Cconws("Illegal file format!\r\n");
  473.                 Cnecin(); }
  474.             else if (Fwrite(handle,sizeof(settings)-6,
  475.                      ((char *)&settings)+6) != sizeof(settings)-6) {
  476.                 Cconws("Could not write to FS.PRG!\r\n");
  477.                 Cnecin(); }
  478.             Fclose(handle); } }
  479. ferr:
  480.     return;
  481. }
  482.  
  483. /* Main program: check video hardware and allow change of preferences    */
  484.  
  485. int main(void)
  486. {
  487.     int                rc = 0;
  488.     struct settings *ptr;
  489.  
  490.     if ((ptr = (struct settings *)docookie(ID,0)) != 0) {
  491.         Cconws("\x1B""E");
  492.         Cconws(copyright);
  493.         Cconws("FalconScreen is already installed...\r\n");
  494.         if (ptr->size == settings.size) {
  495.             settings = *ptr;
  496.             setup();
  497.             *ptr = settings; }
  498.         Pterm0(); }
  499.     if (docookie('_VDO',0) != 0x00030000L || Montype() != 2) {
  500.         Cconws(copyright);
  501.         Cconws("\x1BpYou need a Falcon030 & SVGA-monitor \x1Bq\x07"
  502.                "\r\n\r\n");
  503.         Pterm0(); }
  504.     settings.width = table[settings.n].width;
  505.     settings.height= table[settings.n].height;
  506.     settings.mask  = table[settings.n].mask;
  507.     settings.value = table[settings.n].value;
  508.     settings.planes= table[settings.n].planes;
  509.     if ((Cconis() && (Cnecin() & 0xDF) == 'S') ||
  510.         settings.n < MINN || settings.n > MAXN) {
  511.         Cconws("\x1B""E");
  512.         Cconws(copyright);
  513.         Cconws("Press 'S' for setup...\r\n");
  514.         setup(); }
  515.     else {
  516.         Cconws(copyright);
  517.         Cconws("Press 'S' for setup...\r\n"); }
  518.     Cconws("\r\n");
  519.     if (settings.n < MINN || settings.n > MAXN ||
  520.         table[settings.n].planes != table[settings.n-1].planes)
  521.         Pterm0();
  522.     if ((Vsetmode(-1) & settings.mask) == settings.value) {
  523.         if (docookie('MiNT',0)) {
  524.             Cconws("You cannot replace your boot resolution\r\n"
  525.                    "when running MiNT! Either choose a different\r\n"
  526.                    "initial boot resolution (BOOTCONF.PRG) or\r\n"
  527.                    "start FS before starting MiNT!\r\n");
  528.             Pterm0(); }
  529.         rc = 1; }
  530.     docookie(ID,(long)&settings);
  531.     return(rc);
  532. }
  533.