SCRCNTL.CPP
上传用户:sycq158
上传日期:2008-10-22
资源大小:15361k
文件大小:10k
- /****************************************
- scrcntl.cpp- a module to provide a layer of abstraction
- between the OS graphics architecture and the application
- It provides you the programmer with the ability to create offscreen
- buffers, whose drawing surfaces you have direct access to, which
- blit to the screen across operating systems. To change the
- destination operating system, simply change the file os.h
- Also requires the file palcntl.cpp to load palettes in the bitmaps
- A routine called App_Make_New_Screen must be in another source file. It
- should perform any work that must be done for the app to run in the
- new screen size
- *****************************************/
- #include "os.h"
- #include "scrcntl.h"
- #include "buffnode.h"
- #include "memutil.h"
- #include "scconint.h"
- #include "palette.h"
- #include <mem.h>
- #ifdef OS_WINDOWS
- #include "wingdll.h"
- #endif
- pbuffer_node buffer_list=NULL;
- screen_ptr cur_screen_ptr;
- void App_Make_New_Screen();
- #ifdef OS_DOS
- #define VGA_WIDTH 320
- #define VGA_HEIGHT 200
- #define SVGA_WIDTH 640
- #define SVGA_HEIGHT 480
- #include "vesa.h"
- #include "screen.h"
- void Screen_Copy(long offset, void * src, long ncopy);
- BOOL super_vga;
- void Attempt_Screen_Open(short & width, short & height)
- {
- if ( (width>VGA_WIDTH) || (height>VGA_HEIGHT) ) {
- // must load a super vga screen to get requested dimensions
- VBE_detect();
- if (VESA_InitGraphics(width, height)) {
- // no svga so load vga dimensions
- setgmode(0x13);
- super_vga=FALSE;
- width=VGA_WIDTH;
- height=VGA_HEIGHT;
- } else {
- super_vga=TRUE;
- }
- } else {
- super_vga=FALSE;
- setgmode(0x13);
- width=VGA_WIDTH;
- height=VGA_HEIGHT;
- }
- }
- void Screen_Copy(long offset, void * src, long ncopy) {
- if (cur_screen_ptr==NULL) {
- if (super_vga) {
- VESA_ScreenCopy(offset, src, ncopy);
- } else {
- memcpy(screen+offset, src, ncopy);
- } /* endif */
- } else {
- memcpy(cur_screen_ptr+offset, src, ncopy);
- }
- }
- #endif
- #ifdef OS_WINDOWS
- HBITMAP cur_hbitmap=NULL;
- short stretch_factor=1;
- typedef struct MY_BITMAP_HEADER
- {
- BITMAPINFOHEADER Header;
- RGBQUAD aColors[256];
- } my_bitmap_header;
- my_bitmap_header os_header;
- HBITMAP old_mono_bitmap;
- HDC off_screen_DC;
- WinGdll WinG;
- #endif
- void Allocate_Offscreen_Buffer(poff_screen_buff new_buff) {
- #ifdef OS_DOS
- // allocate the off screen buffer manually
- (*(new_buff->buff_ptr_address))=(video_data_ptr)NewPtr(
- Get_Phys_Screen_Width() * Get_Phys_Screen_Height());
- #endif
- #ifdef OS_WINDOWS
- // copy palette to buffer header
- // this is done now in case you want to load different palettes for each buffer
- // the currently loaded is made the buffer's palette. You don't have to do this
- // in dos because dos bitmaps have no palettes. To keep the bitmap's palette equal to
- // the loaded palette, you must call Change_Screen.
- for (short color_index=0; color_index< PALETTE_COLORS; color_index++) {
- os_header.aColors[color_index].rgbRed=Get_Palette_Red_Val(color_index);
- os_header.aColors[color_index].rgbGreen=Get_Palette_Green_Val(color_index);
- os_header.aColors[color_index].rgbBlue=Get_Palette_Blue_Val(color_index);
- os_header.aColors[color_index].rgbReserved=0;
- }
- // create the bitmap handle in the WinGDC
- new_buff->hbitmap=WinG.pCreateBitmap(off_screen_DC, (BITMAPINFO *)&os_header,
- (PVOID *)new_buff->buff_ptr_address);
- #endif
- }
- void Delete_Offscreen_Buffer(poff_screen_buff delete_buff) {
- #ifdef OS_DOS
- DelPtr( (*(delete_buff->buff_ptr_address)));
- #endif
- #ifdef OS_WINDOWS
- if (cur_hbitmap==delete_buff->hbitmap) {
- SelectObject(off_screen_DC, old_mono_bitmap);
- cur_hbitmap=old_mono_bitmap;
- }
- DeleteObject(delete_buff->hbitmap);
- #endif
- }
- poff_screen_buff Create_Offscreen_Buffer(video_data_ptr * buff_ptr_address)
- {
- // make a new off_screen_buff structure
- poff_screen_buff new_buff=(poff_screen_buff)NewPtr(sizeof(off_screen_buff));
- new_buff->buff_ptr_address=buff_ptr_address;
- // just what is says
- Allocate_Offscreen_Buffer(new_buff);
- // put the new buffer in the list of buffers
- pbuffer_node new_buff_node=BN_Create_Node();
- BN_Set_Data(new_buff_node, new_buff);
- BN_Set_Next_Node(new_buff_node, buffer_list);
- BN_Set_Node(buffer_list, new_buff_node);
- return new_buff;
- }
- void Dispose_Buffer(poff_screen_buff os_buffer) {
- pbuffer_node cur_node, next_node;
- BOOL found;
- // are we dealing with and empty list, if so the node does not exist
- if (BN_Empty_Node(buffer_list)) {
- return;
- }
- // if node is the start of list, update list and delete node
- if (BN_Get_Data(buffer_list)==os_buffer) {
- BN_Set_Node(next_node, BN_Get_Next_Node(buffer_list));
- Delete_Offscreen_Buffer(BN_Get_Data(buffer_list));
- BN_Delete_Node(buffer_list);
- BN_Set_Node(buffer_list, next_node);
- return;
- }
- // find the node to be deleted
- BN_Set_Node(cur_node, buffer_list);
- found=FALSE;
- while (!BN_Empty_Node(BN_Get_Next_Node(cur_node))) {
- if (BN_Get_Data(BN_Get_Next_Node(cur_node))==os_buffer) {
- found=TRUE;
- break;
- }
- BN_Set_Node(cur_node, BN_Get_Next_Node(cur_node));
- } /* endwhile */
- // Remove the node from list and delete it
- if (found) {
- BN_Set_Node(next_node, BN_Get_Next_Node(BN_Get_Next_Node(cur_node)));
- Delete_Offscreen_Buffer(BN_Get_Data(BN_Get_Next_Node(cur_node)));
- BN_Delete_Node(BN_Get_Next_Node(cur_node));
- BN_Set_Next_Node(cur_node, next_node);
- }
- }
- extern "C" short LOGICAL_SCREEN_HEIGHT; // stores without screen orientation
- extern "C" short LOGICAL_SCREEN_WIDTH; // same for width
- void Activate_Graphics() {
- #ifdef OS_DOS
- Attempt_Screen_Open(LOGICAL_SCREEN_WIDTH, LOGICAL_SCREEN_HEIGHT);
- #endif
- }
- void Init_Screen(short width, short height) {
- short valid_width=((width+3)/4)*4; // bitmap should be 32 bits wide, so width must
- // be a multiple of 4
- short valid_height=height;
- #ifdef OS_DOS
- Init_Phys_Screen(valid_width, valid_height);
- #endif
- #ifdef OS_WINDOWS
- if (!WinG.Load()) { //link to WinG DLL.
- MessageBox(0,"Can't find WING32.DLL","WTWIN Error!",MB_OK);
- return;
- }
- Init_Phys_Screen(valid_width, valid_height);
- if(WinG.pRecommendDIBFormat((BITMAPINFO *)&os_header)) {
- // make sure it's 8bpp and remember the orientation
- os_header.Header.biBitCount = 8;
- os_header.Header.biCompression = BI_RGB;
- Set_Phys_Orientation(os_header.Header.biHeight*(-1));
- } else {
- // set it up ourselves
- os_header.Header.biSize = sizeof(BITMAPINFOHEADER);
- os_header.Header.biPlanes = 1;
- os_header.Header.biBitCount = 8;
- os_header.Header.biCompression = BI_RGB;
- os_header.Header.biSizeImage = 0;
- os_header.Header.biClrUsed = 0;
- os_header.Header.biClrImportant = 0;
- }
- os_header.Header.biWidth=Get_Phys_Screen_Width();
- os_header.Header.biHeight=Get_Phys_Screen_Height()*Get_Phys_Orientation() * (-1);
- off_screen_DC=WinG.pCreateDC();
- old_mono_bitmap=(HBITMAP)GetCurrentObject(off_screen_DC, OBJ_BITMAP);
- cur_hbitmap=old_mono_bitmap;
- stretch_factor=1;
- #endif
- Set_Screen_Window(NULL);
- }
- void Change_Screen(short width, short height) {
- short valid_width=((width+3)/4)*4; // bitmap should be 32 bits wide, so width must
- // be a multiple of 4
- short valid_height=height;
- #ifdef OS_DOS
- Attempt_Screen_Open(valid_width, valid_height);
- Set_Phys_Screen(valid_width, valid_height);
- #endif
- #ifdef OS_WINDOWS
- valid_width/=stretch_factor;
- valid_height/=stretch_factor;
- Set_Phys_Screen(valid_width, valid_height);
- // set buffer dimensions
- os_header.Header.biWidth=Get_Phys_Screen_Width();
- os_header.Header.biHeight=Get_Phys_Screen_Height() * Get_Phys_Orientation() * (-1);
- #endif
- // clear all buffers
- pbuffer_node cur_node;
- BN_Set_Node(cur_node, buffer_list);
- while (!BN_Empty_Node(cur_node)) {
- Delete_Offscreen_Buffer(BN_Get_Data(cur_node));
- Allocate_Offscreen_Buffer(BN_Get_Data(cur_node));
- BN_Set_Node(cur_node, BN_Get_Next_Node(cur_node));
- } /* endwhile */
- // let application adjust to the change in size
- App_Make_New_Screen();
- }
- void End_Graphics() {
- // clear all buffers
- pbuffer_node cur_node, next_node;
- BN_Set_Node(cur_node, buffer_list);
- while (!BN_Empty_Node(cur_node)) {
- Delete_Offscreen_Buffer(BN_Get_Data(cur_node));
- BN_Set_Node(next_node, BN_Get_Next_Node(cur_node));
- BN_Delete_Node(cur_node);
- BN_Set_Node(cur_node, next_node);
- } /* endwhile */
- // perform OS dependent graphics shutdowns
- #ifdef OS_DOS
- if (super_vga) {
- VESA_EndGraphics();
- } else {
- setgmode(0x3);
- } /* endif */
- #endif
- #ifdef OS_WINDOWS
- DeleteDC(off_screen_DC);
- WinG.Free(); //terminate WinG DLL link.
- #endif
- }
- void Blt_Buffer(poff_screen_buff os_buffer) {
- #ifdef OS_DOS
- Screen_Copy(0, (*os_buffer->buff_ptr_address), Get_Phys_Screen_Width() * Get_Phys_Screen_Height());
- #endif
- #ifdef OS_WINDOWS
- if (cur_hbitmap!=os_buffer->hbitmap) {
- SelectObject(off_screen_DC, os_buffer->hbitmap);
- cur_hbitmap=os_buffer->hbitmap;
- } /* endif */
- // do a wing blit, calling a liner blit only is stretch factor is 1
- if (stretch_factor != 1)
- WinG.pStretchBlt(cur_screen_ptr,0,0,
- stretch_factor*Get_Phys_Screen_Width(),
- stretch_factor*Get_Phys_Screen_Height(),
- off_screen_DC,0,0,
- Get_Phys_Screen_Width(),
- Get_Phys_Screen_Height());
- else
- WinG.pBitBlt(cur_screen_ptr,0,0,
- Get_Phys_Screen_Width(),
- Get_Phys_Screen_Height(),
- off_screen_DC,0,0);
- #endif
- }
- #ifdef OS_WINDOWS
- void Set_Stretch_Factor(short new_factor) {
- stretch_factor=new_factor;
- }
- short Get_Stretch_Factor() {
- return stretch_factor;
- }
- #endif
- void Set_Screen_Window(screen_ptr new_screen_ptr) {
- cur_screen_ptr=new_screen_ptr;
- #ifdef OS_WINDOWS
- if (cur_screen_ptr==NULL)
- cur_screen_ptr=GetDC(NULL);
- #endif
- }
- void Release_Screen_Window() {
- Set_Screen_Window(NULL);
- }
- screen_ptr Get_Screen_Window() {
- return cur_screen_ptr;
- }
- void Clear_Buffer(poff_screen_buff os_buffer) {
- #ifdef OS_DOS
- memset(*(os_buffer->buff_ptr_address),BLACK_COLOR,
- Get_Phys_Screen_Width() * Get_Phys_Screen_Height() * sizeof(unsigned char));
- #endif
- #ifdef OS_WINDOWS
- if (cur_hbitmap!=os_buffer->hbitmap) {
- SelectObject(off_screen_DC, os_buffer->hbitmap);
- cur_hbitmap=os_buffer->hbitmap;
- } /* endif */
- PatBlt(off_screen_DC, 0, 0, Get_Phys_Screen_Width(), Get_Phys_Screen_Height(), BLACK_COLOR);
- #endif
- }