?? scrcntl.cpp
字號:
/****************************************
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
}
?? 快捷鍵說明
復制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號
Ctrl + =
減小字號
Ctrl + -