?? sdl_driver.c
字號:
/* * An SDL replacement for BUILD's VESA code. * * Written by Ryan C. Gordon. (icculus@clutteredmind.org) * * Please do NOT harrass Ken Silverman about any code modifications * (including this file) to BUILD. *//* * "Build Engine & Tools" Copyright (c) 1993-1997 Ken Silverman * Ken Silverman's official web site: "http://www.advsys.net/ken" * See the included license file "BUILDLIC.TXT" for license info. * This file IS NOT A PART OF Ken Silverman's original release */#include <stdio.h>#include <stdlib.h>#include <stdarg.h>#include <assert.h>#include <string.h>#include "platform.h"#if (!defined PLATFORM_SUPPORTS_SDL)#error This platform apparently does not use SDL. Do not compile this.#endif#include "SDL.h"#include "build.h"#include "display.h"#include "pragmas.h"#include "engine.h"#if (defined USE_OPENGL)#include "buildgl.h"#endiftypedef enum{ RENDERER_SOFTWARE, RENDERER_OPENGL3D, RENDERER_TOTAL} sdl_renderer_type;const char *renderer_name[RENDERER_TOTAL];#define ENVRSTR_RENDERER_SOFTWARE "software"#define ENVRSTR_RENDERER_OPENGL3D "opengl3d"static sdl_renderer_type renderer = RENDERER_SOFTWARE;/* !!! ugh. Clean this up. */#if (defined USE_I386_ASM)#if (!defined __WATCOMC__)#include "a.h"#elseextern long setvlinebpl(long);#pragma aux setvlinebpl parm [eax];#endif /* __WATCOMC__ */#endif /* USE_I386_ASM */#include "cache1d.h"/* * !!! I'd like this to be temporary. --ryan. * !!! That is, the self-modifying part, so I can ditch the mprotect() stuff. */#if ((defined PLATFORM_UNIX) && (defined USE_I386_ASM))#include <sys/mman.h>#include <limits.h>#ifndef PAGESIZE#define PAGESIZE 4096#endif#endif/* * !!! remove the surface_end checks, for speed's sake. They are a * !!! needed safety right now. --ryan. */#define DEFAULT_MAXRESWIDTH 1600#define DEFAULT_MAXRESHEIGHT 1200#define UNLOCK_SURFACE_AND_RETURN if (SDL_MUSTLOCK(surface)) SDL_UnlockSurface(surface); return;int _argc = 0;char **_argv = NULL; /* !!! move these elsewhere? */long xres, yres, bytesperline, frameplace, imageSize, maxpages;char *screen, vesachecked;long buffermode, origbuffermode, linearmode;char permanentupdate = 0, vgacompatible;SDL_Surface *surface = NULL; /* This isn't static so that we can use it elsewhere AH */static int debug_hall_of_mirrors = 0;static Uint32 sdl_flags = SDL_HWPALETTE;static long mouse_x = 0;static long mouse_y = 0;static long mouse_relative_x = 0;static long mouse_relative_y = 0;static short mouse_buttons = 0;static int mouse_grabbed = 0;static unsigned int lastkey = 0;static SDL_TimerID primary_timer = NULL;/* so we can make use of setcolor16()... - DDOI */static unsigned char drawpixel_color=0;/* These hold the colors for the 256 color palette when in 16-color mode - DDOI */static char backup_palette[48];static int in_egapalette = 0;/* The standard EGA palette in BUILD format - DDOI */static char egapalette[] = { 0, 0, 0, 0, 0, 42, 0, 42, 0, 0, 42, 42, 42, 0, 0, 42, 0, 42, 42, 21, 0, 42, 42, 42, 21, 21, 21, 21, 21, 63, 21, 63, 21, 21, 63, 63, 63, 21, 21, 63, 21, 63, 63, 63, 21, 63, 63, 63 };static unsigned int scancodes[SDLK_LAST];static long last_render_ticks = 0;long total_render_time = 1;long total_rendered_frames = 0;static char *titlelong = NULL;static char *titleshort = NULL;void restore256_palette (void);void set16color_palette (void);static FILE *_sdl_debug_file = NULL;static inline void __out_sdldebug(const char *subsystem, const char *fmt, va_list ap){ fprintf(_sdl_debug_file, "%s: ", subsystem); vfprintf(_sdl_debug_file, fmt, ap); fprintf(_sdl_debug_file, "\n"); fflush(_sdl_debug_file);} /* __out_sdldebug */static void sdldebug(const char *fmt, ...){ va_list ap; if (_sdl_debug_file) { va_start(ap, fmt); __out_sdldebug("BUILDSDL", fmt, ap); va_end(ap); } /* if */} /* sdldebug */#if (defined USE_OPENGL)void sgldebug(const char *fmt, ...){ va_list ap; if (_sdl_debug_file) { va_start(ap, fmt); __out_sdldebug("BUILDSDL/GL", fmt, ap); va_end(ap); } /* if */} /* sgldebug */#endifstatic void __append_sdl_surface_flag(SDL_Surface *_surface, char *str, size_t strsize, Uint32 flag, const char *flagstr){ if (_surface->flags & flag) { if ( (strlen(str) + strlen(flagstr)) >= (strsize - 1) ) strcpy(str + (strsize - 5), " ..."); else strcat(str, flagstr); } /* if */} /* append_sdl_surface_flag */#define append_sdl_surface_flag(a, b, c, fl) __append_sdl_surface_flag(a, b, c, fl, " " #fl)#define print_tf_state(str, val) sdldebug("%s: {%s}", str, (val) ? "true" : "false" )static void output_surface_info(SDL_Surface *_surface){ const SDL_VideoInfo *info; char f[256]; if (!_sdl_debug_file) return; if (_surface == NULL) { sdldebug("-WARNING- You've got a NULL screen surface!"); } else { f[0] = '\0'; sdldebug("screen surface is (%dx%dx%dbpp).", _surface->w, _surface->h, _surface->format->BitsPerPixel); append_sdl_surface_flag(_surface, f, sizeof (f), SDL_SWSURFACE); append_sdl_surface_flag(_surface, f, sizeof (f), SDL_HWSURFACE); append_sdl_surface_flag(_surface, f, sizeof (f), SDL_ASYNCBLIT); append_sdl_surface_flag(_surface, f, sizeof (f), SDL_ANYFORMAT); append_sdl_surface_flag(_surface, f, sizeof (f), SDL_HWPALETTE); append_sdl_surface_flag(_surface, f, sizeof (f), SDL_DOUBLEBUF); append_sdl_surface_flag(_surface, f, sizeof (f), SDL_FULLSCREEN); append_sdl_surface_flag(_surface, f, sizeof (f), SDL_OPENGL); append_sdl_surface_flag(_surface, f, sizeof (f), SDL_OPENGLBLIT); append_sdl_surface_flag(_surface, f, sizeof (f), SDL_RESIZABLE); append_sdl_surface_flag(_surface, f, sizeof (f), SDL_NOFRAME); append_sdl_surface_flag(_surface, f, sizeof (f), SDL_HWACCEL); append_sdl_surface_flag(_surface, f, sizeof (f), SDL_SRCCOLORKEY); append_sdl_surface_flag(_surface, f, sizeof (f), SDL_RLEACCELOK); append_sdl_surface_flag(_surface, f, sizeof (f), SDL_RLEACCEL); append_sdl_surface_flag(_surface, f, sizeof (f), SDL_SRCALPHA); append_sdl_surface_flag(_surface, f, sizeof (f), SDL_PREALLOC); if (f[0] == '\0') strcpy(f, " (none)"); sdldebug("New vidmode flags:%s", f); info = SDL_GetVideoInfo(); assert(info != NULL); print_tf_state("hardware surface available", info->hw_available); print_tf_state("window manager available", info->wm_available); print_tf_state("accelerated hardware->hardware blits", info->blit_hw); print_tf_state("accelerated hardware->hardware colorkey blits", info->blit_hw_CC); print_tf_state("accelerated hardware->hardware alpha blits", info->blit_hw_A); print_tf_state("accelerated software->hardware blits", info->blit_sw); print_tf_state("accelerated software->hardware colorkey blits", info->blit_sw_CC); print_tf_state("accelerated software->hardware alpha blits", info->blit_sw_A); print_tf_state("accelerated color fills", info->blit_fill); sdldebug("video memory: (%d)", info->video_mem); } /* else */} /* output_surface_info */static void output_driver_info(void){ char buffer[256]; if (!_sdl_debug_file) return; sdldebug("Using BUILD renderer \"%s\".", renderer_name[renderer]); if (SDL_VideoDriverName(buffer, sizeof (buffer)) == NULL) { sdldebug("-WARNING- SDL_VideoDriverName() returned NULL!"); } /* if */ else { sdldebug("Using SDL video driver \"%s\".", buffer); } /* else */} /* output_driver_info */static Uint8 *get_framebuffer(void){ assert(renderer != RENDERER_OPENGL3D); if (renderer == RENDERER_SOFTWARE) return((Uint8 *) surface->pixels); else if (renderer == RENDERER_OPENGL3D) return((Uint8 *) frameplace); return(NULL);} /* get_framebuffer */int using_opengl(void){ return(renderer == RENDERER_OPENGL3D);} /* using_opengl *//* * !!! This is almost an entire copy of the original setgamemode(). * !!! Figure out what is needed for just 2D mode, and separate that * !!! out. Then, place the original setgamemode() back into engine.c, * !!! and remove our simple implementation (and this function.) * !!! Just be sure to keep the non-DOS things, like the window's * !!! titlebar caption. --ryan. */static char screenalloctype = 255;static void init_new_res_vars(int davidoption){ int i = 0; int j = 0; setupmouse(); SDL_WM_SetCaption(titlelong, titleshort); xdim = xres = surface->w; ydim = yres = surface->h; bytesperline = surface->w; vesachecked = 1; vgacompatible = 1; linearmode = 1; qsetmode = surface->h; activepage = visualpage = 0; horizlookup = horizlookup2 = NULL; if (renderer == RENDERER_OPENGL3D) frameplace = (long) NULL; else frameplace = (long) ( ((Uint8 *) surface->pixels) ); if (screen != NULL) { if (screenalloctype == 0) kkfree((void *)screen); if (screenalloctype == 1) suckcache((long *)screen); screen = NULL; } /* if */ if (davidoption != -1) { switch(vidoption) { case 1:i = xdim*ydim; break; case 2: xdim = 320; ydim = 200; i = xdim*ydim; break; case 6: xdim = 320; ydim = 200; i = 131072; break; default: assert(0); } j = ydim*4*sizeof(long); /* Leave room for horizlookup&horizlookup2 */ screenalloctype = 0; if ((screen = (char *)kkmalloc(i+(j<<1))) == NULL) { allocache((long *)&screen,i+(j<<1),&permanentlock); screenalloctype = 1; } /* !!! FIXME: Should screen get allocated above if in opengl3d mode? */ if (renderer == RENDERER_OPENGL3D) frameplace = (long) NULL; else { frameplace = FP_OFF(screen); horizlookup = (long *)(frameplace+i); horizlookup2 = (long *)(frameplace+i+j); } /* else */ } /* if */ j = 0; for(i = 0; i <= ydim; i++) { ylookup[i] = j; j += bytesperline; } /* for */ horizycent = ((ydim*4)>>1); /* Force drawrooms to call dosetaspect & recalculate stuff */ oxyaspect = oxdimen = oviewingrange = -1; setvlinebpl(bytesperline); if (davidoption != -1) { setview(0L,0L,xdim-1,ydim-1); clearallviews(0L); } /* if */ setbrightness((char) curbrightness, (unsigned char *) &palette[0]); if (searchx < 0) { searchx = halfxdimen; searchy = (ydimen>>1); }} /* init_new_res_vars */static void go_to_new_vid_mode(int vidoption, int w, int h){ getvalidvesamodes(); SDL_ClearError(); surface = SDL_SetVideoMode(w, h, 8, sdl_flags); if (surface == NULL) { fprintf(stderr, "BUILDSDL: Failed to set %dx%d video mode!\n" "BUILDSDL: SDL_Error() says [%s].\n", w, h, SDL_GetError()); SDL_Quit(); exit(13); } /* if */ output_surface_info(surface); init_new_res_vars(vidoption);} /* go_to_new_vid_mode */static int sdl_mouse_button_filter(SDL_Event const *event){ /* * What BUILD expects: * 0 left button pressed if 1 * 1 right button pressed if 1 * 2 middle button pressed if 1 * * (That is, this is what Int 33h (AX=0x05) returns...) */ Uint8 bmask = SDL_GetMouseState(NULL, NULL); mouse_buttons = 0; if (bmask & SDL_BUTTON_LMASK) mouse_buttons |= 1; if (bmask & SDL_BUTTON_RMASK) mouse_buttons |= 2; if (bmask & SDL_BUTTON_MMASK) mouse_buttons |= 4; return(0);} /* sdl_mouse_up_filter */static int sdl_mouse_motion_filter(SDL_Event const *event){ if (surface == NULL) return(0); if (event->type == SDL_JOYBALLMOTION) { mouse_relative_x = event->jball.xrel/100; mouse_relative_y = event->jball.yrel/100; mouse_x += mouse_relative_x; mouse_y += mouse_relative_y; } /* if */ else { if (mouse_grabbed) { mouse_relative_x = event->motion.xrel; mouse_relative_y = event->motion.yrel; mouse_x += mouse_relative_x; mouse_y += mouse_relative_y; } /* if */ else { mouse_relative_x = event->motion.x - mouse_x; mouse_relative_y = event->motion.y - mouse_y; mouse_x = event->motion.x; mouse_y = event->motion.y; } /* else */ } /* else */ if (mouse_x < 0) mouse_x = 0; if (mouse_x > surface->w) mouse_x = surface->w; if (mouse_y < 0) mouse_y = 0; if (mouse_y > surface->h) mouse_y = surface->h; return(0);} /* sdl_mouse_motion_filter *//** * Attempt to flip the video surface to fullscreen or windowed mode. * Attempts to maintain the surface's state, but makes no guarantee * that pointers (i.e., the surface's pixels field) will be the same * after this call. * * Caveats: Your surface pointers will be changing; if you have any other * copies laying about, they are invalidated. * * Do NOT call this from an SDL event filter on Windows. You can * call it based on the return values from SDL_PollEvent, etc, just * not during the function you passed to SDL_SetEventFilter(). * * Thread safe? Likely not. * * @param surface pointer to surface ptr to toggle. May be different * pointer on return. MAY BE NULL ON RETURN IF FAILURE! * @param flags pointer to flags to set on surface. The value pointed * to will be XOR'd with SDL_FULLSCREEN before use. Actual * flags set will be filled into pointer. Contents are * undefined on failure. Can be NULL, in which case the * surface's current flags are used. * @return non-zero on success, zero on failure. */static int attempt_fullscreen_toggle(SDL_Surface **surface, Uint32 *flags){ long framesize = 0; void *pixels = NULL; SDL_Rect clip; Uint32 tmpflags = 0; int w = 0; int h = 0; int bpp = 0; int grabmouse = (SDL_WM_GrabInput(SDL_GRAB_QUERY) == SDL_GRAB_ON); int showmouse = SDL_ShowCursor(-1);#if 0 SDL_Color *palette = NULL; int ncolors = 0;#endif sdldebug("attempting to toggle fullscreen flag..."); if ( (!surface) || (!(*surface)) ) /* don't try if there's no surface. */ { sdldebug("Null surface (?!). Not toggling fullscreen flag."); return(0); } /* if */
?? 快捷鍵說明
復制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號
Ctrl + =
減小字號
Ctrl + -