| diff --git a/port.h b/port.h |
| --- a/port.h |
| +++ b/port.h |
| @@ -331,7 +331,7 @@ void SetInfoDlgColor(unsigned char, unsigned char, unsigned char); |
| #define TITLE "Snes9x" |
| #endif |
| |
| -#if defined(__i386__) || defined(__i486__) || defined(__i586__) || defined(__i686__) || defined(__x86_64__) || defined(__alpha__) || defined(__MIPSEL__) || defined(_M_IX86) || defined(_M_X64) |
| +#if defined(__i386__) || defined(__i486__) || defined(__i586__) || defined(__i686__) || defined(__x86_64__) || defined(__alpha__) || defined(__MIPSEL__) || defined(_M_IX86) || defined(_M_X64) || defined(__native_client__) |
| #define LSB_FIRST |
| #define FAST_LSB_WORD_ACCESS |
| #else |
| diff --git a/unix/Makefile.in b/unix/Makefile.in |
| --- a/unix/Makefile.in |
| +++ b/unix/Makefile.in |
| @@ -2,14 +2,19 @@ |
| @S9XNETPLAY@ |
| @S9XZIP@ |
| @S9XJMA@ |
| +@S9XX11@ |
| |
| # Fairly good and special-char-safe descriptor of the os being built on. |
| OS = `uname -s -r -m|sed \"s/ /-/g\"|tr \"[A-Z]\" \"[a-z]\"|tr \"/()\" \"___\"` |
| BUILDDIR = . |
| |
| -OBJECTS = ../apu/apu.o ../apu/SNES_SPC.o ../apu/SNES_SPC_misc.o ../apu/SNES_SPC_state.o ../apu/SPC_DSP.o ../apu/SPC_Filter.o ../bsx.o ../c4.o ../c4emu.o ../cheats.o ../cheats2.o ../clip.o ../conffile.o ../controls.o ../cpu.o ../cpuexec.o ../cpuops.o ../crosshairs.o ../dma.o ../dsp.o ../dsp1.o ../dsp2.o ../dsp3.o ../dsp4.o ../fxinst.o ../fxemu.o ../gfx.o ../globals.o ../logger.o ../memmap.o ../movie.o ../obc1.o ../ppu.o ../reader.o ../sa1.o ../sa1cpu.o ../screenshot.o ../sdd1.o ../sdd1emu.o ../seta.o ../seta010.o ../seta011.o ../seta018.o ../snapshot.o ../snes9x.o ../spc7110.o ../srtc.o ../tile.o ../filter/2xsai.o ../filter/blit.o ../filter/epx.o ../filter/hq2x.o ../filter/snes_ntsc.o unix.o x11.o |
| +OBJECTS = ../apu/apu.o ../apu/SNES_SPC.o ../apu/SNES_SPC_misc.o ../apu/SNES_SPC_state.o ../apu/SPC_DSP.o ../apu/SPC_Filter.o ../bsx.o ../c4.o ../c4emu.o ../cheats.o ../cheats2.o ../clip.o ../conffile.o ../controls.o ../cpu.o ../cpuexec.o ../cpuops.o ../crosshairs.o ../dma.o ../dsp.o ../dsp1.o ../dsp2.o ../dsp3.o ../dsp4.o ../fxinst.o ../fxemu.o ../gfx.o ../globals.o ../logger.o ../memmap.o ../movie.o ../obc1.o ../ppu.o ../reader.o ../sa1.o ../sa1cpu.o ../screenshot.o ../sdd1.o ../sdd1emu.o ../seta.o ../seta010.o ../seta011.o ../seta018.o ../snapshot.o ../snes9x.o ../spc7110.o ../srtc.o ../tile.o ../filter/2xsai.o ../filter/blit.o ../filter/epx.o ../filter/hq2x.o ../filter/snes_ntsc.o ../unix/unix.o ../unix/nacl.o |
| DEFS = -DMITSHM |
| |
| +ifdef S9XX11 |
| +OBJECTS += ../unix/x11.o |
| +endif |
| + |
| ifdef S9XDEBUGGER |
| OBJECTS += ../debug.o ../fxdbg.o |
| endif |
| diff --git a/unix/configure.ac b/unix/configure.ac |
| --- a/unix/configure.ac |
| +++ b/unix/configure.ac |
| @@ -38,7 +38,7 @@ AC_DEFUN([AC_S9X_COMPILER_FLAG], |
| return (argc); |
| } |
| ], |
| - [snes9x_cv_option_$2="yes"], [snes9x_cv_option_$2="no"]) |
| + [snes9x_cv_option_$2="yes"], [snes9x_cv_option_$2="no"], [AC_MSG_RESULT(skip for crosscompiling)]) |
| ]) |
| |
| CXXFLAGS="[$]OLD_CXXFLAGS" |
| @@ -58,15 +58,15 @@ AC_DEFUN([AC_S9X_COMPILER_FLAG], |
| |
| # Remove -g and -O2 flags manually. |
| |
| -if test "x$CFLAGS" != "x"; then |
| - CFLAGS="`echo \"$CFLAGS\" | sed -e 's/-g//'`" |
| - CFLAGS="`echo \"$CFLAGS\" | sed -e 's/-O2//'`" |
| -fi |
| - |
| -if test "x$CXXFLAGS" != "x"; then |
| - CXXFLAGS="`echo \"$CXXFLAGS\" | sed -e 's/-g//'`" |
| - CXXFLAGS="`echo \"$CXXFLAGS\" | sed -e 's/-O2//'`" |
| -fi |
| +#if test "x$CFLAGS" != "x"; then |
| +# CFLAGS="`echo \"$CFLAGS\" | sed -e 's/-g//'`" |
| +# CFLAGS="`echo \"$CFLAGS\" | sed -e 's/-O2//'`" |
| +#fi |
| +# |
| +#if test "x$CXXFLAGS" != "x"; then |
| +# CXXFLAGS="`echo \"$CXXFLAGS\" | sed -e 's/-g//'`" |
| +# CXXFLAGS="`echo \"$CXXFLAGS\" | sed -e 's/-O2//'`" |
| +#fi |
| |
| # Test what compiler flags we should use. |
| |
| @@ -259,12 +259,13 @@ AC_CHECK_FUNC([mkstemp], |
| S9XDEFS="$S9XDEFS -DHAVE_MKSTEMP" |
| ]) |
| |
| -# Check X11 |
| +# Check X11. |
| + |
| +S9XX11="#S9XX11=1" |
| |
| AC_PATH_XTRA |
| -if test "x$no_x" = "xyes"; then |
| - AC_MSG_ERROR([X11 is required.]) |
| -else |
| +if test "x$no_x" != "xyes"; then |
| + S9XX11="S9XX11=1" |
| S9XFLGS="$S9XFLGS $X_CFLAGS" |
| S9XLIBS="$S9XLIBS $X_PRE_LIBS -lX11 -lXext $X_LIBS $X_EXTRA_LIBS" |
| fi |
| @@ -303,7 +304,7 @@ if test "x$snes9x_have_stdint_h" = "x"; then |
| return (!(sizeof(void *) == sizeof(int))); |
| } |
| ], |
| - [snes9x_ptr_is_int="yes"], [snes9x_ptr_is_int="no"]) |
| + [snes9x_ptr_is_int="yes"], [snes9x_ptr_is_int="no"], [AC_MSG_RESULT(skip for crosscompiling)]) |
| |
| if test "x$snes9x_ptr_is_int" = "xyes"; then |
| AC_MSG_RESULT(yes) |
| @@ -350,7 +351,7 @@ AC_DEFUN([AC_S9X_CHECK_SAR], |
| return (i < 0 ? 0 : 1); |
| } |
| ], |
| - [snes9x_sar_$1="yes"], [snes9x_sar_$1="no"]) |
| + [snes9x_sar_$1="yes"], [snes9x_sar_$1="no"], [AC_MSG_RESULT(skip for crosscompiling)]) |
| |
| CXXFLAGS="[$]OLD_CXXFLAGS" |
| |
| @@ -388,7 +389,7 @@ if test "x$enable_sound" = "xyes"; then |
| AC_MSG_RESULT([yes]) |
| else |
| AC_MSG_RESULT([no]) |
| - AC_MSG_WARN([Your OS is not Linux. Build without sound support.]) |
| + AC_MSG_WARN([Your OS is not Linux. Build without Linux sound support.]) |
| enable_sound="no" |
| fi |
| fi |
| @@ -406,7 +407,7 @@ fi |
| # Output. |
| |
| S9XFLGS="$CXXFLAGS $CPPFLAGS $LDFLAGS $S9XFLGS" |
| -S9XLIBS="$LIBS $S9XLIBS" |
| +S9XLIBS="$LIBS $EXTRA_LIBS $S9XLIBS" |
| |
| S9XFLGS="`echo \"$S9XFLGS\" | sed -e 's/ */ /g'`" |
| S9XDEFS="`echo \"$S9XDEFS\" | sed -e 's/ */ /g'`" |
| @@ -422,6 +423,7 @@ AC_SUBST(S9XDEBUGGER) |
| AC_SUBST(S9XNETPLAY) |
| AC_SUBST(S9XZIP) |
| AC_SUBST(S9XJMA) |
| +AC_SUBST(S9XX11) |
| |
| rm config.info 2>/dev/null |
| |
| diff --git a/unix/keycodes.h b/unix/keycodes.h |
| new file mode 100644 |
| --- /dev/null |
| +++ b/unix/keycodes.h |
| @@ -0,0 +1,271 @@ |
| +/* Copyright (c) 2013 The Native Client Authors. All rights reserved. |
| + * Use of this source code is governed by a BSD-style license that can be |
| + * found in the LICENSE file. */ |
| + |
| +const char* kKeyCodeNames[] = { |
| + NULL, // 0 |
| + NULL, // 1 |
| + NULL, // 2 |
| + "Cancel", // 3 |
| + NULL, // 4 |
| + NULL, // 5 |
| + "Help", // 6 |
| + NULL, // 7 |
| + "BackSpace", // 8 |
| + "Tab", // 9 |
| + NULL, // 10 |
| + NULL, // 11 |
| + "Clear", // 12 |
| + "Return", // 13 |
| + "Enter", // 14 |
| + NULL, // 15 |
| + "Shift", // 16 |
| + "Control", // 17 |
| + "Alt", // 18 |
| + "Pause", // 19 |
| + "CapsLock", // 20 |
| + "Kana", // 21 |
| + "Eisu", // 22 |
| + "Junja", // 23 |
| + "Final", // 24 |
| + "Hanja", // 25 |
| + NULL, // 26 |
| + "Escape", // 27 |
| + "Convert", // 28 |
| + "Nonconvert", // 29 |
| + "Accept", // 30 |
| + "Modechange", // 31 |
| + "Space", // 32 |
| + "PageUp", // 33 |
| + "PageDown", // 34 |
| + "End", // 35 |
| + "Home", // 36 |
| + "Left", // 37 |
| + "Up", // 38 |
| + "Right", // 39 |
| + "Down", // 40 |
| + "Select", // 41 |
| + "Print", // 42 |
| + "Execute", // 43 |
| + "Printscreen", // 44 |
| + "Insert", // 45 |
| + "Delete", // 46 |
| + NULL, |
| + "0", // 48 |
| + "1", // 49 |
| + "2", // 50 |
| + "3", // 51 |
| + "4", // 52 |
| + "5", // 53 |
| + "6", // 54 |
| + "7", // 55 |
| + "8", // 56 |
| + "9", // 57 |
| + "Colon", // 58 |
| + "Semicolon", // 59 |
| + "LessThan", // 60 |
| + "Equals", // 61 |
| + "GreaterThan", // 62 |
| + "QuestionMark", // 63 |
| + "At", // 64 |
| + "A", // 65 |
| + "B", // 66 |
| + "C", // 67 |
| + "D", // 68 |
| + "E", // 69 |
| + "F", // 70 |
| + "G", // 71 |
| + "H", // 72 |
| + "I", // 73 |
| + "J", // 74 |
| + "K", // 75 |
| + "L", // 76 |
| + "M", // 77 |
| + "N", // 78 |
| + "O", // 79 |
| + "P", // 80 |
| + "Q", // 81 |
| + "R", // 82 |
| + "S", // 83 |
| + "T", // 84 |
| + "U", // 85 |
| + "V", // 86 |
| + "W", // 87 |
| + "X", // 88 |
| + "Y", // 89 |
| + "Z", // 90 |
| + "Win", // 91 |
| + NULL, |
| + "ContextMenu", // 93 |
| + NULL, |
| + "Sleep", // 95 |
| + "Numpad0", // 96 |
| + "Numpad1", // 97 |
| + "Numpad2", // 98 |
| + "Numpad3", // 99 |
| + "Numpad4", // 100 |
| + "Numpad5", // 101 |
| + "Numpad6", // 102 |
| + "Numpad7", // 103 |
| + "Numpad8", // 104 |
| + "Numpad9", // 105 |
| + "Multiply", // 106 |
| + "Add", // 107 |
| + "Separator", // 108 |
| + "Subtract", // 109 |
| + "Decimal", // 110 |
| + "Divide", // 111 |
| + "F1", // 112 |
| + "F2", // 113 |
| + "F3", // 114 |
| + "F4", // 115 |
| + "F5", // 116 |
| + "F6", // 117 |
| + "F7", // 118 |
| + "F8", // 119 |
| + "F9", // 120 |
| + "F10", // 121 |
| + "F11", // 122 |
| + "F12", // 123 |
| + "F13", // 124 |
| + "F14", // 125 |
| + "F15", // 126 |
| + "F16", // 127 |
| + "F17", // 128 |
| + "F18", // 129 |
| + "F19", // 130 |
| + "F20", // 131 |
| + "F21", // 132 |
| + "F22", // 133 |
| + "F23", // 134 |
| + "F24", // 135 |
| + NULL, // 136 |
| + NULL, // 137 |
| + NULL, // 138 |
| + NULL, // 139 |
| + NULL, // 140 |
| + NULL, // 141 |
| + NULL, // 142 |
| + NULL, // 143 |
| + "NumLock", // 144 |
| + "ScrollLock", // 145 |
| + "WinOemFjJisho", // 146 |
| + "WinOemFjMasshou", // 147 |
| + "WinOemFjTouroku", // 148 |
| + "WinOemFjLoya", // 149 |
| + "WinOemFjRoya", // 150 |
| + NULL, // 151 |
| + NULL, // 152 |
| + NULL, // 153 |
| + NULL, // 154 |
| + NULL, // 155 |
| + NULL, // 156 |
| + NULL, // 157 |
| + NULL, // 158 |
| + NULL, // 159 |
| + "Circumflex", // 160 |
| + "Exclamation", // 161 |
| + "DoubleQuote", // 162 |
| + "Hash", // 163 |
| + "Dollar", // 164 |
| + "Percent", // 165 |
| + "Ampersand", // 166 |
| + "Underscore", // 167 |
| + "OpenParen", // 168 |
| + "CloseParen", // 169 |
| + "Asterisk", // 170 |
| + "Plus", // 171 |
| + "Pipe", // 172 |
| + "HyphenMinus", // 173 |
| + "OpenCurlyBracket", // 174 |
| + "CloseCurlyBracket", // 175 |
| + "Tilde", // 176 |
| + NULL, // 177 |
| + NULL, // 178 |
| + NULL, // 179 |
| + NULL, // 180 |
| + "VolumeMute", // 181 |
| + "VolumeDown", // 182 |
| + "VolumeUp", // 183 |
| + NULL, // 184 |
| + NULL, // 185 |
| + NULL, // 186 |
| + NULL, // 187 |
| + "Comma", // 188 |
| + NULL, // 189 |
| + "Period", // 190 |
| + "Slash", // 191 |
| + "BackQuote", // 192 |
| + NULL, // 193 |
| + NULL, // 194 |
| + NULL, // 195 |
| + NULL, // 196 |
| + NULL, // 197 |
| + NULL, // 198 |
| + NULL, // 199 |
| + NULL, // 200 |
| + NULL, // 201 |
| + NULL, // 202 |
| + NULL, // 203 |
| + NULL, // 204 |
| + NULL, // 205 |
| + NULL, // 206 |
| + NULL, // 207 |
| + NULL, // 208 |
| + NULL, // 209 |
| + NULL, // 210 |
| + NULL, // 211 |
| + NULL, // 212 |
| + NULL, // 213 |
| + NULL, // 214 |
| + NULL, // 215 |
| + NULL, // 216 |
| + NULL, // 217 |
| + NULL, // 218 |
| + "OpenBracket", // 219 |
| + "BackSlash", // 220 |
| + "CloseBracket", // 221 |
| + "Quote", // 222 |
| + NULL, // 223 |
| + "Meta", // 224 |
| + "AltGr", // 225 |
| + NULL, // 226 |
| + "WinIcoHelp", // 227 |
| + "WinIco00", // 228 |
| + NULL, // 229 |
| + "WinIcoClear", // 230 |
| + NULL, // 231 |
| + NULL, // 232 |
| + "WinOemReset", // 233 |
| + "WinOemJump", // 234 |
| + "WinOemPa1", // 235 |
| + "WinOemPa2", // 236 |
| + "WinOemPa3", // 237 |
| + "WinOemWsctrl", // 238 |
| + "WinOemCusel", // 239 |
| + "WinOemAttn", // 240 |
| + "WinOemFinish", // 241 |
| + "WinOemCopy", // 242 |
| + "WinOemAuto", // 243 |
| + "WinOemEnlw", // 244 |
| + "WinOemBacktab", // 245 |
| + "Attn", // 246 |
| + "CrSel", // 247 |
| + "ExSel", // 248 |
| + "ErEOF", // 249 |
| + "Play", // 250 |
| + "Zoom", // 251 |
| + NULL, // 252 |
| + "PA1", // 253 |
| + "WinOemClear", // 254 |
| +}; |
| + |
| +static inline int StringToCode(const char* name) { |
| + const int kNumKeyCodeNames = sizeof(kKeyCodeNames)/sizeof(kKeyCodeNames[0]); |
| + for (int i = 0; i < kNumKeyCodeNames; ++i) { |
| + if (kKeyCodeNames[i] && strcmp(name, kKeyCodeNames[i]) == 0) { |
| + return i; |
| + } |
| + } |
| + return -1; |
| +} |
| diff --git a/unix/nacl.cpp b/unix/nacl.cpp |
| new file mode 100644 |
| --- /dev/null |
| +++ b/unix/nacl.cpp |
| @@ -0,0 +1,694 @@ |
| +/* Copyright (c) 2013 The Native Client Authors. All rights reserved. |
| + * Use of this source code is governed by a BSD-style license that can be |
| + * found in the LICENSE file. */ |
| + |
| +#ifdef __native_client__ |
| + |
| +#include <assert.h> |
| +#include <errno.h> |
| +#include <fcntl.h> |
| +#include <pthread.h> |
| +#include <stdio.h> |
| +#include <stdlib.h> |
| +#include <string.h> |
| +#include <sys/mount.h> |
| +#include <sys/stat.h> |
| +#include <sys/types.h> |
| +#include <unistd.h> |
| + |
| +#include <string> |
| +#include <vector> |
| +#include <utility> |
| + |
| +#include <ppapi/c/ppb_input_event.h> |
| +#include <ppapi/cpp/audio.h> |
| +#include <ppapi/cpp/audio_config.h> |
| +#include <ppapi/cpp/instance.h> |
| +#include <ppapi/cpp/input_event.h> |
| + |
| +#include "nacl_io/nacl_io.h" |
| +#include "ppapi_simple/ps_context_2d.h" |
| +#include "ppapi_simple/ps_event.h" |
| +#include "ppapi_simple/ps_interface.h" |
| +#include "ppapi_simple/ps_main.h" |
| + |
| +#include "snes9x.h" |
| +#include "apu.h" |
| +#include "blit.h" |
| +#include "conffile.h" |
| +#include "controls.h" |
| +#include "display.h" |
| +#include "logger.h" |
| +#include "memmap.h" |
| +#include "movie.h" |
| +#include "ppu.h" |
| +#include "ring_buffer.h" |
| + |
| +#include "keycodes.h" |
| + |
| +enum { |
| + VIDEOMODE_BLOCKY = 1, |
| + VIDEOMODE_TV, |
| + VIDEOMODE_SMOOTH, |
| + VIDEOMODE_SUPEREAGLE, |
| + VIDEOMODE_2XSAI, |
| + VIDEOMODE_SUPER2XSAI, |
| + VIDEOMODE_EPX, |
| + VIDEOMODE_HQ2X |
| +}; |
| + |
| +typedef void (* Blitter) (uint8 *, int, uint8 *, int, int, int); |
| + |
| + |
| +// Consts |
| +const int kSampleFrameCount = 1024; |
| +const int kSampleSize = 4; // Always 16-bit stereo |
| +const int kFilterBufferPitch = (SNES_WIDTH * 2) * 2; |
| +const uint32 kMousePointerBit = 0x00008000; |
| +const uint32 kKeyboardBit = 0x00000000; |
| +const uint32 kMouseBit = 0x40000000; |
| +const uint32 kJoystickBit = 0x80000000; |
| + |
| +const uint32_t kModifiersMask = |
| + PP_INPUTEVENT_MODIFIER_SHIFTKEY | |
| + PP_INPUTEVENT_MODIFIER_CONTROLKEY | |
| + PP_INPUTEVENT_MODIFIER_ALTKEY | |
| + PP_INPUTEVENT_MODIFIER_METAKEY; |
| +const int kModifierShift = 8; |
| +const uint32_t kKeyCodeMask = 0xff; |
| + |
| + |
| +// Statics |
| +static PSContext2D_t* s_context2d; |
| +static uint8* s_snes_buffer; |
| +static uint8* s_filter_buffer; |
| +static int s_video_mode = VIDEOMODE_BLOCKY; |
| +static bool s_no_repeat = true; |
| +static int s_sample_frame_count; |
| +static pp::Audio s_audio; |
| +static pthread_mutex_t s_audio_mutex; |
| + |
| + |
| +// Externs |
| +typedef std::pair<std::string, std::string> strpair_t; |
| +extern std::vector<strpair_t> keymaps; |
| + |
| +/////////////////////////////////////////////////////////////////////////////// |
| + |
| +int snes9x_main(int argc, char *argv[]); |
| +int snes9x_pepper_main(int argc, char* argv[]) { |
| + PSEventSetFilter(PSE_ALL); |
| + |
| + umount("/"); |
| + mount("", "/", "memfs", 0, NULL); |
| + mkdir("/mnt", 0777); |
| + mount("", "/mnt/html5fs", "html5fs", 0, "type=TEMPORARY"); |
| + mkdir("/home", 0777); |
| + setenv("HOME", "/home", 1); |
| + |
| + if (argc < 1) { |
| + fprintf(stderr, "Expect ROM filename as first argument!\n"); |
| + exit(1); |
| + } |
| + |
| + // Assume that argv[1] is the URL of the ROM. |
| + char* filename = argv[1]; |
| + printf("Loading ROM: %s\n", filename); |
| + |
| + char buffer[PATH_MAX]; |
| + snprintf(buffer, PATH_MAX - 1, "/mnt/html5fs/%s", filename); |
| + buffer[PATH_MAX - 1] = 0; |
| + |
| + printf("Setting argv[1] to \"%s\"\n", buffer); |
| + argv[1] = &buffer[0]; |
| + |
| + return snes9x_main(argc, argv); |
| +} |
| + |
| +PPAPI_SIMPLE_REGISTER_MAIN(snes9x_pepper_main) |
| + |
| +void S9xExtraDisplayUsage() { |
| +} |
| + |
| +void S9xParseDisplayArg(char **argv, int &i, int argc) { |
| + if (!strcasecmp(argv[i], "-setrepeat")) { |
| +// s_no_repeat = FALSE; |
| + } else if (!strncasecmp(argv[i], "-v", 2)) { |
| + switch (argv[i][2]) { |
| + case '1': s_video_mode = VIDEOMODE_BLOCKY; break; |
| + case '2': s_video_mode = VIDEOMODE_TV; break; |
| + case '3': s_video_mode = VIDEOMODE_SMOOTH; break; |
| + case '4': s_video_mode = VIDEOMODE_SUPEREAGLE; break; |
| + case '5': s_video_mode = VIDEOMODE_2XSAI; break; |
| + case '6': s_video_mode = VIDEOMODE_SUPER2XSAI; break; |
| + case '7': s_video_mode = VIDEOMODE_EPX; break; |
| + case '8': s_video_mode = VIDEOMODE_HQ2X; break; |
| + } |
| + } else { |
| + S9xUsage(); |
| + } |
| +} |
| + |
| +const char * S9xParseDisplayConfig(ConfigFile &conf, int pass) { |
| + if (pass != 1) |
| + return "Unix/NaCl"; |
| + |
| + // NaCl needs to use 44100. |
| + Settings.SoundPlaybackRate = 44100; |
| + |
| + if (!conf.GetBool("Unix::ClearAllControls", false)) { |
| + keymaps.push_back(strpair_t("K00:K", "Joypad1 Right")); |
| + keymaps.push_back(strpair_t("K00:Right", "Joypad1 Right")); |
| + keymaps.push_back(strpair_t("K00:H", "Joypad1 Left")); |
| + keymaps.push_back(strpair_t("K00:Left", "Joypad1 Left")); |
| + keymaps.push_back(strpair_t("K00:J", "Joypad1 Down")); |
| + keymaps.push_back(strpair_t("K00:N", "Joypad1 Down")); |
| + keymaps.push_back(strpair_t("K00:Down", "Joypad1 Down")); |
| + keymaps.push_back(strpair_t("K00:U", "Joypad1 Up")); |
| + keymaps.push_back(strpair_t("K00:Up", "Joypad1 Up")); |
| + keymaps.push_back(strpair_t("K00:Return", "Joypad1 Start")); |
| + keymaps.push_back(strpair_t("K00:space", "Joypad1 Select")); |
| + keymaps.push_back(strpair_t("K00:S+D", "Joypad1 ToggleTurbo A")); |
| + keymaps.push_back(strpair_t("K00:C+D", "Joypad1 ToggleSticky A")); |
| + keymaps.push_back(strpair_t("K00:D", "Joypad1 A")); |
| + keymaps.push_back(strpair_t("K00:S+C", "Joypad1 ToggleTurbo B")); |
| + keymaps.push_back(strpair_t("K00:C+C", "Joypad1 ToggleSticky B")); |
| + keymaps.push_back(strpair_t("K00:C", "Joypad1 B")); |
| + keymaps.push_back(strpair_t("K00:S+S", "Joypad1 ToggleTurbo X")); |
| + keymaps.push_back(strpair_t("K00:C+S", "Joypad1 ToggleSticky X")); |
| + keymaps.push_back(strpair_t("K00:S", "Joypad1 X")); |
| + keymaps.push_back(strpair_t("K00:S+X", "Joypad1 ToggleTurbo Y")); |
| + keymaps.push_back(strpair_t("K00:C+X", "Joypad1 ToggleSticky Y")); |
| + keymaps.push_back(strpair_t("K00:X", "Joypad1 Y")); |
| + keymaps.push_back(strpair_t("K00:S+A", "Joypad1 ToggleTurbo L")); |
| + keymaps.push_back(strpair_t("K00:S+V", "Joypad1 ToggleTurbo L")); |
| + keymaps.push_back(strpair_t("K00:C+A", "Joypad1 ToggleSticky L")); |
| + keymaps.push_back(strpair_t("K00:C+V", "Joypad1 ToggleSticky L")); |
| + keymaps.push_back(strpair_t("K00:A", "Joypad1 L")); |
| + keymaps.push_back(strpair_t("K00:V", "Joypad1 L")); |
| + keymaps.push_back(strpair_t("K00:S+Z", "Joypad1 ToggleTurbo R")); |
| + keymaps.push_back(strpair_t("K00:C+Z", "Joypad1 ToggleSticky R")); |
| + keymaps.push_back(strpair_t("K00:Z", "Joypad1 R")); |
| + |
| + keymaps.push_back(strpair_t("K00:Numpad4", "Joypad2 Left")); |
| + keymaps.push_back(strpair_t("K00:Numpad6", "Joypad2 Right")); |
| + keymaps.push_back(strpair_t("K00:Numpad8", "Joypad2 Up")); |
| + keymaps.push_back(strpair_t("K00:Numpad2", "Joypad2 Down")); |
| + keymaps.push_back(strpair_t("K00:Enter", "Joypad2 Start")); |
| + keymaps.push_back(strpair_t("K00:Add", "Joypad2 Select")); |
| + keymaps.push_back(strpair_t("K00:PageUp", "Joypad2 A")); |
| + keymaps.push_back(strpair_t("K00:PageDown", "Joypad2 B")); |
| + keymaps.push_back(strpair_t("K00:Home", "Joypad2 X")); |
| + keymaps.push_back(strpair_t("K00:End", "Joypad2 Y")); |
| + keymaps.push_back(strpair_t("K00:Insert", "Joypad2 L")); |
| + keymaps.push_back(strpair_t("K00:Delete", "Joypad2 R")); |
| + |
| + keymaps.push_back(strpair_t("K00:A+F4", "SoundChannel0")); |
| + keymaps.push_back(strpair_t("K00:C+F4", "SoundChannel0")); |
| + keymaps.push_back(strpair_t("K00:A+F5", "SoundChannel1")); |
| + keymaps.push_back(strpair_t("K00:C+F5", "SoundChannel1")); |
| + keymaps.push_back(strpair_t("K00:A+F6", "SoundChannel2")); |
| + keymaps.push_back(strpair_t("K00:C+F6", "SoundChannel2")); |
| + keymaps.push_back(strpair_t("K00:A+F7", "SoundChannel3")); |
| + keymaps.push_back(strpair_t("K00:C+F7", "SoundChannel3")); |
| + keymaps.push_back(strpair_t("K00:A+F8", "SoundChannel4")); |
| + keymaps.push_back(strpair_t("K00:C+F8", "SoundChannel4")); |
| + keymaps.push_back(strpair_t("K00:A+F9", "SoundChannel5")); |
| + keymaps.push_back(strpair_t("K00:C+F9", "SoundChannel5")); |
| + keymaps.push_back(strpair_t("K00:A+F10", "SoundChannel6")); |
| + keymaps.push_back(strpair_t("K00:C+F10", "SoundChannel6")); |
| + keymaps.push_back(strpair_t("K00:A+F11", "SoundChannel7")); |
| + keymaps.push_back(strpair_t("K00:C+F11", "SoundChannel7")); |
| + keymaps.push_back(strpair_t("K00:A+F12", "SoundChannelsOn")); |
| + keymaps.push_back(strpair_t("K00:C+F12", "SoundChannelsOn")); |
| + |
| + keymaps.push_back(strpair_t("K00:S+1", "BeginRecordingMovie")); |
| + keymaps.push_back(strpair_t("K00:S+2", "EndRecordingMovie")); |
| + keymaps.push_back(strpair_t("K00:S+3", "LoadMovie")); |
| + keymaps.push_back(strpair_t("K00:A+F1", "SaveSPC")); |
| + keymaps.push_back(strpair_t("K00:C+F1", "SaveSPC")); |
| + keymaps.push_back(strpair_t("K00:F10", "LoadOopsFile")); |
| + keymaps.push_back(strpair_t("K00:A+F2", "LoadFreezeFile")); |
| + keymaps.push_back(strpair_t("K00:C+F2", "LoadFreezeFile")); |
| + keymaps.push_back(strpair_t("K00:F11", "LoadFreezeFile")); |
| + keymaps.push_back(strpair_t("K00:A+F3", "SaveFreezeFile")); |
| + keymaps.push_back(strpair_t("K00:C+F3", "SaveFreezeFile")); |
| + keymaps.push_back(strpair_t("K00:F12", "SaveFreezeFile")); |
| + keymaps.push_back(strpair_t("K00:F1", "QuickLoad000")); |
| + keymaps.push_back(strpair_t("K00:F2", "QuickLoad001")); |
| + keymaps.push_back(strpair_t("K00:F3", "QuickLoad002")); |
| + keymaps.push_back(strpair_t("K00:F4", "QuickLoad003")); |
| + keymaps.push_back(strpair_t("K00:F5", "QuickLoad004")); |
| + keymaps.push_back(strpair_t("K00:F6", "QuickLoad005")); |
| + keymaps.push_back(strpair_t("K00:F7", "QuickLoad006")); |
| + keymaps.push_back(strpair_t("K00:F8", "QuickLoad007")); |
| + keymaps.push_back(strpair_t("K00:F9", "QuickLoad008")); |
| + keymaps.push_back(strpair_t("K00:S+F1", "QuickSave000")); |
| + keymaps.push_back(strpair_t("K00:S+F2", "QuickSave001")); |
| + keymaps.push_back(strpair_t("K00:S+F3", "QuickSave002")); |
| + keymaps.push_back(strpair_t("K00:S+F4", "QuickSave003")); |
| + keymaps.push_back(strpair_t("K00:S+F5", "QuickSave004")); |
| + keymaps.push_back(strpair_t("K00:S+F6", "QuickSave005")); |
| + keymaps.push_back(strpair_t("K00:S+F7", "QuickSave006")); |
| + keymaps.push_back(strpair_t("K00:S+F8", "QuickSave007")); |
| + keymaps.push_back(strpair_t("K00:S+F9", "QuickSave008")); |
| + |
| + keymaps.push_back(strpair_t("K00:ScrollLock", "Pause")); |
| + keymaps.push_back(strpair_t("K00:CS+Escape", "Reset")); |
| + keymaps.push_back(strpair_t("K00:S+Escape", "SoftReset")); |
| + keymaps.push_back(strpair_t("K00:Escape", "ExitEmu")); |
| + keymaps.push_back(strpair_t("K00:Tab", "EmuTurbo")); |
| + keymaps.push_back(strpair_t("K00:S+Tab", "ToggleEmuTurbo")); |
| + keymaps.push_back(strpair_t("K00:A+Equals", "IncEmuTurbo")); |
| + keymaps.push_back(strpair_t("K00:A+Subtract", "DecEmuTurbo")); |
| + keymaps.push_back(strpair_t("K00:C+Equals", "IncTurboSpeed")); |
| + keymaps.push_back(strpair_t("K00:C+Subtract", "DecTurboSpeed")); |
| + keymaps.push_back(strpair_t("K00:Equals", "IncFrameRate")); |
| + keymaps.push_back(strpair_t("K00:Subtract", "DecFrameRate")); |
| + keymaps.push_back(strpair_t("K00:S+Equals", "IncFrameTime")); |
| + keymaps.push_back(strpair_t("K00:S+Subtract", "DecFrameTime")); |
| + keymaps.push_back(strpair_t("K00:6", "SwapJoypads")); |
| + keymaps.push_back(strpair_t("K00:Printscreen", "Screenshot")); |
| + |
| + keymaps.push_back(strpair_t("K00:1", "ToggleBG0")); |
| + keymaps.push_back(strpair_t("K00:2", "ToggleBG1")); |
| + keymaps.push_back(strpair_t("K00:3", "ToggleBG2")); |
| + keymaps.push_back(strpair_t("K00:4", "ToggleBG3")); |
| + keymaps.push_back(strpair_t("K00:5", "ToggleSprites")); |
| + keymaps.push_back(strpair_t("K00:9", "ToggleTransparency")); |
| + keymaps.push_back(strpair_t("K00:BackSpace", "ClipWindows")); |
| + keymaps.push_back(strpair_t("K00:A+Escape", "Debugger")); |
| + |
| + keymaps.push_back(strpair_t("M00:B0", "{Mouse1 L,Superscope Fire,Justifier1 Trigger}")); |
| + keymaps.push_back(strpair_t("M00:B1", "{Justifier1 AimOffscreen Trigger,Superscope AimOffscreen}")); |
| + keymaps.push_back(strpair_t("M00:B2", "{Mouse1 R,Superscope Cursor,Justifier1 Start}")); |
| + keymaps.push_back(strpair_t("M00:Pointer", "Pointer Mouse1+Superscope+Justifier1")); |
| + keymaps.push_back(strpair_t("K00:BackQuote", "Superscope ToggleTurbo")); |
| + keymaps.push_back(strpair_t("K00:Slash", "Superscope Pause")); |
| + } |
| + |
| + // s_no_repeat = !conf.GetBool("Unix/NaCl::SetKeyRepeat", TRUE); |
| + |
| + if (conf.Exists("Unix/NaCl::VideoMode")) { |
| + s_video_mode = conf.GetUInt("Unix/NaCl::VideoMode", VIDEOMODE_BLOCKY); |
| + if (s_video_mode < 1 || s_video_mode > 8) |
| + s_video_mode = VIDEOMODE_BLOCKY; |
| + } else { |
| + s_video_mode = VIDEOMODE_BLOCKY; |
| + } |
| + |
| + return "Unix/NaCl"; |
| +} |
| + |
| +const char * S9xSelectFilename(const char *def, const char *dir1, const |
| + char *ext1, const char *title) { |
| + printf("S9xSelectFilename(%s, %s, %s, %s)\n", def, dir1, ext1, title); |
| + return NULL; |
| +} |
| + |
| +void S9xMessage(int type, int number, const char *message) { |
| + printf("S9xMessage \"%s\"\n", message); |
| + const int max = 36 * 3; |
| + static char buffer[max + 1]; |
| + |
| + fprintf(stdout, "%s\n", message); |
| + strncpy(buffer, message, max + 1); |
| + buffer[max] = 0; |
| + S9xSetInfoString(buffer); |
| +} |
| + |
| +const char * S9xStringInput(const char *message) { |
| + printf("S9xStringInput \"%s\"\n", message); |
| + return NULL; |
| +} |
| + |
| +void S9xSetTitle (const char *string) { |
| + printf("S9xSetTitle \"%s\"\n", string); |
| +} |
| + |
| + |
| +// Graphics stuff |
| +void S9xInitDisplay(int argc, char **argv) { |
| + s_context2d = PSContext2DAllocate(PP_IMAGEDATAFORMAT_BGRA_PREMUL); |
| + S9xSetRenderPixelFormat(RGB565); |
| + S9xBlitFilterInit(); |
| + S9xBlit2xSaIFilterInit(); |
| + S9xBlitHQ2xFilterInit(); |
| + |
| + GFX.Pitch = SNES_WIDTH * 2 * 2; |
| + s_snes_buffer = |
| + (uint8 *) calloc(GFX.Pitch * ((SNES_HEIGHT_EXTENDED + 4) * 2), 1); |
| + |
| + GFX.Screen = (uint16 *) (s_snes_buffer + (GFX.Pitch * 2 * 2)); |
| + |
| + s_filter_buffer = |
| + (uint8 *) calloc((SNES_WIDTH * 2) * 2 * (SNES_HEIGHT_EXTENDED * 2), 1); |
| + |
| + S9xGraphicsInit(); |
| +} |
| + |
| +void S9xDeinitDisplay() { |
| + S9xTextMode(); |
| + S9xBlitFilterDeinit(); |
| + S9xBlit2xSaIFilterDeinit(); |
| + S9xBlitHQ2xFilterDeinit(); |
| + PSContext2DFree(s_context2d); |
| +} |
| + |
| +static void Convert16To24(int width, int height); |
| +void S9xPutImage (int width, int height) { |
| + PSContext2DGetBuffer(s_context2d); |
| + if (NULL == s_context2d->data) |
| + return; |
| + |
| + static int prevWidth = 0, prevHeight = 0; |
| + int copyWidth, copyHeight; |
| + Blitter blitFn = NULL; |
| + |
| + if (s_video_mode == VIDEOMODE_BLOCKY || |
| + s_video_mode == VIDEOMODE_TV || |
| + s_video_mode == VIDEOMODE_SMOOTH) { |
| + if ((width <= SNES_WIDTH) && |
| + ((prevWidth != width) || (prevHeight != height))) |
| + S9xBlitClearDelta(); |
| + } |
| + |
| + if (width <= SNES_WIDTH) { |
| + if (height > SNES_HEIGHT_EXTENDED) { |
| + copyWidth = width * 2; |
| + copyHeight = height; |
| + blitFn = S9xBlitPixSimple2x1; |
| + } else { |
| + copyWidth = width * 2; |
| + copyHeight = height * 2; |
| + |
| + switch (s_video_mode) { |
| + case VIDEOMODE_BLOCKY: |
| + blitFn = S9xBlitPixSimple2x2; |
| + break; |
| + case VIDEOMODE_TV: |
| + blitFn = S9xBlitPixTV2x2; |
| + break; |
| + case VIDEOMODE_SMOOTH: |
| + blitFn = S9xBlitPixSmooth2x2; |
| + break; |
| + case VIDEOMODE_SUPEREAGLE: |
| + blitFn = S9xBlitPixSuperEagle16; |
| + break; |
| + case VIDEOMODE_2XSAI: |
| + blitFn = S9xBlitPix2xSaI16; |
| + break; |
| + case VIDEOMODE_SUPER2XSAI: |
| + blitFn = S9xBlitPixSuper2xSaI16; |
| + break; |
| + case VIDEOMODE_EPX: |
| + blitFn = S9xBlitPixEPX16; |
| + break; |
| + case VIDEOMODE_HQ2X: |
| + blitFn = S9xBlitPixHQ2x16; |
| + break; |
| + } |
| + } |
| + } else if (height <= SNES_HEIGHT_EXTENDED) { |
| + copyWidth = width; |
| + copyHeight = height * 2; |
| + |
| + switch (s_video_mode) { |
| + default: |
| + blitFn = S9xBlitPixSimple1x2; |
| + break; |
| + case VIDEOMODE_TV: |
| + blitFn = S9xBlitPixTV1x2; |
| + break; |
| + } |
| + } else { |
| + copyWidth = width; |
| + copyHeight = height; |
| + blitFn = S9xBlitPixSimple1x1; |
| + } |
| + |
| + blitFn((uint8 *) GFX.Screen, GFX.Pitch, s_filter_buffer, |
| + kFilterBufferPitch, width, height); |
| + |
| + if (height < prevHeight) { |
| + int p = kFilterBufferPitch >> 2; |
| + for (int y = SNES_HEIGHT * 2; y < SNES_HEIGHT_EXTENDED * 2; y++) { |
| + uint32 *d = (uint32 *) (s_filter_buffer + y * kFilterBufferPitch); |
| + for (int x = 0; x < p; x++) |
| + *d++ = 0; |
| + } |
| + } |
| + |
| + Convert16To24(copyWidth, copyHeight); |
| + PSContext2DSwapBuffer(s_context2d); |
| + |
| + prevWidth = width; |
| + prevHeight = height; |
| +} |
| + |
| +static void Convert16To24(int width, int height) { |
| + // Draw centered in context2d canvas. |
| + int x_offset, y_offset; |
| + |
| + if (s_context2d->width < width) |
| + width = s_context2d->width; |
| + else |
| + x_offset = (s_context2d->width - width) / 2; |
| + |
| + if (s_context2d->height < height) |
| + height = s_context2d->height; |
| + else |
| + y_offset = (s_context2d->height - height) / 2; |
| + |
| + for (int y = 0; y < height; y++) { |
| + uint16 *s = (uint16 *) (s_filter_buffer + y * kFilterBufferPitch); |
| + uint32 *d = (uint32 *) (s_context2d->data + |
| + (y + y_offset) * s_context2d->width + |
| + x_offset); |
| + |
| + for (int x = 0; x < width; x++) { |
| + uint32 pixel = *s++; |
| + int alpha = 255; |
| + int red = ((pixel >> 11) & 0x1f) << 3; |
| + int green = ((pixel >> 6) & 0x1f) << 3; |
| + int blue = ( pixel & 0x1f) << 3; |
| + *d++ = (alpha << 24) | (red << 16) | (green << 8) | blue; |
| + } |
| + } |
| +} |
| + |
| +// Control/Input stuff |
| +void S9xProcessEvents(bool8 block) { |
| + PSEvent* ps_event; |
| + // Consume all available events. |
| + while ((ps_event = PSEventTryAcquire()) != NULL) { |
| + if (0 != PSContext2DHandleEvent(s_context2d, ps_event)) |
| + return; |
| + if (ps_event->type == PSE_INSTANCE_HANDLEINPUT) { |
| + // Convert Pepper Simple event to a PPAPI C++ event |
| + pp::InputEvent event(ps_event->as_resource); |
| + switch (event.GetType()) { |
| + case PP_INPUTEVENT_TYPE_KEYDOWN: |
| + case PP_INPUTEVENT_TYPE_KEYUP: { |
| + pp::KeyboardInputEvent key(event); |
| + uint32_t modifiers = key.GetModifiers(); |
| + uint32_t key_code = key.GetKeyCode(); |
| + bool key_down = event.GetType() == PP_INPUTEVENT_TYPE_KEYDOWN; |
| + uint32 id = kKeyboardBit; |
| + id |= ((modifiers & kModifiersMask) << kModifierShift); |
| + id |= (key_code & kKeyCodeMask); |
| + S9xReportButton(id, key_down); |
| + break; |
| + } |
| + case PP_INPUTEVENT_TYPE_MOUSEDOWN: |
| + case PP_INPUTEVENT_TYPE_MOUSEUP: { |
| + pp::MouseInputEvent mouse(event); |
| + uint32 id = kMouseBit | (uint32) mouse.GetButton(); |
| + bool mouse_down = event.GetType() == PP_INPUTEVENT_TYPE_MOUSEDOWN; |
| + S9xReportButton(id, mouse_down); |
| + break; |
| + } |
| + case PP_INPUTEVENT_TYPE_MOUSEMOVE: { |
| + pp::MouseInputEvent mouse(event); |
| + uint32 id = kMouseBit | kMousePointerBit; |
| + int16 x = mouse.GetPosition().x(); |
| + int16 y = mouse.GetPosition().y(); |
| + S9xReportPointer(id, x, y); |
| + break; |
| + } |
| + default: |
| + break; |
| + } |
| + } |
| + PSEventRelease(ps_event); |
| + } |
| +} |
| + |
| +s9xcommand_t S9xGetDisplayCommandT(const char *n) { |
| + s9xcommand_t cmd; |
| + |
| + cmd.type = S9xBadMapping; |
| + cmd.multi_press = 0; |
| + cmd.button_norpt = 0; |
| + cmd.port[0] = 0xff; |
| + cmd.port[1] = 0; |
| + cmd.port[2] = 0; |
| + cmd.port[3] = 0; |
| + |
| + return cmd; |
| +} |
| + |
| +char * S9xGetDisplayCommandName(s9xcommand_t cmd) { |
| + return strdup("None"); |
| +} |
| + |
| +bool8 S9xMapDisplayInput(const char *n, s9xcommand_t *cmd) { |
| + int i, d; |
| + |
| + if (!isdigit(n[1]) || !isdigit(n[2]) || n[3] != ':') |
| + goto unrecog; |
| + |
| + d = ((n[1] - '0') * 10 + (n[2] - '0')) << 24; |
| + |
| + switch (n[0]) { |
| + case 'K': { |
| + d |= kKeyboardBit; |
| + |
| + for (i = 4; n[i] != '\0' && n[i] != '+'; i++) ; |
| + |
| + if (n[i] == '\0' || i == 4) { |
| + i = 4; |
| + } else { |
| + for (i = 4; n[i] != '+'; i++) { |
| + switch (n[i]) { |
| + case 'S': |
| + d |= PP_INPUTEVENT_MODIFIER_SHIFTKEY << kModifierShift; |
| + break; |
| + case 'C': |
| + d |= PP_INPUTEVENT_MODIFIER_CONTROLKEY << kModifierShift; |
| + break; |
| + case 'A': |
| + d |= PP_INPUTEVENT_MODIFIER_ALTKEY << kModifierShift; |
| + break; |
| + case 'M': |
| + d |= PP_INPUTEVENT_MODIFIER_METAKEY << kModifierShift; |
| + break; |
| + default: |
| + goto unrecog; |
| + } |
| + } |
| + |
| + i++; |
| + } |
| + |
| + int key_code; |
| + if ((key_code = StringToCode(n + i)) == -1) |
| + goto unrecog; |
| + |
| + d |= key_code & 0xff; |
| + |
| + return S9xMapButton(d, *cmd, false); |
| + } |
| + |
| + case 'M': { |
| + char *c; |
| + int j; |
| + |
| + d |= kMouseBit; |
| + |
| + if (!strncmp(n + 4, "Pointer", 7)) { |
| + d |= kMousePointerBit; |
| + |
| + if (n[11] == '\0') |
| + return S9xMapPointer(d, *cmd, false); |
| + |
| + i = 11; |
| + } else if (n[4] == 'B') { |
| + i = 5; |
| + } else { |
| + goto unrecog; |
| + } |
| + |
| + d |= j = strtol(n + i, &c, 10); |
| + |
| + if ((c != NULL && *c != '\0') || j > kMousePointerBit - 1) |
| + goto unrecog; |
| + |
| + if (d & kMousePointerBit) |
| + return S9xMapPointer(d, *cmd, false); |
| + |
| + return S9xMapButton(d, *cmd, false); |
| + } |
| + |
| + default: |
| + break; |
| + } |
| + |
| +unrecog: |
| + char *err = new char[strlen(n) + 34]; |
| + |
| + sprintf(err, "Unrecognized input device name '%s'", n); |
| + perror(err); |
| + delete [] err; |
| + |
| + return false; |
| +} |
| + |
| +// Sound stuff |
| +static void S9xSoundCallback(void* user_data); |
| +static void PepperSoundCallback(void* samples, |
| + uint32_t buffer_size, |
| + void* user_data); |
| +void S9xOpenSoundDeviceNaCl() { |
| + pp::Instance instance(PSGetInstanceId()); |
| + // Ask the browser/device for an appropriate sample frame count size. |
| + s_sample_frame_count = |
| + pp::AudioConfig::RecommendSampleFrameCount( |
| + &instance, |
| + PP_AUDIOSAMPLERATE_44100, |
| + kSampleFrameCount); |
| + |
| + // Create an audio configuration resource. |
| + pp::AudioConfig audio_config = pp::AudioConfig( |
| + &instance, |
| + PP_AUDIOSAMPLERATE_44100, |
| + s_sample_frame_count); |
| + |
| + // Create an audio resource. |
| + s_audio = pp::Audio( |
| + &instance, |
| + audio_config, |
| + PepperSoundCallback, |
| + NULL); |
| + |
| + pthread_mutex_init(&s_audio_mutex, NULL); |
| + S9xSetSamplesAvailableCallback(S9xSoundCallback, NULL); |
| + |
| + s_audio.StartPlayback(); |
| +} |
| + |
| +static void S9xSoundCallback(void* user_data) { |
| + pthread_mutex_lock(&s_audio_mutex); |
| + S9xFinalizeSamples(); |
| + pthread_mutex_unlock(&s_audio_mutex); |
| +} |
| + |
| +static void PepperSoundCallback(void* samples, |
| + uint32_t buffer_size, |
| + void* user_data) { |
| + pthread_mutex_lock(&s_audio_mutex); |
| + S9xMixSamples((uint8*)samples, buffer_size >> 1); |
| + pthread_mutex_unlock(&s_audio_mutex); |
| +} |
| + |
| + |
| +// Dummy functions |
| +void S9xSetPalette() {} |
| +void S9xTextMode() {} |
| +void S9xGraphicsMode() {} |
| +bool S9xDisplayPollButton(uint32 id, bool *pressed) { return false; } |
| +bool S9xDisplayPollAxis (uint32 id, int16 *value) { return false; } |
| +bool S9xDisplayPollPointer (uint32 id, int16 *x, int16 *y) { return false; } |
| + |
| + |
| +#endif |
| diff --git a/unix/unix.cpp b/unix/unix.cpp |
| --- a/unix/unix.cpp |
| +++ b/unix/unix.cpp |
| @@ -229,6 +229,14 @@ |
| #endif |
| #endif |
| |
| +#if defined(__native_client__) && defined(_NEWLIB_VERSION) |
| +// Definition of timercmp taken from GLibC. |
| +#define timercmp(a, b, CMP) \ |
| + (((a)->tv_sec == (b)->tv_sec) ? \ |
| + ((a)->tv_usec CMP (b)->tv_usec) : \ |
| + ((a)->tv_sec CMP (b)->tv_sec)) |
| +#endif |
| + |
| typedef std::pair<std::string, std::string> strpair_t; |
| |
| ConfigFile::secvec_t keymaps; |
| @@ -318,6 +326,10 @@ bool S9xDisplayPollButton (uint32, bool *); |
| bool S9xDisplayPollAxis (uint32, int16 *); |
| bool S9xDisplayPollPointer (uint32, int16 *, int16 *); |
| |
| +#ifdef __native_client__ |
| +void S9xOpenSoundDeviceNaCl(); |
| +#endif |
| + |
| static long log2 (long); |
| static void SoundTrigger (void); |
| static void InitTimer (void); |
| @@ -1396,6 +1408,10 @@ static void InitTimer (void) |
| |
| bool8 S9xOpenSoundDevice (void) |
| { |
| +#ifdef __native_client__ |
| + S9xOpenSoundDeviceNaCl(); |
| +#endif |
| + |
| #ifndef NOSOUND |
| int J, K; |
| |
| @@ -1545,7 +1561,11 @@ static void sigbrkhandler (int) |
| } |
| #endif |
| |
| +#if defined(__native_client__) |
| +int snes9x_main (int argc, char **argv) |
| +#else |
| int main (int argc, char **argv) |
| +#endif |
| { |
| if (argc < 2) |
| S9xUsage(); |