rw_svgalib.c 6.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312
  1. /*
  2. ** RW_SVGALBI.C
  3. **
  4. ** This file contains ALL Linux specific stuff having to do with the
  5. ** software refresh. When a port is being made the following functions
  6. ** must be implemented by the port:
  7. **
  8. ** SWimp_EndFrame
  9. ** SWimp_Init
  10. ** SWimp_InitGraphics
  11. ** SWimp_SetPalette
  12. ** SWimp_Shutdown
  13. ** SWimp_SwitchFullscreen
  14. */
  15. #include <termios.h>
  16. #include <sys/ioctl.h>
  17. #include <sys/stat.h>
  18. #include <sys/vt.h>
  19. #include <stdarg.h>
  20. #include <stdio.h>
  21. #include <signal.h>
  22. #include <sys/mman.h>
  23. #include <asm/io.h>
  24. #include "vga.h"
  25. #include "vgakeyboard.h"
  26. #include "vgamouse.h"
  27. #include "../ref_soft/r_local.h"
  28. #include "../client/keys.h"
  29. #include "../linux/rw_linux.h"
  30. /*****************************************************************************/
  31. int VGA_width, VGA_height, VGA_rowbytes, VGA_bufferrowbytes, VGA_planar;
  32. byte *VGA_pagebase;
  33. char *framebuffer_ptr;
  34. void VGA_UpdatePlanarScreen (void *srcbuffer);
  35. int num_modes;
  36. vga_modeinfo *modes;
  37. int current_mode;
  38. // Console variables that we need to access from this module
  39. /*****************************************************************************/
  40. void VID_InitModes(void)
  41. {
  42. int i;
  43. // get complete information on all modes
  44. num_modes = vga_lastmodenumber()+1;
  45. modes = malloc(num_modes * sizeof(vga_modeinfo));
  46. for (i=0 ; i<num_modes ; i++)
  47. {
  48. if (vga_hasmode(i))
  49. memcpy(&modes[i], vga_getmodeinfo(i), sizeof (vga_modeinfo));
  50. else
  51. modes[i].width = 0; // means not available
  52. }
  53. // filter for modes i don't support
  54. for (i=0 ; i<num_modes ; i++)
  55. {
  56. if (modes[i].bytesperpixel != 1 && modes[i].colors != 256)
  57. modes[i].width = 0;
  58. }
  59. for (i = 0; i < num_modes; i++)
  60. if (modes[i].width)
  61. ri.Con_Printf(PRINT_ALL, "mode %d: %d %d\n", modes[i].width, modes[i].height);
  62. }
  63. /*
  64. ** SWimp_Init
  65. **
  66. ** This routine is responsible for initializing the implementation
  67. ** specific stuff in a software rendering subsystem.
  68. */
  69. int SWimp_Init( void *hInstance, void *wndProc )
  70. {
  71. vga_init();
  72. VID_InitModes();
  73. return true;
  74. }
  75. int get_mode(int width, int height)
  76. {
  77. int i;
  78. int ok, match;
  79. for (i=0 ; i<num_modes ; i++)
  80. if (modes[i].width &&
  81. modes[i].width == width && modes[i].height == height)
  82. break;
  83. if (i==num_modes)
  84. return -1; // not found
  85. return i;
  86. }
  87. /*
  88. ** SWimp_InitGraphics
  89. **
  90. ** This initializes the software refresh's implementation specific
  91. ** graphics subsystem. In the case of Windows it creates DIB or
  92. ** DDRAW surfaces.
  93. **
  94. ** The necessary width and height parameters are grabbed from
  95. ** vid.width and vid.height.
  96. */
  97. static qboolean SWimp_InitGraphics( qboolean fullscreen )
  98. {
  99. int bsize, zsize, tsize;
  100. SWimp_Shutdown();
  101. current_mode = get_mode(vid.width, vid.height);
  102. if (current_mode < 0) {
  103. ri.Con_Printf (PRINT_ALL, "Mode %d %d not found\n", vid.width, vid.height);
  104. return false; // mode not found
  105. }
  106. // let the sound and input subsystems know about the new window
  107. ri.Vid_NewWindow (vid.width, vid.height);
  108. ri.Con_Printf (PRINT_ALL, "Setting VGAMode: %d\n", current_mode );
  109. // Cvar_SetValue ("vid_mode", (float)modenum);
  110. VGA_width = modes[current_mode].width;
  111. VGA_height = modes[current_mode].height;
  112. VGA_planar = modes[current_mode].bytesperpixel == 0;
  113. VGA_rowbytes = modes[current_mode].linewidth;
  114. vid.rowbytes = modes[current_mode].linewidth;
  115. if (VGA_planar) {
  116. VGA_bufferrowbytes = modes[current_mode].linewidth * 4;
  117. vid.rowbytes = modes[current_mode].linewidth*4;
  118. }
  119. // get goin'
  120. vga_setmode(current_mode);
  121. VGA_pagebase = framebuffer_ptr = (char *) vga_getgraphmem();
  122. // if (vga_setlinearaddressing()>0)
  123. // framebuffer_ptr = (char *) vga_getgraphmem();
  124. if (!framebuffer_ptr)
  125. Sys_Error("This mode isn't hapnin'\n");
  126. vga_setpage(0);
  127. vid.buffer = malloc(vid.rowbytes * vid.height);
  128. if (!vid.buffer)
  129. Sys_Error("Unabled to alloc vid.buffer!\n");
  130. return true;
  131. }
  132. /*
  133. ** SWimp_EndFrame
  134. **
  135. ** This does an implementation specific copy from the backbuffer to the
  136. ** front buffer. In the Win32 case it uses BitBlt or BltFast depending
  137. ** on whether we're using DIB sections/GDI or DDRAW.
  138. */
  139. void SWimp_EndFrame (void)
  140. {
  141. if (!vga_oktowrite())
  142. return; // can't update screen if it's not active
  143. // if (vid_waitforrefresh.value)
  144. // vga_waitretrace();
  145. if (VGA_planar)
  146. VGA_UpdatePlanarScreen (vid.buffer);
  147. else {
  148. int total = vid.rowbytes * vid.height;
  149. int offset;
  150. for (offset=0;offset<total;offset+=0x10000) {
  151. vga_setpage(offset/0x10000);
  152. memcpy(framebuffer_ptr,
  153. vid.buffer + offset,
  154. ((total-offset>0x10000)?0x10000:(total-offset)));
  155. }
  156. }
  157. }
  158. /*
  159. ** SWimp_SetMode
  160. */
  161. rserr_t SWimp_SetMode( int *pwidth, int *pheight, int mode, qboolean fullscreen )
  162. {
  163. rserr_t retval = rserr_ok;
  164. ri.Con_Printf (PRINT_ALL, "setting mode %d:", mode );
  165. if ( !ri.Vid_GetModeInfo( pwidth, pheight, mode ) )
  166. {
  167. ri.Con_Printf( PRINT_ALL, " invalid mode\n" );
  168. return rserr_invalid_mode;
  169. }
  170. ri.Con_Printf( PRINT_ALL, " %d %d\n", *pwidth, *pheight);
  171. if ( !SWimp_InitGraphics( false ) ) {
  172. // failed to set a valid mode in windowed mode
  173. return rserr_invalid_mode;
  174. }
  175. R_GammaCorrectAndSetPalette( ( const unsigned char * ) d_8to24table );
  176. return retval;
  177. }
  178. /*
  179. ** SWimp_SetPalette
  180. **
  181. ** System specific palette setting routine. A NULL palette means
  182. ** to use the existing palette. The palette is expected to be in
  183. ** a padded 4-byte xRGB format.
  184. */
  185. void SWimp_SetPalette( const unsigned char *palette )
  186. {
  187. static int tmppal[256*3];
  188. const unsigned char *pal;
  189. int *tp;
  190. int i;
  191. if ( !palette )
  192. palette = ( const unsigned char * ) sw_state.currentpalette;
  193. if (vga_getcolors() == 256)
  194. {
  195. tp = tmppal;
  196. pal = palette;
  197. for (i=0 ; i < 256 ; i++, pal += 4, tp += 3) {
  198. tp[0] = pal[0] >> 2;
  199. tp[1] = pal[1] >> 2;
  200. tp[2] = pal[2] >> 2;
  201. }
  202. if (vga_oktowrite())
  203. vga_setpalvec(0, 256, tmppal);
  204. }
  205. }
  206. /*
  207. ** SWimp_Shutdown
  208. **
  209. ** System specific graphics subsystem shutdown routine. Destroys
  210. ** DIBs or DDRAW surfaces as appropriate.
  211. */
  212. void SWimp_Shutdown( void )
  213. {
  214. if (vid.buffer) {
  215. free(vid.buffer);
  216. vid.buffer = NULL;
  217. }
  218. vga_setmode(TEXT);
  219. }
  220. /*
  221. ** SWimp_AppActivate
  222. */
  223. void SWimp_AppActivate( qboolean active )
  224. {
  225. }
  226. //===============================================================================
  227. /*
  228. ================
  229. Sys_MakeCodeWriteable
  230. ================
  231. */
  232. void Sys_MakeCodeWriteable (unsigned long startaddr, unsigned long length)
  233. {
  234. int r;
  235. unsigned long addr;
  236. int psize = getpagesize();
  237. addr = (startaddr & ~(psize-1)) - psize;
  238. // fprintf(stderr, "writable code %lx(%lx)-%lx, length=%lx\n", startaddr,
  239. // addr, startaddr+length, length);
  240. r = mprotect((char*)addr, length + startaddr - addr + psize, 7);
  241. if (r < 0)
  242. Sys_Error("Protection change failed\n");
  243. }