📄 svga.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. */#ifdef __linux#include <string.h>#include <ctype.h>#include <unistd.h>#include <sys/types.h>#include <sys/stat.h>#include <sys/io.h>#include <stdlib.h>#include <signal.h>#include <vga.h>#include <vgagl.h>#include <vgakeyboard.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 COUNT(a) (sizeof(a) / sizeof(a[0]))static bool8 planar;static int screen_pitch;static int screen_width;static int screen_height;static int mode = -1;static bool8 stretch = FALSE;static bool8 text_mode = TRUE;static bool8 interpolation = FALSE;static char prev_keystate [128] = "";static bool8 restore_modex = FALSE;static uint8 *DeltaScreen = NULL;static vga_modeinfo *info = NULL;static uint32 video_page_size = 64 * 1024;static uint32 selected_video_page = ~0;extern uint32 joypads [5];#define ATTRCON_ADDR 0x3c0#define MISC_ADDR 0x3c2#define VGAENABLE_ADDR 0x3c3#define SEQ_ADDR 0x3c4#define GRACON_ADDR 0x3ce#define CRTC_ADDR 0x3d4#define STATUS_ADDR 0x3datypedef struct{ unsigned port; unsigned char index; unsigned char value;} Register;typedef Register *RegisterPtr;void outRegArray (Register *r, int n);Register scr256x256[] ={ { 0x3c2, 0x00, 0xe3},{ 0x3d4, 0x00, 0x5f},{ 0x3d4, 0x01, 0x3f}, { 0x3d4, 0x02, 0x40},{ 0x3d4, 0x03, 0x82},{ 0x3d4, 0x04, 0x4A}, { 0x3d4, 0x05, 0x9A},{ 0x3d4, 0x06, 0x23},{ 0x3d4, 0x07, 0xb2}, { 0x3d4, 0x08, 0x00},{ 0x3d4, 0x09, 0x61},{ 0x3d4, 0x10, 0x0a}, { 0x3d4, 0x11, 0xac},{ 0x3d4, 0x12, 0xff},{ 0x3d4, 0x13, 0x20}, { 0x3d4, 0x14, 0x40},{ 0x3d4, 0x15, 0x07},{ 0x3d4, 0x16, 0x1a}, { 0x3d4, 0x17, 0xa3},{ 0x3c4, 0x01, 0x01},{ 0x3c4, 0x04, 0x0e}, { 0x3ce, 0x05, 0x40},{ 0x3ce, 0x06, 0x05},{ 0x3c0, 0x10, 0x41}, { 0x3c0, 0x13, 0x00}};typedef struct{ int width; int height; int mode;} Mode;static Mode modes [] = { {320, 240, G320x240x256}, // 0 {320, 200, G320x200x256}, // 1 {256, 256, G320x200x256}, // 2 {640, 480, G640x480x256}, // 3 {800, 600, G800x600x256}, // 4 {320, 200, G320x200x64K}, // 5 {640, 480, G640x480x64K}, // 6 {800, 600, G800x600x64K}, // 7};int S9xMinCommandLineArgs (){ return (2);}void S9xGraphicsMode (){ if (text_mode) { screen_width = modes [mode].width; screen_height = modes [mode].height; int ret = vga_setmode (modes [mode].mode); if (ret < 0) { fprintf (stderr, "Unable to switch to requested screen mode/resolution:\n"); S9xExit (); } if (vga_setlinearaddressing () < 0) { if (info->flags & EXT_INFO_AVAILABLE) video_page_size = info->aperture_size; else video_page_size = 64 * 1024; } else video_page_size = ~0; if (modes [mode].mode == G320x200x256 && screen_width == 256) { iopl(3); outRegArray (scr256x256, sizeof (scr256x256) / sizeof (Register)); screen_pitch = screen_width; } gl_setcontextvga (modes [mode].mode); if (keyboard_init ()) { fprintf (stdout, "Keyboard initialisation failed.\n"); S9xExit (); } text_mode = FALSE; if (DeltaScreen) memset (DeltaScreen, 0xff, GFX.Pitch * IMAGE_HEIGHT); }}void S9xTextMode (){// if (!text_mode) { keyboard_close (); vga_setmode (TEXT); text_mode = TRUE; }}static struct sigaction sig1handler;static struct sigaction oldsig1handler;static struct sigaction sig2handler;static struct sigaction oldsig2handler;void Sig1HandlerFunction(int){ extern void StopTimer (); StopTimer (); sigaction(SIGUSR2, &sig2handler, NULL); sigaction(SIGUSR1, &oldsig1handler, NULL); sigsetmask (0); raise(SIGUSR1);}void Sig2HandlerFunction(int){ restore_modex = TRUE; sigaction(SIGUSR1, &sig1handler, NULL); sigaction(SIGUSR2, &oldsig2handler, NULL); sigsetmask (0); raise(SIGUSR2);}void S9xInitDisplay (int /*argc*/, char ** /*argv*/){ if (vga_init() < 0) { fprintf (stdout, "Unable to initialise vga.\n"); S9xExit (); } S9xTextMode (); if (mode < 0) { if (Settings.SixteenBit) mode = 6; else mode = 2; } info = vga_getmodeinfo (modes [mode].mode); if (info->flags & IS_MODEX) planar = 1; if (info->flags & CAPABLE_LINEAR) video_page_size = ~0; else if (info->flags & EXT_INFO_AVAILABLE) video_page_size = info->aperture_size; else video_page_size = 64 * 1024; if (!screen_pitch) screen_pitch = info->linewidth; if (info->bytesperpixel > 1) { Settings.Transparency = TRUE; Settings.SixteenBit = TRUE; } else { Settings.Transparency = FALSE; Settings.SixteenBit = FALSE; } if (info->width >= 512 && info->height >= 578) Settings.SupportHiRes = TRUE; if (!Settings.SixteenBit || info->width < 512 || info->height < 240) interpolation = FALSE; if (interpolation) { GFX.Pitch = (IMAGE_WIDTH + 2) * 2; GFX.Screen = (uint8 *) malloc (GFX.Pitch * IMAGE_HEIGHT); GFX.SubScreen = (uint8 *) malloc (GFX.Pitch * IMAGE_HEIGHT); DeltaScreen = (uint8 *) malloc (GFX.Pitch * IMAGE_HEIGHT); GFX.ZBuffer = (uint8 *) malloc ((GFX.Pitch >> 1) * IMAGE_HEIGHT); GFX.SubZBuffer = (uint8 *) malloc ((GFX.Pitch >> 1) * IMAGE_HEIGHT); if (!GFX.Screen || !GFX.SubScreen || !DeltaScreen || !GFX.ZBuffer || !GFX.SubZBuffer) { fprintf (stdout, "Cannot allocate screen buffer.\n"); S9xExit (); } } else if (Settings.SixteenBit) { GFX.Pitch = IMAGE_WIDTH * 2; GFX.Screen = (uint8 *) malloc (GFX.Pitch * IMAGE_HEIGHT); GFX.SubScreen = (uint8 *) malloc (GFX.Pitch * IMAGE_HEIGHT); GFX.ZBuffer = (uint8 *) malloc ((GFX.Pitch >> 1) * IMAGE_HEIGHT); GFX.SubZBuffer = (uint8 *) malloc ((GFX.Pitch >> 1) * IMAGE_HEIGHT); if (!GFX.Screen || !GFX.SubScreen) { fprintf (stdout, "Cannot allocate screen buffer.\n"); S9xExit (); } } else { GFX.Pitch = IMAGE_WIDTH; GFX.Screen = (uint8 *) malloc (GFX.Pitch * IMAGE_HEIGHT); if (!GFX.Screen) { fprintf (stdout, "Cannot allocate screen buffer.\n"); S9xExit (); } GFX.SubScreen = NULL; DeltaScreen = (uint8 *) malloc (GFX.Pitch * IMAGE_HEIGHT); if (!DeltaScreen) { fprintf (stdout, "Cannot allocate shadow screen buffer.\n"); S9xExit (); } GFX.ZBuffer = (uint8 *) malloc (GFX.Pitch * IMAGE_HEIGHT); GFX.SubZBuffer = NULL; } ZeroMemory (GFX.Screen, GFX.Pitch * IMAGE_HEIGHT); if (GFX.SubScreen) ZeroMemory (GFX.SubScreen, GFX.Pitch * IMAGE_HEIGHT); if (DeltaScreen) ZeroMemory (DeltaScreen, GFX.Pitch * IMAGE_HEIGHT); sig1handler.sa_handler = Sig1HandlerFunction; sigemptyset (&sig1handler.sa_mask); sig1handler.sa_flags = 0; sig2handler.sa_handler = Sig2HandlerFunction; sigemptyset (&sig2handler.sa_mask); sig2handler.sa_flags = 0; sigaction (SIGUSR1, &sig1handler, &oldsig1handler); sigaction (SIGUSR2, &sig2handler, &oldsig2handler);}void S9xDeinitDisplay (){ S9xTextMode (); if (GFX.Screen) free ((char *) GFX.Screen); if (GFX.SubScreen) free ((char *) GFX.SubScreen); if (DeltaScreen) free ((char *) DeltaScreen); if (GFX.ZBuffer) free ((char *) GFX.ZBuffer); if (GFX.SubZBuffer) free ((char *) GFX.SubZBuffer); GFX.Screen = NULL; GFX.SubScreen = NULL; DeltaScreen = NULL; GFX.ZBuffer = NULL; GFX.SubZBuffer = NULL;}void S9xSetPalette (){ uint16 Brightness = IPPU.MaxBrightness * 138; for (int i = 0; i < 256; i++) vga_setpalette (i, (((PPU.CGDATA [i] >> 0) & 0x1F) * Brightness) >> 10, (((PPU.CGDATA [i] >> 5) & 0x1F) * Brightness) >> 10, (((PPU.CGDATA [i] >> 10) & 0x1F) * Brightness) >> 10);}void S9xProcessEvents (bool8 block){ int fn = -1; if (restore_modex) { restore_modex = FALSE; ZeroMemory (prev_keystate, 128); if (!text_mode && modes [mode].mode == G320x200x256 && screen_width == 256) { iopl(3); outRegArray (scr256x256, sizeof (scr256x256) / sizeof (Register)); } extern void InitTimer (); InitTimer (); } if (block) {// keyboard_waitforupdate (); usleep (10000); keyboard_update (); } else keyboard_update (); char *keystate = keyboard_getstate (); #define KEY_DOWN(a) (keystate[a])#define KEY_PRESS(a) (keystate[a] && !prev_keystate[a])#define KEY_WASPRESSED(a) (prev_keystate[a] && !keystate[a])#define PROCESS_KEY(k, b, v)\if (KEY_PRESS(k)) b |= v;\if (KEY_WASPRESSED(k)) b &= ~v; if (KEY_PRESS (SCANCODE_ESCAPE)) S9xExit (); // Joypad 1: PROCESS_KEY(SCANCODE_K, joypads [0], SNES_RIGHT_MASK) PROCESS_KEY(SCANCODE_CURSORBLOCKRIGHT, joypads [0], SNES_RIGHT_MASK) PROCESS_KEY(SCANCODE_H, joypads [0], SNES_LEFT_MASK) PROCESS_KEY(SCANCODE_CURSORBLOCKLEFT, joypads [0], SNES_LEFT_MASK) PROCESS_KEY(SCANCODE_N, joypads [0], SNES_DOWN_MASK) PROCESS_KEY(SCANCODE_J, joypads [0], SNES_DOWN_MASK) PROCESS_KEY(SCANCODE_CURSORBLOCKDOWN, joypads [0], SNES_DOWN_MASK) PROCESS_KEY(SCANCODE_U, joypads [0], SNES_UP_MASK) PROCESS_KEY(SCANCODE_CURSORBLOCKUP, joypads [0], SNES_UP_MASK) PROCESS_KEY(SCANCODE_ENTER, joypads [0], SNES_START_MASK) PROCESS_KEY(SCANCODE_SPACE, joypads [0], SNES_SELECT_MASK) PROCESS_KEY(SCANCODE_A, joypads [0], SNES_TL_MASK) PROCESS_KEY(SCANCODE_V, joypads [0], SNES_TL_MASK) PROCESS_KEY(SCANCODE_Q, joypads [0], SNES_TL_MASK) PROCESS_KEY(SCANCODE_Z, joypads [0], SNES_TR_MASK) PROCESS_KEY(SCANCODE_B, joypads [0], SNES_TR_MASK) PROCESS_KEY(SCANCODE_W, joypads [0], SNES_TR_MASK) PROCESS_KEY(SCANCODE_S, joypads [0], SNES_X_MASK) PROCESS_KEY(SCANCODE_M, joypads [0], SNES_X_MASK) PROCESS_KEY(SCANCODE_E, joypads [0], SNES_X_MASK) PROCESS_KEY(SCANCODE_X, joypads [0], SNES_Y_MASK)
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -