📄 x11.cpp
字号:
/* * Snes9x - Portable Super Nintendo Entertainment System (TM) emulator. * * (c) Copyright 1996 - 2001 Gary Henderson (gary@daniver.demon.co.uk) and * Jerremy Koot (jkoot@snes9x.com) * * Super FX C emulator code * (c) Copyright 1997 - 1999 Ivar (Ivar@snes9x.com) and * Gary Henderson. * Super FX assembler emulator code (c) Copyright 1998 zsKnight and _Demo_. * * DSP1 emulator code (c) Copyright 1998 Ivar, _Demo_ and Gary Henderson. * C4 asm and some C emulation code (c) Copyright 2000 zsKnight and _Demo_. * C4 C code (c) Copyright 2001 Gary Henderson (gary@daniver.demon.co.uk). * * DOS port code contains the works of other authors. See headers in * individual files. * * Snes9x homepage: www.snes9x.com * * Permission to use, copy, modify and distribute Snes9x in both binary and * source form, for non-commercial purposes, is hereby granted without fee, * providing that this license information and copyright notice appear with * all copies and any derived work. * * This software is provided 'as-is', without any express or implied * warranty. In no event shall the authors be held liable for any damages * arising from the use of this software. * * Snes9x is freeware for PERSONAL USE only. Commercial users should * seek permission of the copyright holders first. Commercial use includes * charging money for Snes9x or software derived from Snes9x. * * The copyright holders request that bug fixes and improvements to the code * should be forwarded to them so everyone can benefit from the modifications * in future versions. * * Super NES and Super Nintendo Entertainment System are trademarks of * Nintendo Co., Limited and its subsidiary companies. */#include <stdlib.h>#include <ctype.h>#include <string.h>#include <sys/stat.h>#include <fcntl.h>#include <unistd.h>#include <errno.h>#include "snes9x.h"#include "memmap.h"#include "debug.h"#include "ppu.h"#include "snapshot.h"#include "gfx.h"#include "display.h"#include "apu.h"#include "soundux.h"#if 0#define QT_CLEAN_NAMESPACE#include <qapplication.h>#include "snes9x_gui.h"#endif#include <X11/Xlib.h>#include <X11/Xutil.h>#include <X11/keysym.h>#include <X11/cursorfont.h>#ifdef USE_GLIDEvoid S9xGlideEnable (bool8);void S9xGlidePutImage (int, int);void S9xSwitchToGlideMode (bool8);#endif#ifdef USE_DGA_EXTENSION#include <X11/extensions/xf86dga.h>void CreateFullScreenWindow ();void S9xSwitchToFullScreen (bool8 enable);#ifdef USE_VIDMODE_EXTENSION#if defined (__cplusplus) || defined (c_plusplus)#define private c_private#include <X11/extensions/xf86vmode.h>#endif#define ALL_DEVICE_EVENTS 0#endiftypedef struct { bool8 full_screen_available; bool8 is_full_screen; bool8 scale; char *vram; int line_width; int bank_size; int size; int window_width; int window_height; int saved_window_width; int saved_window_height; bool8 saved_image_needs_scaling; Window fs_window;#ifdef USE_VIDMODE_EXTENSION bool8 switch_video_mode; XF86VidModeModeInfo **all_modes; int num_modes; XF86VidModeModeInfo orig; XF86VidModeModeInfo *best; bool8 no_mode_switch; bool8 start_full_screen;#endif} XF86Data;static XF86Data XF86;#endif#ifdef MITSHM#include <sys/ipc.h>#include <sys/shm.h>#include <X11/extensions/XShm.h>#endiftypedef struct{ Display *display; Screen *screen; int screen_num; Visual *visual; Window window; GC gc; XImage *image; uint8 *image_date; int bytes_per_line; int bytes_per_pixel; uint8 *output_screen; uint32 output_pitch; uint8 *interpolated_screen; uint8 *delta_screen; Colormap cmap; Cursor point_cursor; Cursor cross_hair_cursor; XColor colors [256]; bool8 pseudo; bool8 grayscale; uint8 interpolate; bool8 image_needs_scaling; bool8 scale; int depth; int window_width; int window_height; int last_snes_width; int last_snes_height; uint32 red_shift; uint32 blue_shift; uint32 green_shift; uint32 red_size; uint32 green_size; uint32 blue_size; int mouse_x; int mouse_y; uint32 mouse_buttons; bool8 mod1_pressed; bool8 superscope; uint32 superscope_turbo; uint32 superscope_pause; XRectangle box; XRectangle old_box; XColor fixed_colours [256]; uint8 palette [0x10000]; char info_string [256]; void *to_free [6];#ifdef MITSHM XShmSegmentInfo sm_info; int use_shared_memory;#endif} GUIData;static GUIData GUI;extern uint32 joypads [5];#if 0QApplication *app;Snes9xGUI *gui;#endifvoid Scale8 (int width, int height);void Scale16 (int width, int height);void Convert8To16 (int width, int height);void Convert16To8 (int width, int height);void Convert8To24 (int width, int height);void Convert8To24Packed (int width, int height);void Convert16To24 (int width, int height);void Convert16To24Packed (int width, int height);void SetupImage ();int ErrorHandler (Display *, XErrorEvent *);void TVMode (int width, int height);void S9xDisplayStateChange (const char *str, bool8 on);void Init_2xSaI (uint32);void Super2xSaI (uint8 *srcPtr, uint32 srcPitch, uint8 *deltaPtr, uint8 *dstPtr, uint32 dstPitch, int width, int height);void SuperEagle (uint8 *srcPtr, uint32 srcPitch, uint8 *deltaPtr, uint8 *dstPtr, uint32 dstPitch, int width, int height);void _2xSaI (uint8 *srcPtr, uint32 srcPitch, uint8 *deltaPtr, uint8 *dstPtr, uint32 dstPitch, int width, int height);void Scale_2xSaI (uint8 *srcPtr, uint32 srcPitch, uint8 * /* deltaPtr */, uint8 *dstPtr, uint32 dstPitch, uint32 dstWidth, uint32 dstHeight, int width, int height);void S9xDeinitDisplay (){#ifdef USE_GLIDE S9xGlideEnable (FALSE);#endif S9xTextMode (); uint32 i; for (i = 0; i < sizeof (GUI.to_free) / sizeof (GUI.to_free [0]); i++) if (GUI.to_free [i]) { free (GUI.to_free [i]); GUI.to_free [i] = NULL; } if (GUI.image) {#ifdef MITSHM if (GUI.use_shared_memory) { XShmDetach (GUI.display, &GUI.sm_info); GUI.image->data = NULL; XDestroyImage (GUI.image); if (GUI.sm_info.shmaddr) shmdt (GUI.sm_info.shmaddr); if (GUI.sm_info.shmid >= 0) shmctl (GUI.sm_info.shmid, IPC_RMID, 0); GUI.image = NULL; } else#endif { XDestroyImage (GUI.image); GUI.image = NULL; } } XSync (GUI.display, False); XCloseDisplay (GUI.display);}void S9xInitDisplay (int, char **){ if (!(GUI.display = XOpenDisplay (NULL))) { fprintf (stderr, "Failed to connect to X server.\n"); exit (1); } GUI.screen = DefaultScreenOfDisplay (GUI.display); GUI.screen_num = XScreenNumberOfScreen (GUI.screen); GUI.visual = DefaultVisualOfScreen (GUI.screen); GUI.window_width = IMAGE_WIDTH; GUI.window_height = IMAGE_HEIGHT; XVisualInfo plate; XVisualInfo *matches; int count; plate.visualid = XVisualIDFromVisual (GUI.visual); matches = XGetVisualInfo (GUI.display, VisualIDMask, &plate, &count); if (!count) { fprintf (stderr, "Your X Window System server is unwell!\n"); exit (1); } GUI.depth = matches[0].depth; if ((GUI.depth != 8 && GUI.depth != 15 && GUI.depth != 16 && GUI.depth != 24) || (matches[0].c_class != PseudoColor && matches[0].c_class != TrueColor && matches[0].c_class != GrayScale)) { fprintf (stderr, "\Snes9x needs an X Window System server set to 8, 15, 16, 24 or 32-bit colour GUI.depth\n\supporting PseudoColor, TrueColor or GrayScale.\n"); exit (1); } if (GUI.depth >= 15 && !Settings.ForceNoTransparency) { Settings.Transparency = TRUE; Settings.SixteenBit = TRUE; } GUI.pseudo = matches[0].c_class == PseudoColor || matches[0].c_class == GrayScale; GUI.grayscale = matches[0].c_class == GrayScale; if (GUI.depth != 8 || !GUI.pseudo) { GUI.red_shift = ffs (matches[0].red_mask) - 1; GUI.green_shift = ffs (matches[0].green_mask) - 1; GUI.blue_shift = ffs (matches[0].blue_mask) - 1; GUI.red_size = matches[0].red_mask >> GUI.red_shift; GUI.green_size = matches[0].green_mask >> GUI.green_shift; GUI.blue_size = matches[0].blue_mask >> GUI.blue_shift; if (GUI.depth == 16 && GUI.green_size == 63) GUI.green_shift++;#ifdef GFX_MULTI_FORMAT switch (GUI.depth) { default: case 24: case 8: S9xSetRenderPixelFormat (RGB565); Init_2xSaI (565); break; case 16: if (GUI.red_size != GUI.green_size || GUI.blue_size != GUI.green_size) { // 565 format if (GUI.green_shift > GUI.blue_shift && GUI.green_shift > GUI.red_shift) S9xSetRenderPixelFormat (GBR565); else if (GUI.red_shift > GUI.blue_shift) S9xSetRenderPixelFormat (RGB565); else S9xSetRenderPixelFormat (BGR565); Init_2xSaI (565); break; } /* FALL ... */ case 15: if (GUI.green_shift > GUI.blue_shift && GUI.green_shift > GUI.red_shift) S9xSetRenderPixelFormat (GBR555); else if (GUI.red_shift > GUI.blue_shift) S9xSetRenderPixelFormat (RGB555); else S9xSetRenderPixelFormat (BGR555); Init_2xSaI (555); break; }#endif } XFree ((char *) matches); int l = 0; int i; for (i = 0; i < 6; i++) { int r = (i * 31) / (6 - 1); for (int j = 0; j < 6; j++) { int g = (j * 31) / (6 - 1); for (int k = 0; k < 6; k++) { int b = (k * 31) / (6 - 1); GUI.fixed_colours [l].red = r; GUI.fixed_colours [l].green = g; GUI.fixed_colours [l++].blue = b; } } } int *color_diff = new int [0x10000]; int diffr, diffg, diffb, maxdiff = 0, won = 0, lost; int r, d = 8; for (r = 0; r <= (int) MAX_RED; r++) { int cr, g, q; int k = 6 - 1; cr = (r * k) / MAX_RED; q = (r * k) % MAX_RED; if (q > d && cr < k) cr++; diffr = abs (cr * k - r); for (g = 0; g <= (int) MAX_GREEN; g++) { int cg, b; k = 6 - 1; cg = (g * k) / MAX_GREEN; q = (g * k) % MAX_GREEN; if(q > d && cg < k) cg++; diffg = abs (cg * k - g); for (b = 0; b <= (int) MAX_BLUE; b++) { int cb; int rgb = BUILD_PIXEL2(r, g, b); k = 6 - 1; cb = (b * k) / MAX_BLUE; q = (b * k) % MAX_BLUE; if (q > d && cb < k) cb++; diffb = abs (cb * k - b); GUI.palette[rgb] = (cr * 6 + cg) * 6 + cb; color_diff[rgb] = diffr + diffg + diffb; if (color_diff[rgb] > maxdiff) maxdiff = color_diff[rgb]; } } } while (maxdiff > 0 && l < 256) { int newmaxdiff = 0; lost = 0; won++; for (r = MAX_RED; r >= 0; r--) { int g; for (g = MAX_GREEN; g >= 0; g--) { int b; for (b = MAX_BLUE; b >= 0; b--) { int rgb = BUILD_PIXEL2(r, g, b); if (color_diff[rgb] == maxdiff) { if (l >= 256) lost++; else { GUI.fixed_colours [l].red = r; GUI.fixed_colours [l].green = g; GUI.fixed_colours [l].blue = b; GUI.palette [rgb] = l; l++; } color_diff[rgb] = 0; } else if (color_diff[rgb] > newmaxdiff) newmaxdiff = color_diff[rgb]; } } } maxdiff = newmaxdiff; } delete color_diff; GUI.window = XCreateSimpleWindow (GUI.display, RootWindowOfScreen (GUI.screen), (WidthOfScreen(GUI.screen) - GUI.window_width) / 2, (HeightOfScreen(GUI.screen) - GUI.window_height) / 2, GUI.window_width, GUI.window_height, 0, 0, 0);#ifdef USE_DGA_EXTENSION CreateFullScreenWindow ();#endif static XColor bg; static XColor fg; static char data [8] = { 0x01 }; Pixmap bitmap = XCreateBitmapFromData (GUI.display, GUI.window, data, 8, 8); GUI.point_cursor = XCreatePixmapCursor (GUI.display, bitmap, bitmap, &fg, &bg, 0, 0); XDefineCursor (GUI.display, GUI.window, GUI.point_cursor);#ifdef USE_DGA_EXTENSION if (XF86.full_screen_available) XDefineCursor (GUI.display, XF86.fs_window, GUI.point_cursor);#endif GUI.cross_hair_cursor = XCreateFontCursor (GUI.display, XC_crosshair); GUI.gc = DefaultGCOfScreen (GUI.screen); { XSizeHints Hints; XWMHints WMHints; memset ((void *) &Hints, 0, sizeof (XSizeHints)); memset ((void *) &WMHints, 0, sizeof (XWMHints)); Hints.flags = PSize | PMinSize; Hints.min_width = Hints.base_width = SNES_WIDTH; Hints.min_height = Hints.base_height = SNES_HEIGHT_EXTENDED; WMHints.input = True; WMHints.flags = InputHint; XSetWMHints (GUI.display, GUI.window, &WMHints); XSetWMNormalHints (GUI.display, GUI.window, &Hints); } XSelectInput (GUI.display, GUI.window, FocusChangeMask | ExposureMask | KeyPressMask | KeyReleaseMask | StructureNotifyMask | ButtonPressMask | ButtonReleaseMask);#ifdef USE_DGA_EXTENSION if (XF86.full_screen_available) XSelectInput (GUI.display, XF86.fs_window, FocusChangeMask | ExposureMask | KeyPressMask | KeyReleaseMask | StructureNotifyMask | ButtonPressMask | ButtonReleaseMask);#endif if (GUI.pseudo) { GUI.cmap = XCreateColormap (GUI.display, GUI.window, GUI.visual, True); XSetWindowColormap (GUI.display, GUI.window, GUI.cmap); for (i = 0; i < 256; i++) { GUI.colors[i].red = GUI.colors[i].green = GUI.colors[i].blue = 0; GUI.colors[i].pixel = i; GUI.colors[i].flags = DoRed | DoGreen | DoBlue; } XStoreColors (GUI.display, GUI.cmap, GUI.colors, 256); } XMapRaised (GUI.display, GUI.window); XClearWindow (GUI.display, GUI.window); SetupImage (); switch (GUI.depth) { case 8: GUI.bytes_per_pixel = 1; break; case 15: case 16: GUI.bytes_per_pixel = 2; break; case 24:
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -