SCRCNTL.CPP
上传用户:sycq158
上传日期:2008-10-22
资源大小:15361k
文件大小:10k
源码类别:

游戏

开发平台:

Visual C++

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