home *** CD-ROM | disk | FTP | other *** search
/ io Programmo 23 / IOPROG_23.ISO / SOFT / RAYCAST.ZIP / SCRCNTL.CPP < prev    next >
Encoding:
C/C++ Source or Header  |  1995-10-25  |  10.2 KB  |  389 lines

  1. /****************************************
  2. scrcntl.cpp- a module to provide a layer of abstraction
  3. between the OS graphics architecture and the application
  4. It provides you the programmer with the ability to create offscreen
  5. buffers, whose drawing surfaces you have direct access to, which 
  6. blit to the screen across operating systems. To change the
  7. destination operating system, simply change the file os.h
  8. Also requires the file palcntl.cpp to load palettes in the bitmaps
  9. A routine called App_Make_New_Screen must be in another source file. It
  10. should perform any work that must be done for the app to run in the
  11. new screen size
  12. *****************************************/
  13.  
  14. #include "os.h"
  15. #include "scrcntl.h"
  16. #include "buffnode.h"
  17. #include "memutil.h"
  18. #include "scconint.h"
  19. #include "palette.h"
  20. #include <mem.h>
  21.  
  22. #ifdef OS_WINDOWS
  23. #include "wingdll.h"
  24. #endif
  25.  
  26. pbuffer_node buffer_list=NULL;
  27. screen_ptr cur_screen_ptr;
  28. void App_Make_New_Screen();
  29.  
  30. #ifdef OS_DOS
  31.  
  32. #define VGA_WIDTH 320
  33. #define VGA_HEIGHT 200
  34. #define SVGA_WIDTH 640
  35. #define SVGA_HEIGHT 480
  36.  
  37. #include "vesa.h"
  38. #include "screen.h"
  39.  
  40. void Screen_Copy(long offset, void * src, long ncopy);
  41.  
  42. BOOL super_vga;
  43. void Attempt_Screen_Open(short & width, short & height)
  44. {
  45.     if ( (width>VGA_WIDTH) || (height>VGA_HEIGHT) ) {
  46.         // must load a super vga screen to get requested dimensions
  47.         VBE_detect();
  48.         if (VESA_InitGraphics(width, height)) {
  49.             // no svga so load vga dimensions
  50.             setgmode(0x13);
  51.             super_vga=FALSE;
  52.             width=VGA_WIDTH;
  53.             height=VGA_HEIGHT;
  54.         } else {
  55.             super_vga=TRUE;
  56.         }
  57.     } else {
  58.         super_vga=FALSE;
  59.         setgmode(0x13);
  60.         width=VGA_WIDTH;
  61.         height=VGA_HEIGHT;
  62.     }
  63. }
  64.  
  65. void Screen_Copy(long offset, void * src, long ncopy) {
  66.  
  67. if (cur_screen_ptr==NULL) {
  68.     if (super_vga) {
  69.         VESA_ScreenCopy(offset, src, ncopy);
  70.     } else {
  71.         memcpy(screen+offset, src, ncopy);
  72.     } /* endif */
  73. } else {
  74.     memcpy(cur_screen_ptr+offset, src, ncopy);
  75. }
  76.  
  77. }
  78.  
  79. #endif
  80.  
  81. #ifdef OS_WINDOWS
  82. HBITMAP cur_hbitmap=NULL;
  83. short stretch_factor=1;
  84.  
  85. typedef struct MY_BITMAP_HEADER
  86. {
  87.     BITMAPINFOHEADER Header;
  88.     RGBQUAD aColors[256];
  89. } my_bitmap_header;
  90.  
  91. my_bitmap_header os_header;
  92.  
  93. HBITMAP old_mono_bitmap;
  94. HDC off_screen_DC;
  95. WinGdll WinG;
  96. #endif
  97.  
  98. void Allocate_Offscreen_Buffer(poff_screen_buff new_buff) {
  99.  
  100. #ifdef OS_DOS
  101.     // allocate the off screen buffer manually
  102.     (*(new_buff->buff_ptr_address))=(video_data_ptr)NewPtr(
  103.           Get_Phys_Screen_Width() * Get_Phys_Screen_Height());
  104. #endif
  105.  
  106. #ifdef OS_WINDOWS
  107.     // copy palette to buffer header
  108.     // this is done now in case you want to load different palettes for each buffer
  109.     // the currently loaded is made the buffer's palette. You don't have to do this
  110.     // in dos because dos bitmaps have no palettes. To keep the bitmap's palette equal to
  111.     // the loaded palette, you must call Change_Screen.
  112.  
  113.     for (short color_index=0; color_index< PALETTE_COLORS; color_index++) {
  114.         os_header.aColors[color_index].rgbRed=Get_Palette_Red_Val(color_index);
  115.         os_header.aColors[color_index].rgbGreen=Get_Palette_Green_Val(color_index);
  116.         os_header.aColors[color_index].rgbBlue=Get_Palette_Blue_Val(color_index);
  117.         os_header.aColors[color_index].rgbReserved=0;
  118.     }
  119.  
  120.     // create the bitmap handle in the WinGDC
  121.     new_buff->hbitmap=WinG.pCreateBitmap(off_screen_DC, (BITMAPINFO *)&os_header, 
  122.           (PVOID *)new_buff->buff_ptr_address);    
  123. #endif
  124.  
  125. }
  126.  
  127. void Delete_Offscreen_Buffer(poff_screen_buff delete_buff) {
  128.  
  129. #ifdef OS_DOS
  130.   DelPtr( (*(delete_buff->buff_ptr_address)));
  131. #endif
  132.  
  133. #ifdef OS_WINDOWS
  134.     if (cur_hbitmap==delete_buff->hbitmap) {
  135.         SelectObject(off_screen_DC, old_mono_bitmap);
  136.         cur_hbitmap=old_mono_bitmap;
  137.     }
  138.     DeleteObject(delete_buff->hbitmap);
  139. #endif
  140.  
  141. }
  142.  
  143. poff_screen_buff Create_Offscreen_Buffer(video_data_ptr * buff_ptr_address)
  144. {
  145.     // make a new off_screen_buff structure
  146.     poff_screen_buff new_buff=(poff_screen_buff)NewPtr(sizeof(off_screen_buff));
  147.     new_buff->buff_ptr_address=buff_ptr_address;
  148.  
  149.     // just what is says
  150.     Allocate_Offscreen_Buffer(new_buff);
  151.  
  152. // put the new buffer in the list of buffers
  153. pbuffer_node new_buff_node=BN_Create_Node();
  154. BN_Set_Data(new_buff_node, new_buff);
  155. BN_Set_Next_Node(new_buff_node, buffer_list);
  156. BN_Set_Node(buffer_list, new_buff_node);
  157.  
  158. return new_buff;
  159. }
  160.  
  161. void Dispose_Buffer(poff_screen_buff os_buffer) {
  162.     pbuffer_node cur_node, next_node;
  163.     BOOL found;
  164.  
  165.     // are we dealing with and empty list, if so the node does not exist
  166.     if (BN_Empty_Node(buffer_list)) {
  167.         return;
  168.     }
  169.  
  170.     // if node is the start of list, update list and delete node
  171.     if (BN_Get_Data(buffer_list)==os_buffer) {
  172.         BN_Set_Node(next_node, BN_Get_Next_Node(buffer_list));
  173.         Delete_Offscreen_Buffer(BN_Get_Data(buffer_list));
  174.         BN_Delete_Node(buffer_list);
  175.         BN_Set_Node(buffer_list, next_node);
  176.         return;
  177.     }
  178.  
  179.     // find the node to be deleted
  180.     BN_Set_Node(cur_node, buffer_list);
  181.     found=FALSE;
  182.     while (!BN_Empty_Node(BN_Get_Next_Node(cur_node))) {
  183.         if (BN_Get_Data(BN_Get_Next_Node(cur_node))==os_buffer) {
  184.             found=TRUE;
  185.             break;
  186.         }
  187.         BN_Set_Node(cur_node, BN_Get_Next_Node(cur_node));
  188.     } /* endwhile */
  189.  
  190.     // Remove the node from list and delete it
  191.     if (found) {
  192.         BN_Set_Node(next_node, BN_Get_Next_Node(BN_Get_Next_Node(cur_node)));
  193.         Delete_Offscreen_Buffer(BN_Get_Data(BN_Get_Next_Node(cur_node)));
  194.         BN_Delete_Node(BN_Get_Next_Node(cur_node));
  195.         BN_Set_Next_Node(cur_node, next_node);
  196.     }
  197. }
  198.  
  199. extern "C" short LOGICAL_SCREEN_HEIGHT; // stores without screen orientation
  200. extern "C" short LOGICAL_SCREEN_WIDTH; // same for width
  201.  
  202. void Activate_Graphics() {
  203. #ifdef OS_DOS
  204.     Attempt_Screen_Open(LOGICAL_SCREEN_WIDTH,  LOGICAL_SCREEN_HEIGHT);    
  205. #endif
  206. }
  207.  
  208. void Init_Screen(short width, short height) {
  209.  
  210.     short valid_width=((width+3)/4)*4; // bitmap should be 32 bits wide, so width must
  211.       // be a multiple of 4
  212.     short valid_height=height;
  213.  
  214. #ifdef OS_DOS
  215.     Init_Phys_Screen(valid_width, valid_height);
  216. #endif
  217.  
  218. #ifdef OS_WINDOWS
  219. if (!WinG.Load()) { //link to WinG DLL.
  220.     MessageBox(0,"Can't find WING32.DLL","WTWIN Error!",MB_OK);
  221.     return;
  222. }
  223. Init_Phys_Screen(valid_width, valid_height);
  224. if(WinG.pRecommendDIBFormat((BITMAPINFO *)&os_header)) {
  225.     //  make sure it's 8bpp and remember the orientation
  226.  
  227.     os_header.Header.biBitCount = 8;
  228.     os_header.Header.biCompression = BI_RGB;
  229.     Set_Phys_Orientation(os_header.Header.biHeight*(-1));
  230. } else {
  231.     //  set it up ourselves
  232.  
  233.     os_header.Header.biSize = sizeof(BITMAPINFOHEADER);
  234.     os_header.Header.biPlanes = 1;
  235.     os_header.Header.biBitCount = 8;
  236.     os_header.Header.biCompression = BI_RGB;
  237.     os_header.Header.biSizeImage = 0;
  238.     os_header.Header.biClrUsed = 0;
  239.     os_header.Header.biClrImportant = 0;
  240. }
  241.  
  242. os_header.Header.biWidth=Get_Phys_Screen_Width();
  243. os_header.Header.biHeight=Get_Phys_Screen_Height()*Get_Phys_Orientation() * (-1);
  244.  
  245. off_screen_DC=WinG.pCreateDC();
  246.  
  247. old_mono_bitmap=(HBITMAP)GetCurrentObject(off_screen_DC, OBJ_BITMAP);
  248. cur_hbitmap=old_mono_bitmap;
  249.  
  250. stretch_factor=1;
  251. #endif
  252.  
  253. Set_Screen_Window(NULL);
  254. }
  255.  
  256. void Change_Screen(short width, short height) {
  257.     short valid_width=((width+3)/4)*4; // bitmap should be 32 bits wide, so width must
  258.       // be a multiple of 4
  259.     short valid_height=height;
  260.  
  261. #ifdef OS_DOS
  262.   Attempt_Screen_Open(valid_width, valid_height);
  263.   Set_Phys_Screen(valid_width, valid_height);
  264. #endif
  265.  
  266. #ifdef OS_WINDOWS
  267.     valid_width/=stretch_factor;
  268.     valid_height/=stretch_factor;
  269.     Set_Phys_Screen(valid_width, valid_height);
  270.     // set buffer dimensions
  271.     os_header.Header.biWidth=Get_Phys_Screen_Width();
  272.     os_header.Header.biHeight=Get_Phys_Screen_Height() * Get_Phys_Orientation() * (-1);
  273.  
  274. #endif
  275.  
  276. // clear all buffers
  277. pbuffer_node cur_node;
  278. BN_Set_Node(cur_node, buffer_list);
  279. while (!BN_Empty_Node(cur_node)) {
  280.     Delete_Offscreen_Buffer(BN_Get_Data(cur_node));
  281.     Allocate_Offscreen_Buffer(BN_Get_Data(cur_node));
  282.     BN_Set_Node(cur_node, BN_Get_Next_Node(cur_node));
  283. } /* endwhile */
  284.  
  285. // let application adjust to the change in size
  286. App_Make_New_Screen();
  287. }
  288.  
  289. void End_Graphics() {
  290.  
  291. // clear all buffers
  292. pbuffer_node cur_node, next_node;
  293. BN_Set_Node(cur_node, buffer_list);
  294. while (!BN_Empty_Node(cur_node)) {
  295.     Delete_Offscreen_Buffer(BN_Get_Data(cur_node));
  296.     BN_Set_Node(next_node, BN_Get_Next_Node(cur_node));
  297.     BN_Delete_Node(cur_node);
  298.     BN_Set_Node(cur_node, next_node);
  299. } /* endwhile */
  300.  
  301. // perform OS dependent graphics shutdowns
  302. #ifdef OS_DOS
  303. if (super_vga) {
  304.     VESA_EndGraphics();
  305. } else {
  306.     setgmode(0x3);
  307. } /* endif */
  308. #endif
  309.  
  310. #ifdef OS_WINDOWS
  311. DeleteDC(off_screen_DC);
  312. WinG.Free(); //terminate WinG DLL link.
  313. #endif
  314.  
  315. }
  316.  
  317. void Blt_Buffer(poff_screen_buff os_buffer) {
  318. #ifdef OS_DOS
  319.     Screen_Copy(0, (*os_buffer->buff_ptr_address), Get_Phys_Screen_Width() * Get_Phys_Screen_Height());
  320. #endif
  321.  
  322. #ifdef OS_WINDOWS
  323. if (cur_hbitmap!=os_buffer->hbitmap) {
  324.     SelectObject(off_screen_DC, os_buffer->hbitmap);
  325.     cur_hbitmap=os_buffer->hbitmap;
  326. } /* endif */
  327.  
  328. // do a wing blit, calling a liner blit only is stretch factor is 1
  329.     if (stretch_factor != 1)
  330.         WinG.pStretchBlt(cur_screen_ptr,0,0,
  331.                      stretch_factor*Get_Phys_Screen_Width(),
  332.                      stretch_factor*Get_Phys_Screen_Height(),
  333.         off_screen_DC,0,0,
  334.                      Get_Phys_Screen_Width(),
  335.                      Get_Phys_Screen_Height());
  336.     else
  337.         WinG.pBitBlt(cur_screen_ptr,0,0,
  338.                      Get_Phys_Screen_Width(),
  339.                      Get_Phys_Screen_Height(),
  340.                      off_screen_DC,0,0);
  341. #endif
  342.  
  343. }
  344.  
  345. #ifdef OS_WINDOWS
  346. void Set_Stretch_Factor(short new_factor) {
  347.     stretch_factor=new_factor;
  348. }
  349.  
  350. short Get_Stretch_Factor() {
  351.     return stretch_factor;
  352. }
  353. #endif
  354.  
  355. void Set_Screen_Window(screen_ptr new_screen_ptr) {
  356.  
  357. cur_screen_ptr=new_screen_ptr;
  358.  
  359. #ifdef OS_WINDOWS
  360. if (cur_screen_ptr==NULL)
  361.     cur_screen_ptr=GetDC(NULL);
  362. #endif
  363. }
  364.  
  365. void Release_Screen_Window() {
  366.     Set_Screen_Window(NULL);
  367. }
  368.  
  369. screen_ptr Get_Screen_Window() {
  370.     return cur_screen_ptr;
  371. }
  372.  
  373. void Clear_Buffer(poff_screen_buff os_buffer) {
  374. #ifdef OS_DOS
  375. memset(*(os_buffer->buff_ptr_address),BLACK_COLOR,
  376.                 Get_Phys_Screen_Width() * Get_Phys_Screen_Height() * sizeof(unsigned char));
  377. #endif
  378.  
  379. #ifdef OS_WINDOWS
  380. if (cur_hbitmap!=os_buffer->hbitmap) {
  381.     SelectObject(off_screen_DC, os_buffer->hbitmap);
  382.     cur_hbitmap=os_buffer->hbitmap;
  383. } /* endif */
  384.  
  385. PatBlt(off_screen_DC, 0, 0, Get_Phys_Screen_Width(), Get_Phys_Screen_Height(), BLACK_COLOR);
  386. #endif
  387.  
  388. }
  389.