📄 ggi.cpp
字号:
/* * Snes9x - Portable Super Nintendo Entertainment System (TM) emulator. * * (c) Copyright 1996, 1997, 1998 Gary Henderson (gary@daniver.demon.co.uk) and * Jerremy Koot (jkoot@euronet.nl) * * Super FX C emulator code * (c) Copyright 1997, 1998 Lestat (lstat@hotmail.com) and * Gary Henderson. * Super FX assembler emulator code (c) Copyright 1998 zsKnight and _Demo_. * * DSP1 emulator code (c) Copyright 1998 Lestat and Gary Henderson. * DOS port code contains the works of other authors. See headers in * individual files. * * 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 "snes9x.h"#include "memmap.h"#include "debug.h"#include "ppu.h"#include "snapshot.h"#include "gfx.h"#include "display.h"#include "apu.h"#define NEED_GRAPHTYPE_SYMS#define uint32 ggi_uint32 // Ugly workarount, ggi's unit32 is int, not long...#include <ggi/ggi.h>#undef uint32static ggi_visual_t vis;static ggi_directbuffer_t dbuf;static ggi_pixellinearbuffer *plb = NULL;static int mouse_x = 0;static int mouse_y = 0;static uint32 mouse_buttons = 0;static bool8 superscope = FALSE;static uint32 superscope_turbo = 0;static uint32 superscope_pause = 0;static ggi_mode mode;static bool8 double_buffer; /* Use double_buffering, only for 8 bpp and 16 bpp (565). *//* For double buffering: */static uint32 start_y; /* Start-line of the visible screen */static uint32 framebuffer_screen_size;extern uint32 joypads [5];static void Convert16to8(int width, int height);static void Convert16to15(int width, int height);static void Convert16to16(int width, int height);static void Convert16to24(int width, int height);static void Convert16to32(int width, int height);static void Convert8to8(int width, int height);void S9xDeinitDisplay (){ ggiClose(vis);}static void SetModeType(ggi_graphtype type, bool8 double_height){ mode.frames = 1; mode.visible.x = IMAGE_WIDTH; mode.visible.y = IMAGE_HEIGHT; mode.virt.x = IMAGE_WIDTH; mode.virt.y = (double_height)?(IMAGE_HEIGHT*2):(IMAGE_HEIGHT); mode.graphtype = type; mode.size.x = GGI_AUTO; mode.size.y = GGI_AUTO; mode.dpp.x = GGI_AUTO; mode.dpp.y = GGI_AUTO;}static bool8 InitSixteenBit(void){ SetModeType(GT_16BIT, TRUE); ggiCheckMode(vis, &mode); if (mode.graphtype == GT_16BIT) { mode.virt.y = 2*mode.virt.y; if (ggiCheckMode(vis, &mode)==0) { double_buffer = TRUE; return TRUE; } mode.virt.y = mode.virt.y; if (ggiCheckMode(vis, &mode)==0) { double_buffer = FALSE; return TRUE; } } SetModeType(GT_15BIT, FALSE); if (mode.graphtype == GT_15BIT) { if (ggiCheckMode(vis, &mode)==0) { double_buffer = FALSE; return TRUE; } } SetModeType(GT_32BIT, FALSE); if (mode.graphtype == GT_32BIT) { if (ggiCheckMode(vis, &mode)==0) { double_buffer = FALSE; return TRUE; } } SetModeType(GT_24BIT, FALSE); if (mode.graphtype == GT_24BIT) { if (ggiCheckMode(vis, &mode)==0) { double_buffer = FALSE; return TRUE; } } return FALSE; }static bool8 InitEightBit(void){ SetModeType(GT_8BIT, TRUE); ggiCheckMode(vis, &mode); if (mode.graphtype == GT_8BIT) { mode.virt.y = 2*mode.virt.y; if (ggiCheckMode(vis, &mode)==0) { double_buffer = TRUE; return TRUE; } mode.virt.y = mode.virt.y; if (ggiCheckMode(vis, &mode)==0) { double_buffer = FALSE; return TRUE; } } return FALSE;}void S9xInitDisplay (int, char **){ if (ggiInit() != 0) { fprintf(stderr, "unable to initialize libggi, exiting.\n"); S9xExit (); } if ((vis=ggiOpen(NULL)) == NULL) { fprintf(stderr, "unable to open default visual, exiting.\n"); S9xExit (); } if (InitSixteenBit()) { Settings.SixteenBit = TRUE; if (Settings.ForceNoTransparency) { Settings.Transparency = FALSE; } else { Settings.Transparency = TRUE; } } else if (InitEightBit()) { if (Settings.ForceTransparency) { fprintf(stderr, "Transparency not supported in 256 color mode.\n"); S9xExit(); Settings.SixteenBit = TRUE; Settings.Transparency = TRUE; } else { Settings.SixteenBit = FALSE; Settings.Transparency = FALSE; } } else { fprintf(stderr, "Cannot find suitable graphics mode, exiting.\n"); S9xExit (); } printf("Opening screen: %dx%d (%dx%d) (%s)\n", mode.visible.x, mode.visible.y, mode.virt.x, mode.virt.y, ggi_graphmask_sym[mode.graphtype+1]); if (ggiSetMode(vis, &mode) != 0) { fprintf(stderr, "Cannot open graphic mode!\n"); S9xExit (); } ggiSetFlags(vis, GGIFLAG_ASYNC); if ( ggiDBGetBuffer (vis, &dbuf) ) { fprintf (stderr, "Error getting display buffer.\n"); S9xExit (); } if (ggiDBGetLayout (dbuf) != blPixelLinearBuffer) { fprintf (stderr, "Error: nonlinear display buffer.\n"); S9xExit (); } if ( (plb = ggiDBGetPLB (dbuf)) == NULL) { fprintf(stderr, "Error getting pixel linear buffer.\n"); S9xExit (); } framebuffer_screen_size = plb->stride * mode.visible.y; if (double_buffer) { if ( ((mode.graphtype==GT_8BIT) && (plb->setup==sp8a8i8)) || ((mode.graphtype==GT_16BIT) && (plb->setup==sp16a16r5g6b5)) ) { GFX.Screen = (uint8 *) plb->write + framebuffer_screen_size; GFX.Pitch = plb->stride; GFX.SubScreen = (uint8 *) malloc (plb->stride * mode.visible.y ); start_y = 0; ggiSetOrigin(vis, 0, start_y); } else { fprintf(stderr, "Wrong buffer type, fallback to non double_buffer\n"); double_buffer = FALSE; } } if (!double_buffer) { GFX.Screen = (uint8 *) malloc (plb->stride * mode.visible.y ); GFX.Pitch = plb->stride; GFX.SubScreen = (uint8 *) malloc (plb->stride * mode.visible.y ); }}void S9xPutImage (int width, int height){ if (double_buffer) { if (start_y == 0) { start_y = mode.visible.y; GFX.Screen = (uint8 *) plb->write; } else { start_y = 0; GFX.Screen = (uint8 *) plb->write + framebuffer_screen_size; } GFX.Delta = (GFX.SubScreen - GFX.Screen) >> 1; ggiSetOrigin(vis, 0, start_y); } else { if (Settings.SixteenBit) { /* 16 bpp source */ switch (mode.graphtype) { case GT_8BIT: Convert16to8(width, height); break; case GT_15BIT: Convert16to15(width, height); break; case GT_16BIT: Convert16to16(width, height); break; case GT_24BIT: Convert16to24(width, height); break; case GT_32BIT: Convert16to32(width, height); break; default: break; } } else { /* 8 bpp source */ switch (mode.graphtype) { case GT_8BIT: Convert8to8(width, height); break; default: break; } } } ggiFlush(vis);}void S9xSetTitle (const char *string){}bool8 S9xReadMousePosition (int which1, int &x, int &y, uint32 &buttons){ if (which1 == 0) { x = mouse_x; y = mouse_y; buttons = mouse_buttons; return (TRUE); } return (FALSE);}bool8 S9xReadSuperScopePosition (int &x, int &y, uint32 &buttons){ x = mouse_x; y = mouse_y; buttons = (mouse_buttons & 3) | (superscope_turbo << 2) | (superscope_pause << 3); return (TRUE);}void S9xProcessEvents (bool8 block){ ggi_event ev; struct timeval tv = {0,0}; ggi_event_mask mask; uint32 keysym; if ((!block) && ((mask=ggiEventPoll(vis, emAll, &tv))==0)) { return; } do { ggiEventRead(vis, &ev, emAll); uint8 byte1 = 0; uint8 byte2 = 0; uint8 byte3 = 0; uint8 byte4 = 0; switch(ev.any.type) { case evKeyRepeat: break; case evKeyPress: case evKeyRelease: keysym = ev.key.sym; switch ( keysym) { case 'k': case GGI_KEY_RIGHT: byte2 = 1; break; case 'h': case GGI_KEY_LEFT: byte2 = 2; break; case 'j': case 'n': case GGI_KEY_DOWN: byte2 = 4; break; case 'u': case GGI_KEY_UP: byte2 = 8; break; case GGI_KEY_RETURN: byte2 = 16; break; // Start case ' ': byte2 = 32; break; // Select case '.': case 't': case 'd': byte1 = 128; break; // A case '/': case 'y': case 'c': byte2 = 128; break; // B
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -