improved automake config. make dist, VPATH builds, ...
[btb/d2x.git] / unused / vga / framebuf.c
1 /*
2 THE COMPUTER CODE CONTAINED HEREIN IS THE SOLE PROPERTY OF PARALLAX
3 SOFTWARE CORPORATION ("PARALLAX").  PARALLAX, IN DISTRIBUTING THE CODE TO
4 END-USERS, AND SUBJECT TO ALL OF THE TERMS AND CONDITIONS HEREIN, GRANTS A
5 ROYALTY-FREE, PERPETUAL LICENSE TO SUCH END-USERS FOR USE BY SUCH END-USERS
6 IN USING, DISPLAYING,  AND CREATING DERIVATIVE WORKS THEREOF, SO LONG AS
7 SUCH USE, DISPLAY OR CREATION IS FOR NON-COMMERCIAL, ROYALTY OR REVENUE
8 FREE PURPOSES.  IN NO EVENT SHALL THE END-USER USE THE COMPUTER CODE
9 CONTAINED HEREIN FOR REVENUE-BEARING PURPOSES.  THE END-USER UNDERSTANDS
10 AND AGREES TO THE TERMS HEREIN AND ACCEPTS THE SAME BY USE OF THIS FILE.  
11 COPYRIGHT 1993-1999 PARALLAX SOFTWARE CORPORATION.  ALL RIGHTS RESERVED.
12 */
13
14 char framebuf_rcsid[] = "$Id: framebuf.c,v 1.1.1.1 2001-01-19 03:30:15 bradleyb Exp $";
15
16 #include <dos.h>
17 #include <string.h>
18 #include <stdlib.h>
19 #include <stdio.h>
20 #include <i86.h>
21 #include <dos.h>
22 #include "mono.h"
23
24
25 #include "fxdpmi.h"
26 #include "fxvesa.h"
27
28 #define DPMI_INTERRUPT 0x31
29 const VIDEO_INTERRUPT = 0x10;
30
31 typedef struct
32 {
33   short   ModeAttributes;         /* Mode attributes                  */
34   char    WinAAttributes;         /* Window A attributes              */
35   char    WinBAttributes;         /* Window B attributes              */
36   short   WinGranularity;         /* Window granularity in k          */
37   short   WinSize;                /* Window size in k                 */
38   short   WinASegment;            /* Window A segment                 */
39   short   WinBSegment;            /* Window B segment                 */
40   void   *WinFuncPtr;             /* Pointer to window function       */
41   short   BytesPerScanLine;       /* Bytes per scanline               */
42   short   XResolution;            /* Horizontal resolution            */
43   short   YResolution;            /* Vertical resolution              */
44   char    XCharSize;              /* Character cell width             */
45   char    YCharSize;              /* Character cell height            */
46   char    NumberOfPlanes;         /* Number of memory planes          */
47   char    BitsPerPixel;           /* Bits per pixel                   */
48   char    NumberOfBanks;          /* Number of CGA style banks        */
49   char    MemoryModel;            /* Memory model type                */
50   char    BankSize;               /* Size of CGA style banks          */
51   char    NumberOfImagePages;     /* Number of images pages           */
52   char    res1;                   /* Reserved                         */
53   char    RedMaskSize;            /* Size of direct color red mask    */
54   char    RedFieldPosition;       /* Bit posn of lsb of red mask      */
55   char    GreenMaskSize;          /* Size of direct color green mask  */
56   char    GreenFieldPosition;     /* Bit posn of lsb of green mask    */
57   char    BlueMaskSize;           /* Size of direct color blue mask   */
58   char    BlueFieldPosition;      /* Bit posn of lsb of blue mask     */
59   char    RsvdMaskSize;           /* Size of direct color res mask    */
60   char    RsvdFieldPosition;      /* Bit posn of lsb of res mask      */
61   char    DirectColorModeInfo;    /* Direct color mode attributes     */
62   FxU32   PhysBasePtr;            /* Physical address of lfb          */
63   FxU32   OffScreenMemOffset;
64   FxU32   OffScreenMemSize;
65   char    res2[206];              /* Pad to 256 byte block size       */
66 } ModeInfoBlock;
67
68
69 void VesaMain()
70 {
71    FxU16     mode = 0x111;
72    VesaErr_t error;
73
74    if ( ( error = VesaInit( mode ) ) != VESA_ERR_NONE )
75    {
76       printf( "VesaInit failed with error '%s'\n", VesaGetErrorString( error ) );
77       exit( 1 );
78    }
79    else
80    {
81                 char *MyPtr;
82                 MyPtr=(char *)VesaGetPtr();     
83                   memset( (MyPtr+((rand()%0x10000)<<4)+rand()%0x10000),rand()%256, 1 );
84    }
85
86    VesaEnd();
87 }
88
89 /*
90 ** DpmiMapPhysicalToLinear
91 */
92 FxU32 DpmiMapPhysicalToLinear( FxU32 paddr, FxU32 length )
93 {
94    FxU32      laddr;
95    union REGS r;
96
97    /*
98    ** DPMI function 0x800
99    */
100    r.w.ax = 0x800;
101
102    /*
103    ** BX:CX = physical address
104    ** SI:DI = length
105    */
106    r.w.bx = ( FxU16 ) ( paddr >> 16 );
107    r.w.cx = ( FxU16 ) ( paddr & 0x0000FFFF );
108    r.w.si = ( FxU16 ) ( length >> 16 );
109    r.w.di = ( FxU16 ) ( length & 0x0000FFFF );
110    int386( DPMI_INTERRUPT, &r, &r );
111
112    /*
113    ** if cflag set then an error occured
114    */
115    if ( r.w.cflag )
116    {
117       laddr = 0;
118    }
119    else
120    {
121       laddr = r.w.bx;
122       laddr <<= 16;
123       laddr |= r.w.cx;
124    }
125    return laddr;
126 }
127
128 /*
129 ** DpmiAllocDosMem
130 */
131 void *DpmiAllocDosMem( FxU16 size, DpmiSelector_t *pSel )
132 {
133    union REGS  r;
134    void       *ptr;
135    FxU32       seg;
136
137    /*
138    ** AX = DPMI function 0x100
139    */
140    r.w.ax = 0x100;
141
142    /*
143    ** BX = # of paragraphs to allocate
144    */
145    r.w.bx = ( FxI16 ) ( size / 16 + 1 );
146
147    int386( DPMI_INTERRUPT, &r, &r );
148
149    if ( r.w.cflag )
150    {
151       ptr = 0;
152    }
153    else
154    {
155       seg  = r.w.ax;
156      *pSel = r.w.dx;
157
158       ptr = ( void * ) ( seg << 4 );
159    }
160
161    return ptr;
162 }
163
164 /*
165 ** DpmiFreeDosMem
166 */
167 FxBool DpmiFreeDosMem( DpmiSelector_t sel )
168 {
169   union REGS r;
170
171   r.w.ax = 0x101;
172   r.w.bx = sel;
173   int386( DPMI_INTERRUPT, &r, &r );
174
175   if ( r.w.cflag )
176      return FXFALSE;
177   else
178      return FXTRUE;
179 }
180
181 DpmiRMI       RMI;
182 ModeInfoBlock infoblock;
183
184 static void *vesa_lfb_ptr;
185
186 static void VesaGetModeInfo( int mode, ModeInfoBlock *infoblock )
187 {
188   union REGS           r;
189   struct SREGS        sr;
190   DpmiSelector_t   infosel;
191   unsigned short infoseg;
192   ModeInfoBlock *far_infoblock;
193
194   /*
195   ** Allocate some real-mode DOS memory using DPMI function 0x100
196   */
197   far_infoblock = ( ModeInfoBlock * ) DpmiAllocDosMem( sizeof( ModeInfoBlock ), &infosel );
198   infoseg = ( unsigned short ) ( ( ( unsigned long ) far_infoblock ) >> 4 );
199
200   /*
201   ** Get VESA SVGA info block by executing real-mode interrupt
202   ** 0x10, function 0x4F01.  This must be done using DPMI service
203   ** 0x300 since DOS4GW doesn't automatically thunk pointers down
204   ** for VESA functions.
205   */
206   memset( &RMI, 0, sizeof( RMI ) );
207   RMI.EAX = 0x4F01;        // Function 0x4F01
208   RMI.ECX = mode;          //
209   RMI.ES  = infoseg;       // ES:DI -> pointer to real mode buffer
210   RMI.EDI = 0;
211
212   r.x.eax = 0x0300;           // DPMI service "execute real mode interrupt"
213   r.x.ebx = VIDEO_INTERRUPT;  // BL = function to execute
214   r.x.ecx = 0;                // CX = 0
215   segread( &sr );
216   sr.es   = FP_SEG( &RMI );   // ES:EDI -> buffer to RMI struct
217   r.x.edi = FP_OFF( &RMI );
218
219   #define DPMI_INTERRUPT 0x31
220
221   int386x( DPMI_INTERRUPT, &r, &r, &sr );
222
223   /*
224   ** Copy realmode buffer into protected mode buffer
225   */
226   memcpy( infoblock, far_infoblock, sizeof( ModeInfoBlock ) );
227
228   /*
229   ** Free up the memory
230   */
231   DpmiFreeDosMem( infosel );
232 }
233
234 int VesaGetRowSize (int mode)
235  {
236   ModeInfoBlock mi;
237
238   VesaGetModeInfo (mode,&mi);
239   return (mi.BytesPerScanLine);
240  }
241
242 extern int FindArg(char *);
243 /*
244 ** VesaInit
245 **
246 ** VESA initialization function.  Returns a pointer to the
247 ** linear frame buffer.
248 */
249 int VesaInit( int mode )
250 {
251   union REGS r;
252
253
254   if (!FindArg ("-ForceVesa"))
255         return(0);              
256         
257   /*
258   ** Get VESA mode information
259   */
260   VesaGetModeInfo( mode, &infoblock );
261
262   /*
263   ** Check mode information stuff
264   */
265   if ( !( infoblock.ModeAttributes & 0x1 ) ||
266        !( infoblock.ModeAttributes & 0x80 ) )
267   {
268                 mprintf ((0,"mode %x is not supported!\n",mode));
269      return 0;
270   }
271
272   /*
273   ** Get a pointer to the linear frame buffer
274   */
275   if ( ( vesa_lfb_ptr = ( void * ) DpmiMapPhysicalToLinear( infoblock.PhysBasePtr, 0x400000 - 1 ) ) == 0 )
276   {
277                 mprintf ((0,"mode %x mapping not supported!\n",mode));
278                 
279      return 0;
280   }
281
282   /*
283   ** Set the video mode
284   */
285   r.w.ax = 0x4F02;
286   r.w.bx = ( short ) ( mode | 0x4000 );
287   int386( VIDEO_INTERRUPT, &r, &r );
288
289   if ( r.w.ax != 0x004F )
290   {
291      VesaEnd();
292                 mprintf ((0,"mode %x  not set!\n",mode));
293           
294      return 0;
295   }
296         mprintf ((0,"No errors! mode %x is go!\n",mode));
297   return 1;
298 }
299
300 /*
301 ** VesaEnd
302 */
303 void VesaEnd( void )
304 {
305    union REGS r;
306
307    r.w.ax = 0x3;
308    int386( VIDEO_INTERRUPT, &r, &r );
309 }
310
311 /*
312 ** VesaGetPtr
313 */
314 void *VesaGetPtr( void )
315 {
316    return vesa_lfb_ptr;
317 }
318
319 static const char *vesa_errors[] =
320 {
321    "VESA_ERR_NONE",
322    "VESA_ERR_DPMI_MAPPING_FAILED",
323    "VESA_ERR_MODE_NOT_SUPPORTED",
324    "VESA_ERR_MODE_NOT_SET"
325 };
326
327 /*
328 ** VesaGetErrorString
329 */
330 const char *VesaGetErrorString( VesaErr_t err )
331 {
332    return vesa_errors[err];
333 }
334