Compare commits

...
1239 Commits
Author SHA1 Message Date
Twinaphex debba76dc4 (PS3) Multiman fix - different version 2012-04-01 20:15:58 +02:00
Twinaphex 163a7c2e87 (PS3) Hopefully fixes Multiman issue 2012-04-01 20:15:12 +02:00
Themaister fdcfd3fc71 SET_CORE_VERSION. 2012-04-01 20:11:19 +02:00
Themaister 2178a14952 Find drivers before snes_init() to allow rotation to work properly. 2012-04-01 19:38:50 +02:00
Themaister 34bdea0f1c Add rotation to GL driver (PC). 2012-04-01 19:20:37 +02:00
Themaister 2815d5f5cb Defer autoload after sram load. 2012-04-01 16:58:53 +02:00
Themaister 562b28caa7 Add savestate auto load on boot. 2012-04-01 16:57:39 +02:00
Themaister 38a4141eef Add allow_rotate. 2012-04-01 16:13:04 +02:00
TwinAphex51224 525d9b3cf5 (360) Implemented rotation callback function 2012-04-01 16:10:02 +02:00
Twinaphex 0eb49deaa8 (PS3) Forgot to hook up set_rotate function pointer 2012-04-01 01:32:05 +02:00
Twinaphex 239e491382 (PS3) Implemented rotation callback function 2012-04-01 01:01:01 +02:00
Twinaphex ed75cb8031 (PS3) Fixed 'Set default Libsnes core' option 2012-04-01 00:13:45 +02:00
Themaister ba0e7d5f2a Style nit. 2012-03-30 21:18:15 +02:00
Hans-Kristian Arntzen 0308d3fe2b Merge pull request #8 from AlexFolland/master
On ROM checksum mismatch, warn instead of stopping bsv playback.
2012-03-30 12:16:22 -07:00
AlexFolland a2013276d5 instead of stopping, warn about checksum mismatch on bsv playback 2012-03-30 15:13:26 -04:00
Themaister eca337ee55 Allow device to be selected in DirectSound. 2012-03-30 20:09:40 +02:00
Themaister 996d6d25b7 Add support to select device in XAudio2. 2012-03-30 19:53:12 +02:00
Themaister 35a9123bf8 Fix build on Mingw CXX_BUILD. 2012-03-30 19:15:18 +02:00
Themaister 5d4e32ef9d Add support for rotation. 2012-03-30 19:09:34 +02:00
Themaister 29ccd1a5a1 Should fix it properly. 2012-03-29 23:19:41 +02:00
Twinaphex 8ff9ae6b32 Revert "Avoid redundant copy. Remove some now unneeded ifdefs."
This reverts commit b52110f642.
2012-03-29 22:28:46 +02:00
Themaister b52110f642 Avoid redundant copy. Remove some now unneeded ifdefs. 2012-03-29 20:28:22 +02:00
TwinAphex51224 a7b486cef1 (360) Some cleanups to xdk360_video_resources 2012-03-29 17:27:42 +02:00
TwinAphex51224 a33c610149 (360) Don't copy over ssnes.cfg every time during Deployment 2012-03-29 16:54:16 +02:00
Twinaphex 1cc8a24b3c Get rid of Cellframework2 headers in file_browser.h 2012-03-29 16:21:30 +02:00
Twinaphex 75661e7527 (360/PS3) Moved file_browser.c to console/ - 360/PS3 now use
the same file browser code
2012-03-29 16:18:23 +02:00
TwinAphex51224 765ba65188 (360/PS3) Attempt to use the same file browsing code for 360 and
PS3
2012-03-29 16:10:16 +02:00
Twinaphex db7be5736b (360/PS3) OVERRIDE_VIDEO_FRAME_FUNC ifdeffed for 360/PS3 2012-03-29 15:33:28 +02:00
TwinAphex51224 23f9cf8618 (360) Have 360 use HAVE_GRIFFIN_OVERRIDE_VIDEO_FRAME_FUNC too 2012-03-29 15:30:27 +02:00
Twinaphex cf5fb8baaa (PS3) Some more Griffin overrides 2012-03-29 15:07:48 +02:00
Twinaphex 6b88330540 (Griffin) Griffin function override hooks 2012-03-29 14:17:03 +02:00
TwinAphex51224 9653e1f028 (360) Dodge function pointers / make direct calls through HAVE_GRIFFIN
define
2012-03-29 12:14:12 +02:00
TwinAphex51224 a860a71016 (360) 360 uses Griffin now too 2012-03-29 12:04:58 +02:00
Twinaphex 07c839f003 (Griffin) Integrate more source files into griffin.c 2012-03-29 02:10:49 +02:00
Twinaphex dc1616b7ce (PS3) No warnings when compiling griffin.c now 2012-03-29 02:07:05 +02:00
Twinaphex 5553774f6f (PS3) Dodge function pointers / make direct calls through
HAVE_GRIFFIN define
2012-03-29 01:15:22 +02:00
Themaister eee0233abb Wrap driver calls in overridable macros. 2012-03-29 00:30:50 +02:00
Twinaphex f8509ff325 Merge branch 'master' of github.com:Themaister/SSNES 2012-03-28 23:25:40 +02:00
Themaister a3e504ec49 Shut up compiler warning. 2012-03-28 23:32:29 +02:00
Twinaphex 105b6dbddc Merge branch 'master' of github.com:Themaister/SSNES 2012-03-28 23:22:54 +02:00
Twinaphex 24f5b2675b (PS3) Add Griffin to mass include files into one single source unit 2012-03-28 23:22:28 +02:00
Themaister da075bb261 Default initialize config macro values to stop eager compiler warnings. 2012-03-28 23:18:05 +02:00
Themaister 3ae401a2a4 Do not compile in main() in ssnes.c for consoles. 2012-03-28 23:08:57 +02:00
Themaister 104c92fa5d Add audio batch callback. 2012-03-27 22:24:46 +02:00
Twinaphex 29f1138ec6 (PS3) Fix indenting in ps3/file_browser.c 2012-03-26 15:14:25 +02:00
Twinaphex e7419d2fa5 (PS3) Menu cleanups 2012-03-26 15:03:50 +02:00
Twinaphex 6d0b8d1129 (PS3) Add some Windows-specific defines in Makefile 2012-03-26 14:52:58 +02:00
Twinaphex 6332ba3025 ssnes.c - better placement of HAVE_THREADS defines - some more
SSNES_CONSOLE defines
2012-03-26 03:24:28 +02:00
Twinaphex 45021bda3f (PS3) oskutil.c merged with ps3_input.c 2012-03-26 00:36:40 +02:00
TwinAphex51224 64fa27cdad (360) Update 360 solution 2012-03-26 00:27:48 +02:00
Twinaphex e75c1e9923 (PS3) Excluded movie.c from PS3 Makefile 2012-03-26 00:04:12 +02:00
Themaister a63968377a Fix warning. 2012-03-26 00:10:39 +02:00
Themaister 066e9608a1 Add HAVE_BSV_MOVIE define. 2012-03-26 00:06:25 +02:00
Themaister b273de1e99 Move netplay related bsv code to netplay. 2012-03-26 00:06:25 +02:00
Twinaphex 739bbe3aa6 (PS3) Update header on file_browser.c 2012-03-25 23:57:54 +02:00
Twinaphex 1ed6a622f1 (PS3) Move file_browser.c to root of PS3 dir 2012-03-25 23:57:07 +02:00
Twinaphex 5d535f6d54 Remove -DHAVE_SCREENSHOTS_BUILTIN from PS3 Makefile 2012-03-25 23:49:29 +02:00
Themaister c79e536b17 Use positive HAVE_SCREENSHOTS rather than a negative ifdef. 2012-03-25 23:41:20 +02:00
Themaister d73ec9b645 Move hashing code to hash.o. 2012-03-25 23:29:39 +02:00
Themaister 0726204505 If HAVE_ZLIB is set, use zlib internal crc32. 2012-03-25 22:21:08 +02:00
TwinAphex51224 a0a27658bd (360) 360 compile update 2012-03-25 03:12:31 +02:00
Twinaphex db6b9ba4a3 (SSNES_CONSOLE) Merged input_luts.c with console_ext.c 2012-03-25 01:56:27 +01:00
Twinaphex 38ae16f425 SSNES_CONSOLE ifdefs in ssnes.c 2012-03-25 01:19:44 +01:00
Themaister a569625ce9 Do not crash if ffmpeg format cannot be found. 2012-03-23 23:48:17 +01:00
Twinaphex 42b756480b (PS3) Integrated local shader_cg.c into ps3_video_psgl.c 2012-03-23 01:19:44 +01:00
Themaister 4a5104bfcf Use a more correct ifdef. 2012-03-22 22:55:30 +01:00
TwinAphex51224 6e24901d95 (MSVC 2010) Updated MSVC 2010 solution 2012-03-22 01:41:10 +01:00
Twinaphex e5a38bbd51 (SSNES_CONSOLE) More SSNES_CONSOLE ifdefs 2012-03-21 23:58:31 +01:00
Themaister 7ffc9db413 Do not care about cropping on consoles. 2012-03-21 22:47:03 +01:00
Themaister 63274f6f61 Only allow duping if ffmpeg is compiled in. 2012-03-21 22:36:11 +01:00
Themaister b907cb667a Mask away useless code for consoles. 2012-03-21 22:12:18 +01:00
Themaister 5272008f54 Add --no-patch to forcefully disable all patching. 2012-03-20 23:45:58 +01:00
Themaister 4e772003c8 Style nit. 2012-03-20 23:18:10 +01:00
Themaister 48cddde84a Add IPS patching. 2012-03-20 23:08:34 +01:00
Themaister acdc6179bb Add possibility to disable -static-libstdc++ for TDM_GCC. 2012-03-19 23:45:46 +01:00
Twinaphex fadd954618 (PS3) Made local PS3 copy of shader_cg.c 2012-03-19 03:28:04 +01:00
Twinaphex e0295a726a (PS3) Merged Cellframework2 pad_input.c with ps3_input.c from SSNES 2012-03-19 02:55:13 +01:00
Twinaphex f442c8ab5f (PS3) Small change 2012-03-19 01:41:55 +01:00
TwinAphex51224 885c165716 (360) Combine xdk360_video.cpp and xdk360_video_resources.cpp 2012-03-18 00:23:11 +01:00
TwinAphex51224 bd90e1c1a3 (360) Compile fix 2012-03-18 00:16:40 +01:00
Twinaphex 1b995917ce Moved SGUI files to subdir in console/ 2012-03-17 23:59:15 +01:00
Twinaphex 4e3359ec19 Merged console_ext.c / main_wrap.c and got rid of warning in file.c 2012-03-17 23:05:48 +01:00
Twinaphex 8ab536a968 Fix typo 2012-03-17 22:55:48 +01:00
Twinaphex ca25e51812 (PS3) Salamander fixes - still doesn't link with GCC though 2012-03-17 22:51:42 +01:00
Themaister 56e5c9fcec Refactor patch handling. 2012-03-17 01:12:29 +01:00
TwinAphex51224 cd0973d213 (360) Fixed build 2012-03-17 01:10:17 +01:00
Twinaphex 72efdbd916 (PS3) Fixed PS3 and Salamander PS3 builds 2012-03-17 00:58:44 +01:00
Themaister 13373f4873 Merge compat implementations into compat/compat.c. 2012-03-17 00:56:55 +01:00
Twinaphex edad44c950 (PS3) PS3 builds again 2012-03-17 00:45:00 +01:00
TwinAphex51224 6cd800f6ae (360) 360 builds again 2012-03-17 00:52:10 +01:00
Themaister 0ee6aa948e Merge netplay_compat.c into netplay.c. 2012-03-17 00:49:05 +01:00
TwinAphex51224 7974533452 (360) Fixed SSNES Salamander 360 2012-03-17 00:40:48 +01:00
Twinaphex 6c8dd72cd8 (PS3) Build fix for PS3 2012-03-17 00:09:38 +01:00
TwinAphex51224 6b45efa7bc (360) Some build fixes - still not compiling though 2012-03-17 00:13:49 +01:00
Themaister 224db6a4c8 Merge ups.h/bps.h into patch.h. 2012-03-16 23:47:31 +01:00
Themaister ef72584568 Merge ups/bps into patch.c. 2012-03-16 23:42:29 +01:00
Twinaphex 2a6551a62a Fixup includes 2012-03-16 23:31:26 +01:00
Themaister 9ab02b12be Move compat functionality to compat/. 2012-03-16 23:26:57 +01:00
Twinaphex e6b3b96400 (PS3) SDK is always Win32 anyway -so if run on Linux/WINE, we
just use .exe extension instead of setting up all sorts of
complicated symlinks from host-linux to host-win32
2012-03-14 03:19:13 +01:00
TwinAphex51224 47dcb54c1f (PS3/Wii) Make netlogger code portable 2012-03-13 00:45:12 +01:00
Themaister 6cd4989651 Rename macro. 2012-03-12 22:55:19 +01:00
TwinAphex51224 dd9f4be2aa (Wii) Some work on Wii port - included szlib.c - moved input-related
function over to input_luts.c
2012-03-12 22:40:04 +01:00
Themaister 36885e35d7 Kill obsolete test code. 2012-03-12 22:02:34 +01:00
Themaister 49f27c68ff Style nits. 2012-03-12 21:45:43 +01:00
Themaister 5d6c5af8be Style nit. 2012-03-12 18:50:25 +01:00
Themaister 0a2b3ede59 Cleanup. 2012-03-12 17:31:15 +01:00
TwinAphex51224 07a4619a70 (PS3) Now uses new environment extensions too 2012-03-12 17:05:37 +01:00
TwinAphex51224 37b8585df4 (Console) Clean up ssnes_console_get_rom_ext 2012-03-12 14:30:15 +01:00
TwinAphex51224 71189737de (360) Stack size increase - Gunbird 2 in FBA boots now 2012-03-12 06:30:41 +01:00
TwinAphex51224 8781b5c7d3 (360) Works now - environment settings were getting 'defaulted'
- placed init_libsnes_syms now right before menu_init
2012-03-12 04:34:49 +01:00
TwinAphex51224 ed4a81e497 (360) More of aforementioned 2012-03-12 03:53:44 +01:00
TwinAphex51224 e1bbaee64c (360) Set up SSNES 360 for new console environment settings 2012-03-12 03:08:15 +01:00
Themaister d7afd20346 Add new extensions to help FBA. 2012-03-12 00:39:24 +01:00
TwinAphex51224 fe0a6c8d07 (360 FB Alpha 360 libsnes works now 2012-03-11 23:03:20 +01:00
TwinAphex51224 a328bd578e (360/PS3) Some changes needed for FBA on consoles in specific 2012-03-11 22:39:48 +01:00
Themaister 7f4d701b19 Preparations for 0.9.5 release. 2012-03-11 17:52:10 +01:00
TwinAphex51224 06a951ef7f (360) Add NOD3D define to netplay.c too 2012-03-11 16:26:10 +01:00
TwinAphex51224 51b3cafed7 (360) Add xdk360_video_general.h header file 2012-03-11 16:19:47 +01:00
TwinAphex51224 81988fc1ef (360) Don't include D3D/Netcode where not needed through NOD3D/
NONET defines
2012-03-11 16:17:42 +01:00
TwinAphex51224 1f00ce1812 (360) Use C version code in objbase.h for XAudio2 2012-03-11 15:00:15 +01:00
TwinAphex51224 2295c4abd8 (360) Add objbase.h 2012-03-11 14:45:20 +01:00
TwinAphex51224 48230ba533 (360) Use more direct functions for Xaudio2 2012-03-11 07:24:53 +01:00
TwinAphex51224 4737d28644 (360) Add custom Xaudio header 2012-03-11 06:58:56 +01:00
TwinAphex51224 5c4ad2884e (360) Get rid of unused font_texture 2012-03-11 03:57:07 +01:00
TwinAphex51224 e30966bfd0 (360) Get rid of constant table - seem to be getting nowhere with
this
2012-03-11 03:40:52 +01:00
TwinAphex51224 c5d8e1a75c (360) Add constant table for fragment shader too 2012-03-10 20:55:55 +01:00
TwinAphex51224 c2cc7a278f (360) Nit 2012-03-10 18:54:07 +01:00
TwinAphex51224 5cad1e4c39 (360) Stock Cg/HLSL shaders should be now almost the same - only
mall 1/2-line ifdefs should be needed
2012-03-10 18:50:30 +01:00
Themaister 8a6b628bee Allow stopping playback early. 2012-03-10 18:31:25 +01:00
Themaister f78df09c38 Do not fail hard if serializer doesn't match. 2012-03-10 18:10:54 +01:00
TwinAphex51224 40035908f3 (360) Nit. 2012-03-10 17:00:21 +01:00
TwinAphex51224 b0de19f3e0 (360) force_resize_enable member was a hack for hacky orientation,
can go now that we do it properly
2012-03-10 16:57:59 +01:00
TwinAphex51224 a47bcf6cc1 (360) Texture coordinates updated now again per video width/height change 2012-03-10 16:50:11 +01:00
TwinAphex51224 bc307d4b63 (360) Moving away from crufty orientation code 2012-03-10 16:41:10 +01:00
TwinAphex51224 bdb8b3f0fe (360) MVP shader stuff fixed 2012-03-10 15:51:42 +01:00
TwinAphex51224 6053b61b5b (360) MVP stuff - right now ouputs black - to be fixed shortly 2012-03-10 15:32:36 +01:00
Themaister 7489f387c1 Do not block state saving when playing/recording a movie. 2012-03-10 14:08:04 +01:00
TwinAphex51224 31be6766c6 (360) Uses runtime shader compiler - loads stock shader from
file now
2012-03-09 21:50:12 +01:00
Themaister 6b552cfba1 Revert derp. 2012-03-09 18:20:03 +01:00
Themaister 848a67252f Fix subtle regression. 2012-03-09 18:18:35 +01:00
TwinAphex51224 8d5385d1d7 (PS3) Aspect ratio fix 2012-03-09 01:21:10 +01:00
TwinAphex51224 7d8d8f39f7 (360) Add aspect ratio changing - fixed bugs 2012-03-09 01:22:01 +01:00
TwinAphex51224 760d3bbecf (360) WIP aspect ratio changing - currently broken 2012-03-09 00:09:39 +01:00
TwinAphex51224 ac070a6b2b (360) Added gamma correction setting 2012-03-08 23:29:18 +01:00
TwinAphex51224 94f09d2093 (360) Some more replacing of D3D functions 2012-03-08 21:15:18 +01:00
TwinAphex51224 b8e6443710 (360) Use C functions for D3D 2012-03-08 16:14:09 +01:00
TwinAphex51224 8823b47a05 (360) Added screen orientation options - might want to refactor
this later on
2012-03-08 13:45:00 +01:00
Themaister a3351e17f1 Fix hang with FFV1. 2012-03-08 00:45:03 +01:00
Themaister c1544e88aa Cleanups, and fixes h264 with recent FFmpegs. 2012-03-08 00:33:22 +01:00
TwinAphex51224 4e68eb12ab Add back HAVE_ZLIB ifdefs for console_ext.c 2012-03-07 20:32:51 +01:00
TwinAphex51224 428050904c (360) ZIP files can now be unzipped - press X on a ZIP file to
unzip the files to the cache: partition - from the filebrowser
you can then go to the cache partition and load the unzipped ROM.
2012-03-07 20:33:14 +01:00
TwinAphex51224 ee806a0e2c (PS3) Don't compile in gfx_common.c 2012-03-07 17:55:04 +01:00
Themaister e318a1d5a7 Fix incompatibility with non-compilant C runtime. 2012-03-07 12:42:22 +01:00
Themaister ca0986064d Micronit (pt. 2). 2012-03-06 23:50:44 +01:00
Themaister 057846e45b Micronit. 2012-03-06 22:48:45 +01:00
Themaister d4c1cf4853 Style nits. 2012-03-06 22:45:51 +01:00
TwinAphex51224 9708536cd8 (PS3) ZIP files can now be unzipped - if you press X on a ZIP file
in the file browser, it will extract the contents to the /dev_hdd1
partition. You can then start the ROM from there. (problem right
now - savestates/SRAM get saved to this swap partition too -
which we flush at SSNES exit)
2012-03-06 22:20:15 +01:00
TwinAphex51224 f61348e53f (PS3) Mount system cache partition at startup and clear it at
exit - we'll use this for uncompressing ROMs in ZIP archives
2012-03-06 21:03:43 +01:00
TwinAphex51224 556e158020 (Szlib) Added unzip.c and fileapi.c to szlib.c 2012-03-06 20:23:24 +01:00
TwinAphex51224 d9337a2589 (Szlib) Cleanups #3 2012-03-06 18:15:48 +01:00
TwinAphex51224 cc476af1fe (Szlib) Cleanups #2 2012-03-06 18:02:54 +01:00
TwinAphex51224 4365b77577 (Szlib) cleanup 2012-03-06 17:49:49 +01:00
TwinAphex51224 f7c2bfe530 (PS3) Libsnes ports can now set per-system default keybind names 2012-03-06 16:06:47 +01:00
TwinAphex51224 44b873af5b Rename rom_ext.c to console_ext.c - rename xdk360_input.cpp to
xdk360_input.c
2012-03-06 14:12:28 +01:00
TwinAphex51224 4ff4957a45 (360) Use input LUTs in code 2012-03-06 13:35:20 +01:00
TwinAphex51224 3239edccb9 (360) Add keybind LUTs for 360 too 2012-03-06 12:59:40 +01:00
TwinAphex51224 fe0da105b5 (PS3) Add ssnes_ * to LUTs 2012-03-05 23:40:40 +01:00
Themaister 4c361bc648 Nit. 2012-03-05 23:48:14 +01:00
TwinAphex51224 9d17ccf4f3 (PS3) Ping pong commit to get everything working again 2012-03-05 23:32:51 +01:00
Themaister 25a97b1d8c Refactor. 2012-03-05 23:32:38 +01:00
TwinAphex51224 cd9dd6511d (PS3) Input can now be reconfigured 2012-03-05 23:01:26 +01:00
Themaister 37c29144d8 Log error code on dylib failure in Windows. 2012-03-05 21:40:00 +01:00
TwinAphex51224 3c2591f71f Revert "Revert "Remove useless return.""
This reverts commit 4959b8e20e.
2012-03-05 21:31:11 +01:00
TwinAphex51224 6ef7eae423 Revert "Attempt to fix set_keybind_digital."
This reverts commit 379614ca1c.
2012-03-05 21:30:28 +01:00
TwinAphex51224 4959b8e20e Revert "Remove useless return."
This reverts commit 24e807f520.
2012-03-05 21:30:28 +01:00
TwinAphex51224 7e1e293547 (PS3) Input changes 2012-03-05 21:30:28 +01:00
Themaister 4bd53c0b96 Properly extern. 2012-03-05 19:49:19 +01:00
Themaister 47f95020f0 Style nits. 2012-03-05 18:01:27 +01:00
TwinAphex51224 e4506d5a3e (PS3) Keybind name LUT 2012-03-05 17:33:41 +01:00
Themaister b612bb5290 Fix typo. 2012-03-05 17:37:18 +01:00
TwinAphex51224 f453ee7954 (PS3) Input LUTs 2012-03-05 16:57:43 +01:00
TwinAphex51224 0b3f0de625 (360) Will now start at root of game:\\ volume in ROM browser
as default path
2012-03-05 13:27:10 +01:00
TwinAphex51224 80a680a7ee (360) You can change between libsnes cores now from the menu 2012-03-05 13:06:24 +01:00
TwinAphex51224 762c2cb170 (360) Added SSNES Salamander to 360 - will now boot CORE.xex
from SSNES-Salamander.xex and rename CORE.xex once booted.
2012-03-05 12:07:09 +01:00
TwinAphex51224 7b4d48a69f (PS3) Use MAX_PADS for input state array 2012-03-05 07:35:50 +01:00
TwinAphex51224 bd500ae249 (360) Header typos 2012-03-05 01:15:27 +01:00
TwinAphex51224 ad5c890603 (360) Forgot to add new xdk360_input.h header file 2012-03-05 01:10:26 +01:00
TwinAphex51224 f46889daae (360) D-pad mapped to left analog stick -make this configurable
later on (same for PS3 port)
2012-03-05 01:00:09 +01:00
TwinAphex51224 b82d9be0ae (360) Compile in szlib.c 2012-03-04 23:28:32 +01:00
Themaister 449b08e9d5 Fix warning. 2012-03-04 23:17:27 +01:00
TwinAphex51224 a2fe0330eb (360) 360 compiles again 2012-03-04 23:15:25 +01:00
Themaister e3c5ebd937 Add define for strtoull. 2012-03-04 23:09:05 +01:00
TwinAphex51224 afdcae3ee8 (PS3) Link libsnes.a last in link order 2012-03-04 22:43:10 +01:00
TwinAphex51224 d2e3d8db28 (PS3) Compiles in szlib.c now 2012-03-04 21:53:04 +01:00
Themaister 10ac66e734 Legal stuff. 2012-03-04 21:54:07 +01:00
TwinAphex51224 5ebd0b4ed1 Initial commit of SZlib 2012-03-04 21:38:33 +01:00
Themaister 227ae4ca74 Small fix. 2012-03-04 18:24:11 +01:00
Themaister 379614ca1c Attempt to fix set_keybind_digital. 2012-03-04 14:51:43 +01:00
Themaister 24e807f520 Remove useless return. 2012-03-04 13:59:45 +01:00
Themaister 2463924d69 Use uint64_t across the board for joykeys. 2012-03-04 13:55:35 +01:00
Themaister 6e0da33c60 Fix allocation. 2012-03-04 13:20:09 +01:00
Themaister fd54b26532 Add to joyconfig. 2012-03-04 12:01:41 +01:00
Themaister ea0233716e Slow motion mode. 2012-03-04 12:01:07 +01:00
Themaister d891230800 Minor fix. 2012-03-04 01:11:49 +01:00
Themaister 1bf564955c Cleanup. 2012-03-04 00:36:28 +01:00
Themaister f548ebb1a2 Cleanup typedefs. 2012-03-03 23:57:42 +01:00
TwinAphex51224 6e1d48a625 (PS3) Default emulator core setting 2012-03-03 23:26:14 +01:00
TwinAphex51224 b73d8bb569 (PS3) Blending in menu now works correctly across all shaders 2012-03-03 17:58:14 +01:00
TwinAphex51224 ed5e67425c (PS3) Added custom BGM music hooks 2012-03-03 17:23:00 +01:00
TwinAphex51224 d76d8a7d9c (PS3) Updated PARAM.SFO - should now support custom BGM music 2012-03-03 16:53:38 +01:00
TwinAphex51224 8ef9e99960 (PS3) Saves custom viewport settings now 2012-03-03 16:10:03 +01:00
TwinAphex51224 cd08339051 (PS3) D-pad analog stick left mapping - make this configurable later
on
2012-03-03 14:57:28 +01:00
TwinAphex51224 85ee49b2cd (PS3) Add HAVE_RSOUND to PS3 Makefile 2012-03-03 14:12:14 +01:00
TwinAphex51224 5f3453bc38 (PS3) Another commit for multiMAN compatibility 2012-03-03 12:31:51 +01:00
TwinAphex51224 d8720ab9d8 (PS3) Should fix multiMAN compatibility 2012-03-03 12:29:16 +01:00
TwinAphex51224 04a1388640 (PS3) Fixed some settings 2012-03-03 12:09:56 +01:00
TwinAphex51224 db87f664b8 (PS3) Sound options added - reiniting sound has yet to happen 2012-03-03 11:54:14 +01:00
Themaister ae5900aaa1 Add video_h264_record option. 2012-03-02 22:19:49 +01:00
TwinAphex51224 4b67a3c59e (PS3) Compiles in rsound now 2012-03-01 21:32:01 +01:00
TwinAphex51224 c6fa39fde0 (PS3) Implemented Resize mode 2012-03-01 16:55:19 +01:00
TwinAphex51224 051c82daed (PS3) CGP files can now be saved 2012-03-01 14:50:37 +01:00
TwinAphex51224 de9db9bcea (PS3) More control settings - NOTE: public controller config save/load
functions do not work properly and do not save the proper values
2012-03-01 14:22:16 +01:00
TwinAphex51224 9a1cf7525e (PS3) Added oskutil.c 2012-02-29 20:20:25 +01:00
Themaister 90984ce3cc config_read_keybinds takes path. 2012-02-29 19:25:54 +01:00
Themaister dc1d9b674a config_save_keybinds takes a pathname directly. 2012-02-29 19:07:25 +01:00
Themaister 47c9fda3c9 Fix off-by-one bug in joypad ID handling. 2012-02-29 18:59:44 +01:00
TwinAphex51224 452f3f4c43 (PS3) Last control setting can now be changed 2012-02-29 18:41:09 +01:00
TwinAphex51224 6c64a024eb (PS3) Initial joypad button rebinding through menu 2012-02-29 09:16:21 +01:00
Themaister 59dbc4727b Generate for rest of slide window. 2012-02-28 23:01:18 +01:00
Themaister 57e17d9b14 Optimize resampler some more. 2012-02-28 22:58:19 +01:00
Themaister 7b0b1a7004 Only enable SINC by default for 64-bit Windows. 2012-02-28 19:28:06 +01:00
TwinAphex51224 fd99d9f3bc (PS3) You can set IP address of development PC and UDP port (for
UDP logging)
2012-02-28 16:32:52 +01:00
TwinAphex51224 1386c97ad2 (PS3) Multiman fixes 2012-02-28 16:26:54 +01:00
TwinAphex51224 9d19ef4969 (PS3) Small fix for Multiman - argc > 1 2012-02-28 15:54:51 +01:00
TwinAphex51224 ffc6fc5e24 (PS3) Added Multiman hooks 2012-02-28 14:42:29 +01:00
TwinAphex51224 11720b8113 (PS3) Added EMULATOR_CORE_DIR define 2012-02-28 12:07:55 +01:00
TwinAphex51224 308d89ead7 (PS3) Cleaned up Salamander 2012-02-28 11:09:43 +01:00
TwinAphex51224 c5cee1f945 (PS3) Salamander and exitspawn work now - thanks to deank 2012-02-28 10:42:34 +01:00
TwinAphex51224 ee99acfd71 Merge branch 'master' of github.com:Themaister/SSNES 2012-02-28 09:38:50 +01:00
TwinAphex51224 08414d1f5c (PS3) Small push 2012-02-28 09:38:31 +01:00
Themaister 18aebfedc2 Test for IDFT. 2012-02-28 00:52:49 +01:00
Themaister c8173aaf62 Calculate imaginary part correctly. 2012-02-28 00:29:45 +01:00
Themaister c975145914 Use omega to report response. 2012-02-27 21:34:31 +01:00
Themaister 2fecfc7fca Drop phase measurement as they're kinda useless. 2012-02-27 21:13:50 +01:00
TwinAphex51224 a4b3fbcebe Merge branch 'master' of github.com:Themaister/SSNES 2012-02-27 20:08:04 +01:00
TwinAphex51224 f01663550c Added logging features - set HAVE_LOGGING to enable 2012-02-27 20:07:24 +01:00
Themaister 24817543e0 Implement FFT for better SNR verification. 2012-02-27 19:49:00 +01:00
Themaister b50ddfc87a Fix some static analyzer warnings. 2012-02-27 17:29:59 +01:00
Themaister 302dc9460f Add override possibility for logger interface. 2012-02-27 17:24:11 +01:00
TwinAphex51224 351e58b856 (PS3) fixed pkg rule 2012-02-27 14:01:05 +01:00
TwinAphex51224 8aa2eb9741 Merge branch 'master' of github.com:Themaister/SSNES 2012-02-27 13:44:46 +01:00
TwinAphex51224 90165492a1 (PS3) Added makefile targets for PS3 CFW - NOTE: SSNES Salamander
doesn't seem to work yet on CFW PS3 - use make pkg-signed-standalone
for now on CFW PS3 until this gets sorted out.
2012-02-27 13:43:44 +01:00
Themaister afa6776b1d Add cutoff. 2012-02-26 19:18:51 +01:00
TwinAphex51224 60edff831a (PS3) Add override for Salamander -press and hold Triangle button
at startup to launch the first SELF file found in the cores/ directory
2012-02-26 18:12:18 +01:00
TwinAphex51224 98bd071fd3 (PS3) Add non-NPDRM exitspawn fallback 2012-02-26 17:30:01 +01:00
TwinAphex51224 ac5fb991a2 Merge branch 'master' of github.com:Themaister/SSNES 2012-02-26 15:19:40 +01:00
TwinAphex51224 2e5e5f3c35 (PS3) Added SSNES Salamander - emulator cores can now be installed and
you can now switch between cores - if on an older install, remove your
ssnes.cfg file
2012-02-26 15:18:44 +01:00
Themaister 9d0a55285d Rename msvc-ps3 folder. 2012-02-26 02:50:52 +01:00
Themaister 9b4a91fd29 Add rate control to coreaudio. 2012-02-26 01:22:07 +01:00
Themaister b4fe5198b3 Win32 doesn't have memalign ... 2012-02-25 22:37:40 +01:00
Themaister c20df730e3 Make sinc resampler default on PC. 2012-02-25 22:12:49 +01:00
Themaister 37ed625bab Use shuffles/movehl. 2012-02-25 21:47:40 +01:00
Themaister 3446774547 Merge branch 'master' of github.com:Themaister/SSNES 2012-02-25 21:18:09 +01:00
Themaister a5c47a568e Attempt to measure phase distortion as well. 2012-02-25 21:17:48 +01:00
TwinAphex51224 e70ea21a3a (PS3) Remove selected border option again 2012-02-25 20:40:02 +01:00
TwinAphex51224 c310e32dd0 Merge branch 'master' of github.com:Themaister/SSNES
Conflicts:
	console/rom_ext.c
	console/rom_ext.h
2012-02-25 20:15:22 +01:00
TwinAphex51224 248f5efbd6 (PS3) Initial WIP exitspawn loading of external executables -
will flesh this out in subsequent ports
2012-02-25 20:11:57 +01:00
Themaister a03c11d7d0 Clarify a bit. 2012-02-25 17:29:02 +01:00
Themaister 2e9fade00a Add name generation from id. 2012-02-25 17:05:52 +01:00
Themaister 3dc5b21b78 Use lanzcos instead (better SNR). 2012-02-25 16:45:06 +01:00
Themaister dd57e0ae63 Merge branch 'master' of github.com:Themaister/SSNES 2012-02-25 16:33:51 +01:00
Themaister bdc8cd1cb1 Apply deltas to last phase as well. 2012-02-25 16:33:33 +01:00
TwinAphex51224 cacf15a065 Merge branch 'master' of github.com:Themaister/SSNES 2012-02-25 14:39:07 +01:00
TwinAphex51224 989962f5a9 (PS3) Better environment detection rules for Windows 2012-02-25 14:38:28 +01:00
Themaister 7c15f5a537 Merge branch 'master' of github.com:Themaister/SSNES 2012-02-25 14:32:59 +01:00
Themaister 6643bf3e1c Use floating point for sample offsets. 2012-02-25 14:31:57 +01:00
TwinAphex51224 60256eb52f (PS3) Remove SETTING_BORDER - will reintroduce this in CGP Manager
menu (implemented better)
2012-02-25 14:15:25 +01:00
Themaister 74de5350d2 Merge branch 'master' of github.com:Themaister/SSNES
Conflicts:
	audio/test/snr.c
2012-02-25 14:06:15 +01:00
Themaister cd54cc6822 Improve SNR testing routines. 2012-02-25 14:02:56 +01:00
Themaister 2fba62867f Attempt to account for make-up-gain. Still not good ... 2012-02-25 04:51:01 +01:00
Themaister 5f330cbfa5 Fix printf format. 2012-02-25 01:50:08 +01:00
Themaister 9bad6f2bba Add resampler tests. 2012-02-25 01:47:23 +01:00
Themaister 0496ffc007 Optimize sinc resampler a bit. 2012-02-24 21:01:29 +01:00
Themaister bb824b5679 Optional SINC. 2012-02-24 00:28:41 +01:00
Themaister 1ea4b5ce7c Fix build. 2012-02-23 23:57:35 +01:00
Themaister f5a4ea55f5 Add sinc resampler. 2012-02-23 23:53:18 +01:00
Themaister aecd9a1ecb Rename resampler functions to something more generic. 2012-02-23 23:22:08 +01:00
Themaister a797e1dbf4 Merge branch 'master' of github.com:Themaister/SSNES 2012-02-22 23:35:29 +01:00
Themaister 9c664b875a LUT info for Cg. 2012-02-22 23:35:01 +01:00
TwinAphex51224 375d05ed13 (PS3) Fixes the issue with resolution switching + cleaned up
some stuff
2012-02-22 21:42:17 +01:00
Themaister a13684c80c gl_cg_invalidate_context. 2012-02-22 20:45:58 +01:00
TwinAphex51224 678269039b Merge branch 'master' of github.com:Themaister/SSNES 2012-02-22 19:49:51 +01:00
TwinAphex51224 ece5935ef9 (PS3) Improved controls in menu - less twitchy controls 2012-02-22 19:49:22 +01:00
Themaister 341baf6918 If samplerate is not supported, do not fail. 2012-02-21 23:39:50 +01:00
TwinAphex51224 4acf66edfd (PS3) Enable image SPU decompression again 2012-02-21 00:00:17 +01:00
TwinAphex51224 10cfe3daa8 (PS3) update_input works now on PS3 2012-02-20 23:44:56 +01:00
TwinAphex51224 be3839a9df (PS3) Proper FBO scales now 2012-02-20 22:34:11 +01:00
TwinAphex51224 0023b4b2ce Merge branch 'master' of github.com:Themaister/SSNES 2012-02-20 21:06:13 +01:00
TwinAphex51224 17e0f19859 (PS3) Do malloc of pixels inside texture_image_load instead
of outside - same with free - still a problem with load_cgp
2012-02-20 21:05:34 +01:00
Themaister 383b2abe58 Merge branch 'master' of github.com:Themaister/SSNES 2012-02-20 20:36:42 +01:00
Themaister 5ce54cbbab Implement config_save_keybinds. 2012-02-20 20:36:21 +01:00
TwinAphex51224 2c2dcd58f2 (PS3) Initial cgp file loading - not yet working 2012-02-20 20:24:23 +01:00
TwinAphex51224 ee76898cab Merge branch 'master' of github.com:Themaister/SSNES 2012-02-20 19:01:31 +01:00
TwinAphex51224 a41e84749a (PS3) Quit crashes fixed 2012-02-20 19:01:09 +01:00
Themaister d68658b7fb Merge branch 'ratecontrol' 2012-02-20 18:40:07 +01:00
Themaister c833a71d2c Rate control for Pulse and Jack. 2012-02-20 18:39:50 +01:00
Themaister f1b135978c Merge branch 'master' of github.com:Themaister/SSNES 2012-02-20 18:30:44 +01:00
Themaister 6f04c38fda Use larger fragsize for OSS. 2012-02-20 18:30:26 +01:00
TwinAphex51224 cc979581eb Merge branch 'master' of github.com:Themaister/SSNES 2012-02-20 18:17:15 +01:00
TwinAphex51224 fe0ce2b78b (PS3) Better deiniting/freeing up of resources 2012-02-20 18:16:51 +01:00
Themaister b8382416ee Merge branch 'master' of github.com:Themaister/SSNES 2012-02-20 16:23:19 +01:00
Themaister 9bcbd27988 Add gl_cg_reinit(). 2012-02-20 16:22:58 +01:00
TwinAphex51224 3845844b83 Merge branch 'master' of github.com:Themaister/SSNES 2012-02-20 16:11:14 +01:00
TwinAphex51224 d7a29a66b4 (PS3) Add some more notifications to get_environment_settings -
clean up 'block/unblock swap' printfs
2012-02-20 16:10:32 +01:00
Themaister 6a7144d41c Add absolute paths to .cgp. 2012-02-20 15:45:38 +01:00
TwinAphex51224 12cf639dfe (PS3) Initial (WIP) support for external launchers like multiMAN -
also some control flow cleanups
2012-02-20 07:50:59 +01:00
TwinAphex51224 4604a995e9 (PS3) Scale factor can now be changed from ingame menu and
regular menu
2012-02-20 04:07:18 +01:00
Themaister 0b9ee6055f Merge branch 'master' into ratecontrol 2012-02-19 20:22:02 +01:00
TwinAphex51224 acd51a7dad Merge branch 'master' of github.com:Themaister/SSNES 2012-02-19 03:27:15 +01:00
TwinAphex51224 6d98da16b0 (PS3) Add experimental HAVE_SSNES_GL option (for custom GL libs) 2012-02-19 03:26:45 +01:00
Themaister 3407e765c3 Merge branch 'master' into ratecontrol 2012-02-18 13:05:47 +01:00
Themaister 2ef54a7e01 Might fix hat lookup. 2012-02-18 13:00:14 +01:00
Themaister aac2533075 Streamline hat lookup. 2012-02-18 12:32:49 +01:00
Themaister fd2be071f8 Merge branch 'master' into ratecontrol 2012-02-18 12:12:05 +01:00
Themaister 947d2a3514 Fixed joypad index lookup. 2012-02-18 12:09:20 +01:00
Themaister 3fd630e062 Log anatomy of input device. 2012-02-18 11:59:55 +01:00
TwinAphex51224 471dfcd478 (360) Filebrowser can now load ROMs from subdir 2012-02-17 21:28:23 +01:00
TwinAphex51224 8e8f56b5e8 (360) Combined console and font code into one file 2012-02-17 19:35:51 +01:00
Themaister 744a433595 Merge branch 'master' into ratecontrol 2012-02-16 23:02:18 +01:00
TwinAphex51224 f9ab3711eb (360) Remove some comments 2012-02-16 22:34:19 +01:00
TwinAphex51224 96cb22dbaa Merge branch 'master' of github.com:Themaister/SSNES 2012-02-16 22:11:42 +01:00
TwinAphex51224 f2f09ce2ed (360) xdk360_video_debugfonts is no longer class-based 2012-02-16 22:10:54 +01:00
Themaister 6d1ab7ebfd Revert changes with HAVE_XML. The XML read for memory map are not parsed
in any way by SSNES and does not depend on libxml2.

Also keep removal of log where XML map is not found (very likely
anyways).
2012-02-16 20:25:25 +01:00
TwinAphex51224 356d565ce6 (360) xdk360_video_console no longer class-based 2012-02-16 18:19:22 +01:00
TwinAphex51224 8ec0cb4f6c (360) Simplified video console 2012-02-16 17:45:11 +01:00
TwinAphex51224 fd9f020afa (360) Remove PIX calls 2012-02-16 16:28:31 +01:00
TwinAphex51224 52402d02c5 (360) Some improvements to font rendering 2012-02-16 16:14:31 +01:00
TwinAphex51224 1373ba167d (360) Remove font centering/alignment code 2012-02-16 15:43:15 +01:00
TwinAphex51224 668aa9a9ac (360) removed some unused code in console/debug fonts 2012-02-16 15:27:51 +01:00
TwinAphex51224 3585e046de (Core) Add some more HAVE_XML ifdefs 2012-02-16 03:55:22 +01:00
TwinAphex51224 2760b5b0c2 (Core) Don't create 'can't load XML memory map' if HAVE_XML
is not defined for the port
2012-02-16 03:49:13 +01:00
TwinAphex51224 441cd2b82a (PS3) Some cleanups in ps3_video_psgl.c 2012-02-16 03:36:40 +01:00
Themaister fe2134cb8c Fix warning. 2012-02-15 20:19:29 +01:00
TwinAphex51224 04e2541694 Merge branch 'master' of github.com:Themaister/SSNES 2012-02-15 18:58:02 +01:00
TwinAphex51224 878e612584 (PS3) Use new public save slot increment/decrement functions 2012-02-15 18:57:36 +01:00
TwinAphex51224 8dcf132b0c (360) Updated 360 port too 2012-02-15 18:57:29 +01:00
Themaister da7cf7e01d Merge branch 'master' into ratecontrol 2012-02-15 18:55:56 +01:00
TwinAphex51224 317f255eae (Core) Remove obsolete file checking function 2012-02-15 18:43:35 +01:00
Themaister b87e1c4f48 Make ssnes_state_slot_increase/decrease public. 2012-02-15 18:49:23 +01:00
TwinAphex51224 3cc042e2a6 (360) Compile fix for filepath_exists 2012-02-15 02:24:22 +01:00
TwinAphex51224 2cb946ec8b (Core) Add filepath_exists to file.c - needed for console ports 2012-02-15 02:09:55 +01:00
TwinAphex51224 8459f39933 (360) Remove PNGs we are no longer going to use in our GUI 2012-02-15 01:44:16 +01:00
TwinAphex51224 56e57d15bc (PS3) Fixed settings appearance 2012-02-15 01:37:49 +01:00
TwinAphex51224 975536ddbf (PS3) Some cleanups to ingame menu 2012-02-15 01:27:53 +01:00
TwinAphex51224 df997f6d23 (PS3) Better-looking Quick Menu/menu 2012-02-14 22:46:48 +01:00
TwinAphex51224 cb3064201e (PS3) Trying to have tranparent PNG with game image on back
in ingame menu
2012-02-14 21:34:18 +01:00
TwinAphex51224 48d589ffce (360) New Quick Menu 2012-02-14 17:34:25 +01:00
Themaister 16c740ffd8 Merge branch 'master' into ratecontrol 2012-02-14 16:58:55 +01:00
Themaister 80372f54a6 Add rate control calls for more backends. 2012-02-14 16:58:13 +01:00
Themaister a6a068e09e Add write_avail/buffer_size for XAudio. 2012-02-14 16:16:22 +01:00
TwinAphex51224 227f347e70 (360) Added initial Quick Menu 2012-02-14 02:41:35 +01:00
Themaister 438ac4ca4b Begin adding rate control. 2012-02-14 01:16:37 +01:00
TwinAphex51224 69a5faaaab (360) Implement swap callback 2012-02-13 22:53:07 +01:00
TwinAphex51224 1b28ea4945 (360) implement set swap block callback 2012-02-13 22:45:28 +01:00
TwinAphex51224 55a400f521 Merge branch 'master' of github.com:Themaister/SSNES 2012-02-13 22:25:46 +01:00
TwinAphex51224 d77560f1ea (PS3) Implement swap callback as well 2012-02-13 22:25:25 +01:00
TwinAphex51224 786adb23ac (PS3) Implement ssnes_load_state/ssnes_save_state 2012-02-13 22:16:41 +01:00
TwinAphex51224 a03dd57166 (PS3) Use new set swap block callback 2012-02-13 22:07:19 +01:00
Themaister bb642d3010 Merge branch 'master' of github.com:Themaister/SSNES 2012-02-13 22:04:46 +01:00
Themaister 21e39eea2b Use config_get_float. 2012-02-13 22:04:25 +01:00
TwinAphex51224 761f5d7a5c (PS3) Refactoring of ingame menu 2012-02-13 21:37:32 +01:00
Themaister e0408c30ae Slight refactor. Make ssnes_load_state(), ssnes_save_state() public. 2012-02-13 20:57:32 +01:00
Themaister 78136e0191 Make keybind loader public. 2012-02-13 19:20:24 +01:00
Themaister 77e55bb577 Add some video callbacks for consoles. 2012-02-13 19:17:13 +01:00
TwinAphex51224 89b99428f9 (PS3) Fix to Makefile for Win 2012-02-13 17:18:22 +01:00
TwinAphex51224 beeb660103 (360) Added new ingame menu (Right thumb stick) - will still have
to add a 'Quick Menu'
2012-02-13 16:45:08 +01:00
TwinAphex51224 9969474326 (360) Dehardcode control binds 2012-02-13 15:53:50 +01:00
TwinAphex51224 1307648d08 (360) Simplify filtering types to 'point filtering' and 'linear
interpolation' (anisotropic is useless for 2D) - also get rid
of filter_type member in g_console
2012-02-13 15:16:01 +01:00
TwinAphex51224 eeafd335fa (PS3) ingame_menu_item now part of console_settings 2012-02-13 14:33:24 +01:00
TwinAphex51224 32a52f5d01 (PS3) Windows compiler compatibility fix 2012-02-13 14:00:27 +01:00
TwinAphex51224 08f3313a3b (360) Some more cleanups to console/debug fonts/resources 2012-02-13 04:28:44 +01:00
TwinAphex51224 98f30469eb (360) Some cleanups 2012-02-13 02:51:07 +01:00
TwinAphex51224 36309050c4 (360) Skeleton ingame menu - doesn't yet draw anything yet other
than cached game image
2012-02-13 02:35:01 +01:00
TwinAphex51224 5a3b88bdd6 (360) Added /privilege=6 to imagexex command line (allow insecure
sockets - no more 'couldn't resolve symbolic link root name
XlfsUploadCache'
2012-02-13 00:05:23 +01:00
Themaister 000d863ae0 Fix nonblock bug. 2012-02-12 21:12:55 +01:00
Themaister 38d73e9da2 Use SSNES_CONSOLE. 2012-02-12 20:56:57 +01:00
TwinAphex51224 5f649bf2be Merge branch 'master' of github.com:Themaister/SSNES 2012-02-12 18:43:25 +01:00
TwinAphex51224 9609eca940 (360) Added fast forwarding option (hold down RStick down) 2012-02-12 18:42:51 +01:00
Themaister 5f71f48973 Merge branch 'master' of github.com:Themaister/SSNES 2012-02-12 18:07:07 +01:00
Themaister 5aa6acf031 Add *_equal semantics. 2012-02-12 18:05:33 +01:00
TwinAphex51224 ccfa448a66 (360) Some more cleanups 2012-02-12 17:39:02 +01:00
TwinAphex51224 1090eeb159 (360) Some cleanups 2012-02-12 17:13:13 +01:00
TwinAphex51224 3a66829933 (360) Working debug fonts 2012-02-12 15:23:35 +01:00
TwinAphex51224 045e72661a Merge branch 'master' of github.com:Themaister/SSNES 2012-02-12 01:36:01 +01:00
TwinAphex51224 b9ef2ff133 (360) Added missing header file for debug fonts 2012-02-12 01:35:38 +01:00
TwinAphex51224 80136435d2 (360) Experimental WIP debug fonts (not yet working) 2012-02-12 01:34:48 +01:00
Themaister 9c861f13be Fix additional exclamation marks. 2012-02-11 21:16:01 +01:00
Themaister 1cff87c758 Change exclamation marks with dots for less scream factor. 2012-02-11 20:59:41 +01:00
TwinAphex51224 ffc0c1d77e (PS3) Frame advance implemented 2012-02-11 19:22:51 +01:00
TwinAphex51224 2148ce9dec (PS3) Can now return to menu from game by pressing L3 + R3 2012-02-11 16:27:13 +01:00
TwinAphex51224 390628b1e3 (360) Can now return back to game from the menu by pressing
L3 + R3 (if a ROM has already been loaded)
2012-02-11 15:31:11 +01:00
TwinAphex51224 6e753d7d99 (360) Non-HD height fix 2012-02-10 17:32:43 +01:00
TwinAphex51224 c07bcbea53 (360) Support for non-HD TVs 2012-02-10 17:31:20 +01:00
TwinAphex51224 c0cba36dec (360) Added hardware filtering settings 2012-02-10 17:17:44 +01:00
TwinAphex51224 34b85e115b Merge branch 'master' of github.com:Themaister/SSNES 2012-02-09 18:12:37 +01:00
TwinAphex51224 40c3158d7e (360) Some more settings read from/saved to config file 2012-02-09 16:47:29 +01:00
TwinAphex51224 64728e38a4 (PS3) Use new members in g_console 2012-02-09 14:25:13 +01:00
TwinAphex51224 979b54178e (360) Moved some state variables to g_console struct 2012-02-09 14:11:55 +01:00
TwinAphex51224 3a33c5e1ec (360) Push small fix for config file loading/saving 2012-02-09 03:06:43 +01:00
TwinAphex51224 aeeb491a49 (360) Config file gets loaded and saved now 2012-02-09 03:10:20 +01:00
TwinAphex51224 38fb6f0a62 (360) Added header for menu.h 2012-02-09 02:36:09 +01:00
TwinAphex51224 b094151abb (360) Use LTCG 2012-02-09 02:00:24 +01:00
TwinAphex51224 e5e19edc65 (360) Special button mappings added - RSTICK Up - Rewind - RSTICK
Up + RT - Load State - RSTICK Down + RT - Save State -RSTICK
Left + RT - Save State Minus - RSTICK Right + RT - Save State Plus
2012-02-09 00:58:22 +01:00
TwinAphex51224 2cd7349cac (360) No more memset in input_poll function 2012-02-08 21:10:13 +01:00
TwinAphex51224 dc1a32f7f7 (360) Can exit back to menu and load another ROM with thumb stick
left + thumb stick right - loads several ROMs fine but might still
be crash-prone
2012-02-08 18:52:42 +01:00
Themaister 315b28862a Add gl_cg_save_cgp(). 2012-02-08 17:23:44 +01:00
TwinAphex51224 f6edb9a607 (360) Menu - A/B images show up now 2012-02-08 16:10:01 +01:00
TwinAphex51224 93072b926e Merge branch 'master' of github.com:Themaister/SSNES 2012-02-08 15:23:59 +01:00
TwinAphex51224 c161e3bc35 (360) Filebrowser can now navigate subdirs 2012-02-08 15:23:12 +01:00
Themaister 3bda32d6f1 Add SET_VARIABLES interface. 2012-02-06 16:13:29 +01:00
Themaister fea632b0e9 Add environment variable system extension. 2012-02-06 15:51:35 +01:00
TwinAphex51224 d959bc968a Merge branch 'master' of github.com:Themaister/SSNES 2012-02-05 01:49:36 +01:00
TwinAphex51224 e33221b52a (360) Linked static library should now be called libsnes.lib 2012-02-05 01:49:08 +01:00
Themaister c32d321b06 stdbool.h is C99. Use a more proper define. 2012-02-05 00:50:47 +01:00
TwinAphex51224 18d6d58a2b (360) Small fix 2012-02-05 00:32:31 +01:00
TwinAphex51224 996794134f (360) Give menu screens some more real estate (480p lowest res) 2012-02-05 00:25:57 +01:00
TwinAphex51224 02996fbe2e (360) Rudimentary working filebrowser - hardcoded to game://roms/
path right now
2012-02-04 23:40:11 +01:00
TwinAphex51224 e85471a239 (360) renamed fileio.c to file_browser.c 2012-02-04 20:43:56 +01:00
TwinAphex51224 0e2de25f85 (360) Add fileio for 360 2012-02-04 20:33:51 +01:00
TwinAphex51224 402be572ea (360) Added some extra printf reports to get_environment_settting 2012-02-04 14:25:44 +01:00
TwinAphex51224 1317ce1aea (PS3) Rename get_path_settings to get_environment_settings for
consistency
2012-02-04 13:29:02 +01:00
TwinAphex51224 884e39c58d (360) Added get_environment_settings 2012-02-04 13:33:19 +01:00
Themaister 0bb0b96623 Bump to 8 players bind input. 2012-02-04 01:54:19 +01:00
TwinAphex51224 61c1b2bb1b (360) Some settings XUI tweaks 2012-02-03 11:35:47 +01:00
TwinAphex51224 979b7e6479 (360) Can now enable/disable rewind setting in Settings menu -
can now return from Settings menu to main menu
2012-02-03 11:32:31 +01:00
TwinAphex51224 862082915b (360) Fix 360 build 2012-02-02 21:50:11 +01:00
Themaister fba6f36cb8 Fix typo. 2012-02-02 21:04:05 +01:00
Themaister 0cb2436a59 Bump to 8 players max. Futureproofing a bit. 2012-02-02 21:02:36 +01:00
Themaister 18c259e19a Revert "(PS3) Fix for Cg reset context - seems to work on PS3"
This reverts commit 56e862edf8.
Implementation is not quite correct.
2012-02-02 20:42:20 +01:00
Themaister e3a2ab0347 Change perform_reset() to ssnes_game_reset() to better advertise itself
as a public function.
2012-02-02 20:39:28 +01:00
TwinAphex51224 15bc0e0813 (360) Have 360 port use same setting variables as PS3 port
from g_console struct
2012-02-02 19:01:52 +01:00
TwinAphex51224 a328dbd213 (PS3) Overscan options added 2012-02-02 18:39:09 +01:00
TwinAphex51224 09a6566be0 (PS3) Moved some setting variables to g_console 2012-02-02 16:59:06 +01:00
TwinAphex51224 3eaa942e58 (PS3) Some cleanups for keybinding 2012-02-02 16:12:38 +01:00
TwinAphex51224 40ce42c87c (PS3) Initial keybind implementation 2012-02-02 15:46:27 +01:00
TwinAphex51224 a14bdb82b1 (PS3/Core) Increase MAX_PLAYERS from 5 to 7 - PS3 supports 7
controllers at once and there are games in FBA that have simultaneous
six-player support
2012-02-02 15:19:01 +01:00
TwinAphex51224 ee5d43486c (PS3) Use msg_queue for outputting text in-game 2012-02-02 14:41:05 +01:00
TwinAphex51224 02c3977e9d (PS3/Core) Make reset into an extern function so it can be called
from port-specific code
2012-02-02 14:22:43 +01:00
TwinAphex51224 a509d40bf6 Add some information for Wii target 2012-02-02 13:51:15 +01:00
TwinAphex51224 4501832997 Added some information in README.md for the new ports 2012-02-02 13:45:59 +01:00
TwinAphex51224 56e862edf8 (PS3) Fix for Cg reset context - seems to work on PS3 2012-02-02 13:13:16 +01:00
Themaister 945a086edf Verify that binds are in correct order. 2012-02-01 23:02:17 +01:00
Themaister 72f5748b28 Merge branch 'master' of github.com:Themaister/SSNES 2012-02-01 21:33:05 +01:00
Themaister 79f29a3966 Add test case and some fixes for re-entrancy. 2012-02-01 21:32:27 +01:00
TwinAphex51224 6843514f86 (PS3) Initial stab at frame advance - WIP - doesn't work yet -
probably some unforeseen gotcha I need to be aware of
2012-02-01 15:15:15 +01:00
TwinAphex51224 ff6b9bd0bf (PS3) Refactoring of FBO code 2012-02-01 14:24:48 +01:00
Themaister 3576613f52 Merge branch 'master' of github.com:Themaister/SSNES 2012-02-01 00:14:35 +01:00
Themaister 02cfa3f651 Big refactor of GL routines. 2012-02-01 00:14:04 +01:00
TwinAphex51224 87a0d3f413 Merge branch 'master' of github.com:Themaister/SSNES 2012-01-31 20:17:33 +01:00
TwinAphex51224 407205a4e5 (PS3) Create reinit_fbo function 2012-01-31 20:17:12 +01:00
Themaister 6f368200b9 Merge branch 'master' of github.com:Themaister/SSNES 2012-01-31 19:15:34 +01:00
Themaister f669f02407 Drop redundant ifs. 2012-01-31 19:14:48 +01:00
TwinAphex51224 e7d3e524bb (PS3) Added menu font options/settings 2012-01-31 18:51:45 +01:00
TwinAphex51224 d3d97bf11e Merge branch 'master' of github.com:Themaister/SSNES 2012-01-31 18:22:14 +01:00
TwinAphex51224 766bdf727c (PS3) Added aspect ratio settings/options 2012-01-31 18:21:53 +01:00
Themaister f2264ebb3e Do not use av_samples_get_buffer_size as it breaks older FFmpeg. 2012-01-31 18:06:20 +01:00
TwinAphex51224 2c61f2b1e7 (PS3) Use fill_pathname_base for displaying shader names in settings
screen
2012-01-31 14:34:43 +01:00
TwinAphex51224 cab8fd2a80 (PS3) WIP aspect ratio settings 2012-01-31 14:12:00 +01:00
TwinAphex51224 56a1877d15 Merge branch 'master' of github.com:Themaister/SSNES 2012-01-31 12:14:00 +01:00
TwinAphex51224 3096e154c9 (PS3) Add some settings 2012-01-31 12:13:43 +01:00
Themaister accb011196 Add fill_pathname_base. 2012-01-30 22:45:43 +01:00
TwinAphex51224 93068a376a (PS3 MSVS 2010) Get rid of ssnes.cfg copy buildevent rule 2012-01-30 21:43:25 +01:00
TwinAphex51224 5be17933e9 Merge branch 'master' of github.com:Themaister/SSNES 2012-01-30 20:28:21 +01:00
TwinAphex51224 f4183d2c8f (PS3) MSVS 2010f fix plus got rid of some warnings 2012-01-30 20:27:52 +01:00
Themaister 576855de4f Slight refactor. 2012-01-30 20:23:36 +01:00
TwinAphex51224 35b386df0d (PS3) Implemented savestate functionality in ingame menu 2012-01-30 20:05:36 +01:00
TwinAphex51224 2702299e7b (PS3) Added orientation options 2012-01-30 19:44:21 +01:00
TwinAphex51224 65e4357af7 Merge branch 'master' of github.com:Themaister/SSNES 2012-01-30 18:46:43 +01:00
Themaister 904cdd3fb4 Add ps3graphics_set_orientation. 2012-01-30 18:49:05 +01:00
TwinAphex51224 e48ec1ea20 (PS3) Rely on custom border-only.cg file being in the common-shader
subrepo instead of overwriting it for every 'make pkg' operation
2012-01-30 18:45:59 +01:00
Themaister 467023692f Should fix set_filter. 2012-01-30 18:33:47 +01:00
Themaister b861c11253 Fix screenshots. (Mziab) 2012-01-30 18:28:11 +01:00
TwinAphex51224 e538fe4364 (PS3) Implement ssnes_main wrap 2012-01-30 18:17:47 +01:00
Themaister e0aa65efc3 Should fix crash. 2012-01-30 18:21:46 +01:00
Themaister c569d9e179 Call ssnes_main_init(). 2012-01-30 18:15:14 +01:00
Themaister ef280919d3 Add a ssnes_main wrapper for more simple code. 2012-01-30 17:50:00 +01:00
TwinAphex51224 734afe2058 (PS3) Implement file_is_directory on PS3 2012-01-30 17:18:31 +01:00
TwinAphex51224 b4e3786aa1 (PS3) Free 'conf' pointer after use in save_settings 2012-01-30 16:36:08 +01:00
TwinAphex51224 feec19940a (PS3) 'Get all available resolutions' is only fetched one time at
startup
2012-01-30 16:21:22 +01:00
TwinAphex51224 ec97970206 (PS3) Saves to config file now 2012-01-30 15:59:15 +01:00
TwinAphex51224 4a9e7f7b7e Merge branch 'master' of github.com:Themaister/SSNES 2012-01-30 15:18:12 +01:00
TwinAphex51224 73fa4ea199 (PS3) Implemented a bunch of settings :
* Audio can be muted
* Buffering mode can be changed from double to triple buffering
and vice versa
* Default ROM startup dir and cheat path can be specified - now
to save the config file at exit
2012-01-30 15:16:29 +01:00
Themaister ce08251f53 Replace usage of DOUBLE with FLOAT in configs. 2012-01-30 15:14:30 +01:00
TwinAphex51224 bbd6e16bbe (Core) Remove float macros 2012-01-30 14:13:04 +01:00
TwinAphex51224 959411c094 (PS3) Uses config file macros now 2012-01-30 13:45:37 +01:00
TwinAphex51224 a64ae92d9d (PS3) Resolution can be changed now - deiniting/initing of video 2012-01-30 13:18:13 +01:00
TwinAphex51224 bad72987d0 (PS3) V-sync can be switched on/off now 2012-01-30 09:53:16 +01:00
TwinAphex51224 8deab9ea35 (PS3) set_filtering function (WIP) 2012-01-30 09:28:41 +01:00
TwinAphex51224 35e5f2dbc6 (PS3) Remove unnecessary debug printf 2012-01-30 01:43:50 +01:00
Themaister cd11f65956 Merge branch 'master' of github.com:Themaister/SSNES 2012-01-30 01:46:02 +01:00
Themaister 08686bcd06 Debork input some more ... 2012-01-30 01:45:18 +01:00
Themaister 5b0a948797 Refactor input config. 2012-01-30 01:20:35 +01:00
TwinAphex51224 b060c71de4 (PS3) Shaders can be loaded through the menu 2012-01-30 00:48:42 +01:00
Themaister fac78083ca Clarify path operations. 2012-01-30 00:01:59 +01:00
Themaister 230f47d00c Add helper function to replace Cg shaders on-the-fly. 2012-01-29 23:43:11 +01:00
TwinAphex51224 1cfc4c6cc0 (PS3) Fix indenting - somewhat 2012-01-29 23:16:39 +01:00
TwinAphex51224 f89060e7ff (PS3) Take out setting callback - was crashing the PS3 port 2012-01-29 23:11:47 +01:00
TwinAphex51224 16faee9ae2 (PS3) Add MSVS 2010 solution 2012-01-29 23:08:20 +01:00
TwinAphex51224 352b8e4cef (PS3) Still broke, still crashes after 'loading texture image' 2012-01-29 22:06:51 +01:00
Themaister 2c40567030 Properly return false from config_load_file. 2012-01-29 22:00:21 +01:00
Themaister ac3f80d738 Merge branch 'master' of github.com:Themaister/SSNES 2012-01-29 21:44:54 +01:00
Themaister 2721ccb52a Style nits. 2012-01-29 21:44:37 +01:00
TwinAphex51224 0fc36bfe0a (PS3) Some fixes in main.c 2012-01-29 21:35:20 +01:00
Themaister 559fc5b67f Fix issue with _CONSOLE config macro. 2012-01-29 21:32:13 +01:00
Themaister bd15206599 Fixup C++ build. 2012-01-29 19:12:29 +01:00
Themaister e5d3894bc4 Check for AV_NOPTS_VALUE. 2012-01-29 19:10:58 +01:00
Themaister 0bc0ae40a5 Fix audio_encode2. 2012-01-29 19:08:22 +01:00
Themaister 3c15bb06db Attempt to completely flush audio stream as well. 2012-01-29 18:59:56 +01:00
Themaister 9ce3331f04 Use av_samples_get_buffer_size. 2012-01-29 18:13:20 +01:00
Themaister 9508cc4eb3 Start fixing deprecation. Not used as it's broken atm. 2012-01-29 18:01:10 +01:00
Themaister 0bb1f7292c Cleanup settings handling a bit to avoid lots of dummy variables. 2012-01-29 15:52:59 +01:00
TwinAphex51224 b56b09af35 Added common macro file for CONFIG_ macros - used now too by PS3
port
2012-01-29 14:10:57 +01:00
TwinAphex51224 a685701805 (PS3) use custom Makefile rules for shader subrepo 2012-01-29 04:35:42 +01:00
Themaister d207eb0b1e Add callback system to config_set_defaults. 2012-01-28 16:49:06 +01:00
Themaister e8b2cde4cf More graceful error handling. 2012-01-28 15:47:02 +01:00
Themaister bedd5a691b Merge branch 'master' of github.com:Themaister/SSNES 2012-01-28 15:42:20 +01:00
Themaister 57fbad1a54 Expose config load as a global function. 2012-01-28 15:41:57 +01:00
TwinAphex51224 12deb9c54a (Git submodule) Changed url to read-only address so general users
can checkout
2012-01-28 14:04:07 +01:00
TwinAphex51224 8b1be981d3 (PS3) Added Git subrepo checkout rules in Makefile 2012-01-28 13:23:25 +01:00
TwinAphex51224 30d229c30b (PS3) Small rewrite of ps3_video_psgl.c 2012-01-28 11:38:24 +01:00
Themaister f3d9588e37 Merge branch 'master' of github.com:Themaister/SSNES 2012-01-28 00:34:29 +01:00
Themaister b5f77bf65e Use sthread in rsound. 2012-01-28 00:34:06 +01:00
TwinAphex51224 5bfc7be450 (PS3) Added Git subrepo for shaders 2012-01-28 00:34:06 +01:00
TwinAphex51224 fcab353201 (PS3) Updated menu image 2012-01-28 00:34:06 +01:00
Hans-Kristian Arntzen e968d26ba8 Unbind FBO before returning from gl_init_fbo(). 2012-01-28 00:34:06 +01:00
TwinAphex51224 db1765e788 (PS3) Shader texture is correctly applied after first booting a
game, but not before
2012-01-28 00:34:06 +01:00
TwinAphex51224 6e4277d9a6 (PS3) Change to border shader - still texture problems 2012-01-28 00:34:06 +01:00
TwinAphex51224 be56e901bb (PS3) More commits 2012-01-28 00:34:06 +01:00
TwinAphex51224 f803b5fbd3 (PS3) Shader menu texture (WIP) 2012-01-28 00:34:06 +01:00
TwinAphex51224 be62e537c6 (PS3) Added HAVE_SCREENSHOTS_BUILTIN define - is meant for targets
where native screenshot functionality is already supplied, negating
the need of compiling in screenshot.c
2012-01-28 00:34:06 +01:00
TwinAphex51224 7af7d55068 (PS3) use uint32_t * for pixels member as well for PS3 2012-01-28 00:34:06 +01:00
TwinAphex51224 15c5c69241 (PS3) Texture is now loaded 2012-01-28 00:34:06 +01:00
TwinAphex51224 b89554d11a (PS3) Added error logs to image.c for debugging purposes 2012-01-28 00:34:05 +01:00
TwinAphex51224 60760d69db (PS3) Added texture loading hooks, fails somewhere ATM 2012-01-28 00:34:05 +01:00
TwinAphex51224 ab687190a9 (PS3) Added border shaders - we will need a subrepo for all these shaders eventually 2012-01-28 00:34:05 +01:00
TwinAphex51224 a07514c88b (PS3) Fixed the crash at SYSUTIL_REQUEST_EXITGAME triggering 2012-01-28 00:34:05 +01:00
TwinAphex51224 f9de1a8831 (PS3) Doesn't crash anymore 2012-01-28 00:34:05 +01:00
Themaister badf807ae9 Remove useless macro. 2012-01-28 00:34:05 +01:00
TwinAphex51224 36e2b51827 (PS3) Added Git subrepo for shaders 2012-01-27 23:35:38 +01:00
TwinAphex51224 afae4a5cb4 (PS3) Updated menu image 2012-01-27 02:21:02 +01:00
Hans-Kristian Arntzen e9fb18f594 Unbind FBO before returning from gl_init_fbo(). 2012-01-27 01:00:09 +01:00
TwinAphex51224 a061fa081c (PS3) Shader texture is correctly applied after first booting a
game, but not before
2012-01-27 00:40:25 +01:00
TwinAphex51224 88b819ffff (PS3) Change to border shader - still texture problems 2012-01-27 00:31:10 +01:00
TwinAphex51224 730fb03c07 (PS3) More commits 2012-01-27 00:14:42 +01:00
TwinAphex51224 a571cf5e92 (PS3) Shader menu texture (WIP) 2012-01-27 00:07:24 +01:00
TwinAphex51224 7ce5733a45 (PS3) Added HAVE_SCREENSHOTS_BUILTIN define - is meant for targets
where native screenshot functionality is already supplied, negating
the need of compiling in screenshot.c
2012-01-26 03:00:56 +01:00
TwinAphex51224 e73df5e6a9 (PS3) use uint32_t * for pixels member as well for PS3 2012-01-26 02:53:59 +01:00
TwinAphex51224 c2cb9fead0 (PS3) Texture is now loaded 2012-01-26 02:28:54 +01:00
TwinAphex51224 01fb168f51 (PS3) Added error logs to image.c for debugging purposes 2012-01-26 02:01:06 +01:00
TwinAphex51224 f16b269685 (PS3) Added texture loading hooks, fails somewhere ATM 2012-01-26 01:33:39 +01:00
TwinAphex51224 1bfabea14a (PS3) Added border shaders - we will need a subrepo for all these shaders eventually 2012-01-26 00:35:14 +01:00
TwinAphex51224 1160aeed3d (PS3) Fixed the crash at SYSUTIL_REQUEST_EXITGAME triggering 2012-01-25 23:47:30 +01:00
TwinAphex51224 61019ac48c (PS3) Doesn't crash anymore 2012-01-25 23:44:32 +01:00
TwinAphex51224 4642e0ce96 Merge branch 'master' of github.com:Themaister/SSNES 2012-01-25 23:29:16 +01:00
TwinAphex51224 0a81b47932 (PS3) Hook up menu shader code - crashes currently 2012-01-25 23:28:50 +01:00
Themaister 0faa8c3855 Remove useless macro. 2012-01-25 23:08:12 +01:00
Themaister 388e2bb5fc Recognize kp_plus/kp_minus properly. 2012-01-25 23:03:02 +01:00
Themaister 14ffd07b70 Refactorin' ... 2012-01-25 22:55:34 +01:00
Themaister 9cb5eea20b Add some useful interfaces to Cg for PS3. Some cleanups ... 2012-01-25 22:00:18 +01:00
Themaister be03b8ac95 Fix indentation. 2012-01-25 19:57:37 +01:00
TwinAphex51224 b9ce2d4142 (360) Can now navigate to settings screen 2012-01-25 07:19:07 +01:00
TwinAphex51224 422c13242f (PS3) Add menu shader code (WIP) 2012-01-25 04:38:19 +01:00
TwinAphex51224 9e917d4835 (PS3) Take out redundant printf calls for 'rewind_enable' 2012-01-25 03:14:18 +01:00
TwinAphex51224 1cc8a8a121 (PS3) Use ssnes_console_get_rom_ext function in file browser 2012-01-25 03:11:21 +01:00
TwinAphex51224 05e49db12a (360) Compile in rom_ext.c file in 360 build 2012-01-25 03:00:38 +01:00
TwinAphex51224 2acc30e1a4 (PS3) Filled in ssnes_console_get_rom_ext function 2012-01-25 02:49:15 +01:00
Themaister dd1d83768b Add stubs for future rom_ext handling. 2012-01-25 01:10:53 +01:00
Themaister 1451ba9610 Use ARGB_SCE on PS3. 2012-01-25 00:17:00 +01:00
Themaister 3d8c50a768 Netplay compat define no longer needed. 2012-01-25 00:06:32 +01:00
TwinAphex51224 f5f8a71af2 (360) 360 fixes for netplay.c and netplay_compat.c - compiles and
links now
2012-01-25 00:02:59 +01:00
Themaister 5368d0d148 Attempt to implement gethostbyname for 360. 2012-01-24 23:54:06 +01:00
TwinAphex51224 c9fc51fe2a (PS3) Compiles and links in netplay now 2012-01-24 23:09:21 +01:00
Themaister 0e5a9a7772 Adjustments for PS3. 2012-01-24 23:14:11 +01:00
Themaister 6ff762f088 Some init stuff needed for PS3. 2012-01-24 22:38:25 +01:00
Themaister bda70a9168 Fix C++ build. 2012-01-24 22:31:26 +01:00
Themaister 03a892c7f2 Start adding netplay compat layer for legacy stuff. 2012-01-24 21:12:12 +01:00
TwinAphex51224 e6f2aa81f7 (360) Added settings XUI - navigation not yet working 2012-01-24 06:55:27 +01:00
TwinAphex51224 42b101b024 (360) Added libsnes core text to SSNES main screen and
dehardcoded SSNES version number - ASCII to Unicode messiness
inside
2012-01-24 06:11:01 +01:00
TwinAphex51224 38845d6ad5 (360) Add missing shared.h file 2012-01-24 01:20:26 +01:00
TwinAphex51224 a5db76d7db (360) Some error return fixes in menu_init 2012-01-24 01:09:34 +01:00
TwinAphex51224 5181463606 (360) Use SSNES_ERR instead of OutputDebugString 2012-01-24 01:06:12 +01:00
TwinAphex51224 a9ffab7854 (360) Quit button returns to dash 2012-01-24 00:32:44 +01:00
TwinAphex51224 2797ec3a79 (360) file browser button now goes to ROM loading/emulation state 2012-01-24 00:29:03 +01:00
TwinAphex51224 8c672bc613 (360) Added XUI logic (test) 2012-01-24 00:02:02 +01:00
TwinAphex51224 458abe3611 (360) Added image files for menu 2012-01-23 23:09:44 +01:00
TwinAphex51224 08a9525508 (360) XUI additions 2012-01-23 22:22:54 +01:00
TwinAphex51224 730983bf59 (360) Truetype font gets loaded now 2012-01-23 21:49:21 +01:00
TwinAphex51224 c7692e7a72 (360) XUI scene renders now 2012-01-23 21:36:54 +01:00
TwinAphex51224 8da940d0e5 (360) Fixed some deployment rules 2012-01-23 21:30:59 +01:00
TwinAphex51224 05607880f8 (360) Add some more XUI code - resource files from xzp files still
not loading - also added drive mounting code
2012-01-23 05:10:23 +01:00
TwinAphex51224 94ff302111 (360) Changed ZeroMemory to memset - ZeroMemory is just a stupid
typedef for memset
2012-01-23 00:10:25 +01:00
TwinAphex51224 aa32810151 (360) More work on XUI + fixed a bug in input code 2012-01-22 22:45:32 +01:00
TwinAphex51224 6614e4ef92 (360) Added custom build steps 2012-01-22 21:47:34 +01:00
Themaister 7374480126 Merge branch 'master' of github.com:Themaister/SSNES 2012-01-22 19:51:57 +01:00
Themaister d5dc910e5b Cleanups in skeleton config. 2012-01-22 19:51:37 +01:00
TwinAphex51224 367d554fff Merge branch 'master' of github.com:Themaister/SSNES 2012-01-22 19:46:23 +01:00
TwinAphex51224 ea49b02380 (360) Three-stage SSNES main 2012-01-22 19:45:58 +01:00
Themaister b0ddf78db0 Updates for 0.9.4.1. 2012-01-22 19:43:13 +01:00
TwinAphex51224 d4d97bfae1 (360) Use game image drive instead of devkit drive partition -
should work on retail
2012-01-22 02:05:09 +01:00
TwinAphex51224 5706713905 (360) Updated vcxproj files 2012-01-22 01:46:08 +01:00
TwinAphex51224 2fd7c1bb9f (360) Add preliminary WIP XUI menu code - far from complete 2012-01-22 01:43:54 +01:00
TwinAphex51224 e46f09c3b1 (360) Video gets inited before SSNES starts in preparation for XUI 2012-01-21 23:59:27 +01:00
TwinAphex51224 a4dd8bdf30 (360) Exclude netplay.c from Release build for now (again) 2012-01-21 18:57:23 +01:00
TwinAphex51224 2be040a8a7 (360) Added small ifdef to netplay.c - next stumbling block -
both 360 and PS3 don't support sockaddr_storage and getaddrinfo
2012-01-21 18:56:07 +01:00
Themaister e14f5e9ea5 Merge branch 'master' of github.com:Themaister/SSNES 2012-01-21 18:34:28 +01:00
Themaister f9870dfb24 Nicknames for spectator mode as well. 2012-01-21 18:34:07 +01:00
Themaister ec5612a12b Merge branch 'master' of github.com:Themaister/SSNES 2012-01-21 18:13:18 +01:00
TwinAphex51224 d12532aef1 Merge branch 'master' of github.com:Themaister/SSNES 2012-01-21 18:12:57 +01:00
Themaister 7082561e21 Nicknames for regular connection. 2012-01-21 18:12:42 +01:00
TwinAphex51224 763f257d92 (PS3) Show static libsnes library in menu 2012-01-21 18:12:33 +01:00
TwinAphex51224 d55c86bc41 (PS3) Use ssnes_main_clear_state() 2012-01-21 18:00:07 +01:00
TwinAphex51224 3695cf78b9 (PS3) Swap is blocked before going into ingame menu - and unblocked
after exiting ingame menu
2012-01-21 17:50:21 +01:00
TwinAphex51224 26cb567bb9 Merge branch 'master' of github.com:Themaister/SSNES 2012-01-21 17:24:48 +01:00
TwinAphex51224 fabceb0e84 (PS3) Rewind can be set now 2012-01-21 17:24:25 +01:00
Themaister 0a3dc05c27 Fix custom getopt_long for certain arguments.
getopt_long() treats this as equivalent: {"-c", "foo"}, {"-cfoo"}.
This is fixed.
2012-01-21 16:27:51 +01:00
Themaister 8f0a47e6c3 Small cleanup. 2012-01-21 16:14:10 +01:00
Themaister 20528b9d1f Fix buggy log_connection. 2012-01-21 14:58:39 +01:00
Themaister d262049f6b Additional fixes. 2012-01-21 14:46:33 +01:00
Themaister 75408b689d Hook up binds. 2012-01-21 14:24:38 +01:00
Themaister d551d93ce4 Start implementing player flipping. 2012-01-21 14:00:11 +01:00
Themaister 99f622de0e Just rename video_render_cached(). 2012-01-21 12:12:44 +01:00
TwinAphex51224 64cbfd0183 (PS3) Updated main-menu.jpg border picture 2012-01-21 06:42:04 +01:00
TwinAphex51224 64de1a3260 (PS3) Add rewind menu option - note - g_settings.rewind_enable gets
cleared to '0' somewhere in first-stage SSNES init for some weird
reason - can't even enable it right now beacuse of that
2012-01-21 06:06:01 +01:00
TwinAphex51224 4d95765cb5 (PS3) No longer gives framebuffer objects error 2012-01-21 05:20:44 +01:00
TwinAphex51224 e90b7e6a03 (PS3) Added ssnes_render_cached_frame - this is necessary for the
ingame menu - another problem - swap occurs at end of frame
function - this interferes with the swap done later on in the
ingame menu, leading to flickered libdbgfont text. We will somehow
need to divorce the swap from the main frame function
2012-01-21 03:56:31 +01:00
TwinAphex51224 e044275c3e (360) Fix for 360 - INVALID_FILE_ATTRIBUTES is not defined in a
360 header
(PS3) Added g_console.rom_path setting - not using g_extern.system.
fullpath anymore
2012-01-21 02:58:19 +01:00
TwinAphex51224 c5e8eb0283 (PS3) Ingame menu - can return now to SSNES 2012-01-21 02:32:55 +01:00
TwinAphex51224 8e74333ef4 (PS3) First stab at ingame menu 2012-01-21 00:30:01 +01:00
Themaister 2089521856 Menu/in-game-menu logic. 2012-01-20 19:29:26 +01:00
Themaister 057d29bea1 Check for INVALID_FILE_ATTRIBUTES. 2012-01-20 18:31:46 +01:00
Themaister 026fd10bd4 Merge branch 'master' of github.com:Themaister/SSNES 2012-01-20 18:10:29 +01:00
Themaister c492195ab1 Empty string should not be a directory. 2012-01-20 18:09:53 +01:00
TwinAphex51224 d9a72ea076 (PS3) Implemented SSNES control flow 2012-01-20 18:00:33 +01:00
TwinAphex51224 955c0e85c8 (PS3) image.c - added header 2012-01-18 01:02:34 +01:00
TwinAphex51224 3c99021b60 (PS3) custom image.c (for PNG/JPEG decoding) 2012-01-18 00:59:35 +01:00
TwinAphex51224 5453cc0448 (PS3) Added preliminary resolution switching options 2012-01-18 00:18:23 +01:00
TwinAphex51224 c7e32cbbd2 (PS3) Some more work on PS3 menu front 2012-01-17 23:59:23 +01:00
Themaister 5edf67bba8 Fixup comment. 2012-01-17 23:49:03 +01:00
Themaister d109c22b49 Update Windows makefile. 2012-01-16 22:10:31 +01:00
Themaister 98f2f1c23d Updates for 0.9.4. 2012-01-16 22:08:54 +01:00
TwinAphex51224 94bc6ff3a2 (PS3) Some more settings filled in 2012-01-16 17:15:16 +01:00
TwinAphex51224 62dc63542c (PS3) Clean up PS3 GL driver always assume HAVE_FBO and HAVE_CG 2012-01-16 16:46:35 +01:00
TwinAphex51224 dd8acd5872 (PS3) Added SN version number in 'print compiler' function 2012-01-16 16:38:27 +01:00
TwinAphex51224 d1113a5af0 (PS3) Added sysutil screenshot feature 2012-01-16 15:45:55 +01:00
TwinAphex51224 024e10b5a9 (PS3) Implemented some settings 2012-01-16 15:33:18 +01:00
TwinAphex51224 c4b2492872 (PS3) Some cleanups 2012-01-16 04:09:28 +01:00
TwinAphex51224 44bc9fe291 (PS3) Menu refactoring 2012-01-16 04:07:02 +01:00
Themaister ee7bacd2bc Fix critical performance regression. 2012-01-14 23:15:25 +01:00
Themaister 90a2070718 Return 0 from main().
On console targets, main() is overridden to ssnes_main().
2012-01-14 20:45:05 +01:00
Themaister abf34c06c1 Attempt to always return from ssnes_main_init() when errors occur. 2012-01-14 16:08:54 +01:00
Themaister 661836fd77 Deconstruct main() into three separate functions.
Split main() into init/iterate/deinit functions.
2012-01-14 14:08:43 +01:00
Themaister 260f3ac7ce Use a more general SSNES_CONSOLE define. 2012-01-14 13:43:15 +01:00
Themaister f57ab1ccd8 Handle zero sized writes. 2012-01-14 02:03:49 +01:00
Themaister ef206b3a27 Fix directory detection. 2012-01-14 01:42:51 +01:00
TwinAphex51224 2dce493240 (PS3) Sysutil exit callback works in menu too 2012-01-13 01:27:18 +01:00
TwinAphex51224 83c3d7be57 (PS3) Menu fixes 2012-01-13 01:01:08 +01:00
TwinAphex51224 7b0e1e8022 (PS3) Got rid of warnings in main.c 2012-01-13 00:22:43 +01:00
Themaister 86950b4d2a FBO scale are float. 2012-01-13 00:29:01 +01:00
Themaister fe02783fc7 Merge branch 'master' of github.com:Themaister/SSNES 2012-01-13 00:09:27 +01:00
Themaister 072406e3c3 Merge branch 'master' of github.com:Themaister/SSNES 2012-01-13 00:09:13 +01:00
Themaister 751761d99c Add config_get_float. 2012-01-13 00:08:55 +01:00
TwinAphex51224 fe993fafd5 (PS3) Fixed menu speed 2012-01-13 00:01:52 +01:00
TwinAphex51224 057785539b Merge branch 'master' of github.com:Themaister/SSNES 2012-01-12 23:46:10 +01:00
TwinAphex51224 048d2f65e0 (PS3) Fixed controller 2 2012-01-12 23:45:48 +01:00
Themaister c305f4347d Add g_console struct. 2012-01-12 22:53:14 +01:00
TwinAphex51224 3ca62fbbbc (PS3) Pushed PS3 video fix 2012-01-12 22:02:28 +01:00
Themaister 225699f545 No real need to memset(). 2012-01-12 20:41:52 +01:00
Themaister 35ae61fbc7 Use more correct UINT*_C() constants. 2012-01-12 20:16:47 +01:00
Themaister 86dac8c979 Make sure sockets are not closed twice on error. 2012-01-12 09:21:33 +01:00
TwinAphex51224 95431414ae (PS3) Initialize some settings 2012-01-12 00:24:17 +01:00
TwinAphex51224 b3f7224ea1 (PS3) menu works, ROM loads, but screen is black 2012-01-12 00:05:32 +01:00
Themaister e583546778 Add some more needed stuff. 2012-01-11 23:48:48 +01:00
Themaister a39c37e1ee Add some hooks to video init/deinit for PS3. 2012-01-11 23:44:29 +01:00
Themaister 67fb35b645 Merge branch 'master' of github.com:Themaister/SSNES 2012-01-11 23:10:05 +01:00
Themaister 3c1e4c879a Integer scale is bad mmkay. 2012-01-11 23:09:22 +01:00
TwinAphex51224 83a11be669 Merge branch 'master' of github.com:Themaister/SSNES 2012-01-11 22:55:37 +01:00
TwinAphex51224 08e35a62d4 (PS3) Can now compile with SNC as well 2012-01-11 22:55:07 +01:00
Themaister 5461c0d86e Merge branch 'master' of github.com:Themaister/SSNES 2012-01-11 22:52:57 +01:00
Themaister 4eab7c4387 Font scale option. 2012-01-11 22:52:25 +01:00
TwinAphex51224 59aeb77744 (PS3) Some more work on menu 2012-01-11 22:27:07 +01:00
Themaister c6fc8e45ff Log more clearly disconnects. 2012-01-11 21:08:44 +01:00
Themaister 4dde927c12 Add some logging and increase buffer sizes. 2012-01-11 20:50:21 +01:00
Themaister 6325b4cd2e Set larger buffer size to mitigate lags on client connect. 2012-01-11 20:14:59 +01:00
Themaister 4beec3870f Spectator mode. 2012-01-11 19:22:18 +01:00
Themaister 36a2c96cb7 ifdef console oriented binds. 2012-01-11 10:00:24 +01:00
TwinAphex51224 a4a68a2ad5 (PS3) Implemented menu code some more 2012-01-11 02:25:49 +01:00
TwinAphex51224 13a2010ed6 (PS3) Fix 2012-01-11 01:17:04 +01:00
TwinAphex51224 e37fd21424 Merge branch 'master' of github.com:Themaister/SSNES 2012-01-11 01:04:47 +01:00
TwinAphex51224 a2698061a6 (PS3) Loads settings from config file 2012-01-11 01:04:17 +01:00
Themaister d00257382a Always dump 16-bit little endian values for movie record. 2012-01-11 00:55:50 +01:00
TwinAphex51224 51ab2f2509 (PS3) Added initial menu - not yet compiled in 2012-01-10 23:33:44 +01:00
TwinAphex51224 61f9ceccab PATH_MAX gets redefined for PS3/Libxenon 2012-01-10 22:08:24 +01:00
Themaister f836a291a0 Reinstate ssnes.cfg. 2012-01-09 16:05:02 +01:00
Themaister 97725e69eb Add missing license header. 2012-01-08 02:30:32 +01:00
Themaister d186e14eeb VSync one frame earlier. 2012-01-08 02:21:28 +01:00
Themaister 08aaa1021c More aestethically pleasing effect. 2012-01-08 01:32:45 +01:00
Themaister b4248038fb Update license headers. 2012-01-08 01:12:05 +01:00
Themaister ca587ab92e Actually runs. 2012-01-08 01:07:26 +01:00
Themaister 6f5c33848e Begin work on menu for Wii. 2012-01-08 00:57:44 +01:00
Themaister 17d380400e Update AUTHORS. 2012-01-07 17:07:22 +01:00
Themaister 2e456b2570 Rename gl-> to vid-> for consistency. 2012-01-07 15:30:52 +01:00
TwinAphex51224 fe17a42e62 (360) Fixed 2012-01-07 15:28:39 +01:00
Themaister c46866c6e5 Use correct geometries (I hope). 2012-01-07 15:21:23 +01:00
Themaister 3117633adf Actually use a viewport. 2012-01-07 15:11:57 +01:00
Themaister 8a49321648 Rename shader vars again. :D 2012-01-07 15:03:09 +01:00
Themaister 18f027ed41 Rename shader variable names. 2012-01-07 15:00:51 +01:00
TwinAphex51224 79b9c68cb5 (360) Compile fixes 2012-01-07 14:59:11 +01:00
Themaister 2b1344c3cf Clean up and add missing bits to 360 D3D9. 2012-01-07 14:54:55 +01:00
TwinAphex51224 da26925118 (360) Fleshed out video driver some more 2012-01-07 14:13:23 +01:00
Themaister f2a152f7c9 Minor cleanup. 2012-01-07 11:47:53 +01:00
Themaister 1953ea7312 Fix Xenon build. 2012-01-07 11:32:39 +01:00
TwinAphex51224 e55dbe944d (360) changed buf to uint8_t * 2012-01-06 22:55:07 +01:00
Themaister f5ad906e7b Don't need byteswapping on 360. 2012-01-06 22:49:30 +01:00
TwinAphex51224 7cad2bcd6e (360) Some sound fixes 2012-01-06 22:40:40 +01:00
Themaister cc921f25ed Use integer audio on 360. 2012-01-06 22:30:12 +01:00
Themaister 435109ceae Rework SRAM semantics for Sufami. 2012-01-06 20:32:30 +01:00
Themaister ca375f65d5 Call CreateEvent. 2012-01-06 19:45:27 +01:00
Themaister 76212f47bf Fix indentation. 2012-01-06 18:51:45 +01:00
TwinAphex51224 6efb904919 Merge branch 'master' of github.com:Themaister/SSNES 2012-01-06 14:12:38 +01:00
TwinAphex51224 072342cdab (360) Gets to initing audio 2012-01-06 14:12:12 +01:00
Themaister 09761c0786 Merge branch 'master' of github.com:Themaister/SSNES 2012-01-06 00:05:05 +01:00
Themaister c48fab00e8 Remove unneeded header. 2012-01-06 00:04:48 +01:00
TwinAphex51224 d1c562ce4e (360) Small correction to main.c file 2012-01-05 23:19:14 +01:00
Themaister 45cae81d51 Merge branch 'master' of github.com:Themaister/SSNES 2012-01-05 23:10:28 +01:00
Themaister 30e28acfb3 Workaround GetFullPathName not existing on XDK. 2012-01-05 23:09:52 +01:00
TwinAphex51224 00459365c4 Merge branch 'master' of github.com:Themaister/SSNES 2012-01-05 22:47:54 +01:00
TwinAphex51224 649884bc05 (360) Added main files 2012-01-05 22:47:34 +01:00
TwinAphex51224 e1af420b2d (360) More work on 360 2012-01-05 22:46:11 +01:00
Themaister 613f50dd14 Merge branch 'master' of github.com:Themaister/SSNES 2012-01-05 21:45:32 +01:00
Themaister a18c0b2b14 Use const. 2012-01-05 21:43:55 +01:00
TwinAphex51224 d7f8500b3a Merge branch 'master' of github.com:Themaister/SSNES 2012-01-05 20:54:26 +01:00
TwinAphex51224 7ecf9681c5 (360) Updated vcxproj file 2012-01-05 20:54:04 +01:00
Themaister e9ca7acce9 Merge branch 'master' of github.com:Themaister/SSNES 2012-01-05 19:44:39 +01:00
Themaister ea68de8070 Don't use *A() version. 2012-01-05 19:44:11 +01:00
TwinAphex51224 0fa0bfeb74 (360) Compiles in dynamic.c 2012-01-05 19:42:29 +01:00
TwinAphex51224 4a5d0d8dfb (360) Updated solution 2012-01-05 19:35:56 +01:00
Themaister af35a18515 :v 2012-01-05 19:34:15 +01:00
Themaister 5560babc11 Some build fixups. 2012-01-05 19:33:38 +01:00
Themaister 3e76201d80 Rename to C++. 2012-01-05 19:28:19 +01:00
Themaister 5b15d8626c Restructure XAudio2 360 driver. 2012-01-05 19:27:58 +01:00
TwinAphex51224 f8a03a7d5d Merge branch 'master' of github.com:Themaister/SSNES 2012-01-05 18:38:49 +01:00
TwinAphex51224 b7b9acb336 (360) compiles now 2012-01-05 18:38:29 +01:00
Themaister 44e2d66cf5 Mainstub clean. 2012-01-05 17:53:30 +01:00
Themaister 9747767474 Use GetFileAttributes. 2012-01-05 17:41:04 +01:00
Themaister cee33327f8 Ugh 2012-01-05 17:28:11 +01:00
Themaister f70b52a0df Don't use unicode. 2012-01-05 17:27:48 +01:00
Themaister 0b62771b54 Don't use getenv on XBOX. 2012-01-05 17:27:18 +01:00
Themaister b168109672 Fix missing stuff. 2012-01-05 17:23:22 +01:00
Themaister d8b6aebe9a Use plain ASCII for directories. 2012-01-05 17:22:03 +01:00
TwinAphex51224 4812b632c3 (360) Fixed most compile errors for 360 2012-01-05 15:11:55 +01:00
TwinAphex51224 8320d0a0e9 (360) Xaudio2 driver compiles now 2012-01-05 14:48:54 +01:00
TwinAphex51224 a287ebe736 (360) New Xaudio2 driver 2012-01-05 14:17:35 +01:00
TwinAphex51224 ebea0220cd (360) Added 360 solution and added some defines 2012-01-05 13:30:13 +01:00
TwinAphex51224 2b01f36fc0 (360) Added preliminary xdk 360 drivers 2012-01-05 12:37:27 +01:00
Themaister 7e3092dc93 Build in freetype. Will be used later. 2012-01-03 13:04:23 +01:00
Themaister 114c723d59 Only init input once. 2012-01-03 12:22:07 +01:00
Themaister da39f8d3d6 Support classic controller. 2012-01-03 12:11:02 +01:00
Themaister 33b76628aa Far better vsync handling. 2012-01-03 11:32:07 +01:00
Themaister 94162f452d Use RGB5A3 for Wii. 2012-01-03 10:32:51 +01:00
Themaister 318d875981 Small cleanups. 2012-01-03 02:50:45 +01:00
Themaister 520878272c Checks if swapinterval succeeds. 2012-01-02 22:09:55 +01:00
Themaister fc87336c45 MSVC doesn't have PATH_MAX. 2012-01-02 16:03:39 +01:00
Themaister d66e039536 Fix 15->16 bit conversions. 2012-01-02 15:43:46 +01:00
Themaister eeebc2d06b Optimize a bit. 2012-01-02 14:50:03 +01:00
Themaister 7d1ebdf94a Pick linear/nearest filtering correctly. 2012-01-02 13:45:31 +01:00
Themaister 3d1b0ef35b Merge branch 'fix' 2012-01-02 13:33:27 +01:00
Themaister c2ba0d474c Use limits.h and PATH_MAX. 2012-01-02 13:33:03 +01:00
Themaister 793c00e614 Attempt on tiled textures for Wii. 2012-01-02 12:56:09 +01:00
Themaister d4093dc31c Fix build for gekko. 2012-01-02 12:12:30 +01:00
Themaister bc66841a29 More correct save state and rewind handling. 2011-12-27 18:30:14 +01:00
Themaister f4cc8a4bca Update filters. 2011-12-27 03:33:18 +01:00
Themaister 539563f0f4 Add filters to project. 2011-12-27 03:27:28 +01:00
Themaister 8c5d86a6eb Add logging to SDL_Init(). 2011-12-27 01:04:50 +01:00
Themaister 884c113645 Cleanup stupid code. 2011-12-27 00:54:31 +01:00
Themaister 70587bc0df More verbosely log SDL failure. 2011-12-27 00:37:29 +01:00
Themaister df4e0bb1e4 Don't use x64libs. 2011-12-27 00:15:58 +01:00
Themaister cdc92af959 Cleanups. 2011-12-26 16:43:47 +01:00
Themaister 763a5bf2c0 Style nit. 2011-12-26 16:22:34 +01:00
Themaister 8301cf8a2f Style nit. 2011-12-26 16:14:33 +01:00
Themaister 44da8a6749 :v 2011-12-26 01:32:19 +01:00
Themaister 06309ba1e0 Build some more stuff. 2011-12-26 00:06:41 +01:00
Themaister 004ca0fe89 Better formatting. 2011-12-25 21:43:00 +01:00
Themaister 40cce7c9d6 Also log compiler version normally. 2011-12-25 21:39:58 +01:00
Themaister 1c29d31859 Better formatting. 2011-12-25 21:20:07 +01:00
Themaister d3af29fa1f Compiler logging macros. 2011-12-25 21:16:48 +01:00
Themaister c5d1fd32d5 Deinit audio before video. 2011-12-25 19:31:05 +01:00
Themaister a4767d3d43 Add python build. Fix ssize_t define. 2011-12-25 18:25:37 +01:00
Themaister c26f527c20 Enable SSE for 64-bit builds. 2011-12-25 16:50:13 +01:00
Themaister 0c8d85d589 Minor fixes. 2011-12-25 16:47:03 +01:00
Themaister 0c16e1a134 x64 build. 2011-12-25 16:36:56 +01:00
Themaister 0a887395eb Remove useless global. 2011-12-25 16:11:48 +01:00
Themaister 9118976c49 Don't include general.h 2011-12-25 12:56:21 +01:00
Themaister 7f1e599186 Use modern FFmpeg defines. 2011-12-25 12:50:34 +01:00
Themaister 672102d377 Change asserts to ssnes_assert(). 2011-12-25 12:47:47 +01:00
Themaister fe7f05e717 Style nit. 2011-12-25 12:14:26 +01:00
Themaister 0724ab2ca1 Fix assertion bugs. 2011-12-25 12:13:19 +01:00
Themaister c272ba56ad Fix build for Release mode. 2011-12-25 11:45:27 +01:00
Themaister 381498e945 Print feature for DirectSound. 2011-12-25 01:59:30 +01:00
Themaister 70f07196ea gettimeofday() should return int. 2011-12-25 01:54:29 +01:00
Themaister c8dee57278 Set constant macros with define. 2011-12-25 01:45:09 +01:00
Themaister 0ab305156b Fixup header. 2011-12-25 01:41:12 +01:00
Themaister eac468ba19 MSVC compat. 2011-12-25 01:38:59 +01:00
Themaister 18f407110b Fixup compatibility. 2011-12-24 20:43:58 +01:00
Themaister ceee10b56c Fix types. 2011-12-24 15:57:43 +01:00
Themaister 9805bcc5f9 Merge branch 'master' of github.com:Themaister/SSNES 2011-12-24 15:47:47 +01:00
Themaister d5fca50a2f Can build for C++. 2011-12-24 15:26:01 +01:00
Themaister 4ca72bd7e6 Fix endian issues and strict aliasing. 2011-12-24 14:41:19 +01:00
Themaister 62ead00f0f Some additions, but still broken. 2011-12-24 14:41:19 +01:00
TwinAphex51224 5dc573ed38 (Libxenon) Changed texture size to 512x512 - stop libxenon development
for now - no double buffering/triple buffering available - return to
it when it's more mature
2011-12-24 14:41:19 +01:00
TwinAphex51224 fa053ffc2b (Libxenon) Fixed colors 2011-12-24 14:41:18 +01:00
TwinAphex51224 be6c7bad24 (Libxenon) Revert to Xenos driver that works - current issues - colors
are wrong (doing | XE_FMT_ARGB produces 'distorted' graphics but right colors) - no vsync (doing while Xe_IsVBlank(device) Xe_Sync(device) makes everything too
slow
2011-12-24 14:41:18 +01:00
Themaister 2680971bb3 Try some stuff. 2011-12-24 14:41:18 +01:00
Themaister 630f19f248 ... 2011-12-24 14:41:18 +01:00
Themaister ef4bee2e4e Minor fix. 2011-12-24 14:41:18 +01:00
Themaister f182a2ad24 Debork party. Untested. 2011-12-24 14:41:18 +01:00
Themaister 3eb98951f7 :v 2011-12-24 14:41:18 +01:00
Themaister f9d4bbf4d3 Fix endian issues and strict aliasing. 2011-12-19 01:27:04 +01:00
Themaister eff4fcecae Some additions, but still broken. 2011-12-18 13:27:06 +01:00
TwinAphex51224 cbfdc9cf97 (Libxenon) Changed texture size to 512x512 - stop libxenon development
for now - no double buffering/triple buffering available - return to
it when it's more mature
2011-12-16 18:54:12 +01:00
TwinAphex51224 034c7c70fb (Libxenon) Fixed colors 2011-12-16 17:22:37 +01:00
TwinAphex51224 44ad016b91 (Libxenon) Revert to Xenos driver that works - current issues - colors
are wrong (doing | XE_FMT_ARGB produces 'distorted' graphics but right colors) - no vsync (doing while Xe_IsVBlank(device) Xe_Sync(device) makes everything too
slow
2011-12-16 17:09:33 +01:00
Themaister 5ed0d00249 Try some stuff. 2011-12-16 16:38:25 +01:00
Themaister 6336fb4a1b ... 2011-12-16 16:26:44 +01:00
Themaister 99497e21cf Minor fix. 2011-12-16 16:21:58 +01:00
Themaister 0181d97cae Debork party. Untested. 2011-12-16 16:02:30 +01:00
TwinAphex51224 968c73a748 Merge branch 'master' of github.com:Themaister/SSNES 2011-12-16 15:22:56 +01:00
TwinAphex51224 13f9e94f61 (Libxenon 360) Shows video for one/two frames, then crashes 2011-12-16 15:22:25 +01:00
Themaister 8c1018d573 Merge branch 'master' of github.com:Themaister/SSNES 2011-12-16 15:09:46 +01:00
Themaister d4d00a35d7 :v 2011-12-16 15:09:15 +01:00
TwinAphex51224 e3177fd489 (Libxenon) Xenos gfx commit - still broken 2011-12-16 14:43:09 +01:00
Themaister dd1300f1cc Fix rewind granularity setting when not playing movies. 2011-12-16 10:19:45 +01:00
TwinAphex51224 7f03af2b2b (Libxenon) starts up now - borked graphics though :) 2011-12-15 15:32:47 +01:00
TwinAphex51224 f431f77834 (Libxenon) fix (still crashes during init) 2011-12-15 15:19:03 +01:00
TwinAphex51224 7c28a62b40 (Libxenon) No more SDL 2011-12-15 13:54:22 +01:00
TwinAphex51224 a360042f77 Merge branch 'master' of github.com:Themaister/SSNES 2011-12-15 13:38:55 +01:00
TwinAphex51224 82af27cf33 (Libxenon) Initial xenos graphics driver 2011-12-15 13:38:28 +01:00
Themaister 0b78abb31d hrr drr. 2011-12-15 00:28:47 +01:00
Themaister 2fd8ffbf22 Some progress at least. 2011-12-14 23:56:07 +01:00
Themaister 83f7be0cbb Some more stuff. 2011-12-14 22:29:12 +01:00
Themaister 7f5db4d70f Boots up, but broken graphics. 2011-12-14 21:44:03 +01:00
Themaister 4f04c1288b Use fatInit default. 2011-12-14 19:11:46 +01:00
Themaister 8a2c5bf9e1 Some cleanups. 2011-12-14 17:05:23 +01:00
Themaister 5c05e309c1 Xenon input takes prio. 2011-12-14 16:53:13 +01:00
Themaister bd147270eb Use built-in getopt. 2011-12-14 16:40:25 +01:00
Themaister 528cf8d472 Don't use SDL input on xenon. 2011-12-14 16:37:31 +01:00
Themaister 0fce2f409f Add a warning. :3 2011-12-14 16:29:38 +01:00
Themaister fd7b0b05b8 Hurr. 2011-12-14 16:01:16 +01:00
Themaister 9abc7c00c9 It links :o 2011-12-14 14:52:58 +01:00
Themaister ebc5f433cd It links :o 2011-12-14 14:36:23 +01:00
Themaister aa4f79f236 Start working on video. 2011-12-14 14:26:40 +01:00
Themaister 62f5c53b72 Start on Wii input. 2011-12-14 13:20:22 +01:00
Themaister 534163a57f Start adding stuff for Wii. 2011-12-14 12:49:13 +01:00
TwinAphex51224 325a9fb48e (Libxenon) D-pad works now in ROM browser menu 2011-12-14 08:36:04 +01:00
TwinAphex51224 ee43531a99 Merge branch 'master' of github.com:Themaister/SSNES 2011-12-14 01:35:46 +01:00
TwinAphex51224 757fa71469 (Libxenon) Added (non-working) input driver 2011-12-14 01:35:17 +01:00
Themaister bfee7986bd Fix missing break; 2011-12-14 00:58:17 +01:00
Themaister 9aaad17c1a Update Makefile. 2011-12-14 00:44:38 +01:00
Themaister 93874bba83 Fixup makefile. 2011-12-14 00:41:06 +01:00
Themaister 9c67452f10 <________________________< 2011-12-14 00:36:28 +01:00
Themaister 0416a2ae61 Don't use float <_< 2011-12-14 00:30:03 +01:00
Themaister 8bbde14019 Merge branch 'master' of github.com:Themaister/SSNES 2011-12-14 00:25:26 +01:00
Themaister 0e8f2339d8 Might work better ... 2011-12-14 00:25:04 +01:00
TwinAphex51224 9f37427d7a (Libxenon) Compile with -O3 2011-12-13 23:50:56 +01:00
Themaister 6ad4b1f15a Little endian DAC on 360 (lolwut?) 2011-12-13 23:44:55 +01:00
Themaister a39c0f01f9 Should fix up audio driver a bit. 2011-12-13 23:38:05 +01:00
TwinAphex51224 1136820124 (Libxenon) Terribly borked libxenon audio driver :) 2011-12-13 23:17:37 +01:00
TwinAphex51224 2a3f3bad23 (360 Libxenon) Initial xenon 360 audio driver 2011-12-13 22:57:49 +01:00
Themaister 74def91a53 Debork main a bit. 2011-12-13 21:48:17 +01:00
TwinAphex51224 bc62e1be08 (Libxenon) Added slimjim Libxenon filebrowser - from examples 2011-12-13 21:12:50 +01:00
Themaister 25aea134ef Add temporary hack for SDL cond in Xenon. 2011-12-13 19:34:45 +01:00
Themaister e488c3081d Small nit. 2011-12-11 13:14:44 +01:00
Themaister 331f46fb24 Missing stuff. 2011-12-11 12:51:32 +01:00
Themaister e88662cab0 Updates for 0.9.3. 2011-12-11 12:50:16 +01:00
Themaister 395f6d1d3c Build fixups. 2011-12-10 18:02:50 +01:00
Themaister 94bd78b3e1 Merge branch 'master' of github.com:Themaister/SSNES
Conflicts:
	Makefile.xenon
2011-12-10 17:42:07 +01:00
Themaister dc373fb7d0 Gets to link, but fails there. 2011-12-10 17:41:16 +01:00
Themaister 140812d64a Fixup xenon makefile a bit. 2011-12-10 16:26:26 +01:00
TwinAphex51224 a91c4e556f (360 Libxenon) change to makefile - use built-in getopt 2011-12-10 16:22:37 +01:00
Themaister 372c622166 Nits. 2011-12-10 15:23:20 +01:00
TwinAphex51224 d961d68e9c (360 / Libxenon) Added Libxenon Makefile 2011-12-07 03:19:12 +01:00
Themaister 33a325a730 Nit. 2011-12-07 01:13:06 +01:00
Themaister 909b25c7ac Remove XML stuff. 2011-12-04 18:44:50 +01:00
Themaister 77f110c23e Nits. 2011-12-04 18:26:17 +01:00
Themaister 9dc9416ef9 Merge branch 'ssnes-ps3' 2011-12-04 18:13:31 +01:00
Themaister 0b20f11617 Nits. 2011-12-04 18:06:50 +01:00
Themaister c9594776f8 Style nits. 2011-12-04 18:06:50 +01:00
Themaister 8f55b9904d Update license. 2011-12-04 18:06:50 +01:00
Themaister 093ba1c33d Dynamic fix. 2011-12-04 18:06:50 +01:00
Themaister 67a434d563 Clean. 2011-12-04 18:06:50 +01:00
Themaister ff0c3f047a Some cleanups. 2011-12-04 18:06:50 +01:00
Themaister 2934ba301b Nit. 2011-12-04 18:06:50 +01:00
Themaister f3627aaf59 Nits. 2011-12-04 18:03:08 +01:00
Themaister dc8a2dea72 Style nits. 2011-12-04 18:00:55 +01:00
Themaister 329969eb05 Update license. 2011-12-04 17:57:25 +01:00
Themaister 71923af675 Dynamic fix. 2011-12-04 17:54:00 +01:00
Themaister 18e58ca5f4 Clean. 2011-12-04 17:30:44 +01:00
Themaister 8c3aebbbc8 Some cleanups. 2011-12-04 17:29:59 +01:00
Themaister 7f40c11eb7 Merge branch 'master' of github.com:Themaister/SSNES into ssnes-ps3 2011-12-04 17:24:28 +01:00
Themaister 0ed668d1b5 Minor cleanups. 2011-12-04 17:19:21 +01:00
Themaister 1c8632cac9 Nit. 2011-12-04 17:17:49 +01:00
TwinAphex51224 e7324989fc (PS3) Better extra button bindings 2011-12-04 04:11:02 +01:00
TwinAphex51224 a7fc3807b9 (PS3) Cleaned up indenting in ps3_input.c 2011-12-04 04:00:17 +01:00
TwinAphex51224 99ad7bcc51 Merge branch 'master' of github.com:Themaister/SSNES into ssnes-consoles 2011-12-04 03:43:52 +01:00
Themaister 5b88e338df Nits. 2011-12-04 01:42:00 +01:00
Themaister 425af71450 GET_CAN_REWIND. 2011-12-04 01:40:25 +01:00
Themaister 19c5eab07a Minor clean. 2011-12-04 01:30:16 +01:00
Themaister e5286cbe39 Update XAudio for pure C. 2011-12-04 01:10:16 +01:00
Themaister 02d40aa212 Drop shadows for fonts. 2011-12-03 19:48:13 +01:00
Themaister 8a5c537e15 Fix warning. 2011-12-03 04:09:40 +01:00
TwinAphex51224 c6c4f2f4d1 (PS3) Debug fonts hooked up 2011-12-03 03:52:53 +01:00
TwinAphex51224 5bc7ea4045 (PS3) Properly exits now with shader loaded 2011-12-03 03:10:23 +01:00
TwinAphex51224 077acf7894 (PS3) Savestates hooked up (R2 + R3 - save state - L2 + R3 - load state -
R2 + Right stick right - save state plus - R2 + Right stick left - save state minus)
2011-12-03 02:40:20 +01:00
TwinAphex51224 c5f86f12c0 Revert "(PS3) Would not cleanly exit on PS3 without this - perhaps something"
This reverts commit 243e941d81.
2011-12-03 01:56:41 +01:00
TwinAphex51224 243e941d81 (PS3) Would not cleanly exit on PS3 without this - perhaps something
Cg-related needs deiniting prior to exit(0)
2011-12-03 01:54:57 +01:00
TwinAphex51224 d67e6b7c15 (PS3) Cg shader support fixed 2011-12-03 01:26:56 +01:00
Themaister f76bf59fed Merge branch 'master' of github.com:Themaister/SSNES into ssnes-consoles 2011-12-03 00:49:26 +01:00
Themaister 1c4d88eb04 Compiles ... properly. 2011-12-03 00:49:09 +01:00
Themaister ad04db8365 Fix includes. 2011-12-03 00:48:42 +01:00
TwinAphex51224 a63ccbbdab (PS3) Implemented rewind/fast forward hooks 2011-12-03 00:07:01 +01:00
Themaister 278f314c03 Merge branch 'master' of github.com:Themaister/SSNES into ssnes-consoles 2011-12-02 22:57:13 +01:00
Themaister a3abda7e7b Refactor. 2011-12-02 22:56:11 +01:00
Themaister c0a9db111d Fix bug with reordering. 2011-12-02 22:23:19 +01:00
TwinAphex51224 676ce10119 (PS3) Now reads from config file 2011-12-02 22:22:44 +01:00
Themaister c18dce4783 Merge branch 'master' of github.com:Themaister/SSNES into ssnes-consoles 2011-12-02 22:25:37 +01:00
Themaister 088b01b52e More logial ordering. 2011-12-02 21:37:35 +01:00
Themaister c0f436b8ab Minor nit. 2011-12-02 21:25:25 +01:00
Themaister 3377020242 Fixup build. 2011-12-02 21:24:33 +01:00
Themaister 6db58fe1dd Merge branch 'ssnes-consoles' of github.com:Themaister/SSNES into ssnes-consoles 2011-12-02 21:22:36 +01:00
Themaister 67c7cd8de9 No default config path on ps3. 2011-12-02 21:22:14 +01:00
Themaister 457a3d458a Merge branch 'master' of github.com:Themaister/SSNES into ssnes-consoles
Conflicts:
	general.h
2011-12-02 21:18:09 +01:00
Themaister 6538312d86 Fix some includes. 2011-12-02 21:16:51 +01:00
TwinAphex51224 7f1a5075b1 Updated Makefile 2011-12-02 21:14:25 +01:00
Themaister e412ecdefe Do not exit() prematurely. 2011-12-02 19:28:39 +01:00
Themaister 67b89d6f42 Kill off useless font rendering code. 2011-12-02 19:19:48 +01:00
Themaister c8d3278dbc Merge branch 'master' of github.com:Themaister/SSNES into ssnes-consoles 2011-12-02 19:15:21 +01:00
Themaister 3556445660 Add new extension support. 2011-12-02 19:12:47 +01:00
Themaister f28fc0cabb Merge branch 'ssnes-consoles' of github.com:Themaister/SSNES into ssnes-consoles 2011-12-02 16:22:05 +01:00
Themaister e0bc548400 sys_lw synchro. 2011-12-02 16:21:01 +01:00
TwinAphex51224 011a4c8a89 Merge branch 'ssnes-consoles' of github.com:Themaister/SSNES into ssnes-consoles 2011-12-02 15:59:40 +01:00
TwinAphex51224 87bc5220eb (PS3) Takes care of audio pop 2011-12-02 15:59:07 +01:00
Themaister 673d0ed1a2 Minor fix. 2011-12-02 15:55:49 +01:00
Themaister a5079bdda1 Should improve the state of audio. 2011-12-02 15:50:51 +01:00
Themaister fc43e7155e Should fixup input. 2011-12-02 15:33:14 +01:00
TwinAphex51224 4935333b63 (PS3) Updated icon + PARAM.SFO title 2011-12-02 04:52:29 +01:00
TwinAphex51224 5a3232adff (PS3) SSNES PS3 lives :) - audio, video works - controls don't
seem to work
2011-12-02 03:46:31 +01:00
TwinAphex51224 d03f351f33 (PS3) Crashes in find_audio_driver (driver.c) 2011-12-02 03:32:04 +01:00
TwinAphex51224 8d5bf997a9 Made global g_quitting variable in PSGL driver 2011-12-02 02:51:21 +01:00
Themaister 0738480439 Make sure set_defaults is called. 2011-12-02 02:48:04 +01:00
TwinAphex51224 9a5e1a31ad Merge branch 'ssnes-consoles' of github.com:Themaister/SSNES into ssnes-consoles 2011-12-02 02:47:28 +01:00
Themaister 5ab7664f49 Merge branch 'master' of github.com:Themaister/SSNES into ssnes-consoles 2011-12-02 02:48:26 +01:00
TwinAphex51224 1cb2c60ccc Calblack put in video_psgl.c - not sure how to use it there 2011-12-02 02:46:47 +01:00
Themaister 1356d0ab4c .___. 2011-12-02 02:41:32 +01:00
Themaister b4c4a65f2d Clear up input. 2011-12-02 02:34:06 +01:00
Themaister ab3cf8daca Merge branch 'ssnes-consoles' of github.com:Themaister/SSNES into ssnes-consoles 2011-12-02 02:25:40 +01:00
Themaister 2b6c252747 Minor fixes. 2011-12-02 02:22:29 +01:00
TwinAphex51224 ec9a6ac90a Can make a PKG now 2011-12-02 02:07:46 +01:00
Themaister a207549f18 fixup stub. 2011-12-02 01:59:44 +01:00
Themaister efbf9354f9 It ... links! 2011-12-02 01:59:07 +01:00
Themaister 216ddc9fd6 Merge branch 'ssnes-consoles' of github.com:Themaister/SSNES into ssnes-consoles 2011-12-02 01:38:24 +01:00
Themaister 3b668cccd3 Add audio/utils.o. 2011-12-02 01:38:04 +01:00
Themaister 30a86a2845 Merge branch 'master' of github.com:Themaister/SSNES into ssnes-consoles 2011-12-02 01:35:15 +01:00
Themaister a7870aa888 Altivec sample conversion. 2011-12-02 01:34:02 +01:00
TwinAphex51224 271b99981c Won't link right now 2011-12-02 01:28:47 +01:00
Themaister 08ef01bb13 Merge branch 'master' of github.com:Themaister/SSNES into ssnes-consoles
Conflicts:
	dynamic.c
2011-12-02 00:07:54 +01:00
Themaister e778af462a Stub main. 2011-12-02 00:01:48 +01:00
Themaister 9d124b2380 Do not use anything dylib related if not compiled in. 2011-12-01 22:36:26 +01:00
Themaister f24e7cd665 Texrefs (untested). 2011-12-01 22:21:15 +01:00
Themaister e7f1526942 Fix compilation errors. 2011-12-01 21:54:42 +01:00
TwinAphex51224 647b1ba53c (PS3) Comiles now, doesn't link 2011-12-01 21:23:49 +01:00
TwinAphex51224 eac8d9f191 Update to PSGL driver 2011-12-01 11:25:08 +01:00
TwinAphex51224 50babe8432 More commits to PSGL driver 2011-11-30 23:50:31 +01:00
TwinAphex51224 8171977ed7 Preliminary version of PSGL video driver 2011-11-30 21:54:25 +01:00
TwinAphex51224 f8aaf1df1e (PS3) Some more commits 2011-11-30 18:32:45 +01:00
Themaister 04d0d84d01 Fix up more paths. 2011-11-30 18:31:09 +01:00
TwinAphex51224 f4aa9fa865 Merge branch 'master' of github.com:Themaister/SSNES into ssnes-consoles 2011-11-30 18:27:11 +01:00
TwinAphex51224 40ef7d6f00 Improved Makefile a bit 2011-11-30 18:26:42 +01:00
TwinAphex51224 66b7b1691c (PS3) Removed thread.o from Makefile 2011-11-30 18:19:34 +01:00
Themaister 43972d4c35 Fix build. 2011-11-30 18:18:50 +01:00
TwinAphex51224 632545c409 Merge branch 'master' of github.com:Themaister/SSNES into ssnes-consoles 2011-11-30 18:13:27 +01:00
TwinAphex51224 3a47e2cd63 Merge branch 'master' of github.com:Themaister/SSNES into ssnes-consoles 2011-11-30 18:11:06 +01:00
Themaister a221e3e4cd Enable/disable threading support. 2011-11-30 17:46:58 +01:00
Themaister b87f50dc9d Fix include path. 2011-11-30 17:34:18 +01:00
Themaister a5b3f421d1 Fix include paths for libsnes header. 2011-11-30 17:32:30 +01:00
TwinAphex51224 182525afa9 Merge branch 'master' of github.com:Themaister/SSNES into ssnes-consoles 2011-11-30 17:28:11 +01:00
TwinAphex51224 419afbcb83 Progresses to thread.c now 2011-11-30 17:27:47 +01:00
Themaister 12ca70a308 Refactor binds. 2011-11-30 17:25:44 +01:00
TwinAphex51224 1fa7663d3b Put in old input driver too - progresses to dynamic.c now 2011-11-30 17:24:18 +01:00
TwinAphex51224 2e34c6fc5c Moved in old PS3 audio driver 2011-11-30 17:11:42 +01:00
Themaister cb7002559d Put defines in makefile. 2011-11-30 17:01:15 +01:00
TwinAphex51224 36ec92793f Put PACKAGE_VERSION define in Makefile 2011-11-30 16:58:20 +01:00
TwinAphex51224 4187d70b30 Merge branch 'master' of github.com:Themaister/SSNES into ssnes-consoles 2011-11-30 16:56:38 +01:00
Themaister 5969655c3c Do not allow netplay args if not compiled in. 2011-11-30 16:43:09 +01:00
Themaister 09d2ec7d3a Do not build in anything netplay related if not included. 2011-11-30 16:41:00 +01:00
TwinAphex51224 27b975d0fc Add in PS3 define for ssnes_sleep 2011-11-30 16:40:52 +01:00
TwinAphex51224 6da64013fa Merge branch 'master' of github.com:Themaister/SSNES into ssnes-consoles 2011-11-30 16:38:53 +01:00
Themaister d8eb5de380 Do not include netplay header needlessly. 2011-11-30 16:27:16 +01:00
Themaister 23aa8bbe7a Actually use sleep param. 2011-11-30 16:26:23 +01:00
TwinAphex51224 3b5472dbac Merge branch 'master' of github.com:Themaister/SSNES into ssnes-consoles 2011-11-30 16:22:16 +01:00
TwinAphex51224 3b4e60aada Header guards for netplay.c not necessary 2011-11-30 16:21:21 +01:00
TwinAphex51224 8d8fb44c18 Use getopt replacement 2011-11-30 16:19:12 +01:00
TwinAphex51224 b46fb60a6e Merge branch 'master' of github.com:Themaister/SSNES into ssnes-consoles 2011-11-30 16:02:49 +01:00
Themaister f7399bbc8b Fix docs. 2011-11-30 12:09:22 +01:00
Themaister 7f7d47b120 Custom getopt for portability. 2011-11-30 11:48:53 +01:00
TwinAphex51224 e7aa3ed0cc Compile in OpenGL and Cg 2011-11-30 01:41:50 +01:00
TwinAphex51224 0ece8b1319 Added static Makefile for PS3 2011-11-30 01:33:14 +01:00
TwinAphex51224 557e05dd12 initial new branch 2011-11-30 01:07:38 +01:00
Themaister 08a1496501 Use big-endian BSV1 magic.
Keep compatibility with old implementation.
Documentation was suggesting little-endian, but this was not correct.
2011-11-28 02:11:33 +01:00
Themaister 5a24037c61 Update joyconfig. 2011-11-26 16:02:49 +01:00
Themaister 5dbd1ea35c Add mute toggle. 2011-11-26 15:54:58 +01:00
Themaister 2476e3dee3 Updates for 0.9.2. 2011-11-24 13:13:55 +01:00
Themaister c05a5c9fdd Only init Video if it isn't already. 2011-11-23 03:26:56 +01:00
Themaister 503c51d633 Check for additional fonts. 2011-11-22 18:52:20 +01:00
Themaister 46054de4f8 Fix possible segfault. 2011-11-22 17:32:38 +01:00
Themaister 604eb9b973 Can dupe extension. 2011-11-22 17:27:02 +01:00
Themaister 0e72120bdc Updates for 0.9.2-rc2. 2011-11-21 16:30:35 +01:00
Themaister b8064f5d42 New semantics for BSV movie recording. 2011-11-20 20:19:05 +01:00
Themaister 379b14a0f3 Flush more sanely. 2011-11-20 03:19:17 +01:00
Themaister 2a598c0b97 Do not quit SSNES on movie playback end. 2011-11-20 03:00:21 +01:00
Themaister aa124b4c40 Should fix occasional horrible noise on end of recordings. 2011-11-20 02:44:21 +01:00
Themaister bb5e31df0d Still record audio even if audio is not enabled. 2011-11-20 02:06:25 +01:00
Themaister e49d216884 Check for large skews in timing. 2011-11-19 14:16:55 +01:00
Themaister 598d06fcb5 More explicitly log paths. 2011-11-19 01:33:21 +01:00
Themaister 7f13ec88e6 Simplify things a bit. 2011-11-18 18:43:02 +01:00
Themaister c5c60c6f53 Add --bsvrecord. 2011-11-18 18:03:24 +01:00
Themaister 81b0e6d0a3 Use display refresh rates rather than input rate directly. 2011-11-18 15:14:56 +01:00
Themaister da97b29d0b Update FFmpeg to use new define in Win32. 2011-11-18 13:07:24 +01:00
Themaister 69b7f92285 Updates for 0.9.2-rc1. 2011-11-18 12:17:25 +01:00
Themaister 3a9dbbc8b7 Pause while inactive disabled by default. 2011-11-17 21:17:29 +01:00
Themaister bf5db10459 Change timeout message to be less misleading. 2011-11-16 22:30:57 +01:00
Themaister 4fa27a5f0f Binaries link in README. 2011-11-16 21:28:30 +01:00
Themaister 3e7c412738 Custom timing support for FFmpeg recording. 2011-11-16 18:56:42 +01:00
Themaister 88c870dcfa Allow -L/--libsnes from command line. 2011-11-15 21:15:12 +01:00
Themaister 66e1179503 Do not remove -s. 2011-11-15 16:44:40 +01:00
Themaister 4ecea5d0a4 Expose python to external drivers. 2011-11-15 15:41:49 +01:00
Themaister 57816edfd3 Fix some hardcoding. 2011-11-13 17:44:20 +01:00
Themaister 17cf0985c5 Typo. 2011-11-13 17:10:21 +01:00
Themaister 776b0a1e2d Add a helper define for input scale. 2011-11-13 17:09:49 +01:00
Themaister 4a6392aefa Fix wrong placement of line in print_help(). 2011-11-13 01:12:32 +01:00
Themaister 29dd4727b8 Disable used attribs in Cg as well. 2011-11-12 18:31:22 +01:00
Themaister face42a888 Disable used attributes on shader change. 2011-11-12 18:20:54 +01:00
Themaister 45fa6795c3 Fixups. 2011-11-12 16:43:59 +01:00
Themaister a9d339efb4 Use glColorPointer(). 2011-11-12 15:51:37 +01:00
Themaister 60841b01a5 Use custom "stock" program. 2011-11-12 15:26:24 +01:00
Themaister ad67511483 Cleanups. PREV{1-6} for GLSL as well. 2011-11-12 14:18:10 +01:00
Themaister 104fb4fb16 nits. 2011-11-12 13:00:37 +01:00
Themaister 816ef095ed Lots of PREV frames in Cg. 2011-11-12 12:55:03 +01:00
Themaister 48e8472f9c Ring buffer of 8 textures :o 2011-11-12 12:28:07 +01:00
Themaister 1755500b19 Source cleanup. 2011-11-12 01:42:37 +01:00
Themaister 4bfc827eb2 Some fixes to Python. 2011-11-11 19:20:56 +01:00
Themaister ddfeacbd83 Minor fixes and cleanups to BSV. 2011-11-11 00:55:35 +01:00
Themaister 79353f861c Do not report dupes. 2011-11-10 00:49:45 +01:00
Themaister f3f4efe304 Improve error reporting in Cg. 2011-11-10 00:46:39 +01:00
Themaister 51721b4cb6 video_font_enable. 2011-11-10 00:15:41 +01:00
Themaister 477091ce8f Do not force crop_overscan with ffmpeg. 2011-11-10 00:03:52 +01:00
Themaister 2707b87767 Should fix overscan overcrop. 2011-11-09 23:58:14 +01:00
Themaister b3d422b5cd rubyFrameDirection / IN.frame_direction. 2011-11-09 23:45:34 +01:00
Themaister d1dc65f202 Cleaner setup of bind-map. 2011-11-09 22:47:12 +01:00
Themaister 7815940a97 SNES_ENVIRONMENT_OVERSCAN. 2011-11-09 22:18:48 +01:00
Themaister 4f841c208d Use --qp 0 rather than --crf 0 for lossless. 2011-11-07 23:16:32 +01:00
Themaister b4f0d9b8f8 Restrict number of lag frames. 2011-11-06 20:38:42 +01:00
Themaister b96ab2982c Should fix minor issues with timeouts when lag frames > 8. 2011-11-06 20:28:02 +01:00
Themaister 825c1de7d1 Nits. 2011-11-05 15:24:29 +01:00
Themaister 6ada4d87d3 Style nit. 2011-11-05 13:34:41 +01:00
Themaister 53abc92322 Add some metadata. Should be a workaround. 2011-11-05 12:25:09 +01:00
Themaister a816082ac3 Style nit. 2011-11-05 11:44:17 +01:00
Themaister 47e63f1c6b Style nit. 2011-11-05 11:37:04 +01:00
Themaister cdf3d05c8e Should fix spurious timeouts for netplay. 2011-11-04 00:18:17 +01:00
Themaister 389e9ba0dc Style nit. 2011-11-04 00:07:53 +01:00
Themaister a6f7a2311f Minor cleanups for hermite. 2011-11-03 23:48:36 +01:00
Themaister f19d99d523 Log error when netplay init fails. 2011-11-03 21:05:12 +01:00
Themaister e7082fd6ea Warning nit. 2011-11-02 20:33:37 +01:00
Themaister 4806d2fe88 Clear up inconsistencies, and avoid breaking standard compliance. 2011-11-02 20:04:31 +01:00
Themaister f85ff7124b More nits. 2011-11-02 19:34:08 +01:00
Themaister 0f010cf3d2 Fix style nits. 2011-11-02 19:31:36 +01:00
Themaister 95636d4f04 Refactor XVideo driver. Also, attempts harder to find suitable formats. 2011-11-02 17:51:15 +01:00
Themaister 43905e410e Fix build ... *grummel* 2011-11-02 17:04:49 +01:00
Themaister d23a7e3ddf HAVE_OPENGL=1 in Windows. 2011-11-02 17:02:59 +01:00
Themaister 652f4c5856 More explicit checking for inconsistency. 2011-11-02 16:54:45 +01:00
Themaister 90febc4ecf Use dynamic by default.
FFmpeg and Python does not require explicit --enable.
2011-11-02 16:50:34 +01:00
Themaister 34b5994842 Fix minor issue. 2011-11-01 21:28:32 +01:00
Themaister 0c3f6ed66b Cleanup and optimize rewind a bit. Forced POT buffer size. 2011-11-01 21:00:41 +01:00
Themaister f3e487557e Fix some style nits. 2011-11-01 20:27:59 +01:00
Themaister ee12266a2b Fix build for OSX. 2011-11-01 18:45:50 +01:00
Themaister 1981b14de9 Allow OpenGL to be disabled. 2011-11-01 18:24:43 +01:00
Themaister 65665f36cc Fixup netplay. 2011-10-31 22:51:54 +01:00
Themaister a48dc55c41 Fix ugly possible segfault. 2011-10-30 16:58:45 +01:00
Themaister 202a458524 Updates for 0.9.1. 2011-10-30 11:24:16 +01:00
Themaister b4de704a09 Style nit. 2011-10-30 02:12:00 +02:00
Themaister fef5edfac8 Change default aspect handling. 2011-10-30 01:58:08 +02:00
Themaister a6e74775b1 Edge trigger reset. 2011-10-29 13:35:01 +02:00
Themaister ee66a28d05 Style nit. 2011-10-29 13:33:15 +02:00
Themaister 5e28d82af2 Fix compile with HAVE_CONFIGFILE=0. 2011-10-28 17:10:58 +02:00
Themaister c2a06bfa09 Replace some magic numbers. 2011-10-28 09:06:34 +02:00
Themaister 66510e21aa Fixup build for non dynamic builds. 2011-10-28 00:34:42 +02:00
Themaister ec5e3355b9 Add some logging. 2011-10-28 00:23:49 +02:00
Themaister 0522a2d6a0 Start implementing some minor extensions to libsnes. 2011-10-27 23:40:34 +02:00
Themaister fad89f9d2d More gracious error handling for state tracker. 2011-10-26 19:51:10 +02:00
Themaister 97f937ec6d Use floating point values for uniforms from Python. 2011-10-26 10:26:09 +02:00
Themaister 9647006a2b Merge branch 'master' of github.com:Themaister/SSNES 2011-10-25 23:03:20 +02:00
Themaister 418ba455f8 Allow the rest of the buttons in Python.
Fix issue where long type was enforced for return values of uniforms.
2011-10-25 23:02:17 +02:00
Themaister 197d62860b Default screenshot directory. 2011-10-24 21:34:30 +02:00
Themaister 402451626f More accurate colors for screenshot. 2011-10-24 19:23:58 +02:00
Themaister 3739cbfc70 Minor cleanup for rewind. 2011-10-23 17:13:16 +02:00
Themaister 235355ffc7 Check more explicitly for XVideo and Xext. 2011-10-23 12:48:44 +02:00
Themaister 4856d0cac3 Allow screenshots while paused. 2011-10-23 12:38:11 +02:00
Themaister 77a2723bb0 Neat optimizations for SSE. 2011-10-23 02:56:33 +02:00
Themaister 41cd6e21c3 Use _mm* intrinsics. 2011-10-22 23:36:02 +02:00
Themaister 1fc99c7123 Fix deprecation warning. 2011-10-22 22:54:36 +02:00
Themaister fddcc3447c Fix build for Clang. 2011-10-22 22:19:54 +02:00
Themaister 70e9f084b7 Merge branch 'master' of github.com:Themaister/SSNES 2011-10-22 20:20:03 +02:00
Themaister 824790a80d Updates for 0.9. 2011-10-22 20:19:40 +02:00
Themaister 23d23983bc Fix broken #define in header. 2011-10-21 22:12:03 +02:00
Themaister c42655ed91 Logging for paused. 2011-10-20 23:33:15 +02:00
Themaister f46ee78c76 Apply a hack and push the frame several times when changing fullscreen. 2011-10-20 23:28:46 +02:00
Themaister 5d1d188231 Hardcode hermite for 2 channels. 2011-10-20 22:26:41 +02:00
Themaister c55ce543c2 Revert "Use C99 stdio in mingw, yay" :\
This reverts commit de8bc62474.
2011-10-19 18:12:30 +02:00
Themaister de8bc62474 Use C99 stdio in mingw, yay 2011-10-19 18:10:05 +02:00
Themaister 397da887a7 Merge branch 'master' of github.com:Themaister/SSNES 2011-10-19 08:16:26 +02:00
Themaister f44733d7f6 Only show paused rewind for 1 frame. 2011-10-26 03:24:39 +02:00
Themaister 5faa28a1a2 Clarify x/yscale. 2011-10-19 08:16:01 +02:00
Themaister efaa85ff9b Cleaner. 2011-10-18 21:59:37 +02:00
Themaister 8f5580be10 Frame advance goes into pause. 2011-10-18 21:57:28 +02:00
Themaister c7acd99548 Same for SDL ... 2011-10-18 19:52:43 +02:00
Themaister 64ee13e6f4 Push window loop in .alive(). 2011-10-18 19:51:38 +02:00
Themaister e134f8afc7 And yet another ... :) 2011-10-18 19:22:20 +02:00
Themaister dd89e6fbe0 Fix build without FFmpeg. 2011-10-18 19:16:38 +02:00
Themaister a79a1b46f7 Updates for 0.9-rc4. 2011-10-18 19:12:28 +02:00
Themaister 6467f51ea8 Frame caching for more "proper" fullscreen switch. 2011-10-18 17:26:15 +02:00
Themaister 141eefb03b Fix fullscreen pause toggle for windows. 2011-10-18 14:39:54 +02:00
Themaister 068c224d83 Include windows.h properly. 2011-10-18 14:05:30 +02:00
Themaister 5bc8090ea7 Allow fullscreen toggle while paused. 2011-10-18 13:29:39 +02:00
Themaister 466ab1ef8d Frame advance. 2011-10-17 21:30:58 +02:00
Themaister a1c19ed1f5 Minor refactor. 2011-10-17 20:46:38 +02:00
Themaister cce4b7d20c Allow #include depth. 2011-10-17 20:09:57 +02:00
Themaister 80925ffc11 Some Windows fixes. 2011-10-17 19:30:52 +02:00
Themaister 9eb14e328d Add "#include" for config files. 2011-10-17 19:11:31 +02:00
Themaister 5ae0cb1821 Base size for windowed mode calculations. 2011-10-16 21:36:17 +02:00
Themaister fc594f7f0f Fix edge case on input poll. 2011-10-16 15:45:04 +02:00
Themaister 0c4e406ee7 Remove unused variable. 2011-10-16 12:51:14 +02:00
Themaister a082ec5251 Fix segfault. 2011-10-16 04:01:01 +02:00
Themaister 953b5daf0a Pause hooked up. 2011-10-16 02:00:55 +02:00
Themaister b4ff622f32 Title buf hints. Purge samplerate opts. 2011-10-15 20:05:34 +02:00
Themaister f26b54c998 Updates for RC3. 2011-10-15 18:51:58 +02:00
Themaister d7b3f39136 SSE2 optimized a bit :D 2011-10-15 18:09:44 +02:00
Themaister 5bcf601a40 Refactor out audio conversion. 2011-10-15 17:47:29 +02:00
Themaister e91ebdac97 Do not recalculate ratio all the time. 2011-10-15 16:16:13 +02:00
Themaister b2dd12d186 Rewind audio! :D 2011-10-15 14:33:41 +02:00
Themaister 9c79bf0ba2 Refactor audio flushing method. 2011-10-15 13:16:32 +02:00
Themaister f48247a18b Style nits ... 2011-10-15 12:56:48 +02:00
Themaister 48e015558e Style nits. 2011-10-15 12:54:47 +02:00
Themaister 0ff3cbc93b Nits. 2011-10-15 12:51:17 +02:00
Themaister 25f0e162a4 Purge support for libsamplerate. Obsolete. 2011-10-15 12:48:15 +02:00
Themaister 0810812cd9 Slight cleanups when pushing audio. 2011-10-15 12:42:39 +02:00
Themaister 15e0b721e6 Updates for RC2. 2011-10-14 14:07:03 +02:00
Themaister 9d12c3ac87 Use Makefile.win for Phoenix. 2011-10-14 13:34:27 +02:00
Themaister a7c3d8d17a Some slight recording tweaks. 2011-10-14 11:27:02 +02:00
Themaister 8fbfdee011 Do not always force 4.0 / 3 aspect ratio for output. 2011-10-14 11:00:31 +02:00
Themaister bc999e72fa Updates for v0.9-rc1. Use --features rather than spamming down --help. 2011-10-11 20:02:46 +02:00
Themaister c7f8110670 Use glorious x264 RGB. 2011-10-10 22:24:26 +02:00
Themaister b0dbc67281 Fix build when only Cg is being compiled. 2011-10-17 15:35:02 +02:00
Themaister 4916f7b08b Add placeholder define for when libx264 RGB support is built in. 2011-10-09 12:37:53 +02:00
Themaister 1058d94ec1 x264 RGB recording. 2011-10-09 12:27:02 +02:00
Themaister 340dca3c6d Download headers (lib/headers split). 2011-10-08 17:01:40 +02:00
Themaister 4ae0f3da22 Remove obsolete readme. 2011-10-08 01:27:21 +02:00
Themaister 7d2d1ce49e Change "hashing" value used for netplay. 2011-10-07 22:33:38 +02:00
Themaister fa26f6a10c Cache font rendering. Major overhead reduction. 2011-10-07 17:58:22 +02:00
Themaister db71a5cdba New font rendering code for OpenGL. 2011-10-07 17:43:39 +02:00
Themaister 5058fdcd1a Update docs. 2011-10-07 01:36:52 +02:00
Themaister ef04f199d5 Slight cleanups. 2011-10-07 01:21:54 +02:00
Themaister d26dd9d9e7 Slight cleanups. 2011-10-07 00:54:47 +02:00
Themaister d2bc4096de Some fixes to FFmpeg. Conserves RAM better. 2011-10-07 00:04:52 +02:00
Themaister 08ca1a54d3 Remove useless asserts. 2011-10-06 23:44:21 +02:00
Themaister 869eddfc1a Custom FFmpeg recording sizes. 2011-10-06 23:43:48 +02:00
Themaister fbced43f11 Update threading for Win32. 2011-10-06 22:40:47 +02:00
Themaister c996f816b8 Default font path OSX. 2011-10-06 21:12:11 +02:00
Themaister 33ecedb462 Fixup build for OSX. 2011-10-06 20:49:00 +02:00
Themaister a58676c9e1 Linux needs -lrt for clock_gettime. 2011-10-06 20:34:01 +02:00
Themaister 1ee9722e5f Start working on custom thread implementation.
Avoids SDL dependency for this to improve portability.
2011-10-06 20:31:39 +02:00
Themaister 81250657f0 Change default font color to yellow. 2011-10-06 19:10:01 +02:00
Themaister 7d33cccc8e Default fonts. 2011-10-06 19:06:38 +02:00
Themaister 3db79ab2f0 Nits. 2011-10-05 22:56:52 +02:00
Themaister ea0f6813d2 Avoid assertions. 2011-10-05 22:39:54 +02:00
Themaister f6d4d32c03 Dynamic loading by default, add OSD message for netplay DC. 2011-10-05 21:44:17 +02:00
Themaister 892e82141f Fix FTBFS. 2011-10-05 19:57:32 +02:00
Themaister 65ec7fae9c Is this it? 2011-10-05 02:09:54 +02:00
Themaister a0acb75a19 Might push lagframes better. 2011-10-05 01:05:34 +02:00
Themaister bcae973d82 Savestate auto indexing support. 2011-09-27 15:31:25 +02:00
Themaister d01a4fe61b Only load second pass shaders when render-to-texture is set. 2011-09-26 22:45:28 +02:00
Themaister 8d4620b680 FFmpeg API seems to be too fragmented. Give in and #ifdef shit. :v 2011-09-23 22:57:41 +02:00
Themaister c2cedb1b6f Resizing windows in 1.2 should not trigger some init code :) 2011-09-22 21:50:57 +02:00
Themaister 157dcad87b Fix newline typo. 2011-09-22 13:15:16 +03:00
Themaister 8ea5ba171a Updates for 0.8.2. 2011-09-21 21:17:46 +02:00
Themaister fa876b10a3 Style nit. 2011-09-20 12:22:30 +02:00
Themaister 3c58d10eae Small fix. 2011-09-20 12:05:21 +02:00
Themaister a3ee8c8849 Defensive nit. 2011-09-20 11:58:21 +02:00
Themaister 5e14b302bc Replace a VLA with char[MAXPATHLEN]. 2011-09-20 12:50:13 +03:00
Themaister efe3f943d5 Only autosave when the data actually changed. 2011-09-17 10:57:55 +02:00
Themaister 38e7fc6659 Add support for blocking SRAM writes :) 2011-09-16 15:32:21 +02:00
Themaister a1ceb534de nit. 2011-09-13 23:24:06 +02:00
Themaister 0d897dd65d Check some additional WM messages. 2011-09-13 22:38:32 +02:00
Themaister 721d73f451 Fix stupid crash. 2011-09-13 22:16:34 +02:00
Themaister e8bd64e898 Allow SDL driver to work as well in 1.3. 2011-09-13 20:01:22 +02:00
Themaister 7da7ab2ce7 lalala ... 2011-09-13 19:36:15 +02:00
Themaister 3f6183ff15 Updates, fixes ... 2011-09-13 19:30:22 +02:00
Themaister 642316a1e2 Somewhat haphazard. Can't find some needed API calls :\ 2011-09-13 18:50:40 +02:00
Themaister 21c6b75839 Use SwapInterval with SDL 1.3. 2011-09-13 15:00:26 +02:00
Themaister 87d34deb0c Can build with SDL 1.3 on Win32. 2011-09-13 14:57:42 +02:00
Themaister 1b3408919c Can use SDL 1.3 just fine now. 2011-09-13 14:41:45 +02:00
Themaister 23516572b7 Use SK_* keysyms (pretty much SDL 1.2). 2011-09-13 14:40:33 +02:00
Themaister 924848fdad Start working towards SDL 1.2/1.3 compat. 2011-09-13 14:06:49 +02:00
Themaister 4c40e56060 Properly disable it :D 2011-09-11 15:41:46 +02:00
Themaister cf34444505 Disable resizing on OSX. 2011-09-11 15:33:28 +02:00
Themaister 9ca5e4e470 Updates for 0.8.1. 2011-09-10 19:15:05 +02:00
Themaister 32f2689b6a Add LIBXML_TEST_VERSION to XML cheats. 2011-09-09 09:48:46 +02:00
Themaister 13ae61031f Add ttf_font_color to ext driver struct.
Does not need to bump ABI version.
2011-09-09 09:47:32 +02:00
Themaister 1ced96c5e9 Make it non-public. 2011-09-07 18:59:51 +02:00
Themaister 0d905eb3f6 Actually load cheats on startup ... :') 2011-09-07 18:59:01 +02:00
Themaister 32a5460ea7 Small cleanup. 2011-09-06 19:53:22 +02:00
Themaister be5acff69c Update font rendering for SDL. 2011-09-06 18:32:40 +02:00
Themaister 1b0ef5793e Font colors for XVideo. Some cleanups. 2011-09-06 17:56:42 +02:00
Themaister 2bd0caae2e Do not set RESIZABLE on fullscreen (really? :v) 2011-09-06 15:38:32 +02:00
Themaister 3045f2c478 Move cheat initializing as late as possible. 2011-09-06 12:55:21 +03:00
Themaister 1282a142d6 Fix load/save semantics for cheats ... 2011-09-06 12:51:52 +03:00
Themaister ac1a539d22 Fix stupid typo. 2011-09-05 21:21:18 +02:00
Themaister 6f47775239 Add cheat config. 2011-09-05 17:57:30 +02:00
Themaister 0823d72dee Add coloring to fonts. 2011-09-05 17:00:28 +02:00
Themaister 407ad94f58 Style nit. 2011-09-04 21:11:26 +02:00
Themaister b2b103362d Warn if glX VSync call isn't found. 2011-09-04 13:01:54 +02:00
Themaister 231680944f Remove #ifdef for FFmpeg. 2011-09-04 11:37:59 +02:00
224 changed files with 56706 additions and 6170 deletions

No files matched your search

View File
Whitespace-only changes.
+9 -1
View File
@@ -1,7 +1,15 @@
*.o
*.bmpobj
*.so
*.dll
ssnes
/ssnes
/config.h
/config.mk
/tools/ssnes-joyconfig
*.sdf
*.opensdf
*.suo
Debug
Release
ipch
*.user
+884
View File
@@ -0,0 +1,884 @@
/* SSNES - A Super Nintendo Entertainment System (SNES) Emulator frontend for libsnes.
* Copyright (C) 2010-2012 - Hans-Kristian Arntzen
* Copyright (C) 2011-2012 - Daniel De Matteis
*
* Some code herein may be based on code found in BSNES.
*
* SSNES is free software: you can redistribute it and/or modify it under the terms
* of the GNU General Public License as published by the Free Software Found-
* ation, either version 3 of the License, or (at your option) any later version.
*
* SSNES is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
* without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
* PURPOSE. See the GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License along with SSNES.
* If not, see <http://www.gnu.org/licenses/>.
*/
#define NONET
#include <xtl.h>
#include <malloc.h>
#include "xdk360_video.h"
#include "fonts.h"
#include "../general.h"
static video_console_t video_console;
static xdk360_video_font_t m_Font;
void xdk360_console_draw(void)
{
xdk360_video_t *vid = (xdk360_video_t*)g_d3d;
D3DDevice *m_pd3dDevice = vid->xdk360_render_device;
// The top line
unsigned int nTextLine = ( video_console.m_nCurLine -
video_console.m_cScreenHeight + video_console.m_cScreenHeightVirtual -
video_console.m_nScrollOffset + 1 )
% video_console.m_cScreenHeightVirtual;
xdk360_video_font_begin(&m_Font);
for( unsigned int nScreenLine = 0; nScreenLine < video_console.m_cScreenHeight; nScreenLine++ )
{
xdk360_video_font_draw_text(&m_Font, (float)( video_console.m_cxSafeAreaOffset ),
(float)( video_console.m_cySafeAreaOffset +
video_console.m_fLineHeight * nScreenLine ),
video_console.m_colTextColor,
video_console.m_Lines[nTextLine], 0.0f );
nTextLine = ( nTextLine + 1 ) % video_console.m_cScreenHeightVirtual;
}
xdk360_video_font_end(&m_Font);
}
HRESULT xdk360_console_init( LPCSTR strFontFileName, unsigned long colBackColor,
unsigned long colTextColor)
{
xdk360_video_t *vid = (xdk360_video_t*)g_d3d;
D3DDevice *m_pd3dDevice = vid->xdk360_render_device;
video_console.first_message = true;
video_console.m_Buffer = NULL;
video_console.m_Lines = NULL;
video_console.m_nScrollOffset = 0;
// Calculate the safe area
unsigned int uiSafeAreaPct = vid->video_mode.fIsHiDef ? SAFE_AREA_PCT_HDTV
: SAFE_AREA_PCT_4x3;
video_console.m_cxSafeArea = ( vid->d3dpp.BackBufferWidth * uiSafeAreaPct ) / 100;
video_console.m_cySafeArea = ( vid->d3dpp.BackBufferHeight * uiSafeAreaPct ) / 100;
video_console.m_cxSafeAreaOffset = ( vid->d3dpp.BackBufferWidth - video_console.m_cxSafeArea ) / 2;
video_console.m_cySafeAreaOffset = ( vid->d3dpp.BackBufferHeight - video_console.m_cySafeArea ) / 2;
// Create the font
HRESULT hr = xdk360_video_font_init(&m_Font, strFontFileName );
if( FAILED( hr ) )
{
SSNES_ERR( "Could not create font.\n" );
return -1;
}
// Save the colors
video_console.m_colBackColor = colBackColor;
video_console.m_colTextColor = colTextColor;
// Calculate the number of lines on the screen
float fCharWidth, fCharHeight;
xdk360_video_font_get_text_width(&m_Font, L"i", &fCharWidth, &fCharHeight, FALSE);
video_console.m_cScreenHeight = (unsigned int)( video_console.m_cySafeArea / fCharHeight );
video_console.m_cScreenWidth = (unsigned int)( video_console.m_cxSafeArea / fCharWidth );
video_console.m_cScreenHeightVirtual = video_console.m_cScreenHeight;
video_console.m_fLineHeight = fCharHeight;
// Allocate memory to hold the lines
video_console.m_Buffer = new wchar_t[ video_console.m_cScreenHeightVirtual * ( video_console.m_cScreenWidth + 1 ) ];
video_console.m_Lines = new wchar_t *[ video_console.m_cScreenHeightVirtual ];
// Set the line pointers as indexes into the buffer
for( unsigned int i = 0; i < video_console.m_cScreenHeightVirtual; i++ )
video_console.m_Lines[ i ] = video_console.m_Buffer + ( video_console.m_cScreenWidth + 1 ) * i;
video_console.m_nCurLine = 0;
video_console.m_cCurLineLength = 0;
memset( video_console.m_Buffer, 0, video_console.m_cScreenHeightVirtual * ( video_console.m_cScreenWidth + 1 ) * sizeof( wchar_t ) );
xdk360_console_draw();
return hr;
}
void xdk360_console_deinit()
{
// Delete the memory we've allocated
if(video_console.m_Lines)
{
delete[] video_console.m_Lines;
video_console.m_Lines = NULL;
}
if(video_console.m_Buffer)
{
delete[] video_console.m_Buffer;
video_console.m_Buffer = NULL;
}
// Destroy the font
xdk360_video_font_deinit(&m_Font);
}
void xdk360_console_add( wchar_t wch )
{
// If this is a newline, just increment lines and move on
if( wch == L'\n' )
{
video_console.m_nCurLine = ( video_console.m_nCurLine + 1 )
% video_console.m_cScreenHeightVirtual;
video_console.m_cCurLineLength = 0;
memset(video_console.m_Lines[video_console.m_nCurLine], 0,
( video_console.m_cScreenWidth + 1 ) * sizeof( wchar_t ) );
return;
}
int bIncrementLine = FALSE; // Whether to wrap to the next line
if( video_console.m_cCurLineLength == video_console.m_cScreenWidth )
bIncrementLine = TRUE;
else
{
// Try to append the character to the line
video_console.m_Lines[ video_console.m_nCurLine ]
[ video_console.m_cCurLineLength ] = wch;
float fTextWidth, fTextHeight;
xdk360_video_font_get_text_width(&m_Font, video_console.m_Lines[ video_console.m_nCurLine ], &fTextWidth, &fTextHeight, 0);
if( fTextHeight > video_console.m_cxSafeArea )
{
// The line is too long, we need to wrap the character to the next line
video_console.m_Lines[video_console.m_nCurLine]
[ video_console.m_cCurLineLength ] = L'\0';
bIncrementLine = TRUE;
}
}
// If we need to skip to the next line, do so
if( bIncrementLine )
{
video_console.m_nCurLine = ( video_console.m_nCurLine + 1 )
% video_console.m_cScreenHeightVirtual;
video_console.m_cCurLineLength = 0;
memset( video_console.m_Lines[video_console.m_nCurLine],
0, ( video_console.m_cScreenWidth + 1 ) * sizeof( wchar_t ) );
video_console.m_Lines[video_console.m_nCurLine ][0] = wch;
}
video_console.m_cCurLineLength++;
}
void xdk360_console_format(_In_z_ _Printf_format_string_ LPCSTR strFormat, ... )
{
video_console.m_nCurLine = 0;
video_console.m_cCurLineLength = 0;
memset( video_console.m_Buffer, 0,
video_console.m_cScreenHeightVirtual *
( video_console.m_cScreenWidth + 1 ) * sizeof( wchar_t ) );
va_list pArgList;
va_start( pArgList, strFormat );
// Count the required length of the string
unsigned long dwStrLen = _vscprintf( strFormat, pArgList ) + 1;
// +1 = null terminator
char * strMessage = ( char * )_malloca( dwStrLen );
vsprintf_s( strMessage, dwStrLen, strFormat, pArgList );
// Output the string to the console
unsigned long uStringLength = strlen( strMessage );
for( unsigned long i = 0; i < uStringLength; i++ )
{
wchar_t wch;
int ret = MultiByteToWideChar( CP_ACP, // ANSI code page
0, // No flags
&strMessage[i], // Character to convert
1, // Convert one byte
&wch, // Target wide character buffer
1 ); // One wide character
xdk360_console_add( wch );
}
_freea( strMessage );
va_end( pArgList );
}
void xdk360_console_format_w(_In_z_ _Printf_format_string_ LPCWSTR wstrFormat, ... )
{
video_console.m_nCurLine = 0;
video_console.m_cCurLineLength = 0;
memset( video_console.m_Buffer, 0, video_console.m_cScreenHeightVirtual
* ( video_console.m_cScreenWidth + 1 ) * sizeof( wchar_t ) );
va_list pArgList;
va_start( pArgList, wstrFormat );
// Count the required length of the string
unsigned long dwStrLen = _vscwprintf( wstrFormat, pArgList ) + 1; // +1 = null terminator
wchar_t * strMessage = ( wchar_t * )_malloca( dwStrLen * sizeof( wchar_t ) );
vswprintf_s( strMessage, dwStrLen, wstrFormat, pArgList );
// Output the string to the console
unsigned long uStringLength = wcslen( strMessage );
for( unsigned long i = 0; i < uStringLength; i++ )
xdk360_console_add( strMessage[i] );
_freea( strMessage );
va_end( pArgList );
}
#define CALCFONTFILEHEADERSIZE(x) ( sizeof(unsigned long) + (sizeof(float)* 4) + sizeof(unsigned short) + (sizeof(wchar_t)*(x)) )
#define FONTFILEVERSION 5
typedef struct FontFileHeaderImage_t {
unsigned long m_dwFileVersion; // Version of the font file (Must match FONTFILEVERSION)
float m_fFontHeight; // Height of the font strike in pixels
float m_fFontTopPadding; // Padding above the strike zone
float m_fFontBottomPadding; // Padding below the strike zone
float m_fFontYAdvance; // Number of pixels to move the cursor for a line feed
unsigned short m_cMaxGlyph; // Number of font characters (Should be an odd number to maintain DWORD Alignment)
wchar_t m_TranslatorTable[1]; // ASCII to Glyph lookup table, NOTE: It's m_cMaxGlyph+1 in size.
// Entry 0 maps to the "Unknown" glyph.
} FontFileHeaderImage_t;
// Font strike array. Immediately follows the FontFileHeaderImage_t
// structure image
typedef struct FontFileStrikesImage_t {
unsigned long m_dwNumGlyphs; // Size of font strike array (First entry is the unknown glyph)
GLYPH_ATTR m_Glyphs[1]; // Array of font strike uv's etc... NOTE: It's m_dwNumGlyphs in size
} FontFileStrikesImage_t;
static PackedResource m_xprResource;
static const char g_strFontShader[] =
"struct VS_IN\n"
"{\n"
"float2 Pos : POSITION;\n"
"float2 Tex : TEXCOORD0;\n"
"float4 ChannelSelector : TEXCOORD1;\n"
"};\n"
"struct VS_OUT\n"
"{\n"
"float4 Position : POSITION;\n"
"float4 Diffuse : COLOR0_center;\n"
"float2 TexCoord0 : TEXCOORD0;\n"
"float4 ChannelSelector : TEXCOORD1;\n"
"};\n"
"uniform float4 Color : register(c1);\n"
"uniform float2 TexScale : register(c2);\n"
"sampler FontTexture : register(s0);\n"
"VS_OUT FontVertexShader( VS_IN In )\n"
"{\n"
"VS_OUT Out;\n"
"Out.Position.x = (In.Pos.x-0.5);\n"
"Out.Position.y = (In.Pos.y-0.5);\n"
"Out.Position.z = ( 0.0 );\n"
"Out.Position.w = ( 1.0 );\n"
"Out.Diffuse = Color;\n"
"Out.TexCoord0.x = In.Tex.x * TexScale.x;\n"
"Out.TexCoord0.y = In.Tex.y * TexScale.y;\n"
"Out.ChannelSelector = In.ChannelSelector;\n"
"return Out;\n"
"}\n"
"float4 FontPixelShader( VS_OUT In ) : COLOR0\n"
"{\n"
"float4 FontTexel = tex2D( FontTexture, In.TexCoord0 );\n"
"if( dot( In.ChannelSelector, float4(1,1,1,1) ) )\n"
"{\n"
"float value = dot( FontTexel, In.ChannelSelector );\n"
"float4 Color;\n"
"Color.rgb = ( value > 0.5f ? 2*value-1 : 0.0f );\n"
"Color.a = 2 * ( value > 0.5f ? 1.0f : value );\n"
"return Color * In.Diffuse;\n"
"}\n"
"else\n"
"{\n"
"return FontTexel * In.Diffuse;\n"
"}\n"
"}\n";
typedef struct Font_Locals_t {
D3DVertexDeclaration* m_pFontVertexDecl; // Shared vertex buffer
D3DVertexShader* m_pFontVertexShader; // Created vertex shader
D3DPixelShader* m_pFontPixelShader; // Created pixel shader
} Font_Locals_t;
// All elements are defaulted to NULL
static Font_Locals_t s_FontLocals; // Global static instance
static HRESULT xdk360_video_font_create_shaders (xdk360_video_font_t * font)
{
//
// There are only two states the globals could be in,
// Initialized, in which the ref count is increased,
// Uninialized, in which the vertex/pixel shaders need to be
// started up and a vertex array created.
///
HRESULT hr;
if (!s_FontLocals.m_pFontVertexDecl)
{
// Use the do {} while(0); trick for a fake goto
// It simplies tear down on error conditions.
do
{
// Step #1, create my vertex array with 16 bytes per entry
// Floats for the position,
// shorts for the uvs
// 32 bit packed ARGB 8:8:8:8 for color
static const D3DVERTEXELEMENT9 decl[] =
{
{ 0, 0, D3DDECLTYPE_FLOAT2, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0 },
{ 0, 8, D3DDECLTYPE_USHORT2, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_TEXCOORD, 0 },
{ 0, 12, D3DDECLTYPE_D3DCOLOR, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_TEXCOORD, 1 },
D3DDECL_END()
};
// Cache this global into a register
xdk360_video_t *vid = (xdk360_video_t*)g_d3d;
D3DDevice *pd3dDevice = vid->xdk360_render_device;
hr = pd3dDevice->CreateVertexDeclaration( decl, &s_FontLocals.m_pFontVertexDecl );
if (SUCCEEDED(hr))
{
// Step #2, create my vertex shader
ID3DXBuffer* pShaderCode;
hr = D3DXCompileShader( g_strFontShader, sizeof(g_strFontShader)-1 ,
NULL, NULL, "FontVertexShader", "vs.2.0", 0,&pShaderCode, NULL, NULL );
if (SUCCEEDED(hr))
{
hr = pd3dDevice->CreateVertexShader( ( unsigned long * )pShaderCode->GetBufferPointer(),
&s_FontLocals.m_pFontVertexShader );
// Release the compiled shader
pShaderCode->Release();
if(SUCCEEDED(hr))
{
// Step #3, create my pixel shader
hr = D3DXCompileShader( g_strFontShader, sizeof(g_strFontShader)-1 ,
NULL, NULL, "FontPixelShader", "ps.2.0", 0,&pShaderCode, NULL, NULL );
if ( SUCCEEDED(hr))
{
hr = pd3dDevice->CreatePixelShader( ( DWORD* )pShaderCode->GetBufferPointer(),
&s_FontLocals.m_pFontPixelShader );
// Release the compiled shader
pShaderCode->Release();
if (SUCCEEDED(hr))
{
hr = S_OK;
break; // Skip the teardown code
}
}
// If the code got to here, a fatal error has occured
// and a clean shutdown needs to be performed.
D3DResource_Release((D3DResource *)s_FontLocals.m_pFontVertexShader);
}
// Ensure the pointer is NULL
s_FontLocals.m_pFontVertexShader = NULL;
}
D3DResource_Release((D3DResource *)s_FontLocals.m_pFontVertexDecl);
}
// Ensure this pointer is NULL
s_FontLocals.m_pFontVertexDecl = NULL;
}while(0); // Exit point for the break command.
return hr;
}
else
{
D3DResource_AddRef((D3DResource *)s_FontLocals.m_pFontVertexDecl);
D3DResource_AddRef((D3DResource *)s_FontLocals.m_pFontVertexShader);
D3DResource_AddRef((D3DResource *)s_FontLocals.m_pFontPixelShader);
hr = S_OK;
}
return hr; // Return the error code if any
}
void xdk360_video_font_set_size(xdk360_video_font_t * font, float x, float y)
{
font->m_fXScaleFactor = x;
font->m_fYScaleFactor = y;
}
HRESULT xdk360_video_font_init(xdk360_video_font_t * font, const char * strFontFileName)
{
font->m_pFontTexture = NULL;
font->m_dwNumGlyphs = 0L;
font->m_Glyphs = NULL;
font->m_fCursorX = 0.0f;
font->m_fCursorY = 0.0f;
font->m_fXScaleFactor = 2.0f;
font->m_fYScaleFactor = 2.0f;
font->m_cMaxGlyph = 0;
font->m_TranslatorTable = NULL;
font->m_dwNestedBeginCount = 0L;
// Create the font
if( FAILED( m_xprResource.Create( strFontFileName ) ) )
return E_FAIL;
D3DTexture * pFontTexture = m_xprResource.GetTexture( "FontTexture" );
const void * pFontData = m_xprResource.GetData( "FontData");
// Save a copy of the texture
font->m_pFontTexture = pFontTexture;
// Check version of file (to make sure it matches up with the FontMaker tool)
const unsigned char * pData = static_cast<const unsigned char *>(pFontData);
unsigned long dwFileVersion = reinterpret_cast<const FontFileHeaderImage_t *>(pData)->m_dwFileVersion;
if( dwFileVersion == FONTFILEVERSION )
{
font->m_fFontHeight = reinterpret_cast<const FontFileHeaderImage_t *>(pData)->m_fFontHeight;
font->m_fFontTopPadding = reinterpret_cast<const FontFileHeaderImage_t *>(pData)->m_fFontTopPadding;
font->m_fFontBottomPadding = reinterpret_cast<const FontFileHeaderImage_t *>(pData)->m_fFontBottomPadding;
font->m_fFontYAdvance = reinterpret_cast<const FontFileHeaderImage_t *>(pData)->m_fFontYAdvance;
// Point to the translator string which immediately follows the 4 floats
font->m_cMaxGlyph = reinterpret_cast<const FontFileHeaderImage_t *>(pData)->m_cMaxGlyph;
font->m_TranslatorTable = const_cast<FontFileHeaderImage_t*>(reinterpret_cast<const FontFileHeaderImage_t *>(pData))->m_TranslatorTable;
pData += CALCFONTFILEHEADERSIZE( font->m_cMaxGlyph + 1 );
// Read the glyph attributes from the file
font->m_dwNumGlyphs = reinterpret_cast<const FontFileStrikesImage_t *>(pData)->m_dwNumGlyphs;
font->m_Glyphs = reinterpret_cast<const FontFileStrikesImage_t *>(pData)->m_Glyphs; // Pointer
}
else
{
SSNES_ERR( "Incorrect version number on font file.\n" );
return E_FAIL;
}
// Create the vertex and pixel shaders for rendering the font
if( FAILED( xdk360_video_font_create_shaders(font) ) )
{
SSNES_ERR( "Could not create font shaders.\n" );
return E_FAIL;
}
xdk360_video_t *vid = (xdk360_video_t*)g_d3d;
D3DDevice *pd3dDevice = vid->xdk360_render_device;
// Initialize the window
D3DDISPLAYMODE DisplayMode;
pd3dDevice->GetDisplayMode( 0, &DisplayMode );
font->m_rcWindow.x1 = 0;
font->m_rcWindow.y1 = 0;
font->m_rcWindow.x2 = DisplayMode.Width;
font->m_rcWindow.y2 = DisplayMode.Height;
// Determine whether we should save/restore state
font->m_bSaveState = TRUE;
return S_OK;
}
void xdk360_video_font_deinit(xdk360_video_font_t * font)
{
font->m_pFontTexture = NULL;
font->m_dwNumGlyphs = 0L;
font->m_Glyphs = NULL;
font->m_cMaxGlyph = 0;
font->m_TranslatorTable = NULL;
font->m_dwNestedBeginCount = 0L;
// Safely release shaders
// NOTE: They are released in reverse order of creation
// to make sure any interdependencies are dealt with
if( ( s_FontLocals.m_pFontPixelShader != NULL ) && ( s_FontLocals.m_pFontPixelShader->Release() == 0 ) )
s_FontLocals.m_pFontPixelShader = NULL;
if( ( s_FontLocals.m_pFontVertexShader != NULL ) && ( s_FontLocals.m_pFontVertexShader->Release() == 0 ) )
s_FontLocals.m_pFontVertexShader = NULL;
if( ( s_FontLocals.m_pFontVertexDecl != NULL ) && ( s_FontLocals.m_pFontVertexDecl->Release() == 0 ) )
s_FontLocals.m_pFontVertexDecl = NULL;
if( m_xprResource.m_bInitialized)
m_xprResource.Destroy();
}
void xdk360_video_font_set_cursor_position(xdk360_video_font_t *font, float fCursorX, float fCursorY )
{
font->m_fCursorX = floorf( fCursorX );
font->m_fCursorY = floorf( fCursorY );
}
void xdk360_video_font_get_text_width(xdk360_video_font_t * font, const wchar_t * strText, float * pWidth, float * pHeight, int bFirstLineOnly)
{
// Set default text extent in output parameters
int iWidth = 0;
float fHeight = 0.0f;
if( strText )
{
// Initialize counters that keep track of text extent
int ix = 0;
float fy = font->m_fFontHeight; // One character high to start
if( fy > fHeight )
fHeight = fy;
// Loop through each character and update text extent
unsigned long letter;
while( (letter = *strText) != 0 )
{
++strText;
// Handle newline character
if( letter == L'\n' )
{
if( bFirstLineOnly )
break;
ix = 0;
fy += font->m_fFontYAdvance;
// since the height has changed, test against the height extent
if( fy > fHeight )
fHeight = fy;
}
// Handle carriage return characters by ignoring them. This helps when
// displaying text from a file.
if( letter == L'\r' )
continue;
// Translate unprintable characters
const GLYPH_ATTR* pGlyph;
if( letter > font->m_cMaxGlyph )
letter = 0; // Out of bounds?
else
letter = font->m_TranslatorTable[letter]; // Remap ASCII to glyph
pGlyph = &font->m_Glyphs[letter]; // Get the requested glyph
// Get text extent for this character's glyph
ix += pGlyph->wOffset;
ix += pGlyph->wAdvance;
// Since the x widened, test against the x extent
if( ix > iWidth )
iWidth = ix;
}
}
// Convert the width to a float here, load/hit/store. :(
float fWidth = static_cast<float>(iWidth); // Delay the use if fWidth to reduce LHS pain
// Apply the scale factor to the result
fHeight *= font->m_fYScaleFactor;
// Store the final results
*pHeight = fHeight;
fWidth *= font->m_fXScaleFactor;
*pWidth = fWidth;
}
void xdk360_video_font_begin (xdk360_video_font_t * font)
{
// Set state on the first call
if( font->m_dwNestedBeginCount == 0 )
{
// Cache the global pointer into a register
xdk360_video_t *vid = (xdk360_video_t*)g_d3d;
D3DDevice *pD3dDevice = vid->xdk360_render_device;
// Save state
if( font->m_bSaveState )
{
// Note, we are not saving the texture, vertex, or pixel shader,
// since it's not worth the performance. We're more interested
// in saving state that would cause hard to find problems.
pD3dDevice->GetRenderState( D3DRS_ALPHABLENDENABLE,
&font->m_dwSavedState[ SAVEDSTATE_D3DRS_ALPHABLENDENABLE ] );
pD3dDevice->GetRenderState( D3DRS_SRCBLEND, &font->m_dwSavedState[ SAVEDSTATE_D3DRS_SRCBLEND ] );
pD3dDevice->GetRenderState( D3DRS_DESTBLEND, &font->m_dwSavedState[ SAVEDSTATE_D3DRS_DESTBLEND ] );
pD3dDevice->GetRenderState( D3DRS_BLENDOP, &font->m_dwSavedState[ SAVEDSTATE_D3DRS_BLENDOP ] );
pD3dDevice->GetRenderState( D3DRS_ALPHATESTENABLE, &font->m_dwSavedState[ SAVEDSTATE_D3DRS_ALPHATESTENABLE ] );
pD3dDevice->GetRenderState( D3DRS_ALPHAREF, &font->m_dwSavedState[ SAVEDSTATE_D3DRS_ALPHAREF ] );
pD3dDevice->GetRenderState( D3DRS_ALPHAFUNC, &font->m_dwSavedState[ SAVEDSTATE_D3DRS_ALPHAFUNC ] );
pD3dDevice->GetRenderState( D3DRS_FILLMODE, &font->m_dwSavedState[ SAVEDSTATE_D3DRS_FILLMODE ] );
pD3dDevice->GetRenderState( D3DRS_CULLMODE, &font->m_dwSavedState[ SAVEDSTATE_D3DRS_CULLMODE ] );
pD3dDevice->GetRenderState( D3DRS_VIEWPORTENABLE, &font->m_dwSavedState[ SAVEDSTATE_D3DRS_VIEWPORTENABLE ] );
font->m_dwSavedState[ SAVEDSTATE_D3DSAMP_MINFILTER ] = D3DDevice_GetSamplerState_MinFilter( pD3dDevice, 0 );
font->m_dwSavedState[ SAVEDSTATE_D3DSAMP_MAGFILTER ] = D3DDevice_GetSamplerState_MagFilter( pD3dDevice, 0 );
font->m_dwSavedState[ SAVEDSTATE_D3DSAMP_ADDRESSU ] = D3DDevice_GetSamplerState_AddressU( pD3dDevice, 0);
font->m_dwSavedState[ SAVEDSTATE_D3DSAMP_ADDRESSV ] = D3DDevice_GetSamplerState_AddressV( pD3dDevice, 0);
}
// Set the texture scaling factor as a vertex shader constant
D3DSURFACE_DESC TextureDesc;
D3DTexture_GetLevelDesc(font->m_pFontTexture, 0, &TextureDesc); // Get the description
// Set render state
D3DDevice_SetTexture_Inline(pD3dDevice, 0, font->m_pFontTexture);
// Read the TextureDesc here to ensure no load/hit/store from GetLevelDesc()
float vTexScale[4];
vTexScale[0] = 1.0f / TextureDesc.Width; // LHS due to int->float conversion
vTexScale[1] = 1.0f / TextureDesc.Height;
vTexScale[2] = 0.0f;
vTexScale[3] = 0.0f;
D3DDevice_SetRenderState_AlphaBlendEnable( pD3dDevice, TRUE );
D3DDevice_SetRenderState_SrcBlend(pD3dDevice, D3DBLEND_SRCALPHA );
D3DDevice_SetRenderState_DestBlend( pD3dDevice, D3DBLEND_INVSRCALPHA );
D3DDevice_SetRenderState_BlendOp( pD3dDevice, D3DBLENDOP_ADD );
pD3dDevice->SetRenderState( D3DRS_ALPHATESTENABLE, TRUE );
pD3dDevice->SetRenderState( D3DRS_ALPHAREF, 0x08 );
pD3dDevice->SetRenderState( D3DRS_ALPHAFUNC, D3DCMP_GREATEREQUAL );
pD3dDevice->SetRenderState( D3DRS_FILLMODE, D3DFILL_SOLID );
pD3dDevice->SetRenderState( D3DRS_CULLMODE, D3DCULL_CCW );
pD3dDevice->SetRenderState( D3DRS_VIEWPORTENABLE, FALSE );
D3DDevice_SetSamplerState_MinFilter(pD3dDevice, 0, D3DTEXF_LINEAR );
D3DDevice_SetSamplerState_MagFilter(pD3dDevice, 0, D3DTEXF_LINEAR );
D3DDevice_SetSamplerState_AddressU_Inline(pD3dDevice, 0, D3DTADDRESS_CLAMP );
D3DDevice_SetSamplerState_AddressV_Inline(pD3dDevice, 0, D3DTADDRESS_CLAMP );
D3DDevice_SetVertexDeclaration(pD3dDevice, s_FontLocals.m_pFontVertexDecl );
D3DDevice_SetVertexShader(pD3dDevice, s_FontLocals.m_pFontVertexShader );
D3DDevice_SetPixelShader(pD3dDevice, s_FontLocals.m_pFontPixelShader );
// Set the texture scaling factor as a vertex shader constant
// Call here to avoid load hit store from writing to vTexScale above
pD3dDevice->SetVertexShaderConstantF( 2, vTexScale, 1 );
}
// Keep track of the nested begin/end calls.
font->m_dwNestedBeginCount++;
}
void xdk360_video_font_end(xdk360_video_font_t * font)
{
if( --font->m_dwNestedBeginCount > 0 )
return;
// Restore state
if( font->m_bSaveState )
{
// Cache the global pointer into a register
xdk360_video_t *vid = (xdk360_video_t*)g_d3d;
D3DDevice *pD3dDevice = vid->xdk360_render_device;
D3DDevice_SetTexture_Inline(pD3dDevice, 0, NULL);
D3DDevice_SetVertexDeclaration(pD3dDevice, NULL);
D3DDevice_SetVertexShader(pD3dDevice, NULL );
D3DDevice_SetPixelShader(pD3dDevice, NULL );
D3DDevice_SetRenderState_AlphaBlendEnable(pD3dDevice, font->m_dwSavedState[ SAVEDSTATE_D3DRS_ALPHABLENDENABLE ]);
D3DDevice_SetRenderState_SrcBlend(pD3dDevice, font->m_dwSavedState[ SAVEDSTATE_D3DRS_SRCBLEND ] );
D3DDevice_SetRenderState_DestBlend( pD3dDevice, font->m_dwSavedState[ SAVEDSTATE_D3DRS_DESTBLEND ] );
D3DDevice_SetRenderState_BlendOp( pD3dDevice, font->m_dwSavedState[ SAVEDSTATE_D3DRS_BLENDOP ] );
pD3dDevice->SetRenderState( D3DRS_ALPHATESTENABLE, font->m_dwSavedState[ SAVEDSTATE_D3DRS_ALPHATESTENABLE ] );
pD3dDevice->SetRenderState( D3DRS_ALPHAREF, font->m_dwSavedState[ SAVEDSTATE_D3DRS_ALPHAREF ] );
pD3dDevice->SetRenderState( D3DRS_ALPHAFUNC, font->m_dwSavedState[ SAVEDSTATE_D3DRS_ALPHAFUNC ] );
pD3dDevice->SetRenderState( D3DRS_FILLMODE, font->m_dwSavedState[ SAVEDSTATE_D3DRS_FILLMODE ] );
pD3dDevice->SetRenderState( D3DRS_CULLMODE, font->m_dwSavedState[ SAVEDSTATE_D3DRS_CULLMODE ] );
pD3dDevice->SetRenderState( D3DRS_VIEWPORTENABLE, font->m_dwSavedState[ SAVEDSTATE_D3DRS_VIEWPORTENABLE ] );
D3DDevice_SetSamplerState_MinFilter(pD3dDevice, 0, font->m_dwSavedState[ SAVEDSTATE_D3DSAMP_MINFILTER ] );
D3DDevice_SetSamplerState_MagFilter(pD3dDevice, 0, font->m_dwSavedState[ SAVEDSTATE_D3DSAMP_MAGFILTER ] );
D3DDevice_SetSamplerState_AddressU_Inline(pD3dDevice, 0, font->m_dwSavedState[ SAVEDSTATE_D3DSAMP_ADDRESSU ] );
D3DDevice_SetSamplerState_AddressV_Inline(pD3dDevice, 0, font->m_dwSavedState[ SAVEDSTATE_D3DSAMP_ADDRESSV ] );
}
}
void xdk360_video_font_draw_text(xdk360_video_font_t * font, float fOriginX, float fOriginY, unsigned long dwColor,
const wchar_t * strText, float fMaxPixelWidth )
{
if( strText == NULL || strText[0] == L'\0')
return;
xdk360_video_t *vid = (xdk360_video_t*)g_d3d;
D3DDevice *pd3dDevice = vid->xdk360_render_device;
// Set the color as a vertex shader constant
float vColor[4];
vColor[0] = ( ( dwColor & 0x00ff0000 ) >> 16L ) / 255.0F;
vColor[1] = ( ( dwColor & 0x0000ff00 ) >> 8L ) / 255.0F;
vColor[2] = ( ( dwColor & 0x000000ff ) >> 0L ) / 255.0F;
vColor[3] = ( ( dwColor & 0xff000000 ) >> 24L ) / 255.0F;
// Set up stuff to prepare for drawing text
xdk360_video_font_begin(font);
// Perform the actual storing of the color constant here to prevent
// a load-hit-store by inserting work between the store and the use of
// the vColor array.
pd3dDevice->SetVertexShaderConstantF( 1, vColor, 1 );
// Set the starting screen position
if((fOriginX < 0.0f))
fOriginX += font->m_rcWindow.x2;
if( fOriginY < 0.0f )
fOriginY += font->m_rcWindow.y2;
font->m_fCursorX = floorf( fOriginX );
font->m_fCursorY = floorf( fOriginY );
// Adjust for padding
fOriginY -= font->m_fFontTopPadding;
// Add window offsets
float Winx = 0.0f;
float Winy = 0.0f;
fOriginX += Winx;
fOriginY += Winy;
font->m_fCursorX += Winx;
font->m_fCursorY += Winy;
// Begin drawing the vertices
// Declared as volatile to force writing in ascending
// address order. It prevents out of sequence writing in write combined
// memory.
volatile float * pVertex;
unsigned long dwNumChars = wcslen(strText);
HRESULT hr = pd3dDevice->BeginVertices( D3DPT_QUADLIST, 4 * dwNumChars, sizeof( XMFLOAT4 ) ,
( VOID** )&pVertex );
// The ring buffer may run out of space when tiling, doing z-prepasses,
// or using BeginCommandBuffer. If so, make the buffer larger.
if( FAILED( hr ) )
SSNES_ERR( "Ring buffer out of memory.\n" );
// Draw four vertices for each glyph
while( *strText )
{
wchar_t letter;
// Get the current letter in the string
letter = *strText++;
// Handle the newline character
if( letter == L'\n' )
{
font->m_fCursorX = fOriginX;
font->m_fCursorY += font->m_fFontYAdvance * font->m_fYScaleFactor;
continue;
}
// Translate unprintable characters
const GLYPH_ATTR * pGlyph = &font->m_Glyphs[ ( letter <= font->m_cMaxGlyph ) ? font->m_TranslatorTable[letter] : 0 ];
float fOffset = font->m_fXScaleFactor * (float)pGlyph->wOffset;
float fAdvance = font->m_fXScaleFactor * (float)pGlyph->wAdvance;
float fWidth = font->m_fXScaleFactor * (float)pGlyph->wWidth;
float fHeight = font->m_fYScaleFactor * font->m_fFontHeight;
// Setup the screen coordinates
font->m_fCursorX += fOffset;
float X4 = font->m_fCursorX;
float X1 = X4;
float X3 = X4 + fWidth;
float X2 = X1 + fWidth;
float Y1 = font->m_fCursorY;
float Y3 = Y1 + fHeight;
float Y2 = Y1;
float Y4 = Y3;
font->m_fCursorX += fAdvance;
// Select the RGBA channel that the compressed glyph is stored in
// Takes a 4 bit per pixel ARGB value and expand it to an 8 bit per pixel ARGB value
unsigned long dwChannelSelector = pGlyph->wMask; // Convert to 32 bit
// Perform the conversion without branching
// Splat the 4 bit per pixels from 0x1234 to 0x01020304
dwChannelSelector = ((dwChannelSelector&0xF000)<<(24-12))|((dwChannelSelector&0xF00)<<(16-8))|
((dwChannelSelector&0xF0)<<(8-4))|(dwChannelSelector&0xF);
// Perform a vectorized multiply to make 0x01020304 into 0x11223344
dwChannelSelector *= 0x11;
// Add the vertices to draw this glyph
unsigned long tu1 = pGlyph->tu1; // Convert shorts to 32 bit longs for in register merging
unsigned long tv1 = pGlyph->tv1;
unsigned long tu2 = pGlyph->tu2;
unsigned long tv2 = pGlyph->tv2;
// NOTE: The vertexs are 2 floats for the screen coordinates,
// followed by two USHORTS for the u/vs of the character,
// terminated with the ARGB 32 bit color.
// This makes for 16 bytes per vertex data (Easier to read)
// Second NOTE: The uvs are merged and written using a DWORD due
// to the write combining hardware being only able to handle 32,
// 64 and 128 writes. Never store to write combined memory with
// 8 or 16 bit instructions. You've been warned.
pVertex[0] = X1;
pVertex[1] = Y1;
reinterpret_cast<volatile unsigned long *>(pVertex)[2] = (tu1<<16)|tv1; // Merged using big endian rules
reinterpret_cast<volatile unsigned long *>(pVertex)[3] = dwChannelSelector;
pVertex[4] = X2;
pVertex[5] = Y2;
reinterpret_cast<volatile unsigned long *>(pVertex)[6] = (tu2<<16)|tv1; // Merged using big endian rules
reinterpret_cast<volatile unsigned long *>(pVertex)[7] = dwChannelSelector;
pVertex[8] = X3;
pVertex[9] = Y3;
reinterpret_cast<volatile unsigned long *>(pVertex)[10] = (tu2<<16)|tv2; // Merged using big endian rules
reinterpret_cast<volatile unsigned long *>(pVertex)[11] = dwChannelSelector;
pVertex[12] = X4;
pVertex[13] = Y4;
reinterpret_cast<volatile unsigned long *>(pVertex)[14] = (tu1<<16)|tv2; // Merged using big endian rules
reinterpret_cast<volatile unsigned long *>(pVertex)[15] = dwChannelSelector;
pVertex+=16;
dwNumChars--;
}
// Since we allocated vertex data space based on the string length, we now need to
// add some dummy verts for any skipped characters (like newlines, etc.)
while( dwNumChars )
{
pVertex[0] = 0;
pVertex[1] = 0;
pVertex[2] = 0;
pVertex[3] = 0;
pVertex[4] = 0;
pVertex[5] = 0;
pVertex[6] = 0;
pVertex[7] = 0;
pVertex[8] = 0;
pVertex[9] = 0;
pVertex[10] = 0;
pVertex[11] = 0;
pVertex[12] = 0;
pVertex[13] = 0;
pVertex[14] = 0;
pVertex[15] = 0;
pVertex+=16;
dwNumChars--;
}
// Stop drawing vertices
D3DDevice_EndVertices(pd3dDevice);
// Undo window offsets
font->m_fCursorX -= Winx;
font->m_fCursorY -= Winy;
// Call End() to complete the begin/end pair for drawing text
xdk360_video_font_end(font);
}
+121
View File
@@ -0,0 +1,121 @@
/* SSNES - A Super Nintendo Entertainment System (SNES) Emulator frontend for libsnes.
* Copyright (C) 2010-2012 - Hans-Kristian Arntzen
* Copyright (C) 2011-2012 - Daniel De Matteis
*
* Some code herein may be based on code found in BSNES.
*
* SSNES is free software: you can redistribute it and/or modify it under the terms
* of the GNU General Public License as published by the Free Software Found-
* ation, either version 3 of the License, or (at your option) any later version.
*
* SSNES is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
* without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
* PURPOSE. See the GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License along with SSNES.
* If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef SSNES_360_FONTS_H
#define SSNES_360_FONTS_H
#include "xdk360_video_resources.h"
#define PAGE_UP (255)
#define PAGE_DOWN (-255)
#define SCREEN_SIZE_X_DEFAULT 640
#define SCREEN_SIZE_Y_DEFAULT 480
#define SAFE_AREA_PCT_4x3 85
#define SAFE_AREA_PCT_HDTV 90
typedef struct
{
float m_fLineHeight; // height of a single line in pixels
unsigned int m_nScrollOffset; // offset to display text (in lines)
unsigned int first_message;
unsigned int m_cxSafeArea;
unsigned int m_cySafeArea;
unsigned int m_cxSafeAreaOffset;
unsigned int m_cySafeAreaOffset;
unsigned int m_nCurLine; // index of current line being written to
unsigned int m_cCurLineLength; // length of the current line
unsigned long m_colBackColor;
unsigned long m_colTextColor;
unsigned int m_cScreenHeight; // height in lines of screen area
unsigned int m_cScreenHeightVirtual; // height in lines of text storage buffer
unsigned int m_cScreenWidth; // width in characters
wchar_t * m_Buffer; // buffer big enough to hold a full screen
wchar_t ** m_Lines; // pointers to individual lines
} video_console_t;
typedef struct GLYPH_ATTR
{
unsigned short tu1, tv1, tu2, tv2; // Texture coordinates for the image
short wOffset; // Pixel offset for glyph start
short wWidth; // Pixel width of the glyph
short wAdvance; // Pixels to advance after the glyph
unsigned short wMask; // Channel mask
} GLYPH_ATTR;
enum SavedStates
{
SAVEDSTATE_D3DRS_ALPHABLENDENABLE,
SAVEDSTATE_D3DRS_SRCBLEND,
SAVEDSTATE_D3DRS_DESTBLEND,
SAVEDSTATE_D3DRS_BLENDOP,
SAVEDSTATE_D3DRS_ALPHATESTENABLE,
SAVEDSTATE_D3DRS_ALPHAREF,
SAVEDSTATE_D3DRS_ALPHAFUNC,
SAVEDSTATE_D3DRS_FILLMODE,
SAVEDSTATE_D3DRS_CULLMODE,
SAVEDSTATE_D3DRS_ZENABLE,
SAVEDSTATE_D3DRS_STENCILENABLE,
SAVEDSTATE_D3DRS_VIEWPORTENABLE,
SAVEDSTATE_D3DSAMP_MINFILTER,
SAVEDSTATE_D3DSAMP_MAGFILTER,
SAVEDSTATE_D3DSAMP_ADDRESSU,
SAVEDSTATE_D3DSAMP_ADDRESSV,
SAVEDSTATE_COUNT
};
typedef struct
{
unsigned int m_bSaveState;
unsigned long m_dwSavedState[ SAVEDSTATE_COUNT ];
unsigned long m_dwNestedBeginCount;
unsigned long m_cMaxGlyph; // Number of entries in the translator table
unsigned long m_dwNumGlyphs; // Number of valid glyphs
float m_fFontHeight; // Height of the font strike in pixels
float m_fFontTopPadding; // Padding above the strike zone
float m_fFontBottomPadding; // Padding below the strike zone
float m_fFontYAdvance; // Number of pixels to move the cursor for a line feed
float m_fXScaleFactor; // Scaling constants
float m_fYScaleFactor;
float m_fCursorX; // Current text cursor
float m_fCursorY;
D3DRECT m_rcWindow; // Bounds rect of the text window, modify via accessors only!
wchar_t * m_TranslatorTable; // ASCII to glyph lookup table
D3DTexture* m_pFontTexture;
const GLYPH_ATTR* m_Glyphs; // Array of glyphs
} xdk360_video_font_t;
HRESULT xdk360_console_init ( LPCSTR strFontFileName, D3DCOLOR colBackColor, D3DCOLOR colTextColor);
void xdk360_console_deinit (void);
void xdk360_console_format (_In_z_ _Printf_format_string_ LPCSTR strFormat, ... );
void xdk360_console_format_w (_In_z_ _Printf_format_string_ LPCWSTR wstrFormat, ... );
void xdk360_console_draw (void);
HRESULT xdk360_video_font_init(xdk360_video_font_t * font, const char * strFontFileName);
void xdk360_video_font_get_text_width(xdk360_video_font_t * font, const wchar_t * strText, float * pWidth, float * pHeight, int bFirstLineOnly);
void xdk360_video_font_deinit(xdk360_video_font_t * font);
void xdk360_video_font_set_cursor_position(xdk360_video_font_t *font, float fCursorX, float fCursorY );
void xdk360_video_font_begin (xdk360_video_font_t * font);
void xdk360_video_font_end (xdk360_video_font_t * font);
void xdk360_video_font_set_size(float x, float y);
void xdk360_video_font_draw_text(xdk360_video_font_t * font, float fOriginX, float fOriginY, unsigned long dwColor,
const wchar_t * strText, float fMaxPixelWidth );
#endif
+596
View File
@@ -0,0 +1,596 @@
/* SSNES - A Super Nintendo Entertainment System (SNES) Emulator frontend for libsnes.
* Copyright (C) 2010-2012 - Hans-Kristian Arntzen
* Copyright (C) 2011-2012 - Daniel De Matteis
*
* Some code herein may be based on code found in BSNES.
*
* SSNES is free software: you can redistribute it and/or modify it under the terms
* of the GNU General Public License as published by the Free Software Found-
* ation, either version 3 of the License, or (at your option) any later version.
*
* SSNES is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
* without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
* PURPOSE. See the GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License along with SSNES.
* If not, see <http://www.gnu.org/licenses/>.
*/
#include <xtl.h>
#include <xfilecache.h>
#include <stddef.h>
#include <stdint.h>
#include <string>
#include <xbdm.h>
#include "menu.h"
#include "xdk360_input.h"
#include "xdk360_video.h"
#include "../console/console_ext.h"
#include "../console/main_wrap.h"
#include "../conf/config_file.h"
#include "../conf/config_file_macros.h"
#include "../file.h"
#include "../general.h"
#include "shared.h"
#define DEVICE_MEMORY_UNIT0 1
#define DEVICE_MEMORY_UNIT1 2
#define DEVICE_MEMORY_ONBOARD 3
#define DEVICE_CDROM0 4
#define DEVICE_HARDISK0_PART1 5
#define DEVICE_HARDISK0_SYSPART 6
#define DEVICE_USB0 7
#define DEVICE_USB1 8
#define DEVICE_USB2 9
#define DEVICE_TEST 10
#define DEVICE_CACHE 11
typedef struct _STRING {
unsigned short Length;
unsigned short MaximumLength;
char * Buffer;
} STRING;
char DEFAULT_SHADER_FILE[MAX_PATH_LENGTH];
char SYS_CONFIG_FILE[MAX_PATH_LENGTH];
extern "C" int __stdcall ObCreateSymbolicLink( STRING*, STRING*);
int Mounted[20];
int ssnes_main(int argc, char *argv[]);
#undef main
static int DriveMounted(std::string path)
{
WIN32_FIND_DATA findFileData;
memset(&findFileData,0,sizeof(WIN32_FIND_DATA));
std::string searchcmd = path + "\\*.*";
HANDLE hFind = FindFirstFile(searchcmd.c_str(), &findFileData);
if (hFind == INVALID_HANDLE_VALUE)
return 0;
FindClose(hFind);
return 1;
}
static int Mount( int Device, char* MountPoint )
{
char MountConv[260];
sprintf_s( MountConv,"\\??\\%s", MountPoint );
char * SysPath = NULL;
switch( Device )
{
case DEVICE_MEMORY_UNIT0:
SysPath = "\\Device\\Mu0";
break;
case DEVICE_MEMORY_UNIT1:
SysPath = "\\Device\\Mu1";
break;
case DEVICE_MEMORY_ONBOARD:
SysPath = "\\Device\\BuiltInMuSfc";
break;
case DEVICE_CDROM0:
SysPath = "\\Device\\Cdrom0";
break;
case DEVICE_HARDISK0_PART1:
SysPath = "\\Device\\Harddisk0\\Partition1";
break;
case DEVICE_HARDISK0_SYSPART:
SysPath = "\\Device\\Harddisk0\\SystemPartition";
break;
case DEVICE_USB0:
SysPath = "\\Device\\Mass0";
break;
case DEVICE_USB1:
SysPath = "\\Device\\Mass1";
break;
case DEVICE_USB2:
SysPath = "\\Device\\Mass2";
break;
case DEVICE_CACHE:
SysPath = "\\Device\\Harddisk0\\Cache0";
break;
}
STRING sSysPath = { (USHORT)strlen( SysPath ), (USHORT)strlen( SysPath ) + 1, SysPath };
STRING sMountConv = { (USHORT)strlen( MountConv ), (USHORT)strlen( MountConv ) + 1, MountConv };
int res = ObCreateSymbolicLink( &sMountConv, &sSysPath );
if (res != 0)
return res;
return DriveMounted(MountPoint);
}
static void set_default_settings (void)
{
//g_settings
g_settings.rewind_enable = false;
strlcpy(g_settings.video.cg_shader_path, DEFAULT_SHADER_FILE, sizeof(g_settings.video.cg_shader_path));
g_settings.video.vsync = true;
g_settings.video.smooth = true;
g_settings.video.aspect_ratio = -1.0f;
ssnes_default_keybind_lut[SNES_DEVICE_ID_JOYPAD_B] = ssnes_platform_keybind_lut[XDK360_DEVICE_ID_JOYPAD_A];
ssnes_default_keybind_lut[SNES_DEVICE_ID_JOYPAD_Y] = ssnes_platform_keybind_lut[XDK360_DEVICE_ID_JOYPAD_X];
ssnes_default_keybind_lut[SNES_DEVICE_ID_JOYPAD_SELECT] = ssnes_platform_keybind_lut[XDK360_DEVICE_ID_JOYPAD_BACK];
ssnes_default_keybind_lut[SNES_DEVICE_ID_JOYPAD_START] = ssnes_platform_keybind_lut[XDK360_DEVICE_ID_JOYPAD_START];
ssnes_default_keybind_lut[SNES_DEVICE_ID_JOYPAD_UP] = ssnes_platform_keybind_lut[XDK360_DEVICE_ID_JOYPAD_UP];
ssnes_default_keybind_lut[SNES_DEVICE_ID_JOYPAD_DOWN] = ssnes_platform_keybind_lut[XDK360_DEVICE_ID_JOYPAD_DOWN];
ssnes_default_keybind_lut[SNES_DEVICE_ID_JOYPAD_LEFT] = ssnes_platform_keybind_lut[XDK360_DEVICE_ID_JOYPAD_LEFT];
ssnes_default_keybind_lut[SNES_DEVICE_ID_JOYPAD_RIGHT] = ssnes_platform_keybind_lut[XDK360_DEVICE_ID_JOYPAD_RIGHT];
ssnes_default_keybind_lut[SNES_DEVICE_ID_JOYPAD_A] = ssnes_platform_keybind_lut[XDK360_DEVICE_ID_JOYPAD_B];
ssnes_default_keybind_lut[SNES_DEVICE_ID_JOYPAD_X] = ssnes_platform_keybind_lut[XDK360_DEVICE_ID_JOYPAD_Y];
ssnes_default_keybind_lut[SNES_DEVICE_ID_JOYPAD_L] = ssnes_platform_keybind_lut[XDK360_DEVICE_ID_JOYPAD_LB];
ssnes_default_keybind_lut[SNES_DEVICE_ID_JOYPAD_R] = ssnes_platform_keybind_lut[XDK360_DEVICE_ID_JOYPAD_RB];
for(uint32_t x = 0; x < MAX_PLAYERS; x++)
{
for(uint32_t y = 0; y < SSNES_FIRST_META_KEY; y++)
{
g_settings.input.binds[x][y].id = y;
g_settings.input.binds[x][y].joykey = ssnes_default_keybind_lut[y];
}
g_settings.input.dpad_emulation[x] = DPAD_EMULATION_LSTICK;
}
//g_console
g_console.block_config_read = true;
g_console.gamma_correction_enable = false;
g_console.initialize_ssnes_enable = false;
g_console.emulator_initialized = 0;
g_console.mode_switch = MODE_MENU;
g_console.screen_orientation = ORIENTATION_NORMAL;
g_console.throttle_enable = true;
g_console.aspect_ratio_index = 0;
strlcpy(g_console.aspect_ratio_name, "4:3", sizeof(g_console.aspect_ratio_name));
strlcpy(g_console.default_rom_startup_dir, "game:", sizeof(g_console.default_rom_startup_dir));
g_console.custom_viewport_width = 0;
g_console.custom_viewport_height = 0;
g_console.custom_viewport_x = 0;
g_console.custom_viewport_y = 0;
//g_extern
g_extern.state_slot = 0;
g_extern.audio_data.mute = 0;
g_extern.verbose = true;
}
static char **dir_list_new_360(const char *dir, const char *ext)
{
size_t cur_ptr = 0;
size_t cur_size = 32;
char **dir_list = NULL;
WIN32_FIND_DATA ffd;
HANDLE hFind = INVALID_HANDLE_VALUE;
char path_buf[PATH_MAX];
if (strlcpy(path_buf, dir, sizeof(path_buf)) >= sizeof(path_buf))
goto error;
if (strlcat(path_buf, "*", sizeof(path_buf)) >= sizeof(path_buf))
goto error;
if (ext)
{
if (strlcat(path_buf, ext, sizeof(path_buf)) >= sizeof(path_buf))
goto error;
}
hFind = FindFirstFile(path_buf, &ffd);
if (hFind == INVALID_HANDLE_VALUE)
goto error;
dir_list = (char**)calloc(cur_size, sizeof(char*));
if (!dir_list)
goto error;
do
{
// Not a perfect search of course, but hopefully good enough in practice.
if (ffd.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY)
continue;
if (ext && !strstr(ffd.cFileName, ext))
continue;
dir_list[cur_ptr] = (char*)malloc(PATH_MAX);
if (!dir_list[cur_ptr])
goto error;
strlcpy(dir_list[cur_ptr], dir, PATH_MAX);
strlcat(dir_list[cur_ptr], ffd.cFileName, PATH_MAX);
cur_ptr++;
if (cur_ptr + 1 == cur_size) // Need to reserve for NULL.
{
cur_size *= 2;
dir_list = (char**)realloc(dir_list, cur_size * sizeof(char*));
if (!dir_list)
goto error;
// Make sure it's all NULL'd out since we cannot rely on realloc to do this.
memset(dir_list + cur_ptr, 0, (cur_size - cur_ptr) * sizeof(char*));
}
}while (FindNextFile(hFind, &ffd) != 0);
FindClose(hFind);
return dir_list;
error:
SSNES_ERR("Failed to open directory: \"%s\"\n", dir);
if (hFind != INVALID_HANDLE_VALUE)
FindClose(hFind);
dir_list_free(dir_list);
return NULL;
}
static void init_settings (bool load_libsnes_path)
{
char fname_tmp[MAX_PATH_LENGTH];
if(!path_file_exists(SYS_CONFIG_FILE))
{
SSNES_ERR("Config file \"%s\" desn't exist. Creating...\n", "game:\\ssnes.cfg");
FILE * f;
f = fopen(SYS_CONFIG_FILE, "w");
fclose(f);
}
config_file_t * conf = config_file_new(SYS_CONFIG_FILE);
if(load_libsnes_path)
{
CONFIG_GET_STRING(libsnes, "libsnes_path");
if(!strcmp(g_settings.libsnes, ""))
{
//We need to set libsnes to the first entry in the cores
//directory so that it will be saved to the config file
char ** dir_list = dir_list_new_360("game:\\", ".xex");
if (!dir_list)
{
SSNES_ERR("Couldn't read directory.\n");
return;
}
const char * first_xex = dir_list[0];
if(first_xex)
{
fill_pathname_base(fname_tmp, first_xex, sizeof(fname_tmp));
if(strcmp(fname_tmp, "SSNES-Salamander.xex") == 0)
{
SSNES_WARN("First entry is SSNES Salamander itself, increment entry by one and check if it exists.\n");
first_xex = dir_list[1];
fill_pathname_base(fname_tmp, first_xex, sizeof(fname_tmp));
if(!first_xex)
{
//This is very unlikely to happen
SSNES_WARN("There is no second entry - no choice but to set it to SSNES Salamander\n");
first_xex = dir_list[0];
fill_pathname_base(fname_tmp, first_xex, sizeof(fname_tmp));
}
}
SSNES_LOG("Set first .xex entry in dir: [%s] to libsnes path.\n", fname_tmp);
snprintf(g_settings.libsnes, sizeof(g_settings.libsnes), "game:\\%s", fname_tmp);
}
else
{
SSNES_ERR("Failed to set first .xex entry to libsnes path.\n");
}
dir_list_free(dir_list);
}
}
// g_settings
CONFIG_GET_BOOL(rewind_enable, "rewind_enable");
CONFIG_GET_BOOL(video.smooth, "video_smooth");
CONFIG_GET_BOOL(video.vsync, "video_vsync");
CONFIG_GET_FLOAT(video.aspect_ratio, "video_aspect_ratio");
// g_console
CONFIG_GET_BOOL_CONSOLE(throttle_enable, "throttle_enable");
CONFIG_GET_BOOL_CONSOLE(gamma_correction_enable, "gamma_correction_enable");
CONFIG_GET_STRING_CONSOLE(default_rom_startup_dir, "default_rom_startup_dir");
CONFIG_GET_INT_CONSOLE(aspect_ratio_index, "aspect_ratio_index");
CONFIG_GET_INT_CONSOLE(screen_orientation, "screen_orientation");
CONFIG_GET_STRING_CONSOLE(aspect_ratio_name, "aspect_ratio_name");
// g_extern
CONFIG_GET_INT_EXTERN(state_slot, "state_slot");
CONFIG_GET_INT_EXTERN(audio_data.mute, "audio_mute");
}
static void save_settings (void)
{
if(!path_file_exists(SYS_CONFIG_FILE))
{
FILE * f;
f = fopen(SYS_CONFIG_FILE, "w");
fclose(f);
}
config_file_t * conf = config_file_new(SYS_CONFIG_FILE);
if(conf == NULL)
conf = config_file_new(NULL);
// g_settings
config_set_string(conf, "libsnes_path", g_settings.libsnes);
config_set_bool(conf, "rewind_enable", g_settings.rewind_enable);
config_set_bool(conf, "video_smooth", g_settings.video.smooth);
config_set_bool(conf, "video_vsync", g_settings.video.vsync);
// g_console
config_set_string(conf, "default_rom_startup_dir", g_console.default_rom_startup_dir);
config_set_bool(conf, "gamma_correction_enable", g_console.gamma_correction_enable);
config_set_bool(conf, "throttle_enable", g_console.throttle_enable);
config_set_int(conf, "aspect_ratio_index", g_console.aspect_ratio_index);
config_set_int(conf, "custom_viewport_width", g_console.custom_viewport_width);
config_set_int(conf, "custom_viewport_height", g_console.custom_viewport_height);
config_set_int(conf, "custom_viewport_x", g_console.custom_viewport_x);
config_set_int(conf, "custom_viewport_y", g_console.custom_viewport_y);
config_set_int(conf, "screen_orientation", g_console.screen_orientation);
config_set_string(conf, "aspect_ratio_name", g_console.aspect_ratio_name);
// g_extern
config_set_int(conf, "state_slot", g_extern.state_slot);
config_set_int(conf, "audio_mute", g_extern.audio_data.mute);
if (!config_file_write(conf, SYS_CONFIG_FILE))
SSNES_ERR("Failed to write config file to \"%s\". Check permissions.\n", SYS_CONFIG_FILE);
free(conf);
}
static void get_environment_settings (void)
{
DWORD ret;
//for devkits only, we will need to mount all partitions for retail
//in a different way
//DmMapDevkitDrive();
memset(&Mounted, 0, 20);
Mounted[DEVICE_USB0] = Mount(DEVICE_USB0,"Usb0:");
Mounted[DEVICE_USB1] = Mount(DEVICE_USB1,"Usb1:");
Mounted[DEVICE_USB2] = Mount(DEVICE_USB2,"Usb2:");
Mounted[DEVICE_HARDISK0_PART1] = Mount(DEVICE_HARDISK0_PART1,"Hdd1:");
Mounted[DEVICE_HARDISK0_SYSPART] = Mount(DEVICE_HARDISK0_SYSPART,"HddX:");
Mounted[DEVICE_MEMORY_UNIT0] = Mount(DEVICE_MEMORY_UNIT0,"Memunit0:");
Mounted[DEVICE_MEMORY_UNIT1] = Mount(DEVICE_MEMORY_UNIT1,"Memunit1:");
Mounted[DEVICE_MEMORY_ONBOARD] = Mount(DEVICE_MEMORY_ONBOARD,"OnBoardMU:");
Mounted[DEVICE_CDROM0] = Mount(DEVICE_CDROM0,"Dvd:");
ret = XSetFileCacheSize(0x100000);
if(ret != TRUE)
{
SSNES_ERR("Couldn't change number of bytes reserved for file system cache.\n");
}
ret = XFileCacheInit(XFILECACHE_CLEAR_ALL, 0x100000, XFILECACHE_DEFAULT_THREAD, 0, 1);
if(ret != ERROR_SUCCESS)
{
SSNES_ERR("File cache could not be initialized.\n");
}
XFlushUtilityDrive();
//unsigned long result = XMountUtilityDriveEx(XMOUNTUTILITYDRIVE_FORMAT0,8192, 0);
//if(result != ERROR_SUCCESS)
//{
// SSNES_ERR("Couldn't mount/format utility drive.\n");
//}
// detect install environment
unsigned long license_mask;
if (XContentGetLicenseMask(&license_mask, NULL) != ERROR_SUCCESS)
{
printf("SSNES was launched as a standalone DVD, or using DVD emulation, or from the development area of the HDD.\n");
}
else
{
XContentQueryVolumeDeviceType("GAME",&g_console.volume_device_type, NULL);
switch(g_console.volume_device_type)
{
case XCONTENTDEVICETYPE_HDD:
printf("SSNES was launched from a content package on HDD.\n");
break;
case XCONTENTDEVICETYPE_MU:
printf("SSNES was launched from a content package on USB or Memory Unit.\n");
break;
case XCONTENTDEVICETYPE_ODD:
printf("SSNES was launched from a content package on Optical Disc Drive.\n");
break;
default:
printf("SSNES was launched from a content package on an unknown device type.\n");
break;
}
}
strlcpy(DEFAULT_SHADER_FILE, "game:\\media\\shaders\\stock.cg", sizeof(DEFAULT_SHADER_FILE));
strlcpy(SYS_CONFIG_FILE, "game:\\ssnes.cfg", sizeof(SYS_CONFIG_FILE));
}
static bool manage_libsnes_core(void)
{
g_extern.verbose = true;
bool return_code;
bool set_libsnes_path = false;
char tmp_path[1024], tmp_path2[1024], tmp_pathnewfile[1024];
snprintf(tmp_path, sizeof(tmp_path), "game:\\CORE.xex");
SSNES_LOG("Assumed path of CORE.xex: [%s]\n", tmp_path);
if(path_file_exists(tmp_path))
{
//if CORE.xex exists, this indicates we have just installed
//a new libsnes port and that we need to change it to a more
//sane name.
int ret;
ssnes_console_name_from_id(tmp_path2, sizeof(tmp_path2));
strlcat(tmp_path2, ".xex", sizeof(tmp_path2));
snprintf(tmp_pathnewfile, sizeof(tmp_pathnewfile), "game:\\%s", tmp_path2);
if(path_file_exists(tmp_pathnewfile))
{
SSNES_LOG("Upgrading emulator core...\n");
//if libsnes core already exists, then that means we are
//upgrading the libsnes core - so delete pre-existing
//file first
ret = DeleteFile(tmp_pathnewfile);
if(ret != 0)
{
SSNES_LOG("Succeeded in removing pre-existing libsnes core: [%s].\n", tmp_pathnewfile);
}
else
{
SSNES_LOG("Failed to remove pre-existing libsnes core: [%s].\n", tmp_pathnewfile);
}
}
//now attempt the renaming
ret = MoveFileExA(tmp_path, tmp_pathnewfile, NULL);
if(ret == 0)
{
SSNES_ERR("Failed to rename CORE.xex.\n");
}
else
{
SSNES_LOG("Libsnes core [%s] renamed to: [%s].\n", tmp_path, tmp_pathnewfile);
set_libsnes_path = true;
}
}
else
{
SSNES_LOG("CORE.xex was not found, libsnes core path will be loaded from config file.\n");
}
if(set_libsnes_path)
{
//CORE.xex has been renamed, libsnes path will now be set to the recently
//renamed new libsnes core
strlcpy(g_settings.libsnes, tmp_pathnewfile, sizeof(g_settings.libsnes));
return_code = 0;
}
else
{
//There was no CORE.xex present, or the CORE.xex file was not renamed.
//The libsnes core path will still be loaded from the config file
return_code = 1;
}
g_extern.verbose = false;
return return_code;
}
int main(int argc, char *argv[])
{
get_environment_settings();
ssnes_main_clear_state();
config_set_defaults();
bool load_libsnes_path = manage_libsnes_core();
set_default_settings();
init_settings(load_libsnes_path);
init_libsnes_sym();
xdk360_video_init();
xdk360_input_init();
ssnes_input_set_default_keybind_names_for_emulator();
menu_init();
begin_loop:
if(g_console.mode_switch == MODE_EMULATION)
{
bool repeat = false;
input_xdk360.poll(NULL);
do{
repeat = ssnes_main_iterate();
}while(repeat && !g_console.frame_advance_enable);
}
else if(g_console.mode_switch == MODE_MENU)
{
menu_loop();
if(g_console.initialize_ssnes_enable)
{
if(g_console.emulator_initialized)
ssnes_main_deinit();
struct ssnes_main_wrap args = {0};
args.verbose = g_extern.verbose;
args.config_path = SYS_CONFIG_FILE;
args.rom_path = g_console.rom_path;
int init_ret = ssnes_main_init_wrap(&args);
g_console.emulator_initialized = 1;
g_console.initialize_ssnes_enable = 0;
}
}
else
goto begin_shutdown;
goto begin_loop;
begin_shutdown:
if(path_file_exists(SYS_CONFIG_FILE))
save_settings();
xdk360_video_deinit();
if(g_console.return_to_launcher)
{
SSNES_LOG("Attempt to load XEX: [%s].\n", g_console.launch_app_on_exit);
XLaunchNewImage(g_console.launch_app_on_exit, NULL);
}
return 0;
}
Binary file not shown.
+18
View File
@@ -0,0 +1,18 @@
<?xml version="1.0" encoding="utf-8" ?>
<RDF Version="XPR2">
<Texture
Name = "FontTexture"
Source = "Arial_12.tga"
Format = "D3DFMT_LIN_A4R4G4B4"
Levels = "1"
/>
<UserData
Name = "FontData"
DataFile = "Arial_12.abc"
/>
</RDF>
Binary file not shown.

After

Width:  |  Height:  |  Size: 256 KiB

BIN
View File
Binary file not shown.

After

Width:  |  Height:  |  Size: 2.3 KiB

BIN
View File
Binary file not shown.

After

Width:  |  Height:  |  Size: 2.3 KiB

+40
View File
@@ -0,0 +1,40 @@
/*
VERTEX_SHADER
*/
void main_vertex
(
float2 position : POSITION,
float2 texCoord : TEXCOORD0,
uniform float4x4 modelViewProj : register(c0),
out float4 oPosition : POSITION,
out float2 otexCoord : TEXCOORD
)
{
oPosition = mul(modelViewProj, float4(position, 0.0, 1.0));
otexCoord = texCoord;
}
/*
FRAGMENT SHADER
*/
struct output
{
float4 color : COLOR;
};
struct input
{
float2 video_size;
float2 texture_size;
float2 output_size;
};
output main_fragment(float2 texCoord : TEXCOORD0, uniform sampler2D decal : register(s0), uniform input IN)
{
output OUT;
OUT.color = tex2D(decal, texCoord);
return OUT;
}
Binary file not shown.
+159
View File
@@ -0,0 +1,159 @@
<XuiCanvas version="000c">
<Properties>
<Width>1280.000000</Width>
<Height>720.000000</Height>
</Properties>
<XuiScene>
<Properties>
<Id>XuiSceneFileBrowser</Id>
<Width>575.888062</Width>
<Height>336.017609</Height>
<Position>353.995880,209.035965,0.000000</Position>
<ClassOverride>SSNESFileBrowser</ClassOverride>
</Properties>
<XuiText>
<Properties>
<Id>XuiTxtTitle</Id>
<Width>111.840027</Width>
<Height>40.000000</Height>
<Position>28.893612,12.519989,0.000000</Position>
<Text>Filebrowser</Text>
<TextColor>0xff0f0f0f</TextColor>
<DropShadowColor>0x800f0f0f</DropShadowColor>
<Font>Arial Unicode MS</Font>
<TextStyle>21</TextStyle>
</Properties>
</XuiText>
<XuiCommonList>
<Properties>
<Id>XuiRomList</Id>
<Width>536.582458</Width>
<Height>170.800018</Height>
<Position>22.799980,81.600006,0.000000</Position>
<NavLeft>XuiBackButton1</NavLeft>
<NavRight>XuiBackButton1</NavRight>
<NavUp>XuiBtnGameDir</NavUp>
<NavDown>XuiBtnGameDir</NavDown>
</Properties>
<XuiListItem>
<Properties>
<Id>control_ListItem</Id>
<Width>226.000000</Width>
<Height>45.000000</Height>
<Position>7.000000,22.000000,0.000000</Position>
<Anchor>5</Anchor>
<Show>false</Show>
<Visual>XuiButton</Visual>
<InterItemSpacing>0.000000,10.000000,0.000000</InterItemSpacing>
</Properties>
</XuiListItem>
<XuiListItem>
<Properties>
<Id>control_ListItem</Id>
<Width>226.000000</Width>
<Height>45.000000</Height>
<Position>7.000000,22.000000,0.000000</Position>
<Anchor>5</Anchor>
<Show>false</Show>
<Visual>XuiButton</Visual>
<InterItemSpacing>0.000000,10.000000,0.000000</InterItemSpacing>
</Properties>
</XuiListItem>
<XuiListItem>
<Properties>
<Id>control_ListItem</Id>
<Width>226.000000</Width>
<Height>45.000000</Height>
<Position>7.000000,22.000000,0.000000</Position>
<Anchor>5</Anchor>
<Show>false</Show>
<Visual>XuiButton</Visual>
<InterItemSpacing>0.000000,10.000000,0.000000</InterItemSpacing>
</Properties>
</XuiListItem>
<XuiListItem>
<Properties>
<Id>control_ListItem</Id>
<Width>226.000000</Width>
<Height>45.000000</Height>
<Position>7.000000,22.000000,0.000000</Position>
<Anchor>5</Anchor>
<Show>false</Show>
<Visual>XuiButton</Visual>
<InterItemSpacing>0.000000,10.000000,0.000000</InterItemSpacing>
</Properties>
</XuiListItem>
<XuiListItem>
<Properties>
<Id>control_ListItem</Id>
<Width>226.000000</Width>
<Height>45.000000</Height>
<Position>7.000000,22.000000,0.000000</Position>
<Anchor>5</Anchor>
<Show>false</Show>
<Visual>XuiButton</Visual>
<InterItemSpacing>0.000000,10.000000,0.000000</InterItemSpacing>
</Properties>
</XuiListItem>
</XuiCommonList>
<XuiBackButton>
<Properties>
<Id>XuiBackButton1</Id>
<Width>204.599976</Width>
<Height>36.000000</Height>
<Position>353.115234,281.396820,0.000000</Position>
<NavLeft>XuiBtnCacheDir</NavLeft>
<NavRight>XuiBtnGameDir</NavRight>
<NavUp>XuiRomList</NavUp>
<NavDown>XuiRomList</NavDown>
<Text>Go back to menu</Text>
<PressKey>22593</PressKey>
</Properties>
</XuiBackButton>
<XuiText>
<Properties>
<Id>XuiTxtRomPath</Id>
<Width>166.559998</Width>
<Height>28.480011</Height>
<Position>96.000000,42.480011,0.000000</Position>
<TextColor>0xff0f0f0f</TextColor>
<DropShadowColor>0x800f0f0f</DropShadowColor>
</Properties>
</XuiText>
<XuiLabel>
<Properties>
<Id>XuiLblPath</Id>
<Width>72.880005</Width>
<Height>28.000000</Height>
<Position>26.000000,43.000000,0.000000</Position>
<Text>PATH:</Text>
</Properties>
</XuiLabel>
<XuiButton>
<Properties>
<Id>XuiBtnGameDir</Id>
<Width>115.640007</Width>
<Height>38.000000</Height>
<Position>30.000000,277.000000,0.000000</Position>
<NavLeft>XuiBackButton1</NavLeft>
<NavRight>XuiBtnCacheDir</NavRight>
<NavUp>XuiRomList</NavUp>
<NavDown>XuiRomList</NavDown>
<Text>game:</Text>
</Properties>
</XuiButton>
<XuiButton>
<Properties>
<Id>XuiBtnCacheDir</Id>
<Width>119.960014</Width>
<Height>38.000000</Height>
<Position>160.000000,277.000000,0.000000</Position>
<NavLeft>XuiBtnGameDir</NavLeft>
<NavRight>XuiBackButton1</NavRight>
<NavUp>XuiRomList</NavUp>
<NavDown>XuiRomList</NavDown>
<Text>cache:</Text>
</Properties>
</XuiButton>
</XuiScene>
</XuiCanvas>
+145
View File
@@ -0,0 +1,145 @@
<XuiCanvas version="000c">
<Properties>
<Width>1280.000000</Width>
<Height>720.000000</Height>
</Properties>
<XuiScene>
<Properties>
<Id>XuiSceneCoreFileBrowser</Id>
<Width>575.888062</Width>
<Height>336.017609</Height>
<Position>353.995880,209.035965,0.000000</Position>
<ClassOverride>SSNESCoreBrowser</ClassOverride>
</Properties>
<XuiText>
<Properties>
<Id>XuiTxtTitle</Id>
<Width>326.640015</Width>
<Height>40.000000</Height>
<Position>28.893612,12.519989,0.000000</Position>
<Text>Filebrowser - Select a libsnes core</Text>
<TextColor>0xff0f0f0f</TextColor>
<DropShadowColor>0x800f0f0f</DropShadowColor>
<Font>Arial Unicode MS</Font>
<TextStyle>21</TextStyle>
</Properties>
</XuiText>
<XuiCommonList>
<Properties>
<Id>XuiRomList</Id>
<Width>536.582458</Width>
<Height>170.800018</Height>
<Position>22.799980,81.600006,0.000000</Position>
<NavLeft>XuiBackButton1</NavLeft>
<NavRight>XuiBackButton1</NavRight>
<NavUp>XuiBackButton1</NavUp>
<NavDown>XuiBackButton1</NavDown>
</Properties>
<XuiListItem>
<Properties>
<Id>control_ListItem</Id>
<Width>226.000000</Width>
<Height>45.000000</Height>
<Position>7.000000,22.000000,0.000000</Position>
<Anchor>5</Anchor>
<Show>false</Show>
<Visual>XuiButton</Visual>
<InterItemSpacing>0.000000,10.000000,0.000000</InterItemSpacing>
</Properties>
</XuiListItem>
<XuiListItem>
<Properties>
<Id>control_ListItem</Id>
<Width>226.000000</Width>
<Height>45.000000</Height>
<Position>7.000000,22.000000,0.000000</Position>
<Anchor>5</Anchor>
<Show>false</Show>
<Visual>XuiButton</Visual>
<InterItemSpacing>0.000000,10.000000,0.000000</InterItemSpacing>
</Properties>
</XuiListItem>
<XuiListItem>
<Properties>
<Id>control_ListItem</Id>
<Width>226.000000</Width>
<Height>45.000000</Height>
<Position>7.000000,22.000000,0.000000</Position>
<Anchor>5</Anchor>
<Show>false</Show>
<Visual>XuiButton</Visual>
<InterItemSpacing>0.000000,10.000000,0.000000</InterItemSpacing>
</Properties>
</XuiListItem>
<XuiListItem>
<Properties>
<Id>control_ListItem</Id>
<Width>226.000000</Width>
<Height>45.000000</Height>
<Position>7.000000,22.000000,0.000000</Position>
<Anchor>5</Anchor>
<Show>false</Show>
<Visual>XuiButton</Visual>
<InterItemSpacing>0.000000,10.000000,0.000000</InterItemSpacing>
</Properties>
</XuiListItem>
<XuiListItem>
<Properties>
<Id>control_ListItem</Id>
<Width>226.000000</Width>
<Height>45.000000</Height>
<Position>7.000000,22.000000,0.000000</Position>
<Anchor>5</Anchor>
<Show>false</Show>
<Visual>XuiButton</Visual>
<InterItemSpacing>0.000000,10.000000,0.000000</InterItemSpacing>
</Properties>
</XuiListItem>
<XuiListItem>
<Properties>
<Id>control_ListItem</Id>
<Width>226.000000</Width>
<Height>45.000000</Height>
<Position>7.000000,22.000000,0.000000</Position>
<Anchor>5</Anchor>
<Show>false</Show>
<Visual>XuiButton</Visual>
<InterItemSpacing>0.000000,10.000000,0.000000</InterItemSpacing>
</Properties>
</XuiListItem>
</XuiCommonList>
<XuiBackButton>
<Properties>
<Id>XuiBackButton1</Id>
<Width>219.000000</Width>
<Height>36.000000</Height>
<Position>338.715210,281.396820,0.000000</Position>
<NavLeft>XuiRomList</NavLeft>
<NavRight>XuiRomList</NavRight>
<NavUp>XuiRomList</NavUp>
<NavDown>XuiRomList</NavDown>
<Text>Go back to menu</Text>
<PressKey>22593</PressKey>
</Properties>
</XuiBackButton>
<XuiText>
<Properties>
<Id>XuiTxtRomPath</Id>
<Width>166.559998</Width>
<Height>28.480011</Height>
<Position>96.000000,42.480011,0.000000</Position>
<TextColor>0xff0f0f0f</TextColor>
<DropShadowColor>0x800f0f0f</DropShadowColor>
</Properties>
</XuiText>
<XuiLabel>
<Properties>
<Id>XuiLblPath</Id>
<Width>72.880005</Width>
<Height>28.000000</Height>
<Position>26.000000,43.000000,0.000000</Position>
<Text>PATH:</Text>
</Properties>
</XuiLabel>
</XuiScene>
</XuiCanvas>
+116
View File
@@ -0,0 +1,116 @@
<XuiCanvas version="000c">
<Properties>
<Width>1280.000000</Width>
<Height>720.000000</Height>
</Properties>
<XuiScene>
<Properties>
<Id>XuiScene1</Id>
<Width>584.528076</Width>
<Height>363.320007</Height>
<Position>347.429474,184.843964,0.000000</Position>
<ClassOverride>SSNESMain</ClassOverride>
</Properties>
<XuiButton>
<Properties>
<Id>XuiBtnRomBrowser</Id>
<Width>488.312012</Width>
<Height>30.799988</Height>
<Position>38.127724,64.215515,0.000000</Position>
<Pivot>245.362122,102.247192,0.000000</Pivot>
<NavUp>XuiBtnQuit</NavUp>
<NavDown>XuiBtnQuickMenu</NavDown>
<Text>ROM Browser</Text>
</Properties>
</XuiButton>
<XuiText>
<Properties>
<Id>XuiTxtTitle</Id>
<Width>247.200012</Width>
<Height>40.000000</Height>
<Position>43.581604,21.159988,0.000000</Position>
<Text>SSNES 360</Text>
<TextColor>0xff0f0f0f</TextColor>
<DropShadowColor>0x800f0f0f</DropShadowColor>
<Font>Arial Unicode MS</Font>
<TextStyle>21</TextStyle>
</Properties>
</XuiText>
<XuiButton>
<Properties>
<Id>XuiBtnSettings</Id>
<Width>488.312012</Width>
<Height>30.799988</Height>
<Position>38.127960,196.615982,0.000000</Position>
<NavUp>XuiBtnControls</NavUp>
<NavDown>XuiBtnLibsnesCore</NavDown>
<Text>Settings</Text>
</Properties>
</XuiButton>
<XuiButton>
<Properties>
<Id>XuiBtnQuit</Id>
<Width>488.312012</Width>
<Height>30.799988</Height>
<Position>38.327736,287.007996,0.000000</Position>
<Pivot>245.162109,-84.153275,0.000000</Pivot>
<NavUp>XuiBtnLibsnesCore</NavUp>
<NavDown>XuiBtnRomBrowser</NavDown>
<Text>Quit</Text>
</Properties>
</XuiButton>
<XuiLabel>
<Properties>
<Id>XuiLblCore</Id>
<Width>124.000000</Width>
<Height>28.000000</Height>
<Position>12.544006,324.792023,0.000000</Position>
<Text>Libsnes core:</Text>
</Properties>
</XuiLabel>
<XuiText>
<Properties>
<Id>XuiTxtCoreText</Id>
<Width>224.399963</Width>
<Height>34.000000</Height>
<Position>134.944031,324.391998,0.000000</Position>
<TextColor>0xff0f0f0f</TextColor>
<DropShadowColor>0x800f0f0f</DropShadowColor>
<Font>Arial Unicode MS</Font>
</Properties>
</XuiText>
<XuiButton>
<Properties>
<Id>XuiBtnQuickMenu</Id>
<Width>488.312012</Width>
<Height>30.799988</Height>
<Position>38.130001,106.655991,0.000000</Position>
<NavUp>XuiBtnRomBrowser</NavUp>
<NavDown>XuiBtnControls</NavDown>
<Text>Quick Menu</Text>
</Properties>
</XuiButton>
<XuiButton>
<Properties>
<Id>XuiBtnControls</Id>
<Width>488.312012</Width>
<Height>30.799988</Height>
<Position>38.130001,151.655991,0.000000</Position>
<NavUp>XuiBtnQuickMenu</NavUp>
<NavDown>XuiBtnSettings</NavDown>
<Text>Controls</Text>
</Properties>
</XuiButton>
<XuiButton>
<Properties>
<Id>XuiBtnLibsnesCore</Id>
<Width>488.312012</Width>
<Height>30.799988</Height>
<Position>38.127960,241.615982,0.000000</Position>
<NavUp>XuiBtnSettings</NavUp>
<NavDown>XuiBtnQuit</NavDown>
<Text>Change libsnes core</Text>
</Properties>
</XuiButton>
</XuiScene>
</XuiCanvas>
+79
View File
@@ -0,0 +1,79 @@
<XuiCanvas version="000c">
<Properties>
<Width>1280.000000</Width>
<Height>720.000000</Height>
</Properties>
<XuiScene>
<Properties>
<Id>XuiScene1</Id>
<Width>584.528076</Width>
<Height>363.320007</Height>
<Position>347.429474,184.843964,0.000000</Position>
<ClassOverride>SSNESQuickMenu</ClassOverride>
</Properties>
<XuiText>
<Properties>
<Id>XuiTxtTitle</Id>
<Width>121.056023</Width>
<Height>40.000000</Height>
<Position>43.581604,21.159988,0.000000</Position>
<Text>Quick Menu</Text>
<TextColor>0xff0f0f0f</TextColor>
<DropShadowColor>0x800f0f0f</DropShadowColor>
<Font>Arial Unicode MS</Font>
<TextStyle>21</TextStyle>
</Properties>
</XuiText>
<XuiBackButton>
<Properties>
<Id>XuiBackButton</Id>
<Width>208.632019</Width>
<Height>36.000000</Height>
<Position>356.670013,309.000000,0.000000</Position>
<NavLeft>XuiQuickMenuList</NavLeft>
<NavRight>XuiQuickMenuList</NavRight>
<NavUp>XuiQuickMenuList</NavUp>
<NavDown>XuiQuickMenuList</NavDown>
<Text>Go back to menu</Text>
<PressKey>22593</PressKey>
</Properties>
</XuiBackButton>
<XuiCommonList>
<Properties>
<Id>XuiQuickMenuList</Id>
<Width>492.000000</Width>
<Height>232.720001</Height>
<Position>44.880005,64.959991,0.000000</Position>
<NavLeft>XuiBackButton</NavLeft>
<NavRight>XuiBackButton</NavRight>
<NavUp>XuiBackButton</NavUp>
<NavDown>XuiBackButton</NavDown>
<ItemsText>Load State
Save State
Hardware filtering:
Aspect Ratio:
Overscan:
Orientation:
Resize Mode
Frame Advance
Screenshot Mode
Reset
Return to Game
Return to Dashboard
</ItemsText>
</Properties>
<XuiListItem>
<Properties>
<Id>control_ListItem</Id>
<Width>226.000000</Width>
<Height>45.000000</Height>
<Position>7.000000,22.000000,0.000000</Position>
<Anchor>5</Anchor>
<Show>false</Show>
<Visual>XuiButton</Visual>
<InterItemSpacing>0.000000,10.000000,0.000000</InterItemSpacing>
</Properties>
</XuiListItem>
</XuiCommonList>
</XuiScene>
</XuiCanvas>
File diff suppressed because it is too large. Load diff
+94
View File
@@ -0,0 +1,94 @@
<XuiCanvas version="000c">
<Properties>
<Width>1280.000000</Width>
<Height>720.000000</Height>
</Properties>
<XuiScene>
<Properties>
<Id>XuiScene1</Id>
<Width>584.528076</Width>
<Height>363.320007</Height>
<Position>344.000031,184.000015,0.000000</Position>
<ClassOverride>SSNESSettings</ClassOverride>
</Properties>
<XuiText>
<Properties>
<Id>XuiTxtTitle</Id>
<Width>121.056023</Width>
<Height>40.000000</Height>
<Position>43.581604,21.159988,0.000000</Position>
<Text>Settings</Text>
<TextColor>0xff0f0f0f</TextColor>
<DropShadowColor>0x800f0f0f</DropShadowColor>
<Font>Arial Unicode MS</Font>
<TextStyle>21</TextStyle>
</Properties>
</XuiText>
<XuiBackButton>
<Properties>
<Id>XuiBackButton</Id>
<Width>208.632019</Width>
<Height>36.000000</Height>
<Position>356.670013,309.000000,0.000000</Position>
<NavLeft>XuiSettingsList</NavLeft>
<NavRight>XuiSettingsList</NavRight>
<NavUp>XuiSettingsList</NavUp>
<NavDown>XuiSettingsList</NavDown>
<Text>Go back to menu</Text>
<PressKey>22593</PressKey>
</Properties>
</XuiBackButton>
<XuiCommonList>
<Properties>
<Id>XuiSettingsList</Id>
<Width>492.000000</Width>
<Height>232.720001</Height>
<Position>44.880005,64.959991,0.000000</Position>
<NavLeft>XuiBackButton</NavLeft>
<NavRight>XuiBackButton</NavRight>
<NavUp>XuiBackButton</NavUp>
<NavDown>XuiBackButton</NavDown>
<ItemsText>Rewind:
Gamma Correction:
Hardware filtering:
</ItemsText>
</Properties>
<XuiListItem>
<Properties>
<Id>control_ListItem</Id>
<Width>226.000000</Width>
<Height>45.000000</Height>
<Position>7.000000,22.000000,0.000000</Position>
<Anchor>5</Anchor>
<Show>false</Show>
<Visual>XuiButton</Visual>
<InterItemSpacing>0.000000,10.000000,0.000000</InterItemSpacing>
</Properties>
</XuiListItem>
<XuiListItem>
<Properties>
<Id>control_ListItem</Id>
<Width>226.000000</Width>
<Height>45.000000</Height>
<Position>7.000000,22.000000,0.000000</Position>
<Anchor>5</Anchor>
<Show>false</Show>
<Visual>XuiButton</Visual>
<InterItemSpacing>0.000000,10.000000,0.000000</InterItemSpacing>
</Properties>
</XuiListItem>
<XuiListItem>
<Properties>
<Id>control_ListItem</Id>
<Width>226.000000</Width>
<Height>45.000000</Height>
<Position>7.000000,22.000000,0.000000</Position>
<Anchor>5</Anchor>
<Show>false</Show>
<Visual>XuiButton</Visual>
<InterItemSpacing>0.000000,10.000000,0.000000</InterItemSpacing>
</Properties>
</XuiListItem>
</XuiCommonList>
</XuiScene>
</XuiCanvas>
+558
View File
@@ -0,0 +1,558 @@
/* SSNES - A Super Nintendo Entertainment System (SNES) Emulator frontend for libsnes.
* Copyright (C) 2010-2012 - Hans-Kristian Arntzen
* Copyright (C) 2011-2012 - Daniel De Matteis
*
* Some code herein may be based on code found in BSNES.
*
* SSNES is free software: you can redistribute it and/or modify it under the terms
* of the GNU General Public License as published by the Free Software Found-
* ation, either version 3 of the License, or (at your option) any later version.
*
* SSNES is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
* without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
* PURPOSE. See the GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License along with SSNES.
* If not, see <http://www.gnu.org/licenses/>.
*/
#include <stdint.h>
#include <crtdefs.h>
#include <tchar.h>
#include <xtl.h>
#include "../console/fileio/file_browser.h"
#include "../console/console_ext.h"
#include "xdk360_video.h"
#include "menu.h"
#include "shared.h"
#include "../general.h"
CSSNES app;
filebrowser_t browser;
filebrowser_t tmp_browser;
char strbuffer[1024];
static void return_to_game (void)
{
g_console.frame_advance_enable = false;
g_console.menu_enable = false;
g_console.mode_switch = MODE_EMULATION;
}
static void return_to_dashboard (void)
{
g_console.menu_enable = false;
g_console.mode_switch = MODE_EXIT;
g_console.initialize_ssnes_enable = false;
}
/* Register custom classes */
HRESULT CSSNES::RegisterXuiClasses (void)
{
CSSNESMain::Register();
CSSNESFileBrowser::Register();
CSSNESCoreBrowser::Register();
CSSNESQuickMenu::Register();
CSSNESSettings::Register();
return S_OK;
}
/* Unregister custom classes */
HRESULT CSSNES::UnregisterXuiClasses (void)
{
CSSNESMain::Unregister();
CSSNESCoreBrowser::Unregister();
CSSNESFileBrowser::Unregister();
CSSNESQuickMenu::Register();
CSSNESSettings::Unregister();
return S_OK;
}
static void filebrowser_fetch_directory_entries(const char *path, filebrowser_t * browser, CXuiList * romlist,
CXuiTextElement * rompath_title)
{
filebrowser_push_directory(browser, path, true);
unsigned long dwNum_rompath = MultiByteToWideChar(CP_ACP, 0, path, -1, NULL, 0);
wchar_t * rompath_name = new wchar_t[dwNum_rompath];
MultiByteToWideChar(CP_ACP, 0, path, -1, rompath_name, dwNum_rompath);
rompath_title->SetText(rompath_name);
romlist->DeleteItems(0, romlist->GetItemCount());
romlist->InsertItems(0, browser->file_count);
for(unsigned i = 0; i < browser->file_count; i++)
{
unsigned long dwNum = MultiByteToWideChar(CP_ACP, 0, browser->cur[i].d_name, -1, NULL, 0);
wchar_t * entry_name = new wchar_t[dwNum];
MultiByteToWideChar(CP_ACP, 0, browser->cur[i].d_name, -1, entry_name, dwNum);
romlist->SetText(i, entry_name);
delete []entry_name;
}
}
HRESULT CSSNESFileBrowser::OnInit(XUIMessageInit * pInitData, BOOL& bHandled)
{
GetChildById(L"XuiRomList", &m_romlist);
GetChildById(L"XuiBackButton1", &m_back);
GetChildById(L"XuiTxtRomPath", &m_rompathtitle);
GetChildById(L"XuiBtnGameDir", &m_dir_game);
GetChildById(L"XuiBtnCacheDir", &m_dir_cache);
filebrowser_fetch_directory_entries(g_console.default_rom_startup_dir, &browser, &m_romlist, &m_rompathtitle);
return S_OK;
}
HRESULT CSSNESCoreBrowser::OnInit(XUIMessageInit * pInitData, BOOL& bHandled)
{
GetChildById(L"XuiRomList", &m_romlist);
GetChildById(L"XuiBackButton1", &m_back);
GetChildById(L"XuiTxtRomPath", &m_rompathtitle);
filebrowser_new(&tmp_browser, "game:", "xex|XEX");
filebrowser_fetch_directory_entries("game:", &tmp_browser, &m_romlist, &m_rompathtitle);
return S_OK;
}
static const wchar_t * set_filter_element(int index)
{
switch(index)
{
case FALSE:
return L"Hardware filtering: Point filtering";
case TRUE:
return L"Hardware filtering: Linear interpolation";
}
return L"";
}
HRESULT CSSNESSettings::OnInit(XUIMessageInit * pInitData, BOOL& bHandled)
{
GetChildById(L"XuiSettingsList", &m_settingslist);
GetChildById(L"XuiBackButton", &m_back);
m_settingslist.SetText(SETTING_EMU_REWIND_ENABLED, g_settings.rewind_enable ? L"Rewind: ON" : L"Rewind: OFF");
m_settingslist.SetText(SETTING_GAMMA_CORRECTION_ENABLED, g_console.gamma_correction_enable ? L"Gamma correction: ON" : L"Gamma correction: OFF");
m_settingslist.SetText(SETTING_HARDWARE_FILTERING, set_filter_element(g_settings.video.smooth));
return S_OK;
}
HRESULT CSSNESQuickMenu::OnInit(XUIMessageInit * pInitData, BOOL& bHandled)
{
GetChildById(L"XuiQuickMenuList", &m_quickmenulist);
GetChildById(L"XuiBackButton", &m_back);
m_quickmenulist.SetText(MENU_ITEM_HARDWARE_FILTERING, set_filter_element(g_settings.video.smooth));
switch(g_console.screen_orientation)
{
case ORIENTATION_NORMAL:
m_quickmenulist.SetText(MENU_ITEM_ORIENTATION, L"Orientation: Normal");
break;
case ORIENTATION_VERTICAL:
m_quickmenulist.SetText(MENU_ITEM_ORIENTATION, L"Orientation: Vertical");
break;
case ORIENTATION_FLIPPED:
m_quickmenulist.SetText(MENU_ITEM_ORIENTATION, L"Orientation: Flipped");
break;
case ORIENTATION_FLIPPED_ROTATED:
m_quickmenulist.SetText(MENU_ITEM_ORIENTATION, L"Orientation: Flipped Rotated");
break;
}
char aspectratio_label[32];
sprintf(aspectratio_label, "Aspect Ratio: %s", g_console.aspect_ratio_name);
unsigned long dwNum = MultiByteToWideChar(CP_ACP, 0, aspectratio_label, -1, NULL, 0);
wchar_t * aspectratio_label_w = new wchar_t[dwNum];
MultiByteToWideChar(CP_ACP, 0, aspectratio_label, -1, aspectratio_label_w, dwNum);
m_quickmenulist.SetText(MENU_ITEM_KEEP_ASPECT_RATIO, aspectratio_label_w);
delete[] aspectratio_label_w;
return S_OK;
}
HRESULT CSSNESQuickMenu::OnNotifyPress( HXUIOBJ hObjPressed, int & bHandled )
{
int current_index;
if ( hObjPressed == m_quickmenulist)
{
current_index = m_quickmenulist.GetCurSel();
switch(current_index)
{
case MENU_ITEM_LOAD_STATE:
if (g_console.emulator_initialized)
{
ssnes_load_state();
return_to_game();
}
break;
case MENU_ITEM_SAVE_STATE:
if (g_console.emulator_initialized)
{
ssnes_save_state();
return_to_game();
}
break;
case MENU_ITEM_HARDWARE_FILTERING:
g_settings.video.smooth = !g_settings.video.smooth;
m_quickmenulist.SetText(MENU_ITEM_HARDWARE_FILTERING, set_filter_element(g_settings.video.smooth));
break;
case MENU_ITEM_KEEP_ASPECT_RATIO:
{
if(g_console.aspect_ratio_index < LAST_ASPECT_RATIO)
g_console.aspect_ratio_index++;
else
g_console.aspect_ratio_index = 0;
xdk360_set_aspect_ratio(g_console.aspect_ratio_index);
char aspectratio_label[32];
sprintf(aspectratio_label, "Aspect Ratio: %s", g_console.aspect_ratio_name);
unsigned long dwNum = MultiByteToWideChar(CP_ACP, 0, aspectratio_label, -1, NULL, 0);
wchar_t * aspectratio_label_w = new wchar_t[dwNum];
MultiByteToWideChar(CP_ACP, 0, aspectratio_label, -1, aspectratio_label_w, dwNum);
m_quickmenulist.SetText(MENU_ITEM_KEEP_ASPECT_RATIO, aspectratio_label_w);
delete[] aspectratio_label_w;
}
break;
case MENU_ITEM_OVERSCAN_AMOUNT:
break;
case MENU_ITEM_ORIENTATION:
switch(g_console.screen_orientation)
{
case ORIENTATION_NORMAL:
g_console.screen_orientation = ORIENTATION_VERTICAL;
m_quickmenulist.SetText(MENU_ITEM_ORIENTATION, L"Orientation: Vertical");
break;
case ORIENTATION_VERTICAL:
g_console.screen_orientation = ORIENTATION_FLIPPED;
m_quickmenulist.SetText(MENU_ITEM_ORIENTATION, L"Orientation: Flipped");
break;
case ORIENTATION_FLIPPED:
g_console.screen_orientation = ORIENTATION_FLIPPED_ROTATED;
m_quickmenulist.SetText(MENU_ITEM_ORIENTATION, L"Orientation: Flipped Rotated");
break;
case ORIENTATION_FLIPPED_ROTATED:
g_console.screen_orientation = ORIENTATION_NORMAL;
m_quickmenulist.SetText(MENU_ITEM_ORIENTATION, L"Orientation: Normal");
break;
}
video_xdk360.set_rotation(NULL, g_console.screen_orientation);
break;
case MENU_ITEM_RESIZE_MODE:
break;
case MENU_ITEM_FRAME_ADVANCE:
if (g_console.emulator_initialized)
{
g_console.frame_advance_enable = true;
g_console.menu_enable = false;
g_console.mode_switch = MODE_EMULATION;
}
break;
case MENU_ITEM_SCREENSHOT_MODE:
break;
case MENU_ITEM_RESET:
if (g_console.emulator_initialized)
{
return_to_game();
ssnes_game_reset();
}
break;
case MENU_ITEM_RETURN_TO_GAME:
if (g_console.emulator_initialized)
return_to_game();
break;
case MENU_ITEM_RETURN_TO_DASHBOARD:
return_to_dashboard();
break;
}
}
if ( hObjPressed == m_back )
NavigateBack(app.hMainScene);
bHandled = TRUE;
return S_OK;
}
HRESULT CSSNESMain::OnInit(XUIMessageInit * pInitData, BOOL& bHandled)
{
GetChildById(L"XuiBtnRomBrowser", &m_filebrowser);
GetChildById(L"XuiBtnSettings", &m_settings);
GetChildById(L"XuiBtnQuickMenu", &m_quick_menu);
GetChildById(L"XuiBtnControls", &m_controls);
GetChildById(L"XuiBtnQuit", &m_quit);
GetChildById(L"XuiTxtTitle", &m_title);
GetChildById(L"XuiTxtCoreText", &m_core);
GetChildById(L"XuiBtnLibsnesCore", &m_change_libsnes_core);
const char * core_text = snes_library_id();
char package_version[32];
sprintf(package_version, "SSNES %s", PACKAGE_VERSION);
unsigned long dwNum = MultiByteToWideChar(CP_ACP, 0, core_text, -1, NULL, 0);
unsigned long dwNum_package = MultiByteToWideChar(CP_ACP, 0, package_version, -1, NULL, 0);
wchar_t * core_text_utf = new wchar_t[dwNum];
wchar_t * package_version_utf = new wchar_t[dwNum_package];
MultiByteToWideChar(CP_ACP, 0, core_text, -1, core_text_utf, dwNum);
MultiByteToWideChar(CP_ACP, 0, package_version, -1, package_version_utf, dwNum_package);
m_core.SetText(core_text_utf);
m_title.SetText(package_version_utf);
delete []core_text_utf;
delete []package_version_utf;
return S_OK;
}
HRESULT CSSNESFileBrowser::OnNotifyPress( HXUIOBJ hObjPressed, BOOL& bHandled )
{
char path[MAX_PATH_LENGTH];
if(hObjPressed == m_romlist)
{
int index = m_romlist.GetCurSel();
if(browser.cur[index].d_type != FILE_ATTRIBUTE_DIRECTORY)
{
memset(strbuffer, 0, sizeof(strbuffer));
wcstombs(strbuffer, (const wchar_t *)m_romlist.GetText(index), sizeof(strbuffer));
if((strstr(strbuffer, ".zip") || strstr(strbuffer, ".ZIP")) && !g_console.block_zip_extract)
{
char path_tmp[1024];
sprintf(path_tmp, "%s\\%s", FILEBROWSER_GET_CURRENT_DIRECTORY_NAME(browser), strbuffer);
ssnes_extract_zipfile(path_tmp);
}
else
{
memset(g_console.rom_path, 0, sizeof(g_console.rom_path));
sprintf(g_console.rom_path, "%s\\%s", FILEBROWSER_GET_CURRENT_DIRECTORY_NAME(browser), strbuffer);
return_to_game();
g_console.initialize_ssnes_enable = 1;
}
}
else if(browser.cur[index].d_type == FILE_ATTRIBUTE_DIRECTORY)
{
memset(strbuffer, 0, sizeof(strbuffer));
wcstombs(strbuffer, (const wchar_t *)m_romlist.GetText(index), sizeof(strbuffer));
snprintf(path, sizeof(path), "%s\\%s", FILEBROWSER_GET_CURRENT_DIRECTORY_NAME(browser), strbuffer);
filebrowser_fetch_directory_entries(path, &browser, &m_romlist, &m_rompathtitle);
}
}
else if (hObjPressed == m_dir_game)
{
filebrowser_new(&browser, g_console.default_rom_startup_dir, ssnes_console_get_rom_ext());
filebrowser_fetch_directory_entries(g_console.default_rom_startup_dir, &browser, &m_romlist, &m_rompathtitle);
}
else if (hObjPressed == m_dir_cache)
{
filebrowser_new(&browser, "cache:", ssnes_console_get_rom_ext());
filebrowser_fetch_directory_entries("cache:", &browser, &m_romlist, &m_rompathtitle);
}
else if(hObjPressed == m_back)
NavigateBack(app.hMainScene);
bHandled = TRUE;
return S_OK;
}
HRESULT CSSNESCoreBrowser::OnNotifyPress( HXUIOBJ hObjPressed, BOOL& bHandled )
{
char path[MAX_PATH_LENGTH];
if(hObjPressed == m_romlist)
{
int index = m_romlist.GetCurSel();
if(browser.cur[index].d_type != FILE_ATTRIBUTE_DIRECTORY)
{
memset(strbuffer, 0, sizeof(strbuffer));
wcstombs(strbuffer, (const wchar_t *)m_romlist.GetText(index), sizeof(strbuffer));
sprintf(g_console.launch_app_on_exit, "%s\\%s", FILEBROWSER_GET_CURRENT_DIRECTORY_NAME(tmp_browser), strbuffer);
g_console.return_to_launcher = true;
g_console.menu_enable = false;
g_console.mode_switch = MODE_EXIT;
}
else if(tmp_browser.cur[index].d_type == FILE_ATTRIBUTE_DIRECTORY)
{
memset(strbuffer, 0, sizeof(strbuffer));
wcstombs(strbuffer, (const wchar_t *)m_romlist.GetText(index), sizeof(strbuffer));
snprintf(path, sizeof(path), "%s%s\\", FILEBROWSER_GET_CURRENT_DIRECTORY_NAME(tmp_browser), strbuffer);
filebrowser_fetch_directory_entries(path, &tmp_browser, &m_romlist, &m_rompathtitle);
}
}
else if(hObjPressed == m_back)
NavigateBack(app.hMainScene);
bHandled = TRUE;
return S_OK;
}
HRESULT CSSNESSettings::OnNotifyPress( HXUIOBJ hObjPressed, int & bHandled )
{
int current_index;
if ( hObjPressed == m_settingslist)
{
current_index = m_settingslist.GetCurSel();
switch(current_index)
{
case SETTING_EMU_REWIND_ENABLED:
g_settings.rewind_enable = !g_settings.rewind_enable;
m_settingslist.SetText(SETTING_EMU_REWIND_ENABLED, g_settings.rewind_enable ? L"Rewind: ON" : L"Rewind: OFF");
break;
case SETTING_GAMMA_CORRECTION_ENABLED:
g_console.gamma_correction_enable = !g_console.gamma_correction_enable;
m_settingslist.SetText(SETTING_GAMMA_CORRECTION_ENABLED, g_console.gamma_correction_enable ? L"Gamma correction: ON" : L"Gamma correction: OFF");
break;
case SETTING_HARDWARE_FILTERING:
g_settings.video.smooth = !g_settings.video.smooth;
m_settingslist.SetText(SETTING_HARDWARE_FILTERING, set_filter_element(g_settings.video.smooth));
break;
}
}
if ( hObjPressed == m_back )
NavigateBack(app.hMainScene);
bHandled = TRUE;
return S_OK;
}
HRESULT CSSNESMain::OnNotifyPress( HXUIOBJ hObjPressed, int & bHandled )
{
HRESULT hr;
if ( hObjPressed == m_filebrowser )
{
hr = XuiSceneCreate(L"file://game:/media/", L"ssnes_filebrowser.xur", NULL, &app.hFileBrowser);
if (FAILED(hr))
{
SSNES_ERR("Failed to load scene.\n");
}
NavigateForward(app.hFileBrowser);
}
else if ( hObjPressed == m_quick_menu)
{
hr = XuiSceneCreate(L"file://game:/media/", L"ssnes_quickmenu.xur", NULL, &app.hQuickMenu);
if (FAILED(hr))
SSNES_ERR("Failed to load scene.\n");
NavigateForward(app.hQuickMenu);
}
else if ( hObjPressed == m_change_libsnes_core )
{
hr = XuiSceneCreate(L"file://game:/media/", L"ssnes_libsnescore_browser.xur", NULL, &app.hCoreBrowser);
if (FAILED(hr))
{
SSNES_ERR("Failed to load scene.\n");
}
NavigateForward(app.hCoreBrowser);
}
else if ( hObjPressed == m_settings )
{
hr = XuiSceneCreate(L"file://game:/media/", L"ssnes_settings.xur", NULL, &app.hSSNESSettings);
if (FAILED(hr))
SSNES_ERR("Failed to load scene.\n");
NavigateForward(app.hSSNESSettings);
}
else if ( hObjPressed == m_quit )
return_to_dashboard();
bHandled = TRUE;
return S_OK;
}
int menu_init (void)
{
HRESULT hr;
xdk360_video_t *vid = (xdk360_video_t*)g_d3d;
hr = app.InitShared(vid->xdk360_render_device, &vid->d3dpp, XuiPNGTextureLoader);
if (FAILED(hr))
{
SSNES_ERR("Failed initializing XUI application.\n");
return 1;
}
/* Register font */
hr = app.RegisterDefaultTypeface(L"Arial Unicode MS", L"file://game:/media/ssnes.ttf" );
if (FAILED(hr))
{
SSNES_ERR("Failed to register default typeface.\n");
return 1;
}
hr = app.LoadSkin( L"file://game:/media/ssnes_scene_skin.xur");
if (FAILED(hr))
{
SSNES_ERR("Failed to load skin.\n");
return 1;
}
hr = XuiSceneCreate(L"file://game:/media/", L"ssnes_main.xur", NULL, &app.hMainScene);
if (FAILED(hr))
{
SSNES_ERR("Failed to create scene 'ssnes_main.xur'.\n");
return 1;
}
XuiSceneNavigateFirst(app.GetRootObj(), app.hMainScene, XUSER_INDEX_FOCUS);
filebrowser_new(&browser, g_console.default_rom_startup_dir, ssnes_console_get_rom_ext());
return 0;
}
void menu_loop(void)
{
g_console.menu_enable = true;
HRESULT hr;
xdk360_video_t *vid = (xdk360_video_t*)g_d3d;
if(g_console.emulator_initialized)
video_xdk360.set_swap_block_state(NULL, true);
do
{
g_frame_count++;
if(g_console.emulator_initialized)
{
ssnes_render_cached_frame();
}
else
D3DDevice_Clear(vid->xdk360_render_device, 0, NULL,
D3DCLEAR_TARGET, D3DCOLOR_ARGB(255, 32, 32, 64), 1.0, 0, FALSE);
XINPUT_STATE state;
XInputGetState(0, &state);
g_console.menu_enable = !((state.Gamepad.wButtons & XINPUT_GAMEPAD_LEFT_THUMB)
&& (state.Gamepad.wButtons & XINPUT_GAMEPAD_RIGHT_THUMB) && (g_console.emulator_initialized)
&& IS_TIMER_EXPIRED());
g_console.mode_switch = g_console.menu_enable ? MODE_MENU : MODE_EMULATION;
app.RunFrame(); /* Update XUI */
hr = app.Render(); /* Render XUI */
hr = XuiTimersRun(); /* Update XUI timers */
if(g_console.mode_switch == MODE_EMULATION && !g_console.frame_advance_enable)
{
SET_TIMER_EXPIRATION(30);
}
video_xdk360.swap(NULL);
}while(g_console.menu_enable);
if(g_console.emulator_initialized)
video_xdk360.set_swap_block_state(NULL, false);
g_console.ingame_menu_enable = false;
}
+147
View File
@@ -0,0 +1,147 @@
/* SSNES - A Super Nintendo Entertainment System (SNES) Emulator frontend for libsnes.
* Copyright (C) 2010-2012 - Hans-Kristian Arntzen
* Copyright (C) 2011-2012 - Daniel De Matteis
*
* Some code herein may be based on code found in BSNES.
*
* SSNES is free software: you can redistribute it and/or modify it under the terms
* of the GNU General Public License as published by the Free Software Found-
* ation, either version 3 of the License, or (at your option) any later version.
*
* SSNES is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
* without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
* PURPOSE. See the GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License along with SSNES.
* If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef _MENU_XUI_H_
#define _MENU_XUI_H_
#include <xui.h>
#include <xuiapp.h>
enum
{
SETTING_EMU_REWIND_ENABLED = 0,
SETTING_GAMMA_CORRECTION_ENABLED,
SETTING_HARDWARE_FILTERING
};
class CSSNES : public CXuiModule
{
public:
HXUIOBJ hMainScene;
HXUIOBJ hFileBrowser;
HXUIOBJ hCoreBrowser;
HXUIOBJ hQuickMenu;
HXUIOBJ hSSNESSettings;
protected:
/* Override so that Cssnes can register classes */
virtual HRESULT RegisterXuiClasses();
/* Override so that Cssnes can unregister classes */
virtual HRESULT UnregisterXuiClasses();
};
class CSSNESMain: public CXuiSceneImpl
{
protected:
CXuiControl m_filebrowser;
CXuiControl m_quick_menu;
CXuiControl m_controls;
CXuiControl m_settings;
CXuiControl m_change_libsnes_core;
CXuiControl m_quit;
CXuiTextElement m_title;
CXuiTextElement m_core;
public:
HRESULT OnInit( XUIMessageInit* pInitData, int & bHandled );
HRESULT OnNotifyPress( HXUIOBJ hObjPressed, int & bHandled );
XUI_BEGIN_MSG_MAP()
XUI_ON_XM_INIT( OnInit)
XUI_ON_XM_NOTIFY_PRESS( OnNotifyPress )
XUI_END_MSG_MAP();
XUI_IMPLEMENT_CLASS(CSSNESMain, L"SSNESMain", XUI_CLASS_SCENE)
};
class CSSNESFileBrowser: public CXuiSceneImpl
{
protected:
CXuiList m_romlist;
CXuiControl m_back;
CXuiControl m_dir_game;
CXuiControl m_dir_cache;
CXuiTextElement m_rompathtitle;
public:
HRESULT OnInit( XUIMessageInit* pInitData, int & bHandled );
HRESULT OnNotifyPress( HXUIOBJ hObjPressed, int & bHandled );
XUI_BEGIN_MSG_MAP()
XUI_ON_XM_INIT( OnInit)
XUI_ON_XM_NOTIFY_PRESS( OnNotifyPress )
XUI_END_MSG_MAP();
XUI_IMPLEMENT_CLASS(CSSNESFileBrowser, L"SSNESFileBrowser", XUI_CLASS_SCENE)
};
class CSSNESCoreBrowser: public CXuiSceneImpl
{
protected:
CXuiList m_romlist;
CXuiControl m_back;
CXuiTextElement m_rompathtitle;
public:
HRESULT OnInit( XUIMessageInit* pInitData, int & bHandled );
HRESULT OnNotifyPress( HXUIOBJ hObjPressed, int & bHandled );
XUI_BEGIN_MSG_MAP()
XUI_ON_XM_INIT( OnInit)
XUI_ON_XM_NOTIFY_PRESS( OnNotifyPress )
XUI_END_MSG_MAP();
XUI_IMPLEMENT_CLASS(CSSNESCoreBrowser, L"SSNESCoreBrowser", XUI_CLASS_SCENE)
};
class CSSNESQuickMenu: public CXuiSceneImpl
{
protected:
CXuiList m_quickmenulist;
CXuiControl m_back;
public:
HRESULT OnInit( XUIMessageInit* pInitData, int & bHandled );
HRESULT OnNotifyPress( HXUIOBJ hObjPressed, int & bHandled );
XUI_BEGIN_MSG_MAP()
XUI_ON_XM_INIT( OnInit)
XUI_ON_XM_NOTIFY_PRESS( OnNotifyPress )
XUI_END_MSG_MAP();
XUI_IMPLEMENT_CLASS(CSSNESQuickMenu, L"SSNESQuickMenu", XUI_CLASS_SCENE)
};
class CSSNESSettings: public CXuiSceneImpl
{
protected:
CXuiList m_settingslist;
CXuiControl m_back;
public:
HRESULT OnInit( XUIMessageInit* pInitData, int & bHandled );
HRESULT OnNotifyPress( HXUIOBJ hObjPressed, int & bHandled );
XUI_BEGIN_MSG_MAP()
XUI_ON_XM_INIT( OnInit)
XUI_ON_XM_NOTIFY_PRESS( OnNotifyPress )
XUI_END_MSG_MAP();
XUI_IMPLEMENT_CLASS(CSSNESSettings, L"SSNESSettings", XUI_CLASS_SCENE)
};
int menu_init (void);
void menu_loop (void);
extern CSSNES app;
#endif
+323
View File
@@ -0,0 +1,323 @@
/* SSNES - A Super Nintendo Entertainment System (SNES) Emulator frontend for libsnes.
* SSNES Salamander - A frontend for managing some pre-launch tasks.
* Copyright (C) 2010-2012 - Hans-Kristian Arntzen
* Copyright (C) 2011-2012 - Daniel De Matteis
*
* Some code herein may be based on code found in BSNES.
*
* SSNES is free software: you can redistribute it and/or modify it under the terms
* of the GNU General Public License as published by the Free Software Found-
* ation, either version 3 of the License, or (at your option) any later version.
*
* SSNES is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
* without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
* PURPOSE. See the GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License along with SSNES.
* If not, see <http://www.gnu.org/licenses/>.
*/
#include <xtl.h>
#include "../../compat/strl.h"
#include "../../conf/config_file.h"
#include "../../msvc/msvc_compat.h"
#define MAX_PATH_LENGTH 1024
#define SSNES_LOG(...) do { \
fprintf(stderr, "SSNES Salamander: " __VA_ARGS__); \
fflush(stderr); \
} while (0)
#define SSNES_ERR(...) do { \
fprintf(stderr, "SSNES Salamander [ERROR] :: " __VA_ARGS__); \
fflush(stderr); \
} while (0)
#define SSNES_WARN(...) do { \
fprintf(stderr, "SSNES Salamander [WARN] :: " __VA_ARGS__); \
fflush(stderr); \
} while (0)
char LIBSNES_DIR_PATH[MAX_PATH_LENGTH];
char SYS_CONFIG_FILE[MAX_PATH_LENGTH];
char libsnes_path[MAX_PATH_LENGTH];
DWORD volume_device_type;
static bool path_file_exists(const char *path)
{
FILE *dummy = fopen(path, "rb");
if (dummy)
{
fclose(dummy);
return true;
}
return false;
}
static void dir_list_free(char **dir_list)
{
if (!dir_list)
return;
char **orig = dir_list;
while (*dir_list)
free(*dir_list++);
free(orig);
}
static void fill_pathname_base(char *out_dir, const char *in_path, size_t size)
{
const char *ptr = strrchr(in_path, '/');
if (!ptr)
ptr = strrchr(in_path, '\\');
if (ptr)
ptr++;
else
ptr = in_path;
strlcpy(out_dir, ptr, size);
}
static char **dir_list_new(const char *dir, const char *ext)
{
size_t cur_ptr = 0;
size_t cur_size = 32;
char **dir_list = NULL;
WIN32_FIND_DATA ffd;
HANDLE hFind = INVALID_HANDLE_VALUE;
char path_buf[PATH_MAX];
if (strlcpy(path_buf, dir, sizeof(path_buf)) >= sizeof(path_buf))
goto error;
if (strlcat(path_buf, "*", sizeof(path_buf)) >= sizeof(path_buf))
goto error;
if (ext)
{
if (strlcat(path_buf, ext, sizeof(path_buf)) >= sizeof(path_buf))
goto error;
}
hFind = FindFirstFile(path_buf, &ffd);
if (hFind == INVALID_HANDLE_VALUE)
goto error;
dir_list = (char**)calloc(cur_size, sizeof(char*));
if (!dir_list)
goto error;
do
{
// Not a perfect search of course, but hopefully good enough in practice.
if (ffd.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY)
continue;
if (ext && !strstr(ffd.cFileName, ext))
continue;
dir_list[cur_ptr] = (char*)malloc(PATH_MAX);
if (!dir_list[cur_ptr])
goto error;
strlcpy(dir_list[cur_ptr], dir, PATH_MAX);
strlcat(dir_list[cur_ptr], ffd.cFileName, PATH_MAX);
cur_ptr++;
if (cur_ptr + 1 == cur_size) // Need to reserve for NULL.
{
cur_size *= 2;
dir_list = (char**)realloc(dir_list, cur_size * sizeof(char*));
if (!dir_list)
goto error;
// Make sure it's all NULL'd out since we cannot rely on realloc to do this.
memset(dir_list + cur_ptr, 0, (cur_size - cur_ptr) * sizeof(char*));
}
}while (FindNextFile(hFind, &ffd) != 0);
FindClose(hFind);
return dir_list;
error:
SSNES_ERR("Failed to open directory: \"%s\"\n", dir);
if (hFind != INVALID_HANDLE_VALUE)
FindClose(hFind);
dir_list_free(dir_list);
return NULL;
}
static void find_and_set_first_file(void)
{
//Last fallback - we'll need to start the first .xex file
// we can find in the SSNES cores directory
char ** dir_list = dir_list_new("game:\\", ".xex");
if (!dir_list)
{
SSNES_ERR("Failed last fallback - SSNES Salamander will exit.\n");
return;
}
char * first_xex = dir_list[0];
if(first_xex)
{
//Check if it's SSNES Salamander itself - if so, first_xex needs to
//be overridden
char fname_tmp[MAX_PATH_LENGTH], fname[MAX_PATH_LENGTH];
fill_pathname_base(fname_tmp, first_xex, sizeof(fname_tmp));
if(strcmp(fname_tmp, "SSNES-Salamander.xex") == 0)
{
SSNES_WARN("First entry is SSNES Salamander itself, increment entry by one and check if it exists.\n");
first_xex = dir_list[1];
fill_pathname_base(fname_tmp, first_xex, sizeof(fname_tmp));
if(!first_xex)
{
SSNES_WARN("There is no second entry - no choice but to boot SSNES Salamander\n");
first_xex = dir_list[0];
fill_pathname_base(fname_tmp, first_xex, sizeof(fname_tmp));
}
}
SSNES_LOG("Start first entry in libsnes cores dir: [%s].\n", first_xex);
snprintf(fname, sizeof(fname), "game:\\%s", fname_tmp);
strlcpy(libsnes_path, fname, sizeof(libsnes_path));
}
else
{
SSNES_ERR("Failed last fallback - SSNES Salamander will exit.\n");
}
dir_list_free(dir_list);
}
static void init_settings(void)
{
char tmp_str[MAX_PATH_LENGTH];
bool config_file_exists;
if(!path_file_exists(SYS_CONFIG_FILE))
{
config_file_exists = false;
SSNES_ERR("Config file \"%s\" doesn't exist. Creating...\n", SYS_CONFIG_FILE);
FILE * f;
f = fopen(SYS_CONFIG_FILE, "w");
fclose(f);
}
else
config_file_exists = true;
//try to find CORE.xex
char core_xex[1024];
snprintf(core_xex, sizeof(core_xex), "game:\\CORE.xex");
if(path_file_exists(core_xex))
{
//Start CORE.xex
snprintf(libsnes_path, sizeof(libsnes_path), core_xex);
SSNES_LOG("Start [%s].\n", libsnes_path);
}
else
{
if(config_file_exists)
{
config_file_t * conf = config_file_new(SYS_CONFIG_FILE);
config_get_array(conf, "libsnes_path", tmp_str, sizeof(tmp_str));
snprintf(libsnes_path, sizeof(libsnes_path), tmp_str);
}
if(!config_file_exists || !strcmp(libsnes_path, ""))
find_and_set_first_file();
else
{
SSNES_LOG("Start [%s] found in ssnes.cfg.\n", libsnes_path);
}
}
}
static void get_environment_settings (void)
{
//for devkits only, we will need to mount all partitions for retail
//in a different way
//DmMapDevkitDrive();
int result_filecache = XSetFileCacheSize(0x100000);
if(result_filecache != TRUE)
{
SSNES_ERR("Couldn't change number of bytes reserved for file system cache.\n");
}
unsigned long result = XMountUtilityDriveEx(XMOUNTUTILITYDRIVE_FORMAT0,8192, 0);
if(result != ERROR_SUCCESS)
{
SSNES_ERR("Couldn't mount/format utility drive.\n");
}
// detect install environment
unsigned long license_mask;
if (XContentGetLicenseMask(&license_mask, NULL) != ERROR_SUCCESS)
{
SSNES_LOG("SSNES was launched as a standalone DVD, or using DVD emulation, or from the development area of the HDD.\n");
}
else
{
XContentQueryVolumeDeviceType("GAME",&volume_device_type, NULL);
switch(volume_device_type)
{
case XCONTENTDEVICETYPE_HDD:
SSNES_LOG("SSNES was launched from a content package on HDD.\n");
break;
case XCONTENTDEVICETYPE_MU:
SSNES_LOG("SSNES was launched from a content package on USB or Memory Unit.\n");
break;
case XCONTENTDEVICETYPE_ODD:
SSNES_LOG("SSNES was launched from a content package on Optical Disc Drive.\n");
break;
default:
SSNES_LOG("SSNES was launched from a content package on an unknown device type.\n");
break;
}
}
strlcpy(SYS_CONFIG_FILE, "game:\\ssnes.cfg", sizeof(SYS_CONFIG_FILE));
}
int main(int argc, char *argv[])
{
int ret;
XINPUT_STATE state;
get_environment_settings();
XInputGetState(0, &state);
if(state.Gamepad.wButtons & XINPUT_GAMEPAD_Y)
{
//override path, boot first XEX in cores directory
SSNES_LOG("Fallback - Will boot first XEX in SSNES directory.\n");
find_and_set_first_file();
}
else
{
//normal XEX loading path
init_settings();
}
XLaunchNewImage(libsnes_path, NULL);
SSNES_LOG("Launch libsnes core: [%s] (return code: %x]).\n", libsnes_path, ret);
return 1;
}
+64
View File
@@ -0,0 +1,64 @@
/* SSNES - A Super Nintendo Entertainment System (SNES) Emulator frontend for libsnes.
* Copyright (C) 2010-2012 - Hans-Kristian Arntzen
* Copyright (C) 2011-2012 - Daniel De Matteis
*
* Some code herein may be based on code found in BSNES.
*
* SSNES is free software: you can redistribute it and/or modify it under the terms
* of the GNU General Public License as published by the Free Software Found-
* ation, either version 3 of the License, or (at your option) any later version.
*
* SSNES is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
* without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
* PURPOSE. See the GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License along with SSNES.
* If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef _360_SHARED_H
#define _360_SHARED_H
#define MAX_PATH_LENGTH 1024
enum
{
DPAD_EMULATION_NONE,
DPAD_EMULATION_LSTICK,
DPAD_EMULATION_RSTICK
};
enum
{
MODE_EMULATION,
MODE_MENU,
MODE_EXIT
};
enum
{
ORIENTATION_NORMAL,
ORIENTATION_VERTICAL,
ORIENTATION_FLIPPED,
ORIENTATION_FLIPPED_ROTATED,
ORIENTATION_END
};
enum {
MENU_ITEM_LOAD_STATE = 0,
MENU_ITEM_SAVE_STATE,
MENU_ITEM_HARDWARE_FILTERING,
MENU_ITEM_KEEP_ASPECT_RATIO,
MENU_ITEM_OVERSCAN_AMOUNT,
MENU_ITEM_ORIENTATION,
MENU_ITEM_RESIZE_MODE,
MENU_ITEM_FRAME_ADVANCE,
MENU_ITEM_SCREENSHOT_MODE,
MENU_ITEM_RESET,
MENU_ITEM_RETURN_TO_GAME,
MENU_ITEM_RETURN_TO_DASHBOARD
};
#define MENU_ITEM_LAST MENU_ITEM_RETURN_TO_DASHBOARD+1
#endif
+767
View File
@@ -0,0 +1,767 @@
#if !defined( _XOBJBASE_H_ )
#define _XOBJBASE_H_
#include <sal.h>
#if _MSC_VER > 1000
#pragma once
#endif
#define __RPC_FAR
typedef unsigned char byte;
typedef unsigned char boolean;
typedef double DOUBLE;
#ifdef CONST_VTABLE
#define CONST_VTBL const
#else
#define CONST_VTBL
#endif
/****************************************************************************
* Special things for VC5 Com support
****************************************************************************/
#ifndef DECLSPEC_SELECTANY
#if (_MSC_VER >= 1100)
#define DECLSPEC_SELECTANY __declspec(selectany)
#else
#define DECLSPEC_SELECTANY
#endif
#endif
#ifndef DECLSPEC_NOVTABLE
#define DECLSPEC_NOVTABLE
#endif
#ifndef DECLSPEC_UUID
#define DECLSPEC_UUID(x)
#endif
#define MIDL_INTERFACE(x) struct DECLSPEC_UUID(x) DECLSPEC_NOVTABLE
#if _MSC_VER >= 1100
#define EXTERN_GUID(itf,l1,s1,s2,c1,c2,c3,c4,c5,c6,c7,c8) \
EXTERN_C const IID DECLSPEC_SELECTANY itf = {l1,s1,s2,{c1,c2,c3,c4,c5,c6,c7,c8}}
#else
#define EXTERN_GUID(itf,l1,s1,s2,c1,c2,c3,c4,c5,c6,c7,c8) EXTERN_C const IID itf
#endif
#include <pshpack8.h>
#define WINOLEAPI EXTERN_C DECLSPEC_IMPORT HRESULT STDAPICALLTYPE
#define WINOLEAPI_(type) EXTERN_C DECLSPEC_IMPORT type STDAPICALLTYPE
/****** Interface Declaration ***********************************************/
/*
* These are macros for declaring interfaces. They exist so that
* a single definition of the interface is simulataneously a proper
* declaration of the interface structures (C++ abstract classes)
* for both C and C++.
*
* DECLARE_INTERFACE(iface) is used to declare an interface that does
* not derive from a base interface.
* DECLARE_INTERFACE_(iface, baseiface) is used to declare an interface
* that does derive from a base interface.
*
* By default if the source file has a .c extension the C version of
* the interface declaratations will be expanded; if it has a .cpp
* extension the C++ version will be expanded. if you want to force
* the C version expansion even though the source file has a .cpp
* extension, then define the macro "CINTERFACE".
* eg. cl -DCINTERFACE file.cpp
*
*
* Example C expansion:
*
* typedef struct IClassFactory
* {
* const struct IClassFactoryVtbl FAR* lpVtbl;
* } IClassFactory;
*
* typedef struct IClassFactoryVtbl IClassFactoryVtbl;
*
* struct IClassFactoryVtbl
* {
* HRESULT (STDMETHODCALLTYPE * QueryInterface) (
* IClassFactory FAR* This,
* IID FAR* riid,
* LPVOID FAR* ppvObj) ;
* ULONG (STDMETHODCALLTYPE * AddRef) (IClassFactory FAR* This) ;
* ULONG (STDMETHODCALLTYPE * Release) (IClassFactory FAR* This) ;
* HRESULT (STDMETHODCALLTYPE * CreateInstance) (
* IClassFactory FAR* This,
* LPUNKNOWN pUnkOuter,
* IID FAR* riid,
* LPVOID FAR* ppvObject);
* HRESULT (STDMETHODCALLTYPE * LockServer) (
* IClassFactory FAR* This,
* BOOL fLock);
* };
*/
#define interface struct
#define STDMETHOD(method) HRESULT (STDMETHODCALLTYPE * method)
#define STDMETHOD_(type,method) type (STDMETHODCALLTYPE * method)
#define STDMETHODV(method) HRESULT (STDMETHODVCALLTYPE * method)
#define STDMETHODV_(type,method) type (STDMETHODVCALLTYPE * method)
#if !defined(BEGIN_INTERFACE)
#define BEGIN_INTERFACE
#define END_INTERFACE
#endif
#define PURE
#define THIS_ INTERFACE FAR* This,
#define THIS INTERFACE FAR* This
#ifdef CONST_VTABLE
#undef CONST_VTBL
#define CONST_VTBL const
#define DECLARE_INTERFACE(iface) typedef interface iface { \
const struct iface##Vtbl FAR* lpVtbl; \
} iface; \
typedef const struct iface##Vtbl iface##Vtbl; \
const struct iface##Vtbl
#else
#undef CONST_VTBL
#define CONST_VTBL
#define DECLARE_INTERFACE(iface) typedef interface iface { \
struct iface##Vtbl FAR* lpVtbl; \
} iface; \
typedef struct iface##Vtbl iface##Vtbl; \
struct iface##Vtbl
#endif
#define DECLARE_INTERFACE_(iface, baseiface) DECLARE_INTERFACE(iface)
/****** Additional basic types **********************************************/
#ifndef FARSTRUCT
#define FARSTRUCT
#endif // FARSTRUCT
#ifndef HUGEP
#if defined(_WIN32) || defined(_MPPC_)
#define HUGEP
#else
#define HUGEP __huge
#endif // WIN32
#endif // HUGEP
#include <stdlib.h>
#define LISet32(li, v) ((li).HighPart = (v) < 0 ? -1 : 0, (li).LowPart = (v))
#define ULISet32(li, v) ((li).HighPart = 0, (li).LowPart = (v))
#if defined(_WIN32) && !defined(OLE2ANSI)
typedef WCHAR OLECHAR;
typedef /* [string] */ OLECHAR __RPC_FAR *LPOLESTR;
typedef /* [string] */ const OLECHAR __RPC_FAR *LPCOLESTR;
#define OLESTR(str) L##str
#else
typedef char OLECHAR;
typedef LPSTR LPOLESTR;
typedef LPCSTR LPCOLESTR;
#define OLESTR(str) str
#endif
/* Forward Declarations */
#ifndef __IUnknown_FWD_DEFINED__
#define __IUnknown_FWD_DEFINED__
typedef interface IUnknown IUnknown;
#endif /* __IUnknown_FWD_DEFINED__ */
#ifndef __IUnknown_INTERFACE_DEFINED__
#define __IUnknown_INTERFACE_DEFINED__
/* interface IUnknown */
/* [unique][uuid][object][local] */
typedef /* [unique] */ IUnknown __RPC_FAR *LPUNKNOWN;
typedef /* [unique] */ IUnknown __RPC_FAR *PUNKNOWN;
//////////////////////////////////////////////////////////////////
// IID_IUnknown and all other system IIDs are provided in UUID.LIB
// Link that library in with your proxies, clients and servers
//////////////////////////////////////////////////////////////////
EXTERN_C const IID IID_IUnknown;
typedef struct IUnknownVtbl
{
BEGIN_INTERFACE
HRESULT ( STDMETHODCALLTYPE __RPC_FAR *QueryInterface )(
IUnknown __RPC_FAR * This,
/* [in] */ __in REFIID riid,
/* [iid_is][out] */ __deref_out void __RPC_FAR *__RPC_FAR *ppvObject);
ULONG ( STDMETHODCALLTYPE __RPC_FAR *AddRef )(
IUnknown __RPC_FAR * This);
ULONG ( STDMETHODCALLTYPE __RPC_FAR *Release )(
IUnknown __RPC_FAR * This);
END_INTERFACE
} IUnknownVtbl;
interface IUnknown
{
CONST_VTBL struct IUnknownVtbl __RPC_FAR *lpVtbl;
};
#define IUnknown_QueryInterface(This,riid,ppvObject) \
(This)->lpVtbl -> QueryInterface(This,riid,ppvObject)
#define IUnknown_AddRef(This) \
(This)->lpVtbl -> AddRef(This)
#define IUnknown_Release(This) \
(This)->lpVtbl -> Release(This)
/* interface __MIDL_itf_unknwn_0005 */
/* [local] */
#endif // VC6 hack
#ifndef __ISequentialStream_FWD_DEFINED__
#define __ISequentialStream_FWD_DEFINED__
typedef interface ISequentialStream ISequentialStream;
#endif /* __ISequentialStream_FWD_DEFINED__ */
#ifndef __ISequentialStream_INTERFACE_DEFINED__
#define __ISequentialStream_INTERFACE_DEFINED__
/* interface ISequentialStream */
/* [unique][uuid][object] */
EXTERN_C const IID IID_ISequentialStream;
typedef struct ISequentialStreamVtbl
{
BEGIN_INTERFACE
HRESULT ( STDMETHODCALLTYPE __RPC_FAR *QueryInterface )(
ISequentialStream __RPC_FAR * This,
/* [in] */ __in REFIID riid,
/* [iid_is][out] */ __deref_out void __RPC_FAR *__RPC_FAR *ppvObject);
ULONG ( STDMETHODCALLTYPE __RPC_FAR *AddRef )(
ISequentialStream __RPC_FAR * This);
ULONG ( STDMETHODCALLTYPE __RPC_FAR *Release )(
ISequentialStream __RPC_FAR * This);
/* [local] */ HRESULT ( STDMETHODCALLTYPE __RPC_FAR *Read )(
ISequentialStream __RPC_FAR * This,
/* [length_is][size_is][out] */ __out_bcount_part_opt(cb, *pcbRead) void __RPC_FAR *pv,
/* [in] */ __in ULONG cb,
/* [out] */ __out_opt ULONG __RPC_FAR *pcbRead);
/* [local] */ HRESULT ( STDMETHODCALLTYPE __RPC_FAR *Write )(
ISequentialStream __RPC_FAR * This,
/* [size_is][in] */ __in_bcount_opt(cb) const void __RPC_FAR *pv,
/* [in] */ __in ULONG cb,
/* [out] */ __out_opt ULONG __RPC_FAR *pcbWritten);
END_INTERFACE
} ISequentialStreamVtbl;
interface ISequentialStream
{
CONST_VTBL struct ISequentialStreamVtbl __RPC_FAR *lpVtbl;
};
#define ISequentialStream_QueryInterface(This,riid,ppvObject) \
(This)->lpVtbl -> QueryInterface(This,riid,ppvObject)
#define ISequentialStream_AddRef(This) \
(This)->lpVtbl -> AddRef(This)
#define ISequentialStream_Release(This) \
(This)->lpVtbl -> Release(This)
#define ISequentialStream_Read(This,pv,cb,pcbRead) \
(This)->lpVtbl -> Read(This,pv,cb,pcbRead)
#define ISequentialStream_Write(This,pv,cb,pcbWritten) \
(This)->lpVtbl -> Write(This,pv,cb,pcbWritten)
#endif /* __ISequentialStream_INTERFACE_DEFINED__ */
#ifndef __IStream_FWD_DEFINED__
#define __IStream_FWD_DEFINED__
typedef interface IStream IStream;
#endif /* __IStream_FWD_DEFINED__ */
#ifndef __IStream_INTERFACE_DEFINED__
#define __IStream_INTERFACE_DEFINED__
/* interface IStream */
/* [unique][uuid][object] */
typedef /* [unique] */ IStream __RPC_FAR *LPSTREAM;
typedef struct tagSTATSTG
{
LPOLESTR pwcsName;
DWORD type;
ULARGE_INTEGER cbSize;
FILETIME mtime;
FILETIME ctime;
FILETIME atime;
DWORD grfMode;
DWORD grfLocksSupported;
CLSID clsid;
DWORD grfStateBits;
DWORD reserved;
} STATSTG;
typedef
enum tagSTGTY
{ STGTY_STORAGE = 1,
STGTY_STREAM = 2,
STGTY_LOCKBYTES = 3,
STGTY_PROPERTY = 4
} STGTY;
typedef
enum tagSTREAM_SEEK
{ STREAM_SEEK_SET = 0,
STREAM_SEEK_CUR = 1,
STREAM_SEEK_END = 2
} STREAM_SEEK;
typedef
enum tagLOCKTYPE
{ LOCK_WRITE = 1,
LOCK_EXCLUSIVE = 2,
LOCK_ONLYONCE = 4
} LOCKTYPE;
EXTERN_C const IID IID_IStream;
typedef struct IStreamVtbl
{
BEGIN_INTERFACE
HRESULT ( STDMETHODCALLTYPE __RPC_FAR *QueryInterface )(
IStream __RPC_FAR * This,
/* [in] */ __in REFIID riid,
/* [iid_is][out] */ __deref_out void __RPC_FAR *__RPC_FAR *ppvObject);
ULONG ( STDMETHODCALLTYPE __RPC_FAR *AddRef )(
IStream __RPC_FAR * This);
ULONG ( STDMETHODCALLTYPE __RPC_FAR *Release )(
IStream __RPC_FAR * This);
/* [local] */ HRESULT ( STDMETHODCALLTYPE __RPC_FAR *Read )(
IStream __RPC_FAR * This,
/* [length_is][size_is][out] */ __out_bcount_part_opt(cb, *pcbRead) void __RPC_FAR *pv,
/* [in] */ __in ULONG cb,
/* [out] */ __out_opt ULONG __RPC_FAR *pcbRead);
/* [local] */ HRESULT ( STDMETHODCALLTYPE __RPC_FAR *Write )(
IStream __RPC_FAR * This,
/* [size_is][in] */ __in_bcount_opt(cb) const void __RPC_FAR *pv,
/* [in] */ __in ULONG cb,
/* [out] */ __out_opt ULONG __RPC_FAR *pcbWritten);
/* [local] */ HRESULT ( STDMETHODCALLTYPE __RPC_FAR *Seek )(
IStream __RPC_FAR * This,
/* [in] */ __in LARGE_INTEGER dlibMove,
/* [in] */ __in DWORD dwOrigin,
/* [out] */ __out_opt ULARGE_INTEGER __RPC_FAR *plibNewPosition);
HRESULT ( STDMETHODCALLTYPE __RPC_FAR *SetSize )(
IStream __RPC_FAR * This,
/* [in] */ __in ULARGE_INTEGER libNewSize);
/* [local] */ HRESULT ( STDMETHODCALLTYPE __RPC_FAR *CopyTo )(
IStream __RPC_FAR * This,
/* [unique][in] */ __in IStream __RPC_FAR *pstm,
/* [in] */ __in ULARGE_INTEGER cb,
/* [out] */ __out_opt ULARGE_INTEGER __RPC_FAR *pcbRead,
/* [out] */ __out_opt ULARGE_INTEGER __RPC_FAR *pcbWritten);
HRESULT ( STDMETHODCALLTYPE __RPC_FAR *Commit )(
IStream __RPC_FAR * This,
/* [in] */ __in DWORD grfCommitFlags);
HRESULT ( STDMETHODCALLTYPE __RPC_FAR *Revert )(
IStream __RPC_FAR * This);
HRESULT ( STDMETHODCALLTYPE __RPC_FAR *LockRegion )(
IStream __RPC_FAR * This,
/* [in] */ __in ULARGE_INTEGER libOffset,
/* [in] */ __in ULARGE_INTEGER cb,
/* [in] */ __in DWORD dwLockType);
HRESULT ( STDMETHODCALLTYPE __RPC_FAR *UnlockRegion )(
IStream __RPC_FAR * This,
/* [in] */ __in ULARGE_INTEGER libOffset,
/* [in] */ __in ULARGE_INTEGER cb,
/* [in] */ __in DWORD dwLockType);
HRESULT ( STDMETHODCALLTYPE __RPC_FAR *Stat )(
IStream __RPC_FAR * This,
/* [out] */ __out STATSTG __RPC_FAR *pstatstg,
/* [in] */ __in DWORD grfStatFlag);
HRESULT ( STDMETHODCALLTYPE __RPC_FAR *Clone )(
IStream __RPC_FAR * This,
/* [out] */ __deref_out_opt IStream __RPC_FAR *__RPC_FAR *ppstm);
END_INTERFACE
} IStreamVtbl;
interface IStream
{
CONST_VTBL struct IStreamVtbl __RPC_FAR *lpVtbl;
};
#define IStream_QueryInterface(This,riid,ppvObject) \
(This)->lpVtbl -> QueryInterface(This,riid,ppvObject)
#define IStream_AddRef(This) \
(This)->lpVtbl -> AddRef(This)
#define IStream_Release(This) \
(This)->lpVtbl -> Release(This)
#define IStream_Read(This,pv,cb,pcbRead) \
(This)->lpVtbl -> Read(This,pv,cb,pcbRead)
#define IStream_Write(This,pv,cb,pcbWritten) \
(This)->lpVtbl -> Write(This,pv,cb,pcbWritten)
#define IStream_Seek(This,dlibMove,dwOrigin,plibNewPosition) \
(This)->lpVtbl -> Seek(This,dlibMove,dwOrigin,plibNewPosition)
#define IStream_SetSize(This,libNewSize) \
(This)->lpVtbl -> SetSize(This,libNewSize)
#define IStream_CopyTo(This,pstm,cb,pcbRead,pcbWritten) \
(This)->lpVtbl -> CopyTo(This,pstm,cb,pcbRead,pcbWritten)
#define IStream_Commit(This,grfCommitFlags) \
(This)->lpVtbl -> Commit(This,grfCommitFlags)
#define IStream_Revert(This) \
(This)->lpVtbl -> Revert(This)
#define IStream_LockRegion(This,libOffset,cb,dwLockType) \
(This)->lpVtbl -> LockRegion(This,libOffset,cb,dwLockType)
#define IStream_UnlockRegion(This,libOffset,cb,dwLockType) \
(This)->lpVtbl -> UnlockRegion(This,libOffset,cb,dwLockType)
#define IStream_Stat(This,pstatstg,grfStatFlag) \
(This)->lpVtbl -> Stat(This,pstatstg,grfStatFlag)
#define IStream_Clone(This,ppstm) \
(This)->lpVtbl -> Clone(This,ppstm)
#endif /* __IStream_INTERFACE_DEFINED__ */
#ifndef __IClassFactory_FWD_DEFINED__
#define __IClassFactory_FWD_DEFINED__
typedef interface IClassFactory IClassFactory;
#endif /* __IClassFactory_FWD_DEFINED__ */
#ifndef __IClassFactory_INTERFACE_DEFINED__
#define __IClassFactory_INTERFACE_DEFINED__
/* interface IClassFactory */
/* [unique][uuid][object] */
typedef /* [unique] */ IClassFactory __RPC_FAR *LPCLASSFACTORY;
EXTERN_C const IID IID_IClassFactory;
typedef struct IClassFactoryVtbl
{
BEGIN_INTERFACE
HRESULT ( STDMETHODCALLTYPE __RPC_FAR *QueryInterface )(
IClassFactory __RPC_FAR * This,
/* [in] */ __in REFIID riid,
/* [iid_is][out] */ __deref_out void __RPC_FAR *__RPC_FAR *ppvObject);
ULONG ( STDMETHODCALLTYPE __RPC_FAR *AddRef )(
IClassFactory __RPC_FAR * This);
ULONG ( STDMETHODCALLTYPE __RPC_FAR *Release )(
IClassFactory __RPC_FAR * This);
/* [local] */ HRESULT ( STDMETHODCALLTYPE __RPC_FAR *CreateInstance )(
IClassFactory __RPC_FAR * This,
/* [unique][in] */ __in_opt IUnknown __RPC_FAR *pUnkOuter,
/* [in] */ __in REFIID riid,
/* [iid_is][out] */ __deref_out void __RPC_FAR *__RPC_FAR *ppvObject);
/* [local] */ HRESULT ( STDMETHODCALLTYPE __RPC_FAR *LockServer )(
IClassFactory __RPC_FAR * This,
/* [in] */ __in BOOL fLock);
END_INTERFACE
} IClassFactoryVtbl;
interface IClassFactory
{
CONST_VTBL struct IClassFactoryVtbl __RPC_FAR *lpVtbl;
};
#define IClassFactory_QueryInterface(This,riid,ppvObject) \
(This)->lpVtbl -> QueryInterface(This,riid,ppvObject)
#define IClassFactory_AddRef(This) \
(This)->lpVtbl -> AddRef(This)
#define IClassFactory_Release(This) \
(This)->lpVtbl -> Release(This)
#define IClassFactory_CreateInstance(This,pUnkOuter,riid,ppvObject) \
(This)->lpVtbl -> CreateInstance(This,pUnkOuter,riid,ppvObject)
#define IClassFactory_LockServer(This,fLock) \
(This)->lpVtbl -> LockServer(This,fLock)
#endif /* __IClassFactory_INTERFACE_DEFINED__ */
#ifndef __IPersist_FWD_DEFINED__
#define __IPersist_FWD_DEFINED__
typedef interface IPersist IPersist;
#endif /* __IPersist_FWD_DEFINED__ */
#ifndef __IPersist_INTERFACE_DEFINED__
#define __IPersist_INTERFACE_DEFINED__
/* interface IPersist */
/* [uuid][object] */
typedef /* [unique] */ IPersist __RPC_FAR *LPPERSIST;
EXTERN_C const IID IID_IPersist;
typedef struct IPersistVtbl
{
BEGIN_INTERFACE
HRESULT ( STDMETHODCALLTYPE __RPC_FAR *QueryInterface )(
IPersist __RPC_FAR * This,
/* [in] */ __in REFIID riid,
/* [iid_is][out] */ __deref_out void __RPC_FAR *__RPC_FAR *ppvObject);
ULONG ( STDMETHODCALLTYPE __RPC_FAR *AddRef )(
IPersist __RPC_FAR * This);
ULONG ( STDMETHODCALLTYPE __RPC_FAR *Release )(
IPersist __RPC_FAR * This);
HRESULT ( STDMETHODCALLTYPE __RPC_FAR *GetClassID )(
IPersist __RPC_FAR * This,
/* [out] */ __out CLSID __RPC_FAR *pClassID);
END_INTERFACE
} IPersistVtbl;
interface IPersist
{
CONST_VTBL struct IPersistVtbl __RPC_FAR *lpVtbl;
};
#define IPersist_QueryInterface(This,riid,ppvObject) \
(This)->lpVtbl -> QueryInterface(This,riid,ppvObject)
#define IPersist_AddRef(This) \
(This)->lpVtbl -> AddRef(This)
#define IPersist_Release(This) \
(This)->lpVtbl -> Release(This)
#define IPersist_GetClassID(This,pClassID) \
(This)->lpVtbl -> GetClassID(This,pClassID)
#endif /* __IPersist_INTERFACE_DEFINED__ */
#ifndef __IPersistStream_FWD_DEFINED__
#define __IPersistStream_FWD_DEFINED__
typedef interface IPersistStream IPersistStream;
#endif /* __IPersistStream_FWD_DEFINED__ */
#ifndef __IPersistStream_INTERFACE_DEFINED__
#define __IPersistStream_INTERFACE_DEFINED__
/* interface IPersistStream */
/* [unique][uuid][object] */
typedef /* [unique] */ IPersistStream __RPC_FAR *LPPERSISTSTREAM;
EXTERN_C const IID IID_IPersistStream;
typedef struct IPersistStreamVtbl
{
BEGIN_INTERFACE
HRESULT ( STDMETHODCALLTYPE __RPC_FAR *QueryInterface )(
IPersistStream __RPC_FAR * This,
/* [in] */ __in REFIID riid,
/* [iid_is][out] */ __deref_out void __RPC_FAR *__RPC_FAR *ppvObject);
ULONG ( STDMETHODCALLTYPE __RPC_FAR *AddRef )(
IPersistStream __RPC_FAR * This);
ULONG ( STDMETHODCALLTYPE __RPC_FAR *Release )(
IPersistStream __RPC_FAR * This);
HRESULT ( STDMETHODCALLTYPE __RPC_FAR *GetClassID )(
IPersistStream __RPC_FAR * This,
/* [out] */ __out CLSID __RPC_FAR *pClassID);
HRESULT ( STDMETHODCALLTYPE __RPC_FAR *IsDirty )(
IPersistStream __RPC_FAR * This);
HRESULT ( STDMETHODCALLTYPE __RPC_FAR *Load )(
IPersistStream __RPC_FAR * This,
/* [unique][in] */ __in_opt IStream __RPC_FAR *pStm);
HRESULT ( STDMETHODCALLTYPE __RPC_FAR *Save )(
IPersistStream __RPC_FAR * This,
/* [unique][in] */ __in_opt IStream __RPC_FAR *pStm,
/* [in] */ __in BOOL fClearDirty);
HRESULT ( STDMETHODCALLTYPE __RPC_FAR *GetSizeMax )(
IPersistStream __RPC_FAR * This,
/* [out] */ __out ULARGE_INTEGER __RPC_FAR *pcbSize);
END_INTERFACE
} IPersistStreamVtbl;
interface IPersistStream
{
CONST_VTBL struct IPersistStreamVtbl __RPC_FAR *lpVtbl;
};
#define IPersistStream_QueryInterface(This,riid,ppvObject) \
(This)->lpVtbl -> QueryInterface(This,riid,ppvObject)
#define IPersistStream_AddRef(This) \
(This)->lpVtbl -> AddRef(This)
#define IPersistStream_Release(This) \
(This)->lpVtbl -> Release(This)
#define IPersistStream_GetClassID(This,pClassID) \
(This)->lpVtbl -> GetClassID(This,pClassID)
#define IPersistStream_IsDirty(This) \
(This)->lpVtbl -> IsDirty(This)
#define IPersistStream_Load(This,pStm) \
(This)->lpVtbl -> Load(This,pStm)
#define IPersistStream_Save(This,pStm,fClearDirty) \
(This)->lpVtbl -> Save(This,pStm,fClearDirty)
#define IPersistStream_GetSizeMax(This,pcbSize) \
(This)->lpVtbl -> GetSizeMax(This,pcbSize)
#endif /* __IPersistStream_INTERFACE_DEFINED__ */
#include <guiddef.h>
#ifndef INITGUID
#include <cguid.h>
#endif
#ifndef RC_INVOKED
#include <poppack.h>
#endif // RC_INVOKED
#endif // _XOBJBASE_H_
+506
View File
@@ -0,0 +1,506 @@
/*
xaudio.h (2010-08-14) / (2012-12-04)
authors: OV2, Themaister
*/
// Kinda stripped down. Only contains the bare essentials used in SSNES.
#ifndef XAUDIO2_XDK360_H
#define XAUDIO2_XDK360_H
#include <comdecl.h> // For DEFINE_CLSID and DEFINE_IID
DEFINE_CLSID(XAudio2, 3eda9b49, 2085, 498b, 9b, b2, 39, a6, 77, 84, 93, de);
DEFINE_CLSID(XAudio2_Debug, 47199894, 7cc2, 444d, 98, 73, ce, d2, 56, 2c, c6, 0e);
DEFINE_IID(IXAudio2, 8bcf1f58, 9fe7, 4583, 8a, c6, e2, ad, c4, 65, c8, bb);
// Ignore the rest of this header if only the GUID definitions were requested
#ifndef GUID_DEFS_ONLY
#include "objbase.h" // Xbox COM declarations (IUnknown, etc)
#include <audiodefs.h> // Basic audio data types and constants
#include <xma2defs.h> // Data types and constants for XMA2 audio
// All structures defined in this file use tight field packing
#pragma pack(push, 1)
// Numeric boundary values
#define XAUDIO2_MAX_BUFFER_BYTES 0x80000000 // Maximum bytes allowed in a source buffer
#define XAUDIO2_MAX_QUEUED_BUFFERS 64 // Maximum buffers allowed in a voice queue
#define XAUDIO2_MAX_BUFFERS_SYSTEM 2 // Maximum buffers allowed for system threads (Xbox 360 only)
#define XAUDIO2_MAX_AUDIO_CHANNELS 64 // Maximum channels in an audio stream
#define XAUDIO2_MIN_SAMPLE_RATE 1000 // Minimum audio sample rate supported
#define XAUDIO2_MAX_SAMPLE_RATE 200000 // Maximum audio sample rate supported
#define XAUDIO2_MAX_VOLUME_LEVEL 16777216.0f // Maximum acceptable volume level (2^24)
#define XAUDIO2_MIN_FREQ_RATIO (1/1024.0f) // Minimum SetFrequencyRatio argument
#define XAUDIO2_MAX_FREQ_RATIO 1024.0f // Maximum MaxFrequencyRatio argument
#define XAUDIO2_DEFAULT_FREQ_RATIO 2.0f // Default MaxFrequencyRatio argument
#define XAUDIO2_MAX_FILTER_ONEOVERQ 1.5f // Maximum XAUDIO2_FILTER_PARAMETERS.OneOverQ
#define XAUDIO2_MAX_FILTER_FREQUENCY 1.0f // Maximum XAUDIO2_FILTER_PARAMETERS.Frequency
#define XAUDIO2_MAX_LOOP_COUNT 254 // Maximum non-infinite XAUDIO2_BUFFER.LoopCount
#define XAUDIO2_MAX_INSTANCES 8 // Maximum simultaneous XAudio2 objects on Xbox 360
#define XAUDIO2_MAX_RATIO_TIMES_RATE_XMA_MONO 600000
#define XAUDIO2_MAX_RATIO_TIMES_RATE_XMA_MULTICHANNEL 300000
// Numeric values with special meanings
#define XAUDIO2_COMMIT_NOW 0 // Used as an OperationSet argument
#define XAUDIO2_COMMIT_ALL 0 // Used in IXAudio2::CommitChanges
#define XAUDIO2_INVALID_OPSET (UINT32)(-1) // Not allowed for OperationSet arguments
#define XAUDIO2_NO_LOOP_REGION 0 // Used in XAUDIO2_BUFFER.LoopCount
#define XAUDIO2_LOOP_INFINITE 255 // Used in XAUDIO2_BUFFER.LoopCount
#define XAUDIO2_DEFAULT_CHANNELS 0 // Used in CreateMasteringVoice
#define XAUDIO2_DEFAULT_SAMPLERATE 0 // Used in CreateMasteringVoice
// Flags
#define XAUDIO2_DEBUG_ENGINE 0x0001 // Used in XAudio2Create on Windows only
#define XAUDIO2_VOICE_NOPITCH 0x0002 // Used in IXAudio2::CreateSourceVoice
#define XAUDIO2_VOICE_NOSRC 0x0004 // Used in IXAudio2::CreateSourceVoice
#define XAUDIO2_VOICE_USEFILTER 0x0008 // Used in IXAudio2::CreateSource/SubmixVoice
#define XAUDIO2_VOICE_MUSIC 0x0010 // Used in IXAudio2::CreateSourceVoice
#define XAUDIO2_PLAY_TAILS 0x0020 // Used in IXAudio2SourceVoice::Stop
#define XAUDIO2_END_OF_STREAM 0x0040 // Used in XAUDIO2_BUFFER.Flags
#define XAUDIO2_SEND_USEFILTER 0x0080 // Used in XAUDIO2_SEND_DESCRIPTOR.Flags
// Default parameters for the built-in filter
#define XAUDIO2_DEFAULT_FILTER_TYPE LowPassFilter
#define XAUDIO2_DEFAULT_FILTER_FREQUENCY XAUDIO2_MAX_FILTER_FREQUENCY
#define XAUDIO2_DEFAULT_FILTER_ONEOVERQ 1.0f
// Internal XAudio2 constants
#define XAUDIO2_QUANTUM_NUMERATOR 2 // On Xbox 360, XAudio2 processes audio
#define XAUDIO2_QUANTUM_DENOMINATOR 375 // in 5.333ms chunks (= 2/375 seconds)
#define XAUDIO2_QUANTUM_MS (1000.0f * XAUDIO2_QUANTUM_NUMERATOR / XAUDIO2_QUANTUM_DENOMINATOR)
// XAudio2 error codes
#define FACILITY_XAUDIO2 0x896
#define XAUDIO2_E_INVALID_CALL 0x88960001 // An API call or one of its arguments was illegal
#define XAUDIO2_E_XMA_DECODER_ERROR 0x88960002 // The XMA hardware suffered an unrecoverable error
#define XAUDIO2_E_XAPO_CREATION_FAILED 0x88960003 // XAudio2 failed to initialize an XAPO effect
#define XAUDIO2_E_DEVICE_INVALIDATED 0x88960004 // An audio device became unusable (unplugged, etc)
#define FWD_DECLARE(x) typedef interface x x
FWD_DECLARE(IXAudio2);
FWD_DECLARE(IXAudio2Voice);
FWD_DECLARE(IXAudio2SourceVoice);
FWD_DECLARE(IXAudio2SubmixVoice);
FWD_DECLARE(IXAudio2MasteringVoice);
FWD_DECLARE(IXAudio2EngineCallback);
FWD_DECLARE(IXAudio2VoiceCallback);
typedef enum XAUDIO2_XBOX_HWTHREAD_SPECIFIER
{
XboxThread0 = 0x01,
XboxThread1 = 0x02,
XboxThread2 = 0x04,
XboxThread3 = 0x08,
XboxThread4 = 0x10,
XboxThread5 = 0x20,
XAUDIO2_ANY_PROCESSOR = XboxThread4,
XAUDIO2_DEFAULT_PROCESSOR = XAUDIO2_ANY_PROCESSOR
} XAUDIO2_XBOX_HWTHREAD_SPECIFIER, XAUDIO2_PROCESSOR;
typedef enum XAUDIO2_DEVICE_ROLE
{
NotDefaultDevice = 0x0,
DefaultConsoleDevice = 0x1,
DefaultMultimediaDevice = 0x2,
DefaultCommunicationsDevice = 0x4,
DefaultGameDevice = 0x8,
GlobalDefaultDevice = 0xf,
InvalidDeviceRole = ~GlobalDefaultDevice
} XAUDIO2_DEVICE_ROLE;
typedef struct XAUDIO2_DEVICE_DETAILS
{
WCHAR DeviceID[256]; // String identifier for the audio device.
WCHAR DisplayName[256]; // Friendly name suitable for display to a human.
XAUDIO2_DEVICE_ROLE Role; // Roles that the device should be used for.
WAVEFORMATEXTENSIBLE OutputFormat; // The device's native PCM audio output format.
} XAUDIO2_DEVICE_DETAILS;
typedef struct XAUDIO2_VOICE_DETAILS
{
UINT32 CreationFlags; // Flags the voice was created with.
UINT32 InputChannels; // Channels in the voice's input audio.
UINT32 InputSampleRate; // Sample rate of the voice's input audio.
} XAUDIO2_VOICE_DETAILS;
// Used in XAUDIO2_VOICE_SENDS below
typedef struct XAUDIO2_SEND_DESCRIPTOR
{
UINT32 Flags; // Either 0 or XAUDIO2_SEND_USEFILTER.
IXAudio2Voice* pOutputVoice; // This send's destination voice.
} XAUDIO2_SEND_DESCRIPTOR;
// Used in the voice creation functions and in IXAudio2Voice::SetOutputVoices
typedef struct XAUDIO2_VOICE_SENDS
{
UINT32 SendCount; // Number of sends from this voice.
XAUDIO2_SEND_DESCRIPTOR* pSends; // Array of SendCount send descriptors.
} XAUDIO2_VOICE_SENDS;
// Used in XAUDIO2_EFFECT_CHAIN below
typedef struct XAUDIO2_EFFECT_DESCRIPTOR
{
IUnknown* pEffect; // Pointer to the effect object's IUnknown interface.
BOOL InitialState; // TRUE if the effect should begin in the enabled state.
UINT32 OutputChannels; // How many output channels the effect should produce.
} XAUDIO2_EFFECT_DESCRIPTOR;
// Used in the voice creation functions and in IXAudio2Voice::SetEffectChain
typedef struct XAUDIO2_EFFECT_CHAIN
{
UINT32 EffectCount; // Number of effects in this voice's effect chain.
XAUDIO2_EFFECT_DESCRIPTOR* pEffectDescriptors; // Array of effect descriptors.
} XAUDIO2_EFFECT_CHAIN;
// Used in XAUDIO2_FILTER_PARAMETERS below
typedef enum XAUDIO2_FILTER_TYPE
{
LowPassFilter, // Attenuates frequencies above the cutoff frequency.
BandPassFilter, // Attenuates frequencies outside a given range.
HighPassFilter, // Attenuates frequencies below the cutoff frequency.
NotchFilter // Attenuates frequencies inside a given range.
} XAUDIO2_FILTER_TYPE;
// Used in IXAudio2Voice::Set/GetFilterParameters and Set/GetOutputFilterParameters
typedef struct XAUDIO2_FILTER_PARAMETERS
{
XAUDIO2_FILTER_TYPE Type; // Low-pass, band-pass or high-pass.
float Frequency; // Radian frequency (2 * sin(pi*CutoffFrequency/SampleRate));
// must be >= 0 and <= XAUDIO2_MAX_FILTER_FREQUENCY
// (giving a maximum CutoffFrequency of SampleRate/6).
float OneOverQ; // Reciprocal of the filter's quality factor Q;
// must be > 0 and <= XAUDIO2_MAX_FILTER_ONEOVERQ.
} XAUDIO2_FILTER_PARAMETERS;
// Used in IXAudio2SourceVoice::SubmitSourceBuffer
typedef struct XAUDIO2_BUFFER
{
UINT32 Flags; // Either 0 or XAUDIO2_END_OF_STREAM.
UINT32 AudioBytes; // Size of the audio data buffer in bytes.
const BYTE* pAudioData; // Pointer to the audio data buffer.
UINT32 PlayBegin; // First sample in this buffer to be played.
UINT32 PlayLength; // Length of the region to be played in samples,
// or 0 to play the whole buffer.
UINT32 LoopBegin; // First sample of the region to be looped.
UINT32 LoopLength; // Length of the desired loop region in samples,
// or 0 to loop the entire buffer.
UINT32 LoopCount; // Number of times to repeat the loop region,
// or XAUDIO2_LOOP_INFINITE to loop forever.
void* pContext; // Context value to be passed back in callbacks.
} XAUDIO2_BUFFER;
typedef struct XAUDIO2_BUFFER_WMA
{
const UINT32* pDecodedPacketCumulativeBytes; // Decoded packet's cumulative size array.
// Each element is the number of bytes accumulated
// when the corresponding XWMA packet is decoded in
// order. The array must have PacketCount elements.
UINT32 PacketCount; // Number of XWMA packets submitted. Must be >= 1 and
// divide evenly into XAUDIO2_BUFFER.AudioBytes.
} XAUDIO2_BUFFER_WMA;
// Returned by IXAudio2SourceVoice::GetState
typedef struct XAUDIO2_VOICE_STATE
{
void* pCurrentBufferContext; // The pContext value provided in the XAUDIO2_BUFFER
// that is currently being processed, or NULL if
// there are no buffers in the queue.
UINT32 BuffersQueued; // Number of buffers currently queued on the voice
// (including the one that is being processed).
UINT64 SamplesPlayed; // Total number of samples produced by the voice since
// it began processing the current audio stream.
} XAUDIO2_VOICE_STATE;
#define XAUDIO2_LOG_ERRORS 0x0001 // For handled errors with serious effects.
#define XAUDIO2_LOG_WARNINGS 0x0002 // For handled errors that may be recoverable.
#define XAUDIO2_LOG_INFO 0x0004 // Informational chit-chat (e.g. state changes).
#define XAUDIO2_LOG_DETAIL 0x0008 // More detailed chit-chat.
#define XAUDIO2_LOG_API_CALLS 0x0010 // Public API function entries and exits.
#define XAUDIO2_LOG_FUNC_CALLS 0x0020 // Internal function entries and exits.
#define XAUDIO2_LOG_TIMING 0x0040 // Delays detected and other timing data.
#define XAUDIO2_LOG_LOCKS 0x0080 // Usage of critical sections and mutexes.
#define XAUDIO2_LOG_MEMORY 0x0100 // Memory heap usage information.
#define XAUDIO2_LOG_STREAMING 0x1000 // Audio streaming information.
#define X2DEFAULT(x)
#undef INTERFACE
#define INTERFACE IXAudio2
DECLARE_INTERFACE_(IXAudio2, IUnknown)
{
STDMETHOD(QueryInterface) (THIS_ REFIID riid, __deref_out void** ppvInterface) PURE;
STDMETHOD_(ULONG, AddRef) (THIS) PURE;
STDMETHOD_(ULONG, Release) (THIS) PURE;
STDMETHOD(GetDeviceCount) (THIS_ __out UINT32* pCount) PURE;
STDMETHOD(GetDeviceDetails) (THIS_ UINT32 Index, __out XAUDIO2_DEVICE_DETAILS* pDeviceDetails) PURE;
STDMETHOD(Initialize) (THIS_ UINT32 Flags X2DEFAULT(0),
XAUDIO2_PROCESSOR XAudio2Processor X2DEFAULT(XAUDIO2_DEFAULT_PROCESSOR)) PURE;
STDMETHOD(RegisterForCallbacks) (__in IXAudio2EngineCallback* pCallback) PURE;
STDMETHOD_(void, UnregisterForCallbacks) (__in IXAudio2EngineCallback* pCallback) PURE;
STDMETHOD(CreateSourceVoice) (THIS_ __deref_out IXAudio2SourceVoice** ppSourceVoice,
__in const WAVEFORMATEX* pSourceFormat,
UINT32 Flags X2DEFAULT(0),
float MaxFrequencyRatio X2DEFAULT(XAUDIO2_DEFAULT_FREQ_RATIO),
__in_opt IXAudio2VoiceCallback* pCallback X2DEFAULT(NULL),
__in_opt const XAUDIO2_VOICE_SENDS* pSendList X2DEFAULT(NULL),
__in_opt const XAUDIO2_EFFECT_CHAIN* pEffectChain X2DEFAULT(NULL)) PURE;
STDMETHOD(CreateSubmixVoice) (THIS_ __deref_out IXAudio2SubmixVoice** ppSubmixVoice,
UINT32 InputChannels, UINT32 InputSampleRate,
UINT32 Flags X2DEFAULT(0), UINT32 ProcessingStage X2DEFAULT(0),
__in_opt const XAUDIO2_VOICE_SENDS* pSendList X2DEFAULT(NULL),
__in_opt const XAUDIO2_EFFECT_CHAIN* pEffectChain X2DEFAULT(NULL)) PURE;
STDMETHOD(CreateMasteringVoice) (THIS_ __deref_out IXAudio2MasteringVoice** ppMasteringVoice,
UINT32 InputChannels X2DEFAULT(XAUDIO2_DEFAULT_CHANNELS),
UINT32 InputSampleRate X2DEFAULT(XAUDIO2_DEFAULT_SAMPLERATE),
UINT32 Flags X2DEFAULT(0), UINT32 DeviceIndex X2DEFAULT(0),
__in_opt const XAUDIO2_EFFECT_CHAIN* pEffectChain X2DEFAULT(NULL)) PURE;
STDMETHOD(StartEngine) (THIS) PURE;
STDMETHOD_(void, StopEngine) (THIS) PURE;
STDMETHOD(CommitChanges) (THIS_ UINT32 OperationSet) PURE;
};
#undef INTERFACE
#define INTERFACE IXAudio2Voice
DECLARE_INTERFACE(IXAudio2Voice)
{
#define Declare_IXAudio2Voice_Methods() \
STDMETHOD_(void, GetVoiceDetails) (THIS_ __out XAUDIO2_VOICE_DETAILS* pVoiceDetails) PURE; \
\
STDMETHOD(SetOutputVoices) (THIS_ __in_opt const XAUDIO2_VOICE_SENDS* pSendList) PURE; \
\
STDMETHOD(SetEffectChain) (THIS_ __in_opt const XAUDIO2_EFFECT_CHAIN* pEffectChain) PURE; \
\
STDMETHOD(EnableEffect) (THIS_ UINT32 EffectIndex, \
UINT32 OperationSet X2DEFAULT(XAUDIO2_COMMIT_NOW)) PURE; \
\
STDMETHOD(DisableEffect) (THIS_ UINT32 EffectIndex, \
UINT32 OperationSet X2DEFAULT(XAUDIO2_COMMIT_NOW)) PURE; \
\
STDMETHOD_(void, GetEffectState) (THIS_ UINT32 EffectIndex, __out BOOL* pEnabled) PURE; \
\
STDMETHOD(SetEffectParameters) (THIS_ UINT32 EffectIndex, \
__in_bcount(ParametersByteSize) const void* pParameters, \
UINT32 ParametersByteSize, \
UINT32 OperationSet X2DEFAULT(XAUDIO2_COMMIT_NOW)) PURE; \
\
STDMETHOD(GetEffectParameters) (THIS_ UINT32 EffectIndex, \
__out_bcount(ParametersByteSize) void* pParameters, \
UINT32 ParametersByteSize) PURE; \
\
STDMETHOD(SetFilterParameters) (THIS_ __in const XAUDIO2_FILTER_PARAMETERS* pParameters, \
UINT32 OperationSet X2DEFAULT(XAUDIO2_COMMIT_NOW)) PURE; \
\
STDMETHOD_(void, GetFilterParameters) (THIS_ __out XAUDIO2_FILTER_PARAMETERS* pParameters) PURE; \
\
STDMETHOD(SetOutputFilterParameters) (THIS_ __in_opt IXAudio2Voice* pDestinationVoice, \
__in const XAUDIO2_FILTER_PARAMETERS* pParameters, \
UINT32 OperationSet X2DEFAULT(XAUDIO2_COMMIT_NOW)) PURE; \
\
STDMETHOD_(void, GetOutputFilterParameters) (THIS_ __in_opt IXAudio2Voice* pDestinationVoice, \
__out XAUDIO2_FILTER_PARAMETERS* pParameters) PURE; \
\
STDMETHOD(SetVolume) (THIS_ float Volume, \
UINT32 OperationSet X2DEFAULT(XAUDIO2_COMMIT_NOW)) PURE; \
\
STDMETHOD_(void, GetVolume) (THIS_ __out float* pVolume) PURE; \
\
STDMETHOD(SetChannelVolumes) (THIS_ UINT32 Channels, __in_ecount(Channels) const float* pVolumes, \
UINT32 OperationSet X2DEFAULT(XAUDIO2_COMMIT_NOW)) PURE; \
\
STDMETHOD_(void, GetChannelVolumes) (THIS_ UINT32 Channels, __out_ecount(Channels) float* pVolumes) PURE; \
\
STDMETHOD(SetOutputMatrix) (THIS_ __in_opt IXAudio2Voice* pDestinationVoice, \
UINT32 SourceChannels, UINT32 DestinationChannels, \
__in_ecount(SourceChannels * DestinationChannels) const float* pLevelMatrix, \
UINT32 OperationSet X2DEFAULT(XAUDIO2_COMMIT_NOW)) PURE; \
\
STDMETHOD_(void, GetOutputMatrix) (THIS_ __in_opt IXAudio2Voice* pDestinationVoice, \
UINT32 SourceChannels, UINT32 DestinationChannels, \
__out_ecount(SourceChannels * DestinationChannels) float* pLevelMatrix) PURE; \
\
STDMETHOD_(void, DestroyVoice) (THIS) PURE
Declare_IXAudio2Voice_Methods();
};
#undef INTERFACE
#define INTERFACE IXAudio2SourceVoice
DECLARE_INTERFACE_(IXAudio2SourceVoice, IXAudio2Voice)
{
Declare_IXAudio2Voice_Methods();
STDMETHOD(Start) (THIS_ UINT32 Flags X2DEFAULT(0), UINT32 OperationSet X2DEFAULT(XAUDIO2_COMMIT_NOW)) PURE;
STDMETHOD(Stop) (THIS_ UINT32 Flags X2DEFAULT(0), UINT32 OperationSet X2DEFAULT(XAUDIO2_COMMIT_NOW)) PURE;
STDMETHOD(SubmitSourceBuffer) (THIS_ __in const XAUDIO2_BUFFER* pBuffer, __in_opt const XAUDIO2_BUFFER_WMA* pBufferWMA X2DEFAULT(NULL)) PURE;
STDMETHOD(FlushSourceBuffers) (THIS) PURE;
STDMETHOD(Discontinuity) (THIS) PURE;
STDMETHOD(ExitLoop) (THIS_ UINT32 OperationSet X2DEFAULT(XAUDIO2_COMMIT_NOW)) PURE;
STDMETHOD_(void, GetState) (THIS_ __out XAUDIO2_VOICE_STATE* pVoiceState) PURE;
STDMETHOD(SetFrequencyRatio) (THIS_ float Ratio,
UINT32 OperationSet X2DEFAULT(XAUDIO2_COMMIT_NOW)) PURE;
STDMETHOD_(void, GetFrequencyRatio) (THIS_ __out float* pRatio) PURE;
STDMETHOD(SetSourceSampleRate) (THIS_ UINT32 NewSourceSampleRate) PURE;
};
#undef INTERFACE
#define INTERFACE IXAudio2SubmixVoice
DECLARE_INTERFACE_(IXAudio2SubmixVoice, IXAudio2Voice)
{
Declare_IXAudio2Voice_Methods();
};
#undef INTERFACE
#define INTERFACE IXAudio2MasteringVoice
DECLARE_INTERFACE_(IXAudio2MasteringVoice, IXAudio2Voice)
{
Declare_IXAudio2Voice_Methods();
};
#undef INTERFACE
#define INTERFACE IXAudio2EngineCallback
DECLARE_INTERFACE(IXAudio2EngineCallback)
{
STDMETHOD_(void, OnProcessingPassStart) (THIS) PURE;
STDMETHOD_(void, OnProcessingPassEnd) (THIS) PURE;
STDMETHOD_(void, OnCriticalError) (THIS_ HRESULT Error) PURE;
};
#undef INTERFACE
#define INTERFACE IXAudio2VoiceCallback
DECLARE_INTERFACE(IXAudio2VoiceCallback)
{
STDMETHOD_(void, OnVoiceProcessingPassStart) (THIS_ UINT32 BytesRequired) PURE;
STDMETHOD_(void, OnVoiceProcessingPassEnd) (THIS) PURE;
STDMETHOD_(void, OnStreamEnd) (THIS) PURE;
STDMETHOD_(void, OnBufferStart) (THIS_ void* pBufferContext) PURE;
STDMETHOD_(void, OnBufferEnd) (THIS_ void* pBufferContext) PURE;
STDMETHOD_(void, OnLoopEnd) (THIS_ void* pBufferContext) PURE;
STDMETHOD_(void, OnVoiceError) (THIS_ void* pBufferContext, HRESULT Error) PURE;
};
// IXAudio2
#define IXAudio2_QueryInterface(This,riid,ppvInterface) ((This)->lpVtbl->QueryInterface(This,riid,ppvInterface))
#define IXAudio2_AddRef(This) ((This)->lpVtbl->AddRef(This))
#define IXAudio2_Release(This) ((This)->lpVtbl->Release(This))
#define IXAudio2_GetDeviceCount(This,puCount) ((This)->lpVtbl->GetDeviceCount(This,puCount))
#define IXAudio2_GetDeviceDetails(This,Index,pDeviceDetails) ((This)->lpVtbl->GetDeviceDetails(This,Index,pDeviceDetails))
#define IXAudio2_Initialize(This,Flags,XAudio2Processor) ((This)->lpVtbl->Initialize(This,Flags,XAudio2Processor))
#define IXAudio2_CreateSourceVoice(This,ppSourceVoice,pSourceFormat,Flags,MaxFrequencyRatio,pCallback,pSendList,pEffectChain) ((This)->lpVtbl->CreateSourceVoice(This,ppSourceVoice,pSourceFormat,Flags,MaxFrequencyRatio,pCallback,pSendList,pEffectChain))
#define IXAudio2_CreateSubmixVoice(This,ppSubmixVoice,InputChannels,InputSampleRate,Flags,ProcessingStage,pSendList,pEffectChain) ((This)->lpVtbl->CreateSubmixVoice(This,ppSubmixVoice,InputChannels,InputSampleRate,Flags,ProcessingStage,pSendList,pEffectChain))
#define IXAudio2_CreateMasteringVoice(This,ppMasteringVoice,InputChannels,InputSampleRate,Flags,DeviceIndex,pEffectChain) ((This)->lpVtbl->CreateMasteringVoice(This,ppMasteringVoice,InputChannels,InputSampleRate,Flags,DeviceIndex,pEffectChain))
#define IXAudio2_StartEngine(This) ((This)->lpVtbl->StartEngine(This))
#define IXAudio2_StopEngine(This) ((This)->lpVtbl->StopEngine(This))
#define IXAudio2_CommitChanges(This,OperationSet) ((This)->lpVtbl->CommitChanges(This,OperationSet))
// IXAudio2Voice
#define IXAudio2Voice_GetVoiceDetails(This,pVoiceDetails) ((This)->lpVtbl->GetVoiceDetails(This,pVoiceDetails))
#define IXAudio2Voice_SetOutputVoices(This,pSendList) ((This)->lpVtbl->SetOutputVoices(This,pSendList))
#define IXAudio2Voice_SetEffectChain(This,pEffectChain) ((This)->lpVtbl->SetEffectChain(This,pEffectChain))
#define IXAudio2Voice_EnableEffect(This,EffectIndex,OperationSet) ((This)->lpVtbl->EnableEffect(This,EffectIndex,OperationSet))
#define IXAudio2Voice_DisableEffect(This,EffectIndex,OperationSet) ((This)->lpVtbl->DisableEffect(This,EffectIndex,OperationSet))
#define IXAudio2Voice_GetEffectState(This,EffectIndex,pEnabled) ((This)->lpVtbl->GetEffectState(This,EffectIndex,pEnabled))
#define IXAudio2Voice_SetEffectParameters(This,EffectIndex,pParameters,ParametersByteSize, OperationSet) ((This)->lpVtbl->SetEffectParameters(This,EffectIndex,pParameters,ParametersByteSize,OperationSet))
#define IXAudio2Voice_GetEffectParameters(This,EffectIndex,pParameters,ParametersByteSize) ((This)->lpVtbl->GetEffectParameters(This,EffectIndex,pParameters,ParametersByteSize))
#define IXAudio2Voice_SetFilterParameters(This,pParameters,OperationSet) ((This)->lpVtbl->SetFilterParameters(This,pParameters,OperationSet))
#define IXAudio2Voice_GetFilterParameters(This,pParameters) ((This)->lpVtbl->GetFilterParameters(This,pParameters))
#define IXAudio2Voice_SetOutputFilterParameters(This,pDestinationVoice,pParameters,OperationSet) ((This)->lpVtbl->SetOutputFilterParameters(This,pDestinationVoice,pParameters,OperationSet))
#define IXAudio2Voice_GetOutputFilterParameters(This,pDestinationVoice,pParameters) ((This)->lpVtbl->GetOutputFilterParameters(This,pDestinationVoice,pParameters))
#define IXAudio2Voice_SetVolume(This,Volume,OperationSet) ((This)->lpVtbl->SetVolume(This,Volume,OperationSet))
#define IXAudio2Voice_GetVolume(This,pVolume) ((This)->lpVtbl->GetVolume(This,pVolume))
#define IXAudio2Voice_SetChannelVolumes(This,Channels,pVolumes,OperationSet) ((This)->lpVtbl->SetChannelVolumes(This,Channels,pVolumes,OperationSet))
#define IXAudio2Voice_GetChannelVolumes(This,Channels,pVolumes) ((This)->lpVtbl->GetChannelVolumes(This,Channels,pVolumes))
#define IXAudio2Voice_SetOutputMatrix(This,pDestinationVoice,SourceChannels,DestinationChannels,pLevelMatrix,OperationSet) ((This)->lpVtbl->SetOutputMatrix(This,pDestinationVoice,SourceChannels,DestinationChannels,pLevelMatrix,OperationSet))
#define IXAudio2Voice_GetOutputMatrix(This,pDestinationVoice,SourceChannels,DestinationChannels,pLevelMatrix) ((This)->lpVtbl->GetOutputMatrix(This,pDestinationVoice,SourceChannels,DestinationChannels,pLevelMatrix))
#define IXAudio2Voice_DestroyVoice(This) ((This)->lpVtbl->DestroyVoice(This))
// IXAudio2SourceVoice
#define IXAudio2SourceVoice_GetVoiceDetails IXAudio2Voice_GetVoiceDetails
#define IXAudio2SourceVoice_SetOutputVoices IXAudio2Voice_SetOutputVoices
#define IXAudio2SourceVoice_SetEffectChain IXAudio2Voice_SetEffectChain
#define IXAudio2SourceVoice_EnableEffect IXAudio2Voice_EnableEffect
#define IXAudio2SourceVoice_DisableEffect IXAudio2Voice_DisableEffect
#define IXAudio2SourceVoice_GetEffectState IXAudio2Voice_GetEffectState
#define IXAudio2SourceVoice_SetEffectParameters IXAudio2Voice_SetEffectParameters
#define IXAudio2SourceVoice_GetEffectParameters IXAudio2Voice_GetEffectParameters
#define IXAudio2SourceVoice_SetFilterParameters IXAudio2Voice_SetFilterParameters
#define IXAudio2SourceVoice_GetFilterParameters IXAudio2Voice_GetFilterParameters
#define IXAudio2SourceVoice_SetOutputFilterParameters IXAudio2Voice_SetOutputFilterParameters
#define IXAudio2SourceVoice_GetOutputFilterParameters IXAudio2Voice_GetOutputFilterParameters
#define IXAudio2SourceVoice_SetVolume IXAudio2Voice_SetVolume
#define IXAudio2SourceVoice_GetVolume IXAudio2Voice_GetVolume
#define IXAudio2SourceVoice_SetChannelVolumes IXAudio2Voice_SetChannelVolumes
#define IXAudio2SourceVoice_GetChannelVolumes IXAudio2Voice_GetChannelVolumes
#define IXAudio2SourceVoice_SetOutputMatrix IXAudio2Voice_SetOutputMatrix
#define IXAudio2SourceVoice_GetOutputMatrix IXAudio2Voice_GetOutputMatrix
#define IXAudio2SourceVoice_DestroyVoice IXAudio2Voice_DestroyVoice
#define IXAudio2SourceVoice_Start(This,Flags,OperationSet) ((This)->lpVtbl->Start(This,Flags,OperationSet))
#define IXAudio2SourceVoice_Stop(This,Flags,OperationSet) ((This)->lpVtbl->Stop(This,Flags,OperationSet))
#define IXAudio2SourceVoice_SubmitSourceBuffer(This,pBuffer,pBufferWMA) ((This)->lpVtbl->SubmitSourceBuffer(This,pBuffer,pBufferWMA))
#define IXAudio2SourceVoice_FlushSourceBuffers(This) ((This)->lpVtbl->FlushSourceBuffers(This))
#define IXAudio2SourceVoice_Discontinuity(This) ((This)->lpVtbl->Discontinuity(This))
#define IXAudio2SourceVoice_ExitLoop(This,OperationSet) ((This)->lpVtbl->ExitLoop(This,OperationSet))
#define IXAudio2SourceVoice_GetState(This,pVoiceState) ((This)->lpVtbl->GetState(This,pVoiceState))
#define IXAudio2SourceVoice_SetFrequencyRatio(This,Ratio,OperationSet) ((This)->lpVtbl->SetFrequencyRatio(This,Ratio,OperationSet))
#define IXAudio2SourceVoice_GetFrequencyRatio(This,pRatio) ((This)->lpVtbl->GetFrequencyRatio(This,pRatio))
#define IXAudio2SourceVoice_SetSourceSampleRate(This,NewSourceSampleRate) ((This)->lpVtbl->SetSourceSampleRate(This,NewSourceSampleRate))
// IXAudio2SubmixVoice
#define IXAudio2SubmixVoice_GetVoiceDetails IXAudio2Voice_GetVoiceDetails
#define IXAudio2SubmixVoice_SetOutputVoices IXAudio2Voice_SetOutputVoices
#define IXAudio2SubmixVoice_SetEffectChain IXAudio2Voice_SetEffectChain
#define IXAudio2SubmixVoice_EnableEffect IXAudio2Voice_EnableEffect
#define IXAudio2SubmixVoice_DisableEffect IXAudio2Voice_DisableEffect
#define IXAudio2SubmixVoice_GetEffectState IXAudio2Voice_GetEffectState
#define IXAudio2SubmixVoice_SetEffectParameters IXAudio2Voice_SetEffectParameters
#define IXAudio2SubmixVoice_GetEffectParameters IXAudio2Voice_GetEffectParameters
#define IXAudio2SubmixVoice_SetFilterParameters IXAudio2Voice_SetFilterParameters
#define IXAudio2SubmixVoice_GetFilterParameters IXAudio2Voice_GetFilterParameters
#define IXAudio2SubmixVoice_SetOutputFilterParameters IXAudio2Voice_SetOutputFilterParameters
#define IXAudio2SubmixVoice_GetOutputFilterParameters IXAudio2Voice_GetOutputFilterParameters
#define IXAudio2SubmixVoice_SetVolume IXAudio2Voice_SetVolume
#define IXAudio2SubmixVoice_GetVolume IXAudio2Voice_GetVolume
#define IXAudio2SubmixVoice_SetChannelVolumes IXAudio2Voice_SetChannelVolumes
#define IXAudio2SubmixVoice_GetChannelVolumes IXAudio2Voice_GetChannelVolumes
#define IXAudio2SubmixVoice_SetOutputMatrix IXAudio2Voice_SetOutputMatrix
#define IXAudio2SubmixVoice_GetOutputMatrix IXAudio2Voice_GetOutputMatrix
#define IXAudio2SubmixVoice_DestroyVoice IXAudio2Voice_DestroyVoice
// IXAudio2MasteringVoice
#define IXAudio2MasteringVoice_GetVoiceDetails IXAudio2Voice_GetVoiceDetails
#define IXAudio2MasteringVoice_SetOutputVoices IXAudio2Voice_SetOutputVoices
#define IXAudio2MasteringVoice_SetEffectChain IXAudio2Voice_SetEffectChain
#define IXAudio2MasteringVoice_EnableEffect IXAudio2Voice_EnableEffect
#define IXAudio2MasteringVoice_DisableEffect IXAudio2Voice_DisableEffect
#define IXAudio2MasteringVoice_GetEffectState IXAudio2Voice_GetEffectState
#define IXAudio2MasteringVoice_SetEffectParameters IXAudio2Voice_SetEffectParameters
#define IXAudio2MasteringVoice_GetEffectParameters IXAudio2Voice_GetEffectParameters
#define IXAudio2MasteringVoice_SetFilterParameters IXAudio2Voice_SetFilterParameters
#define IXAudio2MasteringVoice_GetFilterParameters IXAudio2Voice_GetFilterParameters
#define IXAudio2MasteringVoice_SetOutputFilterParameters IXAudio2Voice_SetOutputFilterParameters
#define IXAudio2MasteringVoice_GetOutputFilterParameters IXAudio2Voice_GetOutputFilterParameters
#define IXAudio2MasteringVoice_SetVolume IXAudio2Voice_SetVolume
#define IXAudio2MasteringVoice_GetVolume IXAudio2Voice_GetVolume
#define IXAudio2MasteringVoice_SetChannelVolumes IXAudio2Voice_SetChannelVolumes
#define IXAudio2MasteringVoice_GetChannelVolumes IXAudio2Voice_GetChannelVolumes
#define IXAudio2MasteringVoice_SetOutputMatrix IXAudio2Voice_SetOutputMatrix
#define IXAudio2MasteringVoice_GetOutputMatrix IXAudio2Voice_GetOutputMatrix
#define IXAudio2MasteringVoice_DestroyVoice IXAudio2Voice_DestroyVoice
STDAPI XAudio2Create(__deref_out IXAudio2** ppXAudio2, UINT32 Flags X2DEFAULT(0),
XAUDIO2_PROCESSOR XAudio2Processor X2DEFAULT(XAUDIO2_DEFAULT_PROCESSOR));
// Undo the #pragma pack(push, 1) directive at the top of this file
#pragma pack(pop)
#endif // #ifndef GUID_DEFS_ONLY
#endif
+228
View File
@@ -0,0 +1,228 @@
/* SSNES - A Super Nintendo Entertainment System (SNES) Emulator frontend for libsnes.
* Copyright (C) 2010-2011 - Hans-Kristian Arntzen
*
* Some code herein may be based on code found in BSNES.
*
* SSNES is free software: you can redistribute it and/or modify it under the terms
* of the GNU General Public License as published by the Free Software Found-
* ation, either version 3 of the License, or (at your option) any later version.
*
* SSNES is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
* without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
* PURPOSE. See the GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License along with SSNES.
* If not, see <http://www.gnu.org/licenses/>.
*/
#include "../driver.h"
#include <stdlib.h>
#include <xtl.h>
#include "xaudio-c/xaudio.h"
#include "../general.h"
#define MAX_BUFFERS 16
#define MAX_BUFFERS_MASK 15
struct XAudio : public IXAudio2VoiceCallback
{
XAudio() :
buf(0), pXAudio2(0), pMasteringVoice(0),
pSourceVoice(0), nonblock(false), bufsize(0),
bufptr(0), write_buffer(0), buffers(0), hEvent(0)
{}
~XAudio()
{
if (pSourceVoice)
{
pSourceVoice->Stop(0, XAUDIO2_COMMIT_NOW);
pSourceVoice->DestroyVoice();
}
if (pMasteringVoice)
pMasteringVoice->DestroyVoice();
if (pXAudio2)
pXAudio2->Release();
if (hEvent)
CloseHandle(hEvent);
free(buf);
}
bool init(unsigned rate, unsigned latency)
{
size_t bufsize_ = latency * rate / 1000;
size_t size = bufsize_ * 2 * sizeof(int16_t);
SSNES_LOG("XAudio2: Requesting %d ms latency, using %d ms latency.\n", latency, (int)bufsize_ * 1000 / rate);
if (FAILED(XAudio2Create(&pXAudio2, 0, XAUDIO2_DEFAULT_PROCESSOR)))
return false;
if (FAILED(pXAudio2->CreateMasteringVoice(&pMasteringVoice, 2, rate, 0, 0, NULL)))
return false;
WAVEFORMATEX wfx = {0};
wfx.wFormatTag = WAVE_FORMAT_PCM;
wfx.nChannels = 2;
wfx.nSamplesPerSec = rate;
wfx.nBlockAlign = 2 * sizeof(int16_t);
wfx.wBitsPerSample = sizeof(int16_t) * 8;
wfx.nAvgBytesPerSec = wfx.nSamplesPerSec * wfx.nBlockAlign;
wfx.cbSize = 0;
if (FAILED(pXAudio2->CreateSourceVoice(&pSourceVoice, &wfx,
XAUDIO2_VOICE_NOSRC, XAUDIO2_DEFAULT_FREQ_RATIO, this, 0, 0)))
return false;
hEvent = CreateEvent(0, FALSE, FALSE, 0);
bufsize = size / MAX_BUFFERS;
buf = (uint8_t*)malloc(bufsize * MAX_BUFFERS);
memset(buf, 0, bufsize * MAX_BUFFERS);
if (FAILED(pSourceVoice->Start(0, XAUDIO2_COMMIT_NOW)))
return false;
return true;
}
// It's really 16-bit, but we have to byteswap.
size_t write(const uint8_t *buffer, size_t size)
{
if (nonblock)
{
size_t avail = bufsize * (MAX_BUFFERS - buffers - 1);
if (avail == 0)
return 0;
if (avail < size)
size = avail;
}
unsigned bytes = size;
while (bytes)
{
unsigned need = min(bytes, bufsize - bufptr);
uint8_t *base_write = buf + write_buffer * bufsize + bufptr;
memcpy(base_write, buffer, need);
bufptr += need;
buffer += need;
bytes -= need;
if (bufptr == bufsize)
{
while (buffers == MAX_BUFFERS - 1)
WaitForSingleObject(hEvent, INFINITE);
XAUDIO2_BUFFER xa2buffer = {0};
xa2buffer.AudioBytes = bufsize;
xa2buffer.pAudioData = buf + write_buffer * bufsize;
if (FAILED(pSourceVoice->SubmitSourceBuffer(&xa2buffer, NULL)))
return 0;
InterlockedIncrement(&buffers);
bufptr = 0;
write_buffer = (write_buffer + 1) & MAX_BUFFERS_MASK;
}
}
return size;
}
STDMETHOD_(void, OnBufferStart) (void *) {}
STDMETHOD_(void, OnBufferEnd) (void *)
{
InterlockedDecrement(&buffers);
SetEvent(hEvent);
}
STDMETHOD_(void, OnLoopEnd) (void *) {}
STDMETHOD_(void, OnStreamEnd) () {}
STDMETHOD_(void, OnVoiceError) (void *, HRESULT) {}
STDMETHOD_(void, OnVoiceProcessingPassEnd) () {}
STDMETHOD_(void, OnVoiceProcessingPassStart) (UINT32) {}
uint8_t *buf;
IXAudio2 *pXAudio2;
IXAudio2MasteringVoice *pMasteringVoice;
IXAudio2SourceVoice *pSourceVoice;
bool nonblock;
unsigned bufsize;
unsigned bufptr;
unsigned write_buffer;
volatile long buffers;
HANDLE hEvent;
};
static void *xa_init(const char *device, unsigned rate, unsigned latency)
{
if (latency < 8)
latency = 8; // Do not allow shenanigans.
XAudio *xa = new XAudio;
if (!xa->init(rate, latency))
goto error;
return xa;
error:
SSNES_ERR("Failed to init XAudio2.\n");
delete xa;
return NULL;
}
static ssize_t xa_write(void *data, const void *buf, size_t size)
{
XAudio *xa = (XAudio*)data;
size_t ret = xa->write((const uint8_t*)buf, size);
if (ret == 0 && !xa->nonblock)
return -1;
return ret;
}
static bool xa_stop(void *data)
{
(void)data;
return true;
}
static void xa_set_nonblock_state(void *data, bool state)
{
XAudio *xa = (XAudio*)data;
xa->nonblock = state;
}
static bool xa_start(void *data)
{
(void)data;
return true;
}
static void xa_free(void *data)
{
XAudio *xa = (XAudio*)data;
if (xa)
delete xa;
}
static bool xa_use_float(void *data)
{
(void)data;
return false;
}
const audio_driver_t audio_xdk360 = {
xa_init,
xa_write,
xa_stop,
xa_start,
xa_set_nonblock_state,
xa_free,
xa_use_float,
"xdk360"
};
+189
View File
@@ -0,0 +1,189 @@
/* SSNES - A Super Nintendo Entertainment System (SNES) Emulator frontend for libsnes.
* Copyright (C) 2010-2012 - Hans-Kristian Arntzen
* Copyright (C) 2011-2012 - Daniel De Matteis
*
* Some code herein may be based on code found in BSNES.
*
* SSNES is free software: you can redistribute it and/or modify it under the terms
* of the GNU General Public License as published by the Free Software Found-
* ation, either version 3 of the License, or (at your option) any later version.
*
* SSNES is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
* without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
* PURPOSE. See the GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License along with SSNES.
* If not, see <http://www.gnu.org/licenses/>.
*/
#include <stdint.h>
#include <stdlib.h>
#include <xtl.h>
#include "../driver.h"
#include "../general.h"
#include "../libsnes.hpp"
#include "../console/console_ext_input.h"
#include "xdk360_input.h"
#include "xdk360_video_general.h"
#include "shared.h"
static uint64_t state[4];
static unsigned pads_connected;
static void xdk360_input_poll(void *data)
{
(void)data;
pads_connected = 0;
for (unsigned i = 0; i < 4; i++)
{
XINPUT_STATE state_tmp;
unsigned long retval = XInputGetState(i, &state_tmp);
pads_connected += (retval == ERROR_DEVICE_NOT_CONNECTED) ? 0 : 1;
state[i] = state_tmp.Gamepad.wButtons;
state[i] |= ((state_tmp.Gamepad.sThumbLX < -DEADZONE)) << 16;
state[i] |= ((state_tmp.Gamepad.sThumbLX > DEADZONE)) << 17;
state[i] |= ((state_tmp.Gamepad.sThumbLY > DEADZONE)) << 18;
state[i] |= ((state_tmp.Gamepad.sThumbLY < -DEADZONE)) << 19;
state[i] |= ((state_tmp.Gamepad.sThumbRX < -DEADZONE)) << 20;
state[i] |= ((state_tmp.Gamepad.sThumbRX > DEADZONE)) << 21;
state[i] |= ((state_tmp.Gamepad.sThumbRY > DEADZONE)) << 22;
state[i] |= ((state_tmp.Gamepad.sThumbRY < -DEADZONE)) << 23;
state[i] |= ((state_tmp.Gamepad.bLeftTrigger > 128 ? 1 : 0)) << 24;
state[i] |= ((state_tmp.Gamepad.bRightTrigger > 128 ? 1 : 0)) << 25;
}
}
static int16_t xdk360_input_state(void *data, const struct snes_keybind **binds,
bool port, unsigned device,
unsigned index, unsigned id)
{
(void)data;
unsigned player;
uint64_t button;
player = 0;
if (device != SNES_DEVICE_JOYPAD)
return 0;
if (port == SNES_PORT_2)
{
if(pads_connected < 2)
return 0;
player = 1;
if (device == SNES_DEVICE_MULTITAP)
player += index;
}
button = binds[player][id].joykey;
return (state[player] & button) ? 1 : 0;
}
static void xdk360_free_input(void *data)
{
(void)data;
}
static void* xdk360_input_initialize(void)
{
return (void*)-1;
}
void xdk360_input_init(void)
{
for(unsigned i = 0; i < 4; i++)
xdk360_input_map_dpad_to_stick(g_settings.input.dpad_emulation[i], i);
}
void xdk360_input_map_dpad_to_stick(uint32_t map_dpad_enum, uint32_t controller_id)
{
switch(map_dpad_enum)
{
case DPAD_EMULATION_NONE:
g_settings.input.binds[controller_id][SNES_DEVICE_ID_JOYPAD_UP].joykey = ssnes_platform_keybind_lut[XDK360_DEVICE_ID_JOYPAD_UP];
g_settings.input.binds[controller_id][SNES_DEVICE_ID_JOYPAD_DOWN].joykey = ssnes_platform_keybind_lut[XDK360_DEVICE_ID_JOYPAD_DOWN];
g_settings.input.binds[controller_id][SNES_DEVICE_ID_JOYPAD_LEFT].joykey = ssnes_platform_keybind_lut[XDK360_DEVICE_ID_JOYPAD_LEFT];
g_settings.input.binds[controller_id][SNES_DEVICE_ID_JOYPAD_RIGHT].joykey = ssnes_platform_keybind_lut[XDK360_DEVICE_ID_JOYPAD_RIGHT];
break;
case DPAD_EMULATION_LSTICK:
g_settings.input.binds[controller_id][SNES_DEVICE_ID_JOYPAD_UP].joykey = ssnes_platform_keybind_lut[XDK360_DEVICE_ID_LSTICK_UP_DPAD];
g_settings.input.binds[controller_id][SNES_DEVICE_ID_JOYPAD_DOWN].joykey = ssnes_platform_keybind_lut[XDK360_DEVICE_ID_LSTICK_DOWN_DPAD];
g_settings.input.binds[controller_id][SNES_DEVICE_ID_JOYPAD_LEFT].joykey = ssnes_platform_keybind_lut[XDK360_DEVICE_ID_LSTICK_LEFT_DPAD];
g_settings.input.binds[controller_id][SNES_DEVICE_ID_JOYPAD_RIGHT].joykey = ssnes_platform_keybind_lut[XDK360_DEVICE_ID_LSTICK_RIGHT_DPAD];
break;
case DPAD_EMULATION_RSTICK:
g_settings.input.binds[controller_id][SNES_DEVICE_ID_JOYPAD_UP].joykey = ssnes_platform_keybind_lut[XDK360_DEVICE_ID_RSTICK_UP_DPAD];
g_settings.input.binds[controller_id][SNES_DEVICE_ID_JOYPAD_DOWN].joykey = ssnes_platform_keybind_lut[XDK360_DEVICE_ID_RSTICK_DOWN_DPAD];
g_settings.input.binds[controller_id][SNES_DEVICE_ID_JOYPAD_LEFT].joykey = ssnes_platform_keybind_lut[XDK360_DEVICE_ID_RSTICK_LEFT_DPAD];
g_settings.input.binds[controller_id][SNES_DEVICE_ID_JOYPAD_RIGHT].joykey = ssnes_platform_keybind_lut[XDK360_DEVICE_ID_RSTICK_RIGHT_DPAD];
break;
}
}
static bool xdk360_key_pressed(void *data, int key)
{
(void)data;
XINPUT_STATE state;
bool retval;
XInputGetState(0, &state);
retval = false;
switch(key)
{
case SSNES_FAST_FORWARD_HOLD_KEY:
return ((state.Gamepad.sThumbRY < -DEADZONE) && !(state.Gamepad.bRightTrigger > 128));
case SSNES_LOAD_STATE_KEY:
return ((state.Gamepad.sThumbRY > DEADZONE) && (state.Gamepad.bRightTrigger > 128));
case SSNES_SAVE_STATE_KEY:
return ((state.Gamepad.sThumbRY < -DEADZONE) && (state.Gamepad.bRightTrigger > 128));
case SSNES_STATE_SLOT_PLUS:
return ((state.Gamepad.sThumbRX > DEADZONE) && (state.Gamepad.bRightTrigger > 128));
case SSNES_STATE_SLOT_MINUS:
return ((state.Gamepad.sThumbRX < -DEADZONE) && (state.Gamepad.bRightTrigger > 128));
case SSNES_FRAMEADVANCE:
if(g_console.frame_advance_enable)
{
g_console.menu_enable = true;
g_console.ingame_menu_enable = true;
g_console.mode_switch = MODE_MENU;
}
return false;
case SSNES_REWIND:
return ((state.Gamepad.sThumbRY > DEADZONE) && !(state.Gamepad.bRightTrigger > 128));
case SSNES_QUIT_KEY:
if(IS_TIMER_EXPIRED())
{
uint32_t left_thumb_pressed = (state.Gamepad.wButtons & XINPUT_GAMEPAD_LEFT_THUMB);
uint32_t right_thumb_pressed = (state.Gamepad.wButtons & XINPUT_GAMEPAD_RIGHT_THUMB);
g_console.menu_enable = right_thumb_pressed && left_thumb_pressed && IS_TIMER_EXPIRED();
g_console.ingame_menu_enable = right_thumb_pressed && !left_thumb_pressed;
if(g_console.menu_enable || (g_console.ingame_menu_enable
&& !g_console.menu_enable))
{
g_console.mode_switch = MODE_MENU;
SET_TIMER_EXPIRATION(30);
retval = g_console.menu_enable;
}
retval = g_console.ingame_menu_enable ? g_console.ingame_menu_enable : g_console.menu_enable;
}
}
return retval;
}
const input_driver_t input_xdk360 = {
xdk360_input_initialize,
xdk360_input_poll,
xdk360_input_state,
xdk360_key_pressed,
xdk360_free_input,
"xdk360"};
+37
View File
@@ -0,0 +1,37 @@
/* SSNES - A Super Nintendo Entertainment System (SNES) Emulator frontend for libsnes.
* Copyright (C) 2010-2012 - Hans-Kristian Arntzen
* Copyright (C) 2011-2012 - Daniel De Matteis
*
* Some code herein may be based on code found in BSNES.
*
* SSNES is free software: you can redistribute it and/or modify it under the terms
* of the GNU General Public License as published by the Free Software Found-
* ation, either version 3 of the License, or (at your option) any later version.
*
* SSNES is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
* without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
* PURPOSE. See the GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License along with SSNES.
* If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef _XDK360_INPUT_H
#define _XDK360_INPUT_H
#define XINPUT_GAMEPAD_LSTICK_LEFT_MASK (65536)
#define XINPUT_GAMEPAD_LSTICK_RIGHT_MASK (131072)
#define XINPUT_GAMEPAD_LSTICK_UP_MASK (262144)
#define XINPUT_GAMEPAD_LSTICK_DOWN_MASK (524288)
#define XINPUT_GAMEPAD_RSTICK_LEFT_MASK (1048576)
#define XINPUT_GAMEPAD_RSTICK_RIGHT_MASK (2097152)
#define XINPUT_GAMEPAD_RSTICK_UP_MASK (4194304)
#define XINPUT_GAMEPAD_RSTICK_DOWN_MASK (8388608)
#define XINPUT_GAMEPAD_LEFT_TRIGGER (16777216)
#define XINPUT_GAMEPAD_RIGHT_TRIGGER (33554432)
#define DEADZONE (16000)
extern void xdk360_input_init(void);
extern void xdk360_input_map_dpad_to_stick(uint32_t map_dpad_enum, uint32_t controller_id);
#endif
+680
View File
@@ -0,0 +1,680 @@
/* SSNES - A Super Nintendo Entertainment System (SNES) Emulator frontend for libsnes.
* Copyright (C) 2010-2012 - Hans-Kristian Arntzen
* Copyright (C) 2011-2012 - Daniel De Matteis
*
* Some code herein may be based on code found in BSNES.
*
* SSNES is free software: you can redistribute it and/or modify it under the terms
* of the GNU General Public License as published by the Free Software Found-
* ation, either version 3 of the License, or (at your option) any later version.
*
* SSNES is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
* without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
* PURPOSE. See the GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License along with SSNES.
* If not, see <http://www.gnu.org/licenses/>.
*/
#include <xtl.h>
#include <xgraphics.h>
#include "../driver.h"
#include "xdk360_video.h"
#include "xdk360_video_resources.h"
#include "../general.h"
#include "../message.h"
#include "shared.h"
#ifdef HAVE_CONFIG_H
#include "config.h"
#endif
static bool g_quitting;
static bool g_first_msg;
unsigned g_frame_count;
void *g_d3d;
struct hlsl_program_t
{
D3DXHANDLE vid_size_f;
D3DXHANDLE tex_size_f;
D3DXHANDLE out_size_f;
D3DXHANDLE vid_size_v;
D3DXHANDLE tex_size_v;
D3DXHANDLE out_size_v;
XMMATRIX modelViewProj;
} hlsl_program;
struct XPR_HEADER
{
unsigned long dwMagic;
unsigned long dwHeaderSize;
unsigned long dwDataSize;
};
#define XPR2_MAGIC_VALUE (0x58505232)
PackedResource::PackedResource()
{
m_pSysMemData = NULL;
m_dwSysMemDataSize = 0L;
m_pVidMemData = NULL;
m_dwVidMemDataSize = 0L;
m_pResourceTags = NULL;
m_dwNumResourceTags = 0L;
m_bInitialized = FALSE;
}
PackedResource::~PackedResource()
{
Destroy();
}
void * PackedResource::GetData( const char * strName ) const
{
if( m_pResourceTags == NULL || strName == NULL )
return NULL;
for( unsigned long i = 0; i < m_dwNumResourceTags; i++ )
{
if( !_stricmp( strName, m_pResourceTags[i].strName ) )
return &m_pSysMemData[m_pResourceTags[i].dwOffset];
}
return NULL;
}
HRESULT PackedResource::Create( const char * strFilename )
{
unsigned long dwNumBytesRead;
HANDLE hFile = CreateFile( strFilename, GENERIC_READ, FILE_SHARE_READ, NULL,
OPEN_EXISTING, FILE_ATTRIBUTE_READONLY, NULL );
if( hFile == INVALID_HANDLE_VALUE )
{
SSNES_ERR( "File <%s> not found.\n", strFilename );
return E_FAIL;
}
// Read in and verify the XPR magic header
XPR_HEADER xprh;
if( !ReadFile( hFile, &xprh, sizeof( XPR_HEADER ), &dwNumBytesRead, NULL ) )
{
SSNES_ERR( "Error reading XPR header in file <%s>.\n", strFilename );
CloseHandle( hFile );
return E_FAIL;
}
if( xprh.dwMagic != XPR2_MAGIC_VALUE )
{
SSNES_ERR( "Invalid Xbox Packed Resource (.xpr) file: Magic = 0x%08lx.\n", xprh.dwMagic );
CloseHandle( hFile );
return E_FAIL;
}
// Compute memory requirements
m_dwSysMemDataSize = xprh.dwHeaderSize;
m_dwVidMemDataSize = xprh.dwDataSize;
// Allocate memory
m_pSysMemData = (BYTE*)malloc(m_dwSysMemDataSize);
if( m_pSysMemData == NULL )
{
SSNES_ERR( "Could not allocate system memory.\n" );
m_dwSysMemDataSize = 0;
return E_FAIL;
}
m_pVidMemData = ( BYTE* )XMemAlloc( m_dwVidMemDataSize, MAKE_XALLOC_ATTRIBUTES( 0, 0, 0, 0, eXALLOCAllocatorId_GameMax,
XALLOC_PHYSICAL_ALIGNMENT_4K, XALLOC_MEMPROTECT_WRITECOMBINE, 0, XALLOC_MEMTYPE_PHYSICAL ) );
if( m_pVidMemData == NULL )
{
SSNES_ERR( "Could not allocate physical memory.\n" );
m_dwSysMemDataSize = 0;
m_dwVidMemDataSize = 0;
free(m_pSysMemData);
m_pSysMemData = NULL;
return E_FAIL;
}
// Read in the data from the file
if( !ReadFile( hFile, m_pSysMemData, m_dwSysMemDataSize, &dwNumBytesRead, NULL ) ||
!ReadFile( hFile, m_pVidMemData, m_dwVidMemDataSize, &dwNumBytesRead, NULL ) )
{
SSNES_ERR( "Unable to read Xbox Packed Resource (.xpr) file.\n" );
CloseHandle( hFile );
return E_FAIL;
}
// Done with the file
CloseHandle( hFile );
// Extract resource table from the header data
m_dwNumResourceTags = *( unsigned long * )( m_pSysMemData + 0 );
m_pResourceTags = ( RESOURCE* )( m_pSysMemData + 4 );
// Patch up the resources
for( unsigned long i = 0; i < m_dwNumResourceTags; i++ )
{
m_pResourceTags[i].strName = ( char * )( m_pSysMemData + ( unsigned long )m_pResourceTags[i].strName );
// Fixup the texture memory
if( ( m_pResourceTags[i].dwType & 0xffff0000 ) == ( RESOURCETYPE_TEXTURE & 0xffff0000 ) )
{
D3DTexture* pTexture = ( D3DTexture* )&m_pSysMemData[m_pResourceTags[i].dwOffset];
// Adjust Base address according to where memory was allocated
XGOffsetBaseTextureAddress( pTexture, m_pVidMemData, m_pVidMemData );
}
}
m_bInitialized = TRUE;
return S_OK;
}
void PackedResource::Destroy()
{
delete[] m_pSysMemData;
m_pSysMemData = NULL;
m_dwSysMemDataSize = 0L;
if( m_pVidMemData != NULL )
XMemFree( m_pVidMemData, MAKE_XALLOC_ATTRIBUTES( 0, 0, 0, 0, eXALLOCAllocatorId_GameMax,
0, 0, 0, XALLOC_MEMTYPE_PHYSICAL ) );
m_pVidMemData = NULL;
m_dwVidMemDataSize = 0L;
m_pResourceTags = NULL;
m_dwNumResourceTags = 0L;
m_bInitialized = FALSE;
}
static void xdk360_gfx_free(void * data)
{
if (g_d3d)
return;
xdk360_video_t *vid = (xdk360_video_t*)data;
if (!vid)
return;
D3DResource_Release((D3DResource *)vid->lpTexture);
D3DResource_Release((D3DResource *)vid->vertex_buf);
D3DResource_Release((D3DResource *)vid->pVertexDecl);
D3DResource_Release((D3DResource *)vid->pPixelShader);
D3DResource_Release((D3DResource *)vid->pVertexShader);
D3DDevice_Release(vid->xdk360_render_device);
Direct3D_Release();
free(vid);
}
static void set_viewport(bool force_full)
{
xdk360_video_t *vid = (xdk360_video_t*)g_d3d;
D3DDevice_Clear(vid->xdk360_render_device, 0, NULL, D3DCLEAR_TARGET,
0xff000000, 1.0f, 0, FALSE);
int width = vid->video_mode.fIsHiDef ? 1280 : 640;
int height = vid->video_mode.fIsHiDef ? 720 : 480;
int m_viewport_x_temp, m_viewport_y_temp, m_viewport_width_temp, m_viewport_height_temp;
float m_zNear, m_zFar;
m_viewport_x_temp = 0;
m_viewport_y_temp = 0;
m_viewport_width_temp = width;
m_viewport_height_temp = height;
m_zNear = 0.0f;
m_zFar = 1.0f;
if (!force_full)
{
float desired_aspect = g_settings.video.aspect_ratio;
float device_aspect = (float)width / height;
float delta;
// If the aspect ratios of screen and desired aspect ratio are sufficiently equal (floating point stuff),
//if(g_console.aspect_ratio_index == ASPECT_RATIO_CUSTOM)
//{
// m_viewport_x_temp = g_console.custom_viewport_x;
// m_viewport_y_temp = g_console.custom_viewport_y;
// m_viewport_width_temp = g_console.custom_viewport_width;
// m_viewport_height_temp = g_console.custom_viewport_height;
//}
if (device_aspect > desired_aspect)
{
delta = (desired_aspect / device_aspect - 1.0) / 2.0 + 0.5;
m_viewport_x_temp = (int)(width * (0.5 - delta));
m_viewport_width_temp = (int)(2.0 * width * delta);
width = (unsigned)(2.0 * width * delta);
}
else
{
delta = (device_aspect / desired_aspect - 1.0) / 2.0 + 0.5;
m_viewport_y_temp = (int)(height * (0.5 - delta));
m_viewport_height_temp = (int)(2.0 * height * delta);
height = (unsigned)(2.0 * height * delta);
}
}
D3DVIEWPORT9 vp = {0};
vp.Width = m_viewport_width_temp;
vp.Height = m_viewport_height_temp;
vp.X = m_viewport_x_temp;
vp.Y = m_viewport_y_temp;
vp.MinZ = m_zNear;
vp.MaxZ = m_zFar;
D3DDevice_SetViewport(vid->xdk360_render_device, &vp);
//if(gl->overscan_enable && !force_full)
//{
// m_left = -gl->overscan_amount/2;
// m_right = 1 + gl->overscan_amount/2;
// m_bottom = -gl->overscan_amount/2;
//}
}
static void xdk360_set_orientation(void * data, uint32_t orientation)
{
(void)data;
xdk360_video_t *vid = (xdk360_video_t*)g_d3d;
FLOAT angle;
switch(orientation)
{
case ORIENTATION_NORMAL:
angle = M_PI * 0 / 180;
break;
case ORIENTATION_VERTICAL:
angle = M_PI * 270 / 180;
break;
case ORIENTATION_FLIPPED:
angle = M_PI * 180 / 180;
break;
case ORIENTATION_FLIPPED_ROTATED:
angle = M_PI * 90 / 180;
break;
}
hlsl_program.modelViewProj = XMMatrixRotationZ(angle);
}
void xdk360_set_aspect_ratio(uint32_t aspectratio_index)
{
switch(aspectratio_index)
{
case ASPECT_RATIO_4_3:
g_settings.video.aspect_ratio = 1.33333333333;
strlcpy(g_console.aspect_ratio_name, "4:3", sizeof(g_console.aspect_ratio_name));
break;
case ASPECT_RATIO_5_4:
g_settings.video.aspect_ratio = 1.25;
strlcpy(g_console.aspect_ratio_name, "5:4", sizeof(g_console.aspect_ratio_name));
break;
case ASPECT_RATIO_8_7:
g_settings.video.aspect_ratio = 1.14287142857;
strlcpy(g_console.aspect_ratio_name, "8:7", sizeof(g_console.aspect_ratio_name));
break;
case ASPECT_RATIO_16_9:
g_settings.video.aspect_ratio = 1.777778;
strlcpy(g_console.aspect_ratio_name, "16:9", sizeof(g_console.aspect_ratio_name));
break;
case ASPECT_RATIO_16_10:
g_settings.video.aspect_ratio = 1.6;
strlcpy(g_console.aspect_ratio_name, "16:10", sizeof(g_console.aspect_ratio_name));
break;
case ASPECT_RATIO_16_15:
g_settings.video.aspect_ratio = 3.2;
strlcpy(g_console.aspect_ratio_name, "16:15", sizeof(g_console.aspect_ratio_name));
break;
case ASPECT_RATIO_19_14:
g_settings.video.aspect_ratio = 1.36;
strlcpy(g_console.aspect_ratio_name, "19:14", sizeof(g_console.aspect_ratio_name));
break;
case ASPECT_RATIO_2_1:
g_settings.video.aspect_ratio = 2.0;
strlcpy(g_console.aspect_ratio_name, "2:1", sizeof(g_console.aspect_ratio_name));
break;
case ASPECT_RATIO_3_2:
g_settings.video.aspect_ratio = 1.5;
strlcpy(g_console.aspect_ratio_name, "3:2", sizeof(g_console.aspect_ratio_name));
break;
case ASPECT_RATIO_3_4:
g_settings.video.aspect_ratio = 1.5;
strlcpy(g_console.aspect_ratio_name, "3:4", sizeof(g_console.aspect_ratio_name));
break;
case ASPECT_RATIO_1_1:
g_settings.video.aspect_ratio = 1.0;
strlcpy(g_console.aspect_ratio_name, "1:1", sizeof(g_console.aspect_ratio_name));
break;
case ASPECT_RATIO_AUTO:
strlcpy(g_console.aspect_ratio_name, "(Auto)", sizeof(g_console.aspect_ratio_name));
break;
case ASPECT_RATIO_CUSTOM:
strlcpy(g_console.aspect_ratio_name, "(Custom)", sizeof(g_console.aspect_ratio_name));
break;
}
g_settings.video.force_aspect = false;
set_viewport(false);
}
static void *xdk360_gfx_init(const video_info_t *video, const input_driver_t **input, void **input_data)
{
HRESULT ret;
if (g_d3d)
return g_d3d;
xdk360_video_t *vid = (xdk360_video_t*)calloc(1, sizeof(xdk360_video_t));
if (!vid)
return NULL;
vid->xdk360_device = Direct3DCreate9(D3D_SDK_VERSION);
if (!vid->xdk360_device)
{
free(vid);
return NULL;
}
// Get video settings
memset(&vid->video_mode, 0, sizeof(vid->video_mode));
XGetVideoMode(&vid->video_mode);
memset(&vid->d3dpp, 0, sizeof(vid->d3dpp));
// no letterboxing in 4:3 mode (if widescreen is
// unsupported
if(!vid->video_mode.fIsWideScreen)
vid->d3dpp.Flags |= D3DPRESENTFLAG_NO_LETTERBOX;
vid->d3dpp.BackBufferWidth = vid->video_mode.fIsHiDef ? 1280 : 640;
vid->d3dpp.BackBufferHeight = vid->video_mode.fIsHiDef ? 720 : 480;
vid->d3dpp.BackBufferFormat = g_console.gamma_correction_enable ? (D3DFORMAT)MAKESRGBFMT(D3DFMT_A8R8G8B8) : D3DFMT_A8R8G8B8;
vid->d3dpp.FrontBufferFormat = g_console.gamma_correction_enable ? (D3DFORMAT)MAKESRGBFMT(D3DFMT_LE_X8R8G8B8) : D3DFMT_LE_X8R8G8B8;
vid->d3dpp.MultiSampleType = D3DMULTISAMPLE_NONE;
vid->d3dpp.MultiSampleQuality = 0;
vid->d3dpp.BackBufferCount = 2;
vid->d3dpp.EnableAutoDepthStencil = FALSE;
vid->d3dpp.SwapEffect = D3DSWAPEFFECT_DISCARD;
vid->d3dpp.PresentationInterval = video->vsync ? D3DPRESENT_INTERVAL_ONE : D3DPRESENT_INTERVAL_IMMEDIATE;
// D3DCREATE_HARDWARE_VERTEXPROCESSING is ignored on 360
ret = Direct3D_CreateDevice(D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL, NULL, D3DCREATE_HARDWARE_VERTEXPROCESSING, &vid->d3dpp, &vid->xdk360_render_device);
ID3DXBuffer* pShaderCodeV = NULL;
ID3DXBuffer* pShaderCodeP = NULL;
ID3DXBuffer* pErrorMsg = NULL;
ret = D3DXCompileShaderFromFile(
g_settings.video.cg_shader_path, //filepath
NULL, //macros
NULL, //includes
"main_vertex", // main function
"vs_2_0", // shader profile
0, // flags
&pShaderCodeV, // compiled operations
&pErrorMsg, // errors
NULL); // constants
if (SUCCEEDED(ret))
{
SSNES_LOG("Vertex shader program from [%s] successfully compiled.\n", "game:\\media\\shaders\\stock.cg");
ret = D3DXCompileShaderFromFile(
g_settings.video.cg_shader_path, //filepath
NULL, //macros
NULL, //includes
"main_fragment", // main function
"ps_2_0", // shader profile
0, // flags
&pShaderCodeP, // compiled operations
&pErrorMsg, // errors
NULL); // constants
}
if (FAILED(ret))
{
if(pErrorMsg)
SSNES_LOG("%s\n", (char*)pErrorMsg->GetBufferPointer());
D3DDevice_Release(vid->xdk360_render_device);
Direct3D_Release();
free(vid);
return NULL;
}
else
{
SSNES_LOG("Pixel shader program from [%s] successfully compiled.\n", "game:\\media\\shaders\\stock.cg");
}
vid->pVertexShader = D3DDevice_CreateVertexShader((const DWORD*)pShaderCodeV->GetBufferPointer());
vid->pPixelShader = D3DDevice_CreatePixelShader((const DWORD*)pShaderCodeP->GetBufferPointer());
pShaderCodeV->Release();
pShaderCodeP->Release();
vid->lpTexture = (D3DTexture*) D3DDevice_CreateTexture(512, 512, 1, 1, 0, D3DFMT_LIN_X1R5G5B5,
0, D3DRTYPE_TEXTURE);
D3DLOCKED_RECT d3dlr;
D3DTexture_LockRect(vid->lpTexture, 0, &d3dlr, NULL, D3DLOCK_NOSYSLOCK);
memset(d3dlr.pBits, 0, 512 * d3dlr.Pitch);
D3DTexture_UnlockRect(vid->lpTexture, 0);
vid->last_width = 512;
vid->last_height = 512;
vid->vertex_buf = D3DDevice_CreateVertexBuffer(4 * sizeof(DrawVerticeFormats), 0, 0);
static const DrawVerticeFormats init_verts[] = {
{ -1.0f, -1.0f, 0.0f, 1.0f },
{ 1.0f, -1.0f, 1.0f, 1.0f },
{ -1.0f, 1.0f, 0.0f, 0.0f },
{ 1.0f, 1.0f, 1.0f, 0.0f },
};
void *verts_ptr = (BYTE*)D3DVertexBuffer_Lock(vid->vertex_buf, 0, 0, 0);
memcpy(verts_ptr, init_verts, sizeof(init_verts));
D3DVertexBuffer_Unlock(vid->vertex_buf);
static const D3DVERTEXELEMENT9 VertexElements[] =
{
{ 0, 0 * sizeof(float), D3DDECLTYPE_FLOAT2, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0 },
{ 0, 2 * sizeof(float), D3DDECLTYPE_FLOAT2, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_TEXCOORD, 0 },
D3DDECL_END()
};
vid->pVertexDecl = D3DDevice_CreateVertexDeclaration(VertexElements);
D3DDevice_Clear(vid->xdk360_render_device, 0, NULL, D3DCLEAR_TARGET,
0xff000000, 1.0f, 0, FALSE);
D3DDevice_SetRenderState_CullMode(vid->xdk360_render_device, D3DCULL_NONE);
D3DDevice_SetRenderState_ZEnable(vid->xdk360_render_device, FALSE);
D3DVIEWPORT9 vp = {0};
vp.Width = vid->video_mode.fIsHiDef ? 1280 : 640;
vp.Height = vid->video_mode.fIsHiDef ? 720 : 480;
vp.MinZ = 0.0f;
vp.MaxZ = 1.0f;
D3DDevice_SetViewport(vid->xdk360_render_device, &vp);
xdk360_set_orientation(NULL, g_console.screen_orientation);
return vid;
}
static bool xdk360_gfx_frame(void *data, const void *frame,
unsigned width, unsigned height, unsigned pitch, const char *msg)
{
xdk360_video_t *vid = (xdk360_video_t*)data;
g_frame_count++;
D3DDevice_Clear(vid->xdk360_render_device, 0, NULL, D3DCLEAR_TARGET,
0xff000000, 1.0f, 0, FALSE);
if (vid->last_width != width || vid->last_height != height)
{
D3DLOCKED_RECT d3dlr;
D3DTexture_LockRect(vid->lpTexture, 0, &d3dlr, NULL, D3DLOCK_NOSYSLOCK);
memset(d3dlr.pBits, 0, 512 * d3dlr.Pitch);
D3DTexture_UnlockRect(vid->lpTexture, 0);
float tex_w = width / 512.0f;
float tex_h = height / 512.0f;
const DrawVerticeFormats verts[] = {
{ -1.0f, -1.0f, 0.0f, tex_h },
{ 1.0f, -1.0f, tex_w, tex_h },
{ -1.0f, 1.0f, 0.0f, 0.0f },
{ 1.0f, 1.0f, tex_w, 0.0f },
};
void *verts_ptr = (BYTE*)D3DVertexBuffer_Lock(vid->vertex_buf, 0, 0, 0);
memcpy(verts_ptr, verts, sizeof(verts));
D3DVertexBuffer_Unlock(vid->vertex_buf);
vid->last_width = width;
vid->last_height = height;
}
vid->xdk360_render_device->SetVertexShaderConstantF(0, (FLOAT*)&hlsl_program.modelViewProj, 4);
//TODO: Update the shader constants
D3DLOCKED_RECT d3dlr;
D3DTexture_LockRect(vid->lpTexture, 0, &d3dlr, NULL, D3DLOCK_NOSYSLOCK);
for (unsigned y = 0; y < height; y++)
{
const uint8_t *in = (const uint8_t*)frame + y * pitch;
uint8_t *out = (uint8_t*)d3dlr.pBits + y * d3dlr.Pitch;
memcpy(out, in, width * sizeof(uint16_t));
}
D3DTexture_UnlockRect(vid->lpTexture, 0);
D3DDevice_SetTexture_Inline(vid->xdk360_render_device, 0, vid->lpTexture);
D3DDevice_SetSamplerState(vid->xdk360_render_device, 0, D3DSAMP_MINFILTER, g_settings.video.smooth ? D3DTEXF_LINEAR : D3DTEXF_POINT);
D3DDevice_SetSamplerState(vid->xdk360_render_device, 0, D3DSAMP_MAGFILTER, g_settings.video.smooth ? D3DTEXF_LINEAR : D3DTEXF_POINT);
D3DDevice_SetSamplerState(vid->xdk360_render_device, 0, D3DSAMP_ADDRESSU, D3DTADDRESS_BORDER);
D3DDevice_SetSamplerState(vid->xdk360_render_device, 0, D3DSAMP_ADDRESSV, D3DTADDRESS_BORDER);
D3DDevice_SetVertexShader(vid->xdk360_render_device, vid->pVertexShader);
D3DDevice_SetPixelShader(vid->xdk360_render_device, vid->pPixelShader);
D3DDevice_SetVertexDeclaration(vid->xdk360_render_device, vid->pVertexDecl);
D3DDevice_SetStreamSource_Inline(vid->xdk360_render_device, 0, vid->vertex_buf, 0,
sizeof(DrawVerticeFormats));
D3DDevice_DrawVertices(vid->xdk360_render_device, D3DPT_TRIANGLESTRIP, 0, D3DVERTEXCOUNT(D3DPT_TRIANGLESTRIP, 2));
if (msg)
{
if(IS_TIMER_EXPIRED() || g_first_msg)
{
xdk360_console_format(msg);
g_first_msg = 0;
SET_TIMER_EXPIRATION(30);
}
xdk360_console_draw();
}
if(!vid->block_swap)
D3DDevice_Present(vid->xdk360_render_device);
return true;
}
static void xdk360_set_swap_block_swap (void * data, bool toggle)
{
(void)data;
xdk360_video_t *vid = (xdk360_video_t*)g_d3d;
vid->block_swap = toggle;
if(toggle)
SSNES_LOG("Swap is set to blocked.\n");
else
SSNES_LOG("Swap is set to non-blocked.\n");
}
static void xdk360_swap (void * data)
{
(void)data;
xdk360_video_t *vid = (xdk360_video_t*)g_d3d;
D3DDevice_Present(vid->xdk360_render_device);
}
static void xdk360_gfx_set_nonblock_state(void *data, bool state)
{
xdk360_video_t *vid = (xdk360_video_t*)data;
SSNES_LOG("D3D Vsync => %s\n", state ? "off" : "on");
if(state)
D3DDevice_SetRenderState_PresentInterval(vid->xdk360_render_device, D3DPRESENT_INTERVAL_IMMEDIATE);
else
D3DDevice_SetRenderState_PresentInterval(vid->xdk360_render_device, D3DPRESENT_INTERVAL_ONE);
}
static bool xdk360_gfx_alive(void *data)
{
(void)data;
return !g_quitting;
}
static bool xdk360_gfx_focus(void *data)
{
(void)data;
return true;
}
void xdk360_video_set_vsync(bool vsync)
{
xdk360_gfx_set_nonblock_state(g_d3d, vsync);
}
// 360 needs a working graphics stack before SSNESeven starts.
// To deal with this main.c,
// the top level module owns the instance, and is created beforehand.
// When SSNES gets around to init it, it is already allocated.
// When SSNES wants to free it, it is ignored.
void xdk360_video_init(void)
{
video_info_t video_info = {0};
// Might have to supply correct values here.
video_info.vsync = g_settings.video.vsync;
video_info.force_aspect = false;
video_info.smooth = g_settings.video.smooth;
video_info.input_scale = 2;
g_d3d = xdk360_gfx_init(&video_info, NULL, NULL);
g_first_msg = true;
HRESULT hr = xdk360_console_init("game:\\media\\Arial_12.xpr",
0xff000000, 0xffffffff );
if(FAILED(hr))
{
SSNES_ERR("Couldn't create debug console.\n");
}
}
void xdk360_video_deinit(void)
{
void *data = g_d3d;
g_d3d = NULL;
xdk360_console_deinit();
xdk360_gfx_free(data);
}
const video_driver_t video_xdk360 = {
xdk360_gfx_init,
xdk360_gfx_frame,
xdk360_gfx_set_nonblock_state,
xdk360_gfx_alive,
xdk360_gfx_focus,
NULL,
xdk360_gfx_free,
"xdk360",
xdk360_set_swap_block_swap,
xdk360_swap,
xdk360_set_orientation
};
+84
View File
@@ -0,0 +1,84 @@
/* SSNES - A Super Nintendo Entertainment System (SNES) Emulator frontend for libsnes.
* Copyright (C) 2010-2012 - Hans-Kristian Arntzen
* Copyright (C) 2011-2012 - Daniel De Matteis
*
* Some code herein may be based on code found in BSNES.
*
* SSNES is free software: you can redistribute it and/or modify it under the terms
* of the GNU General Public License as published by the Free Software Found-
* ation, either version 3 of the License, or (at your option) any later version.
*
* SSNES is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
* without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
* PURPOSE. See the GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License along with SSNES.
* If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef _XDK360_VIDEO_H
#define _XDK360_VIDEO_H
#include <stdint.h>
#include "fonts.h"
#include "xdk360_video_general.h"
typedef struct {
float x;
float y;
float z;
float rhw;
float u;
float v;
} primitive_t;
#define DFONT_MAX 4096
#define PRIM_FVF (D3DFVF_XYZRHW | D3DFVF_TEX1)
typedef struct DrawVerticeFormats
{
float x, y;
float u, v;
} DrawVerticeFormats;
typedef struct xdk360_video
{
bool block_swap;
bool vsync;
unsigned last_width, last_height;
IDirect3D9* xdk360_device;
IDirect3DDevice9* xdk360_render_device;
IDirect3DVertexShader9 *pVertexShader;
IDirect3DPixelShader9* pPixelShader;
IDirect3DVertexDeclaration9* pVertexDecl;
IDirect3DVertexBuffer9* vertex_buf;
IDirect3DTexture9* lpTexture;
D3DPRESENT_PARAMETERS d3dpp;
XVIDEO_MODE video_mode;
} xdk360_video_t;
enum
{
ASPECT_RATIO_4_3,
ASPECT_RATIO_5_4,
ASPECT_RATIO_8_7,
ASPECT_RATIO_16_9,
ASPECT_RATIO_16_10,
ASPECT_RATIO_16_15,
ASPECT_RATIO_19_14,
ASPECT_RATIO_2_1,
ASPECT_RATIO_3_2,
ASPECT_RATIO_3_4,
ASPECT_RATIO_1_1,
ASPECT_RATIO_AUTO,
ASPECT_RATIO_CUSTOM
};
void xdk360_video_init(void);
void xdk360_video_deinit(void);
void xdk360_video_set_vsync(bool vsync);
void xdk360_set_aspect_ratio(uint32_t aspectratio_index);
extern void *g_d3d;
#endif
+30
View File
@@ -0,0 +1,30 @@
/* SSNES - A Super Nintendo Entertainment System (SNES) Emulator frontend for libsnes.
* Copyright (C) 2010-2012 - Hans-Kristian Arntzen
* Copyright (C) 2011-2012 - Daniel De Matteis
*
* Some code herein may be based on code found in BSNES.
*
* SSNES is free software: you can redistribute it and/or modify it under the terms
* of the GNU General Public License as published by the Free Software Found-
* ation, either version 3 of the License, or (at your option) any later version.
*
* SSNES is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
* without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
* PURPOSE. See the GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License along with SSNES.
* If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef _XDK360_VIDEO_GENERAL_H
#define _XDK360_VIDEO_GENERAL_H
#define LAST_ASPECT_RATIO ASPECT_RATIO_CUSTOM
#define IS_TIMER_NOT_EXPIRED() (g_frame_count < g_console.timer_expiration_frame_count)
#define IS_TIMER_EXPIRED() (!(IS_TIMER_NOT_EXPIRED()))
#define SET_TIMER_EXPIRATION(value) g_console.timer_expiration_frame_count = g_frame_count + value;
extern unsigned g_frame_count;
#endif
+131
View File
@@ -0,0 +1,131 @@
/* SSNES - A Super Nintendo Entertainment System (SNES) Emulator frontend for libsnes.
* Copyright (C) 2010-2012 - Hans-Kristian Arntzen
* Copyright (C) 2011-2012 - Daniel De Matteis
*
* Some code herein may be based on code found in BSNES.
*
* SSNES is free software: you can redistribute it and/or modify it under the terms
* of the GNU General Public License as published by the Free Software Found-
* ation, either version 3 of the License, or (at your option) any later version.
*
* SSNES is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
* without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
* PURPOSE. See the GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License along with SSNES.
* If not, see <http://www.gnu.org/licenses/>.
*/
#pragma once
#ifndef SSNES360_RESOURCES_H
#define SSNES360_RESOURCES_H
//--------------------------------------------------------------------------------------
// Name tag for resources. An app may initialize this structure, and pass
// it to the resource's Create() function. From then on, the app may call
// GetResource() to retrieve a resource using an ascii name.
//--------------------------------------------------------------------------------------
struct RESOURCE
{
unsigned long dwType;
unsigned long dwOffset;
unsigned long dwSize;
char * strName;
};
// Resource types
enum
{
RESOURCETYPE_USERDATA = ( ( 'U' << 24 ) | ( 'S' << 16 ) | ( 'E' << 8 ) | ( 'R' ) ),
RESOURCETYPE_TEXTURE = ( ( 'T' << 24 ) | ( 'X' << 16 ) | ( '2' << 8 ) | ( 'D' ) ),
RESOURCETYPE_CUBEMAP = ( ( 'T' << 24 ) | ( 'X' << 16 ) | ( 'C' << 8 ) | ( 'M' ) ),
RESOURCETYPE_VOLUMETEXTURE = ( ( 'T' << 24 ) | ( 'X' << 16 ) | ( '3' << 8 ) | ( 'D' ) ),
RESOURCETYPE_VERTEXBUFFER = ( ( 'V' << 24 ) | ( 'B' << 16 ) | ( 'U' << 8 ) | ( 'F' ) ),
RESOURCETYPE_INDEXBUFFER = ( ( 'I' << 24 ) | ( 'B' << 16 ) | ( 'U' << 8 ) | ( 'F' ) ),
RESOURCETYPE_EOF = 0xffffffff
};
//--------------------------------------------------------------------------------------
// Name: PackedResource
//--------------------------------------------------------------------------------------
class PackedResource
{
protected:
unsigned char * m_pSysMemData; // Alloc'ed memory for resource headers etc.
unsigned long m_dwSysMemDataSize;
unsigned char * m_pVidMemData; // Alloc'ed memory for resource data, etc.
unsigned long m_dwVidMemDataSize;
RESOURCE* m_pResourceTags; // Tags to associate names with the resources
unsigned long m_dwNumResourceTags; // Number of resource tags
public:
int m_bInitialized; // Resource is fully initialized
// Loads the resources out of the specified bundle
HRESULT Create( const char * strFilename );
void Destroy();
// Helper function to make sure a resource is registered
D3DResource* RegisterResource( D3DResource* pResource ) const
{
return pResource;
}
// Functions to retrieve resources by their offset
void * GetData( unsigned long dwOffset ) const
{
return &m_pSysMemData[dwOffset];
}
D3DResource* GetResource( unsigned long dwOffset ) const
{
return (( D3DResource* )GetData( dwOffset ) );
}
D3DTexture* GetTexture( unsigned long dwOffset ) const
{
return ( D3DTexture* )GetResource( dwOffset );
}
D3DArrayTexture* GetArrayTexture( unsigned long dwOffset ) const
{
return ( D3DArrayTexture* )GetResource( dwOffset );
}
D3DVertexBuffer* GetVertexBuffer( unsigned long dwOffset ) const
{
return ( D3DVertexBuffer* )GetResource( dwOffset );
}
// Functions to retrieve resources by their name
void * GetData( const char * strName ) const;
D3DResource* GetResource( const char * strName ) const
{
return ( ( D3DResource* )GetData( strName ) );
}
D3DTexture* GetTexture( const char * strName ) const
{
return ( D3DTexture* )GetResource( strName );
}
D3DArrayTexture* GetArrayTexture( const char * strName ) const
{
return ( D3DArrayTexture* )GetResource( strName );
}
D3DVertexBuffer* GetVertexBuffer( const char * strName ) const
{
return ( D3DVertexBuffer* )GetResource( strName );
}
PackedResource();
~PackedResource();
};
#endif
+5
View File
@@ -6,3 +6,8 @@ Devin J. Pohly - <[email protected]>
Chris Moeller - <[email protected]>
- CoreAudio audio driver
Daniel De Matteis - <[email protected]>
- PlayStation 3 port
- XBox 360 XDK port
+61 -21
View File
@@ -2,12 +2,17 @@ include config.mk
TARGET = ssnes tools/ssnes-joyconfig
OBJ = ssnes.o file.o driver.o settings.o dynamic.o message.o rewind.o movie.o autosave.o gfx/gfx_common.o ups.o bps.o strl.o screenshot.o
JOYCONFIG_OBJ = tools/ssnes-joyconfig.o conf/config_file.o strl.o
OBJ = ssnes.o file.o hash.o driver.o settings.o dynamic.o message.o rewind.o gfx/gfx_common.o patch.o compat/compat.o screenshot.o audio/utils.o
JOYCONFIG_OBJ = tools/ssnes-joyconfig.o conf/config_file.o compat/compat.o
HEADERS = $(wildcard */*.h) $(wildcard *.h)
LIBS = -lm
DEFINES = -DHAVE_CONFIG_H
DEFINES = -DHAVE_CONFIG_H -DHAVE_SCREENSHOTS
ifeq ($(REENTRANT_TEST), 1)
DEFINES += -Dmain=ssnes_main
OBJ += console/test.o
endif
ifneq ($(findstring Darwin,$(OS)),)
OSX := 1
@@ -23,17 +28,23 @@ ifneq ($(findstring BSD,$(OS)),)
DYLIB_LIB = -lc
endif
ifeq ($(HAVE_SRC), 1)
LIBS += $(SRC_LIBS)
DEFINES += $(SRC_CFLAGS)
else
OBJ += audio/hermite.o
ifneq ($(findstring Linux,$(OS)),)
LIBS += -lrt
endif
ifeq ($(HAVE_THREADS), 1)
OBJ += autosave.o thread.o
LIBS += -lpthread
endif
ifeq ($(HAVE_CONFIGFILE), 1)
OBJ += conf/config_file.o
endif
ifeq ($(HAVE_BSV_MOVIE), 1)
OBJ += movie.o
endif
ifeq ($(HAVE_NETPLAY), 1)
OBJ += netplay.o
endif
@@ -89,20 +100,24 @@ ifeq ($(HAVE_COREAUDIO), 1)
endif
ifeq ($(HAVE_SDL), 1)
OBJ += gfx/sdl.o gfx/gl.o input/sdl.o audio/sdl.o fifo_buffer.o
OBJ += gfx/sdl_gfx.o gfx/sdlwrap.o input/sdl_input.o audio/sdl_audio.o fifo_buffer.o
DEFINES += $(SDL_CFLAGS) $(BSD_LOCAL_INC)
LIBS += $(SDL_LIBS)
ifeq ($(HAVE_OPENGL), 1)
OBJ += gfx/gl.o
ifeq ($(OSX),1)
LIBS += -framework OpenGL
LIBS += -framework OpenGL
else
LIBS += -lGL
LIBS += -lGL
endif
endif
endif
ifeq ($(HAVE_XVIDEO), 1)
OBJ += gfx/xvideo.o input/x11_input.o
LIBS += $(XVIDEO_LIBS)
DEFINES += $(XVIDEO_CFLAGS)
LIBS += $(XVIDEO_LIBS) $(X11_LIBS) $(XEXT_LIBS)
DEFINES += $(XVIDEO_CFLAGS) $(X11_CFLAGS) $(XEXT_CFLAGS)
endif
ifeq ($(HAVE_CG), 1)
@@ -111,13 +126,23 @@ ifeq ($(HAVE_CG), 1)
endif
ifeq ($(HAVE_XML), 1)
OBJ += gfx/shader_glsl.o gfx/image.o gfx/snes_state.o sha256.o cheats.o
OBJ += cheats.o
LIBS += $(XML_LIBS)
DEFINES += $(XML_CFLAGS)
ifeq ($(HAVE_OPENGL), 1)
OBJ += gfx/shader_glsl.o
endif
endif
ifeq ($(HAVE_XML), 1)
OBJ += gfx/snes_state.o gfx/image.o
else ifeq ($(HAVE_CG), 1)
OBJ += gfx/snes_state.o gfx/image.o
endif
ifeq ($(HAVE_DYLIB), 1)
OBJ += gfx/ext.o audio/ext.o
OBJ += gfx/ext_gfx.o audio/ext_audio.o
LIBS += $(DYLIB_LIB)
endif
@@ -144,26 +169,37 @@ else
LIBS += $(libsnes)
endif
ifeq ($(HAVE_STRL), 1)
DEFINES += -DHAVE_STRL
endif
ifeq ($(HAVE_PYTHON), 1)
DEFINES += $(PYTHON_CFLAGS) -Wno-unused-parameter
LIBS += $(PYTHON_LIBS)
OBJ += gfx/py_state/py_state.o
endif
ifeq ($(HAVE_SINC), 1)
OBJ += audio/sinc.o
else
OBJ += audio/hermite.o
endif
ifneq ($(V),1)
Q := @
endif
CFLAGS += -Wall -O3 -g -I. -pedantic
OPTIMIZE_FLAG = -O3
ifeq ($(DEBUG), 1)
OPTIMIZE_FLAG = -O0
endif
CFLAGS += -Wall $(OPTIMIZE_FLAG) -g -I. -pedantic
ifeq ($(CXX_BUILD), 1)
CFLAGS += -std=c++0x -xc++ -D__STDC_CONSTANT_MACROS
else
ifneq ($(findstring icc,$(CC)),)
CFLAGS += -std=c99
CFLAGS += -std=c99 -D_GNU_SOURCE
else
CFLAGS += -std=gnu99
endif
endif
all: $(TARGET) config.mk
@@ -176,7 +212,11 @@ ssnes: $(OBJ)
@$(if $(Q), $(shell echo echo LD $@),)
tools/ssnes-joyconfig: $(JOYCONFIG_OBJ)
ifeq ($(CXX_BUILD), 1)
$(Q)$(CXX) -o $@ $(JOYCONFIG_OBJ) $(SDL_LIBS) $(LDFLAGS) $(LIBRARY_DIRS)
else
$(Q)$(CC) -o $@ $(JOYCONFIG_OBJ) $(SDL_LIBS) $(LDFLAGS) $(LIBRARY_DIRS)
endif
@$(if $(Q), $(shell echo echo LD $@),)
%.o: %.c config.h config.mk $(HEADERS)
+157
View File
@@ -0,0 +1,157 @@
SSNES_VERSION = "0.9.5"
#which compiler to build with - GCC or SNC
#set to GCC for debug builds for use with debugger
CELL_BUILD_TOOLS = SNC
CELL_GPU_TYPE = RSX
CELL_PSGL_VERSION = ultra-opt
DEBUG = 0
DOWNLOAD_SHADERS = 1
STRIPPING_ENABLE = 0
HAVE_SSNES_GL = 0
HAVE_LOGGER = 0
CONTENT_ID_FULL = UP0001-SSNE10000_00-0000000000000001
CONTENT_ID = SSNE10000
PC_DEVELOPMENT_IP_ADDRESS = "192.168.1.7"
PC_DEVELOPMENT_UDP_PORT = 3490
CELL_MK_DIR ?= $(CELL_SDK)/samples/mk
include $(CELL_MK_DIR)/sdk.makedef.mk
PPU_TARGET = ssnes.elf
SALAMANDER_TARGET = ssnes-salamander.elf
EBOOT_PATH = ps3/pkg/USRDIR/EBOOT.BIN
CORE_PATH = ps3/pkg/USRDIR/cores/CORE.SELF
LDDIRS = -L. -L$(CELL_SDK)/target/ppu/lib/PSGL/RSX/ultra-opt
INCDIRS = -I. -Ips3 -Icommon
PKG_SCRIPT = ps3/ps3py/pkg.py
ifeq ($(shell uname), Linux)
PKG_FINALIZE = package_finalize
MAKE_SELF_WC = make_self_wc
MAKE_SELF = make_self_npdrm
PYTHON2 = python2
GIT = git
else
PKG_FINALIZE = package_finalize.exe
MAKE_SELF_WC = make_self_wc.exe
MAKE_SELF = make_self_npdrm.exe
PYTHON2 = python2.exe
GIT = git.exe
endif
PPU_SRCS = console/griffin/griffin.c \
console/szlib/szlib.c
ifeq ($(HAVE_SSNES_GL), 1)
DEFINES = -DHAVE_SSNES_GL
GL_LIBS := -lSSNESGL -lSSNESGLcgc
else
GL_LIBS := -L$(CELL_SDK)/target/ppu/lib/PSGL/RSX/ultra-opt -lPSGL -lPSGLcgc
endif
ifeq ($(CELL_BUILD_TOOLS), SNC)
PPU_CXXLD = $(CELL_SDK)/host-win32/sn/bin/ps3ppuld.exe
PPU_CXX = $(CELL_SDK)/host-win32/sn/bin/ps3ppusnc.exe
PPU_CC = $(CELL_SDK)/host-win32/sn/bin/ps3ppusnc.exe
else
PPU_CXX = $(CELL_SDK)/host-win32/ppu/bin/ppu-lv2-g++.exe
PPU_CC = $(CELL_SDK)/host-win32/ppu/bin/ppu-lv2-gcc.exe
PPU_CXXLD = $(CELL_SDK)/host-win32/ppu/bin/ppu-lv2-ld.exe
endif
PPU_LDLIBS = -ldbgfont $(GL_LIBS) -lsnes -lcgc -lgcm_cmd -lgcm_sys_stub -lresc_stub -lm -lio_stub -lfs_stub -lsysutil_stub -lsysutil_game_stub -lsysutil_screenshot_stub -lsysutil_np_stub -lpngdec_stub -ljpgdec_stub -lsysmodule_stub -laudio_stub -lnet_stub -lnetctl_stub -lpthread
DEFINES += -DSSNES_CONSOLE -DHAVE_OPENGL -DHAVE_CG -DHAVE_FBO -DHAVE_RSOUND -DHAVE_ZLIB -D__CELLOS_LV2__ -DHAVE_CONFIGFILE=1 -DHAVE_NETPLAY=1 -DHAVE_SOCKET_LEGACY=1 -DHAVE_GRIFFIN=1 -DPACKAGE_VERSION=\"$(SSNES_VERSION)\" -Dmain=ssnes_main -DPC_DEVELOPMENT_IP_ADDRESS=\"$(PC_DEVELOPMENT_IP_ADDRESS)\" -DPC_DEVELOPMENT_UDP_PORT=$(PC_DEVELOPMENT_UDP_PORT)
ifeq ($(DEBUG), 1)
PPU_OPTIMIZE_LV := -O0 -g
else
PPU_OPTIMIZE_LV := -O3 -g
endif
PPU_CFLAGS = $(PPU_OPTIMIZE_LV) $(INCDIRS) $(DEFINES)
PPU_CXXFLAGS = $(PPU_OPTIMIZE_LV) $(INCDIRS) $(DEFINES)
ifeq ($(HAVE_LOGGER), 1)
PPU_CFLAGS += -DHAVE_LOGGER
PPU_SRCS += console/logger/logger.c
endif
EXIST_EBOOT_WILDCARD := $(wildcard $(EBOOT_PATH))
EXIST_CORE_WILDCARD := $(wildcard $(CORE_PATH))
EBOOT_EXISTS = 1
CORE_EXISTS = 1
ifneq ($(strip $(EXIST_EBOOT_WILDCARD)),)
EBOOT_EXISTS = 0
endif
ifneq ($(strip $(EXIST_CORE_WILDCARD)),)
CORE_EXISTS = 0
endif
include $(CELL_MK_DIR)/sdk.target.mk
MAKE_FSELF = $(CELL_SDK)/host-win32/bin/make_fself.exe
MAKE_FSELF_NPDRM = $(CELL_SDK)/host-win32/bin/make_fself_npdrm.exe
MAKE_PACKAGE_NPDRM = $(CELL_SDK)/host-win32/bin/make_package_npdrm.exe
.PHONY: create-selfs-npdrm create-npdrm-core create-core create-npdrm-salamander create-npdrm-salamander create-shaders clean-selfs
create-npdrm-core:
$(MAKE_FSELF_NPDRM) $(PPU_TARGET) $(CORE_PATH)
create-core:
$(MAKE_SELF_WC) $(PPU_TARGET) $(CORE_PATH)
create-npdrm-salamander:
$(MAKE_FSELF_NPDRM) $(SALAMANDER_TARGET) $(EBOOT_PATH)
create-salamander:
$(MAKE_SELF) $(SALAMANDER_TARGET) $(EBOOT_PATH) $(CONTENT_ID_FULL)
create-shaders:
ifeq ($(DOWNLOAD_SHADERS),1)
$(RM) -rf ps3/pkg/USRDIR/cores/shaders
$(GIT) clone git://github.com/twinaphex/common-shaders.git ps3/pkg/USRDIR/cores/shaders
endif
pkg: $(PPU_TARGET) create-shaders create-npdrm-salamander create-npdrm-core
$(MAKE_PACKAGE_NPDRM) ps3/pkg/package.conf ps3/pkg
pkg-signed: $(PPU_TARGET) create-shaders create-salamander create-core
$(PYTHON2) $(PKG_SCRIPT) --contentid $(CONTENT_ID_FULL) ps3/pkg/ ssnes-ps3-cfw-$(SSNES_VERSION).pkg
pkg-signed-standalone: $(PPU_TARGET) create-shaders create-core
$(MAKE_SELF) $(PPU_TARGET) $(EBOOT_PATH) $(CONTENT_ID)
$(PYTHON2) $(PKG_SCRIPT) --contentid $(CONTENT_ID_FULL) ps3/pkg/ ssnes-ps3-cfw-$(SSNES_VERSION).pkg
pkg-signed-cfw: $(PPU_TARGET) create-shaders create-salamander create-core
$(PYTHON2) $(PKG_SCRIPT) --contentid $(CONTENT_ID_FULL) ps3/pkg/ ssnes-ps3-cfw-$(SSNES_VERSION)-kmeaw.pkg
$(PKG_FINALIZE) ssnes-ps3-cfw-$(SSNES_VERSION)-kmeaw.pkg
pkg-signed-cfw-standalone: $(PPU_TARGET) create-shaders create-core
$(MAKE_SELF) $(PPU_TARGET) $(EBOOT_PATH) $(CONTENT_ID)
$(PYTHON2) $(PKG_SCRIPT) --contentid $(CONTENT_ID_FULL) ps3/pkg/ ssnes-ps3-cfw-$(SSNES_VERSION).pkg
$(PKG_FINALIZE) ssnes-ps3-cfw-$(SSNES_VERSION)-kmeaw.pkg
clean-selfs:
ifeq ($(EBOOT_EXISTS),1)
@echo "WARNING: Couldn't find file to delete: [$(EBOOT_PATH)], skipping this step."
else
rm $(EBOOT_PATH)
endif
ifeq ($(CORE_EXISTS),1)
@echo "WARNING: Couldn't find file to delete: [$(CORE_PATH)], skipping this step."
else
rm $(CORE_PATH)
endif
+50
View File
@@ -0,0 +1,50 @@
CELL_BUILD_TOOLS = SNC
CELL_SDK ?= /usr/local/cell
CELL_GPU_TYPE = RSX
CELL_PSGL_VERSION = opt
HAVE_LOGGER = 0
CELL_MK_DIR ?= $(CELL_SDK)/samples/mk
include $(CELL_MK_DIR)/sdk.makedef.mk
MAKE_SELF_WC = make_self_wc
MAKE_SELF = make_self_npdrm
PKG_SCRIPT = ps3/ps3py/pkg.py
PKG_FINALIZE = package_finalize
STRIP = $(CELL_SDK)/host-win32/ppu/bin/ppu-lv2-strip.exe
COPY = cp
MOVE = mv
PPU_CFLAGS += -I. -D__CELLOS_LV2__
PPU_SRCS = ps3/salamander/main.c compat/compat.c conf/config_file.c
ifeq ($(HAVE_LOGGER), 1)
PPU_CFLAGS += -DHAVE_LOGGER
PPU_SRCS += console/logger/logger.c
endif
PPU_TARGET = ssnes-salamander.elf
ifeq ($(CELL_BUILD_TOOLS),SNC)
PPU_CFLAGS += -Xbranchless=1 -Xfastmath=1 -Xassumecorrectsign=1 -Xassumecorrectalignment=1 -Xunroll=1 -Xautovecreg=1
PPU_CXXFLAGS += -Xbranchless=1 -Xfastmath=1 -Xassumecorrectsign=1 -Xassumecorrectalignment=1 -Xunroll=1 -Xautovecreg=1
PPU_CXXLD = $(CELL_SDK)/host-win32/sn/bin/ps3ppuld.exe
PPU_CXX = $(CELL_SDK)/host-win32/sn/bin/ps3ppusnc.exe
PPU_CC = $(CELL_SDK)/host-win32/sn/bin/ps3ppusnc.exe
else
PPU_CXX = $(CELL_SDK)/host-win32/ppu/bin/ppu-lv2-g++.exe
PPU_CC = $(CELL_SDK)/host-win32/ppu/bin/ppu-lv2-gcc.exe
PPU_CXXLD = $(CELL_SDK)/host-win32/ppu/bin/ppu-lv2-ld.exe
endif
PPU_LDLIBS += -lpthread -lm -lnet_stub -lnetctl_stub -lm -ldbgfont_gcm -lgcm_cmd -lgcm_sys_stub -lio_stub -lsysmodule_stub -lsysutil_stub -lsysutil_game_stub -lfs_stub -lsysutil_np_stub
PPU_OPTIMIZE_LV := -O2
include $(CELL_MK_DIR)/sdk.target.mk
MAKE_FSELF = $(CELL_SDK)/host-win32/bin/make_fself.exe
MAKE_FSELF_NPDRM = $(CELL_SDK)/host-win32/bin/make_fself_npdrm.exe
MAKE_PACKAGE_NPDRM = $(CELL_SDK)/host-win32/bin/make_package_npdrm.exe
+67
View File
@@ -0,0 +1,67 @@
###
##
# Makefile for SSNES Wii.
## Doesn't really work yet, beware :V
###
##
DEBUG = 0
HAVE_LOGGER = 0
PC_DEVELOPMENT_IP_ADDRESS = "192.168.1.7"
PC_DEVELOPMENT_UDP_PORT = 3490
CC = $(DEVKITPPC)/bin/powerpc-eabi-gcc
CXX = $(DEVKITPPC)/bin/powerpc-eabi-g++
LD = $(DEVKITPPC)/bin/powerpc-eabi-ld
DOL_TARGET := ssnes.dol
ELF_TARGET := ssnes.elf
INCLUDE := -I. -I$(DEVKITPRO)/libogc/include
LIBDIRS := -L$(DEVKITPRO)/libogc/lib/wii -L.
MACHDEP := -DGEKKO -mrvl -mcpu=750 -meabi -mhard-float
CFLAGS += -Wall -std=gnu99 $(MACHDEP) $(INCLUDE)
CXXFLAGS += -Wall -std=gnu99 $(MACHDEP) $(INCLUDE)
LDFLAGS := $(MACHDEP)
LIBS := -lfat -lsnes -lwiiuse -logc -lbte -lfreetype
OBJ = wii/main.o fifo_buffer.o ssnes.o driver.o gfx/fonts.o file.o settings.o message.o rewind.o movie.o ups.o bps.o strl.o screenshot.o audio/hermite.o dynamic.o audio/utils.o conf/config_file.o wii/audio.o wii/input.o wii/video.o console/sgui/sgui.o console/sgui/list.o console/sgui/font.bmpobj console/main_wrap.o console/console_ext.o console/szlib/szlib.o
ifeq ($(HAVE_LOGGER), 1)
CFLAGS += -DHAVE_LOGGER
OBJ += console/logger/logger.o
endif
CFLAGS += -std=gnu99 -DSSNES_CONSOLE -DHAVE_CONFIGFILE=1 -DHAVE_GETOPT_LONG -DHAVE_FREETYPE -DPACKAGE_VERSION=\"0.9.5\" -Dmain=ssnes_main -Wno-char-subscripts -DPC_DEVELOPMENT_IP_ADDRESS=\"$(PC_DEVELOPMENT_IP_ADDRESS)\" -DPC_DEVELOPMENT_UDP_PORT=$(PC_DEVELOPMENT_UDP_PORT)
ifeq ($(DEBUG), 1)
CFLAGS += -O0 -g
CXXFLAGS += -O0 -g
else
CLFAGS += -O3
CXXFLAGS += -O3
endif
all: $(DOL_TARGET)
%.dol: %.elf
$(DEVKITPPC)/bin/elf2dol $< $@
$(ELF_TARGET): $(OBJ)
$(CXX) -o $@ $(LDFLAGS) $(LIBDIRS) $(OBJ) $(LIBS)
%.o: %.c
$(CC) $(CFLAGS) -c -o $@ $<
%.bmpobj: %.bmp
$(LD) -r -b binary -o $@ $<
clean:
rm -f $(DOL_TARGET)
rm -f $(ELF_TARGET)
rm -f $(OBJ)
.PHONY: clean
+56 -20
View File
@@ -1,7 +1,7 @@
TARGET = ssnes.exe
JTARGET = ssnes-joyconfig.exe
OBJ = ssnes.o file.o driver.o conf/config_file.o settings.o dynamic.o message.o rewind.o movie.o autosave.o gfx/gfx_common.o bps.o ups.o strl.o screenshot.o audio/hermite.o
JOBJ = conf/config_file.o tools/main-stub.o tools/ssnes-joyconfig.o strl.o
OBJ = ssnes.o file.o driver.o conf/config_file.o settings.o hash.o dynamic.o message.o rewind.o movie.o gfx/gfx_common.o patch.o compat/compat.o screenshot.o audio/utils.o
JOBJ = conf/config_file.o tools/ssnes-joyconfig.o compat/compat.o
CC = gcc
CXX = g++
@@ -10,8 +10,11 @@ HAVE_DINPUT = 1
HAVE_XAUDIO = 1
HAVE_DSOUND = 1
HAVE_SDL = 1
HAVE_OPENGL = 1
HAVE_DYLIB = 1
HAVE_NETPLAY = 1
HAVE_THREADS = 1
DYNAMIC = 1
ifeq ($(SLIM),)
HAVE_SDL_IMAGE = 1
@@ -26,17 +29,31 @@ endif
libsnes ?= -lsnes
LIBS = -lm -lshlwapi
DEFINES = -I. -DHAVE_CONFIGFILE
LDFLAGS = -L. -static-libgcc -s
LDCXXFLAGS = -static-libstdc++
LIBS = -lm
DEFINES = -I. -DHAVE_CONFIGFILE -DHAVE_SCREENSHOTS -DHAVE_BSV_MOVIE -DPACKAGE_VERSION=\"0.9.5\"
LDFLAGS = -L. -static-libgcc
LDCXXFLAGS = -s
ifeq ($(TDM_GCC),)
LDCXXFLAGS += -static-libstdc++
endif
ifeq ($(HAVE_SDL), 1)
OBJ += gfx/sdl.o gfx/gl.o input/sdl.o audio/sdl.o fifo_buffer.o
LIBS += -lSDL -lopengl32
OBJ += gfx/sdl_gfx.o gfx/gl.o gfx/sdlwrap.o input/sdl_input.o audio/sdl_audio.o fifo_buffer.o
LIBS += -lSDL
DEFINES += -ISDL -DHAVE_SDL
endif
ifeq ($(HAVE_THREADS), 1)
OBJ += autosave.o thread.o
DEFINES += -DHAVE_THREADS
endif
ifeq ($(HAVE_OPENGL), 1)
DEFINES += -DHAVE_OPENGL
LIBS += -lopengl32
endif
ifeq ($(HAVE_SDL_IMAGE), 1)
LIBS += -lSDL_image
DEFINES += -DHAVE_SDL_IMAGE
@@ -67,7 +84,7 @@ ifeq ($(HAVE_RSOUND), 1)
endif
ifeq ($(HAVE_XML), 1)
OBJ += gfx/shader_glsl.o gfx/image.o gfx/snes_state.o sha256.o cheats.o
OBJ += gfx/shader_glsl.o gfx/image.o gfx/snes_state.o cheats.o
DEFINES += -Ilibxml2 -DHAVE_XML
LIBS += -lxml2 -liconv
endif
@@ -99,7 +116,7 @@ ifeq ($(HAVE_FBO), 1)
endif
ifeq ($(HAVE_DYLIB), 1)
OBJ += gfx/ext.o audio/ext.o
OBJ += gfx/ext_gfx.o audio/ext_audio.o
endif
ifeq ($(HAVE_PYTHON), 1)
@@ -117,15 +134,31 @@ endif
ifeq ($(HAVE_FFMPEG), 1)
LIBS += -lavformat -lavcodec -lavutil -lswscale -lws2_32 -lz
DEFINES += -DHAVE_FFMPEG -Iffmpeg
DEFINES += -DHAVE_FFMPEG_ALLOC_CONTEXT3
DEFINES += -DHAVE_FFMPEG_AVCODEC_OPEN2
DEFINES += -DHAVE_FFMPEG_AVIO_OPEN
DEFINES += -DHAVE_FFMPEG_AVFORMAT_WRITE_HEADER
DEFINES += -DHAVE_FFMPEG_AVFORMAT_NEW_STREAM
DEFINES += -DHAVE_X264RGB
OBJ += record/ffemu.o
endif
ifneq ($(V),1)
ifeq ($(HAVE_SINC), 1)
OBJ += audio/sinc.o
else
OBJ += audio/hermite.o
endif
ifneq ($(V), 1)
Q := @
endif
CFLAGS += -Wall -O3 -std=gnu99 -I.
CXXFLAGS += -Wall -O3 -pedantic -I.
CFLAGS += -Wall -O3 -I.
ifeq ($(CXX_BUILD), 1)
CFLAGS += -std=c++0x -xc++ -D__STDC_CONSTANT_MACROS
else
CFLAGS += -std=gnu99
endif
all: $(TARGET) $(JTARGET)
@@ -137,13 +170,12 @@ $(TARGET): $(OBJ)
$(Q)$(CC) $(CFLAGS) $(DEFINES) -c -o $@ $<
@$(if $(Q), $(shell echo echo CC $<),)
%.o: %.cpp
$(Q)$(CXX) $(CXXFLAGS) $(DEFINES) -c -o $@ $<
@$(if $(Q), $(shell echo echo CXX $<),)
$(JTARGET): $(JOBJ)
ifeq ($(CXX_BUILD), 1)
$(Q)$(CXX) -o $@ $(JOBJ) -lSDL $(LDFLAGS)
else
$(Q)$(CC) -o $@ $(JOBJ) -lSDL $(LDFLAGS)
endif
@$(if $(Q), $(shell echo echo LD $@),)
clean:
@@ -160,17 +192,21 @@ clean:
rm -f tools/*.o
dist_x86: all
zip -r ssnes-win32-0.8.zip $(TARGET) $(JTARGET) ssnes.cfg snes.dll SDL.dll
zip -r ssnes-win32-0.9.5.zip $(TARGET) $(JTARGET) ssnes.cfg snes.dll SDL.dll
dist_x86_64: all
zip -r ssnes-win64-0.8.zip $(TARGET) $(JTARGET) ssnes.cfg snes.dll SDL.dll
zip -r ssnes-win64-0.9.5.zip $(TARGET) $(JTARGET) ssnes.cfg snes.dll SDL.dll
libs_x86:
wget https://github.com/downloads/Themaister/SSNES/SSNES-win32-libs.zip --no-check-certificate
unzip SSNES-win32-libs.zip
wget https://github.com/downloads/Themaister/SSNES/SSNES-win32-headers.zip --no-check-certificate
unzip SSNES-win32-headers.zip
libs_x86_64:
wget https://github.com/downloads/Themaister/SSNES/SSNES-win64-libs.zip --no-check-certificate
unzip SSNES-win64-libs.zip
wget https://github.com/downloads/Themaister/SSNES/SSNES-win64-headers.zip --no-check-certificate
unzip SSNES-win64-headers.zip
.PHONY: all install uninstall clean dist_x86 dist_x86_64 libs_x86 libs_x86_64
+55
View File
@@ -0,0 +1,55 @@
###
##
# Makefile for SSNES libxenon.
##
###
##
DEBUG = 0
CC = xenon-gcc
CXX = xenon-g++
OBJCOPY = xenon-objcopy
STRIP = xenon-strip
PPU_TARGET := ssnes-libxenon.elf
PPU_TARGET_ADJUSTED := ssnes-libxenon.elf32
LDDIRS = -L. -L$(DEVKITXENON)/usr/lib -L$(DEVKITXENON)/xenon/lib/32
INCDIRS = -I. -I$(DEVKITXENON)/usr/include
OBJ = fifo_buffer.o ssnes.o driver.o file.o settings.o message.o rewind.o movie.o gfx/gfx_common.o ups.o bps.o strl.o screenshot.o audio/hermite.o dynamic.o audio/utils.o conf/config_file.o xenon/main.o xenon/xenon360_audio.o xenon/xenon360_input.o xenon/xenon360_video.o
LIBS = -lsnes -lxenon -lm -lc
DEFINES = -std=gnu99 -DHAVE_CONFIGFILE=1 -DPACKAGE_VERSION=\"0.9.5\" -DSSNES_CONSOLE -DHAVE_GETOPT_LONG=1 -Dmain=ssnes_main
DEFINES += -maltivec -mhard-float -m32 -mpowerpc64 -mcpu=cell -mtune=cell -fno-pic -g -Wall -DXENON $(INCDIRS)
DEFINES += -u read -u _start -u exc_base
ifeq ($(DEBUG), 1)
OPTIMIZE_LV := -O0 -g
else
OPTIMIZE_LV := -O3
endif
all: $(PPU_TARGET_ADJUSTED)
CFLAGS := $(OPTIMIZE_LV) $(DEFINES)
LDFLAGS := -m32 -n -T $(DEVKITXENON)/app.lds
$(PPU_TARGET_ADJUSTED): $(PPU_TARGET)
$(OBJCOPY) -O elf32-powerpc --adjust-vma 0x80000000 $< $@
$(STRIP) $@
$(PPU_TARGET): $(OBJ)
$(CXX) -o $@ $(OBJ) $(LDFLAGS) $(LDDIRS) $(LIBS)
%.o: %.c config.h
$(CC) $(CFLAGS) -c -o $@ $<
clean:
rm -f $(PPU_TARGET)
rm -f $(OBJ)
.PHONY: clean
+53
View File
@@ -7,11 +7,23 @@ SSNES is a simple frontend for the libsnes library.
libsnes is the emulator core of [bSNES](http://www.byuu.org), the most accurate SNES emulator to date, in library form. The libsnes API has been implemented by SNES9x as well, allowing multiple different cores to be used for an emulator that supports libsnes.
This enables the possibility of custom front-ends for the emulator.
# Binaries
Latest Windows binaries are currently hosted on my [homepage](http://themaister.net/ssnes.html).
# Philosophy
SSNES attempts to be very small and lean, while still having all the useful core features expected from an emulator.
It is used through command-line.
# Platforms
SSNES has been ported to the following platforms :
- PlayStation3
- Xbox 360 (Libxenon/XeXDK)
- Wii (Libogc)
# Dependencies
SSNES requires these libraries to build:
@@ -82,7 +94,48 @@ In MSYS:
<tt>mingw32-make -f Makefile.win32 libs</tt>. # You will need to have wget in your patch for this command! MSYS should provide this.</br>
<tt>mingw32-make -f Makefile.win32</tt>
<b>Win32 (MSVC)</b><br />
In addition to Mingw, it is also possible to compile a Win32 version of SSNES with Microsoft Visual Studio 2010.
You will need Microsoft Visual Studio 2010 intalled (or higher) in order to compile SSNES with the MSVC compiler.
The solution file can be found at the following location:
<tt>msvc/SSNES/SSNES.sln</tt>
<b>PlayStation3</b><br/>
<tt>make -f Makefile.ps3</tt>
A PKG file will be built which you will be able to install on a jailbroken PS3.
NOTE: A pre-existing libsnes library needs to be present in the root directory in order to link SSNES PS3. This file needs to be called 'libsnes.a'.
<b> Xbox 360 (XeXDK)</b><br />
You will need Microsoft Visual Studio 2010 installed (or higher) in order to compile SSNES 360.
The solution file can be found at the following location:
<tt>msvc-360/SSNES-360/SSNES-360.sln</tt>
NOTE: A pre-existing libsnes library needs to be present in the root directory in order to link SSNES 360.
<b> Xbox 360 (Libxenon)</b><br />
You will need to have the libxenon libraries and a working Devkit Xenon toolchain installed in order to compile SSNES 360 Libxenon.
<tt>make -f Makefile.xenon</tt>
NOTE: A pre-existing libsnes library needs to be present in the root directory in order to link SSNES 360 Libxenon. This file needs to be called 'libsnes.a'.
<b> Wii</b><br >
You will need to have the libogc libraries and a working Devkit PPC toolchain installed in order to compile SSNES Wii.
<tt>make -f Makefile.wii</tt>
NOTE: A pre-existing libsnes library needs to be present in the root directory in order to link SSNES Wii. This file needs to be called 'libsnes.a'.
# Filters, bSNES XML shaders and Cg shader support
-39
View File
@@ -1,39 +0,0 @@
===================================================
SSNES - Simple Super Nintendo Emulator System
===================================================
SSNES is a simplistic emulator frontend designed for use without any GUI.
It is used from command line, but is designed to play well with eventual GUI frontends,
as the configuration file format is very simple.
This allows for great portability and focus on what matters in a frontend, such as video and audio performance.
Its core libraries for video and input are OpenGL and SDL, with many different audio library supported.
On first use you should get accustomed to how SSNES works.
- SSNES emphasizes simplicity. It has no graphical user interface, and is primarily used through the command line.
It is recommended for experienced users.
It is possible though to create a GUI which can use SSNES.
- SSNES isn't dependant on any emulator core, such as bSNES, SNES9x or ZSNES.
SSNES only talks to the libsnes interface,
which was created initially by bSNES but it has an implementation available for SNES9x as well.
- SSNES is configured through a config file. In the Win32 distribution, there should be a ssnes.cfg included.
This config file serves as a base for your custom configuration file.
It is recommended that you go through the config file and alter any configurations you might use.
This is a good way to learn about the features SSNES have.
It is possible to pick which configuration file you want with the '-c' flag.
E.g.: ssnes.exe -c myconfig.cfg rom.sfc.
- When unsure which command line flags to use, use the command: ssnes.exe --help.
- When something is not working as expected, try using verbose logging first to see what is happening:
E.g.: ssnes.exe -v romfile.sfc
If something is not working, and you want to file a bug report,
please include console output with the -v flag turned on.
- SSNES does not support zipped roms directly. It only supports roms with extentions .sfc and .smc.
However, SSNES can read roms from stdin,
which makes it possible to create wrapper programs that can support every zip format under the sun.
This can also be performed by a GUI frontend.
+57 -44
View File
@@ -1,5 +1,5 @@
/* SSNES - A Super Nintendo Entertainment System (SNES) Emulator frontend for libsnes.
* Copyright (C) 2010-2011 - Hans-Kristian Arntzen
* Copyright (C) 2010-2012 - Hans-Kristian Arntzen
*
* Some code herein may be based on code found in BSNES.
*
@@ -16,12 +16,12 @@
*/
#include "driver.h"
#include "../driver.h"
#include <stdlib.h>
#include <asoundlib.h>
#include "general.h"
#include "../general.h"
#define TRY_ALSA(x) if ( x < 0 ) { \
#define TRY_ALSA(x) if (x < 0) { \
goto error; \
}
@@ -30,11 +30,13 @@ typedef struct alsa
snd_pcm_t *pcm;
bool nonblock;
bool has_float;
size_t buffer_size;
} alsa_t;
static bool __alsa_use_float(void *data)
static bool alsa_use_float(void *data)
{
alsa_t *alsa = data;
alsa_t *alsa = (alsa_t*)data;
return alsa->has_float;
}
@@ -49,27 +51,30 @@ static bool find_float_format(snd_pcm_t *pcm, snd_pcm_hw_params_t *params)
return false;
}
static void* __alsa_init(const char* device, unsigned rate, unsigned latency)
static void *alsa_init(const char *device, unsigned rate, unsigned latency)
{
alsa_t *alsa = calloc(1, sizeof(alsa_t));
if ( alsa == NULL )
alsa_t *alsa = (alsa_t*)calloc(1, sizeof(alsa_t));
if (!alsa)
return NULL;
snd_pcm_hw_params_t *params = NULL;
snd_pcm_sw_params_t *sw_params = NULL;
const char *alsa_dev = "default";
if ( device != NULL )
if (device)
alsa_dev = device;
unsigned latency_usec = latency * 1000;
unsigned channels = 2;
unsigned periods = 4;
snd_pcm_uframes_t buffer_size;
snd_pcm_format_t format;
TRY_ALSA(snd_pcm_open(&alsa->pcm, alsa_dev, SND_PCM_STREAM_PLAYBACK, SND_PCM_NONBLOCK));
unsigned int latency_usec = latency * 1000;
TRY_ALSA(snd_pcm_hw_params_malloc(&params));
alsa->has_float = find_float_format(alsa->pcm, params);
snd_pcm_format_t format = alsa->has_float ? SND_PCM_FORMAT_FLOAT : SND_PCM_FORMAT_S16;
unsigned int channels = 2;
format = alsa->has_float ? SND_PCM_FORMAT_FLOAT : SND_PCM_FORMAT_S16;
TRY_ALSA(snd_pcm_hw_params_any(alsa->pcm, params));
TRY_ALSA(snd_pcm_hw_params_set_access(alsa->pcm, params, SND_PCM_ACCESS_RW_INTERLEAVED));
@@ -78,16 +83,15 @@ static void* __alsa_init(const char* device, unsigned rate, unsigned latency)
TRY_ALSA(snd_pcm_hw_params_set_rate(alsa->pcm, params, rate, 0));
TRY_ALSA(snd_pcm_hw_params_set_buffer_time_near(alsa->pcm, params, &latency_usec, NULL));
unsigned periods = 4;
TRY_ALSA(snd_pcm_hw_params_set_periods_near(alsa->pcm, params, &periods, NULL));
TRY_ALSA(snd_pcm_hw_params(alsa->pcm, params));
snd_pcm_uframes_t buffer_size;
snd_pcm_hw_params_get_period_size(params, &buffer_size, NULL);
SSNES_LOG("ALSA: Period size: %d frames\n", (int)buffer_size);
snd_pcm_hw_params_get_buffer_size(params, &buffer_size);
SSNES_LOG("ALSA: Buffer size: %d frames\n", (int)buffer_size);
alsa->buffer_size = snd_pcm_frames_to_bytes(alsa->pcm, buffer_size);
TRY_ALSA(snd_pcm_sw_params_malloc(&sw_params));
TRY_ALSA(snd_pcm_sw_params_current(alsa->pcm, sw_params));
@@ -117,16 +121,16 @@ error:
return NULL;
}
static ssize_t __alsa_write(void* data, const void* buf, size_t size)
static ssize_t alsa_write(void *data, const void *buf, size_t size)
{
alsa_t *alsa = data;
alsa_t *alsa = (alsa_t*)data;
snd_pcm_sframes_t frames;
snd_pcm_sframes_t written = 0;
int rc;
size = snd_pcm_bytes_to_frames(alsa->pcm, size); // Frames to write
while (written < size)
while (written < (snd_pcm_sframes_t)size)
{
if (!alsa->nonblock)
{
@@ -141,16 +145,16 @@ static ssize_t __alsa_write(void* data, const void* buf, size_t size)
frames = snd_pcm_writei(alsa->pcm, (const char*)buf + written * 2 * (alsa->has_float ? sizeof(float) : sizeof(int16_t)), size - written);
if ( frames == -EPIPE || frames == -EINTR || frames == -ESTRPIPE )
if (frames == -EPIPE || frames == -EINTR || frames == -ESTRPIPE)
{
if ( snd_pcm_recover(alsa->pcm, frames, 1) < 0 )
if (snd_pcm_recover(alsa->pcm, frames, 1) < 0)
return -1;
return 0;
}
else if ( frames == -EAGAIN && alsa->nonblock )
else if (frames == -EAGAIN && alsa->nonblock)
return 0;
else if ( frames < 0 )
else if (frames < 0)
return -1;
written += frames;
@@ -159,28 +163,28 @@ static ssize_t __alsa_write(void* data, const void* buf, size_t size)
return snd_pcm_frames_to_bytes(alsa->pcm, size);
}
static bool __alsa_stop(void *data)
static bool alsa_stop(void *data)
{
return true;
}
static void __alsa_set_nonblock_state(void *data, bool state)
static void alsa_set_nonblock_state(void *data, bool state)
{
alsa_t *alsa = data;
alsa_t *alsa = (alsa_t*)data;
alsa->nonblock = state;
}
static bool __alsa_start(void *data)
static bool alsa_start(void *data)
{
return true;
}
static void __alsa_free(void *data)
static void alsa_free(void *data)
{
alsa_t *alsa = data;
if ( alsa )
alsa_t *alsa = (alsa_t*)data;
if (alsa)
{
if ( alsa->pcm )
if (alsa->pcm)
{
snd_pcm_drop(alsa->pcm);
snd_pcm_close(alsa->pcm);
@@ -189,19 +193,28 @@ static void __alsa_free(void *data)
}
}
static size_t alsa_write_avail(void *data)
{
alsa_t *alsa = (alsa_t*)data;
return snd_pcm_frames_to_bytes(alsa->pcm, snd_pcm_avail_update(alsa->pcm));
}
static size_t alsa_buffer_size(void *data)
{
alsa_t *alsa = (alsa_t*)data;
return alsa->buffer_size;
}
const audio_driver_t audio_alsa = {
.init = __alsa_init,
.write = __alsa_write,
.stop = __alsa_stop,
.start = __alsa_start,
.use_float = __alsa_use_float,
.set_nonblock_state = __alsa_set_nonblock_state,
.free = __alsa_free,
.ident = "alsa"
alsa_init,
alsa_write,
alsa_stop,
alsa_start,
alsa_set_nonblock_state,
alsa_free,
alsa_use_float,
"alsa",
alsa_write_avail,
alsa_buffer_size,
};
+71 -50
View File
@@ -1,6 +1,6 @@
/* SSNES - A Super Nintendo Entertainment System (SNES) Emulator frontend for libsnes.
* Copyright (C) 2010-2011 - Hans-Kristian Arntzen
* Copyright (C) 2011 - Chris Moeller
* Copyright (C) 2010-2012 - Hans-Kristian Arntzen
* Copyright (C) 2011-2012 - Chris Moeller
*
* Some code herein may be based on code found in BSNES.
*
@@ -21,7 +21,7 @@
#include "general.h"
#include "fifo_buffer.h"
#include <stdlib.h>
#include <stdbool.h>
#include "../boolean.h"
#include <pthread.h>
#include <CoreAudio/CoreAudio.h>
@@ -39,11 +39,12 @@ typedef struct coreaudio
fifo_buffer_t *buffer;
bool nonblock;
size_t buffer_size;
} coreaudio_t;
static void coreaudio_free(void *data)
{
coreaudio_t *dev = data;
coreaudio_t *dev = (coreaudio_t*)data;
if (!dev)
return;
@@ -66,7 +67,7 @@ static OSStatus audio_cb(void *userdata, AudioUnitRenderActionFlags *action_flag
const AudioTimeStamp *time_stamp, UInt32 bus_number,
UInt32 number_frames, AudioBufferList *io_data)
{
coreaudio_t *dev = userdata;
coreaudio_t *dev = (coreaudio_t*)userdata;
(void)time_stamp;
(void)bus_number;
(void)number_frames;
@@ -95,11 +96,11 @@ static OSStatus audio_cb(void *userdata, AudioUnitRenderActionFlags *action_flag
return noErr;
}
static void* coreaudio_init(const char* device, unsigned rate, unsigned latency)
static void *coreaudio_init(const char *device, unsigned rate, unsigned latency)
{
(void)device;
coreaudio_t *dev = calloc(1, sizeof(*dev));
coreaudio_t *dev = (coreaudio_t*)calloc(1, sizeof(*dev));
if (!dev)
return NULL;
@@ -115,40 +116,46 @@ static void* coreaudio_init(const char* device, unsigned rate, unsigned latency)
AudioObjectSetPropertyData(kAudioObjectSystemObject, &addr, 0, NULL,
sizeof(CFRunLoopRef), &run_loop);
ComponentDescription desc = {
.componentType = kAudioUnitType_Output,
.componentSubType = kAudioUnitSubType_HALOutput,
.componentManufacturer = kAudioUnitManufacturer_Apple,
};
ComponentDescription desc = {0};
desc.componentType = kAudioUnitType_Output;
desc.componentSubType = kAudioUnitSubType_HALOutput;
desc.componentManufacturer = kAudioUnitManufacturer_Apple;
Component comp = FindNextComponent(NULL, &desc);
AudioStreamBasicDescription stream_desc = {0};
AudioStreamBasicDescription real_desc;
AudioChannelLayout layout = {0};
AURenderCallbackStruct cb = {0};
Component comp = NULL;
OSStatus res = noErr;
UInt32 i_size = 0;
size_t fifo_size;
comp = FindNextComponent(NULL, &desc);
if (comp == NULL)
goto error;
OSStatus res = OpenAComponent(comp, &dev->dev);
res = OpenAComponent(comp, &dev->dev);
if (res != noErr)
goto error;
dev->dev_alive = true;
AudioStreamBasicDescription stream_desc = {
.mSampleRate = rate,
.mBitsPerChannel = sizeof(float) * CHAR_BIT,
.mChannelsPerFrame = 2,
.mBytesPerPacket = 2 * sizeof(float),
.mBytesPerFrame = 2 * sizeof(float),
.mFramesPerPacket = 1,
.mFormatID = kAudioFormatLinearPCM,
.mFormatFlags = kAudioFormatFlagIsFloat | kAudioFormatFlagIsPacked | (is_little_endian() ? 0 : kAudioFormatFlagIsBigEndian),
};
stream_desc.mSampleRate = rate;
stream_desc.mBitsPerChannel = sizeof(float) * CHAR_BIT;
stream_desc.mChannelsPerFrame = 2;
stream_desc.mBytesPerPacket = 2 * sizeof(float);
stream_desc.mBytesPerFrame = 2 * sizeof(float);
stream_desc.mFramesPerPacket = 1;
stream_desc.mFormatID = kAudioFormatLinearPCM;
stream_desc.mFormatFlags = kAudioFormatFlagIsFloat | kAudioFormatFlagIsPacked | (is_little_endian() ? 0 : kAudioFormatFlagIsBigEndian);
res = AudioUnitSetProperty(dev->dev, kAudioUnitProperty_StreamFormat,
kAudioUnitScope_Input, 0, &stream_desc, sizeof(stream_desc));
if (res != noErr)
goto error;
AudioStreamBasicDescription real_desc;
UInt32 i_size = sizeof(real_desc);
i_size = sizeof(real_desc);
res = AudioUnitGetProperty(dev->dev, kAudioUnitProperty_StreamFormat, kAudioUnitScope_Input, 0, &real_desc, &i_size);
if (res != noErr)
goto error;
@@ -165,20 +172,16 @@ static void* coreaudio_init(const char* device, unsigned rate, unsigned latency)
if (real_desc.mFormatID != stream_desc.mFormatID)
goto error;
AudioChannelLayout layout = {
.mChannelLayoutTag = kAudioChannelLayoutTag_UseChannelBitmap,
.mChannelBitmap = (1 << 2) - 1,
};
layout.mChannelLayoutTag = kAudioChannelLayoutTag_UseChannelBitmap;
layout.mChannelBitmap = 0x03;
res = AudioUnitSetProperty(dev->dev, kAudioUnitProperty_AudioChannelLayout,
kAudioUnitScope_Input, 0, &layout, sizeof(layout));
if (res != noErr)
goto error;
AURenderCallbackStruct cb = {
.inputProc = audio_cb,
.inputProcRefCon = dev,
};
cb.inputProc = audio_cb;
cb.inputProcRefCon = dev;
res = AudioUnitSetProperty(dev->dev, kAudioUnitProperty_SetRenderCallback,
kAudioUnitScope_Input, 0, &cb, sizeof(cb));
@@ -189,8 +192,9 @@ static void* coreaudio_init(const char* device, unsigned rate, unsigned latency)
if (res != noErr)
goto error;
size_t fifo_size = (latency * g_settings.audio.out_rate) / 1000;
fifo_size = (latency * g_settings.audio.out_rate) / 1000;
fifo_size *= 2 * sizeof(float);
dev->buffer_size = fifo_size;
dev->buffer = fifo_new(fifo_size);
if (!dev->buffer)
@@ -210,11 +214,11 @@ error:
return NULL;
}
static ssize_t coreaudio_write(void* data, const void* buf_, size_t size)
static ssize_t coreaudio_write(void *data, const void *buf_, size_t size)
{
coreaudio_t *dev = data;
coreaudio_t *dev = (coreaudio_t*)data;
const uint8_t *buf = buf_;
const uint8_t *buf = (const uint8_t*)buf_;
size_t written = 0;
while (size > 0)
@@ -246,19 +250,19 @@ static ssize_t coreaudio_write(void* data, const void* buf_, size_t size)
static bool coreaudio_stop(void *data)
{
coreaudio_t *dev = data;
coreaudio_t *dev = (coreaudio_t*)data;
return AudioOutputUnitStop(dev->dev) == noErr;
}
static void coreaudio_set_nonblock_state(void *data, bool state)
{
coreaudio_t *dev = data;
coreaudio_t *dev = (coreaudio_t*)data;
dev->nonblock = state;
}
static bool coreaudio_start(void *data)
{
coreaudio_t *dev = data;
coreaudio_t *dev = (coreaudio_t*)data;
return AudioOutputUnitStart(dev->dev) == noErr;
}
@@ -268,14 +272,31 @@ static bool coreaudio_use_float(void *data)
return true;
}
static size_t coreaudio_write_avail(void *data)
{
coreaudio_t *dev = (coreaudio_t*)data;
pthread_mutex_lock(&dev->lock);
size_t avail = fifo_write_avail(dev->buffer);
pthread_mutex_unlock(&dev->lock);
return avail;
}
static size_t coreaudio_buffer_size(void *data)
{
coreaudio_t *dev = (coreaudio_t*)data;
return dev->buffer_size;
}
const audio_driver_t audio_coreaudio = {
.init = coreaudio_init,
.write = coreaudio_write,
.stop = coreaudio_stop,
.start = coreaudio_start,
.set_nonblock_state = coreaudio_set_nonblock_state,
.free = coreaudio_free,
.use_float = coreaudio_use_float,
.ident = "coreaudio"
coreaudio_init,
coreaudio_write,
coreaudio_stop,
coreaudio_start,
coreaudio_set_nonblock_state,
coreaudio_free,
coreaudio_use_float,
"coreaudio",
coreaudio_write_avail,
coreaudio_buffer_size,
};
+76 -37
View File
@@ -1,5 +1,5 @@
/* SSNES - A Super Nintendo Entertainment System (SNES) Emulator frontend for libsnes.
* Copyright (C) 2010-2011 - Hans-Kristian Arntzen
* Copyright (C) 2010-2012 - Hans-Kristian Arntzen
*
* Some code herein may be based on code found in BSNES.
*
@@ -15,16 +15,16 @@
* If not, see <http://www.gnu.org/licenses/>.
*/
#include "driver.h"
#include "../driver.h"
#include <stdlib.h>
#include <stdbool.h>
#include "../boolean.h"
#include <stddef.h>
#include <stdint.h>
#include <string.h>
#include <dsound.h>
#include "fifo_buffer.h"
#include "general.h"
#include "../fifo_buffer.h"
#include "../general.h"
typedef struct dsound
{
@@ -111,7 +111,7 @@ static inline void release_region(dsound_t *ds, const struct audio_lock *region)
static DWORD CALLBACK dsound_thread(PVOID data)
{
dsound_t *ds = data;
dsound_t *ds = (dsound_t*)data;
SetThreadPriority(GetCurrentThread(), THREAD_PRIORITY_TIME_CRITICAL);
DWORD write_ptr;
@@ -218,7 +218,7 @@ static void dsound_clear_buffer(dsound_t *ds)
static void dsound_free(void *data)
{
dsound_t *ds = data;
dsound_t *ds = (dsound_t*)data;
if (ds)
{
if (ds->thread)
@@ -249,28 +249,53 @@ static void dsound_free(void *data)
}
}
static void* dsound_init(const char *device, unsigned rate, unsigned latency)
struct dsound_dev
{
dsound_t *ds = calloc(1, sizeof(*ds));
unsigned device;
unsigned total_count;
LPGUID guid;
};
static BOOL CALLBACK enumerate_cb(LPGUID guid, LPCSTR desc, LPCSTR module, LPVOID context)
{
struct dsound_dev *dev = (struct dsound_dev*)context;
SSNES_LOG("\t%u: %s\n", dev->total_count, desc);
if (dev->device == dev->total_count)
dev->guid = guid;
dev->total_count++;
return TRUE;
}
static void *dsound_init(const char *device, unsigned rate, unsigned latency)
{
WAVEFORMATEX wfx = {0};
DSBUFFERDESC bufdesc = {0};
struct dsound_dev dev = {0};
dsound_t *ds = (dsound_t*)calloc(1, sizeof(*ds));
if (!ds)
goto error;
InitializeCriticalSection(&ds->crit);
if (DirectSoundCreate(NULL, &ds->ds, NULL) != DS_OK)
if (device)
dev.device = strtoul(device, NULL, 0);
SSNES_LOG("DirectSound devices:\n");
DirectSoundEnumerate(enumerate_cb, &dev);
if (DirectSoundCreate(dev.guid, &ds->ds, NULL) != DS_OK)
goto error;
if (IDirectSound_SetCooperativeLevel(ds->ds, GetDesktopWindow(), DSSCL_PRIORITY) != DS_OK)
goto error;
WAVEFORMATEX wfx = {
.wFormatTag = WAVE_FORMAT_PCM,
.nChannels = 2,
.nSamplesPerSec = rate,
.wBitsPerSample = 16,
.nBlockAlign = 2 * sizeof(int16_t),
.nAvgBytesPerSec = rate * 2 * sizeof(int16_t),
};
wfx.wFormatTag = WAVE_FORMAT_PCM;
wfx.nChannels = 2;
wfx.nSamplesPerSec = rate;
wfx.wBitsPerSample = 16;
wfx.nBlockAlign = 2 * sizeof(int16_t);
wfx.nAvgBytesPerSec = rate * 2 * sizeof(int16_t);
ds->buffer_size = (latency * wfx.nAvgBytesPerSec) / 1000;
ds->buffer_size /= CHUNK_SIZE;
@@ -281,12 +306,10 @@ static void* dsound_init(const char *device, unsigned rate, unsigned latency)
SSNES_LOG("[DirectSound]: Setting buffer size of %u bytes\n", ds->buffer_size);
SSNES_LOG("[DirectSound]: Latency = %u ms\n", (unsigned)((1000 * ds->buffer_size) / wfx.nAvgBytesPerSec));
DSBUFFERDESC bufdesc = {
.dwSize = sizeof(DSBUFFERDESC),
.dwFlags = DSBCAPS_GETCURRENTPOSITION2 | DSBCAPS_GLOBALFOCUS,
.dwBufferBytes = ds->buffer_size,
.lpwfxFormat = &wfx,
};
bufdesc.dwSize = sizeof(DSBUFFERDESC);
bufdesc.dwFlags = DSBCAPS_GETCURRENTPOSITION2 | DSBCAPS_GLOBALFOCUS;
bufdesc.dwBufferBytes = ds->buffer_size;
bufdesc.lpwfxFormat = &wfx;
ds->event = CreateEvent(NULL, false, false, NULL);
if (!ds->event)
@@ -312,21 +335,21 @@ static void* dsound_init(const char *device, unsigned rate, unsigned latency)
return ds;
error:
SSNES_ERR("[DirectSound] Error occured in init!\n");
SSNES_ERR("[DirectSound] Error occured in init.\n");
dsound_free(ds);
return NULL;
}
static bool dsound_stop(void *data)
{
dsound_t *ds = data;
dsound_t *ds = (dsound_t*)data;
dsound_stop_thread(ds);
return IDirectSoundBuffer_Stop(ds->dsb) == DS_OK;
}
static bool dsound_start(void *data)
{
dsound_t *ds = data;
dsound_t *ds = (dsound_t*)data;
dsound_clear_buffer(ds);
if (!dsound_start_thread(ds))
@@ -337,14 +360,14 @@ static bool dsound_start(void *data)
static void dsound_set_nonblock_state(void *data, bool state)
{
dsound_t *ds = data;
dsound_t *ds = (dsound_t*)data;
ds->nonblock = state;
}
static ssize_t dsound_write(void *data, const void *buf_, size_t size)
{
dsound_t *ds = data;
const uint8_t *buf = buf_;
dsound_t *ds = (dsound_t*)data;
const uint8_t *buf = (const uint8_t*)buf_;
if (!ds->thread_alive)
return -1;
@@ -374,14 +397,30 @@ static ssize_t dsound_write(void *data, const void *buf_, size_t size)
return written;
}
static size_t dsound_write_avail(void *data)
{
dsound_t *ds = (dsound_t*)data;
EnterCriticalSection(&ds->crit);
size_t avail = fifo_write_avail(ds->buffer);
LeaveCriticalSection(&ds->crit);
return avail;
}
static size_t dsound_buffer_size(void *data)
{
return 4 * 1024;
}
const audio_driver_t audio_dsound = {
.init = dsound_init,
.write = dsound_write,
.stop = dsound_stop,
.start = dsound_start,
.set_nonblock_state = dsound_set_nonblock_state,
.free = dsound_free,
.ident = "dsound"
dsound_init,
dsound_write,
dsound_stop,
dsound_start,
dsound_set_nonblock_state,
dsound_free,
NULL,
"dsound",
dsound_write_avail,
dsound_buffer_size,
};
-16
View File
@@ -1,16 +0,0 @@
TARGET = ssnes_iir_filter.so
OBJ = ssnes_iir_filter.o
all: $(TARGET)
$(TARGET): $(OBJ)
$(CC) -o $@ -shared $(OBJ) -lm
%.o: %.c
$(CC) -c -o $@ $< -g -std=c99 -fPIC -O3 -march=native $(CFLAGS)
clean:
rm -f $(TARGET)
rm -f $(OBJ)
.PHONY: clean
-16
View File
@@ -1,16 +0,0 @@
TARGET = iir_filter
OBJ = ssnes_iir_filter.o
all: $(TARGET)
$(TARGET): $(OBJ)
$(CC) -o $@ $(OBJ) -lm
%.o: %.c
$(CC) -c -o $@ $< -g -std=c99 -O3 -march=native $(CFLAGS) -DTEST -DLOG
clean:
rm -f $(TARGET)
rm -f $(OBJ)
.PHONY: clean
+1 -1
View File
@@ -61,7 +61,7 @@ typedef struct ssnes_audio_driver_info
typedef struct ssnes_audio_driver
{
// Initializes the device.
void* (*init)(const ssnes_audio_driver_info_t *info);
void *(*init)(const ssnes_audio_driver_info_t *info);
// Write data in buffer to audio driver.
// A frame here is defined as one combined sample of left and right
+1 -1
View File
@@ -87,7 +87,7 @@ typedef struct ssnes_dsp_input
typedef struct ssnes_dsp_plugin
{
// Creates a handle of the plugin. Returns NULL if failed.
void* (*init)(const ssnes_dsp_info_t *info);
void *(*init)(const ssnes_dsp_info_t *info);
// Processes input data.
// The plugin is allowed to return variable sizes for output data.
-418
View File
@@ -1,418 +0,0 @@
#include "ssnes_dsp.h"
#include <stdlib.h>
#include <string.h>
#include <stdint.h>
#include <stdio.h>
#include <math.h>
#include <complex.h>
// Simple IIR/EQ filter implementation, optimized for SSE3.
#ifdef __SSE3__ // Build with -march=native or -msse3 to let this be detected! D:
#define USE_SSE3
#endif
#ifdef USE_SSE3
#include <pmmintrin.h>
#endif
// Make a test build with standalone main()
//#define TEST
#ifdef TEST
#include <stdio.h>
#include <assert.h>
#endif
// Log filter coeffs for debugging
//#define LOG
#define min(x, y) ((x) < (y) ? (x) : (y))
#ifndef M_PI
#define M_PI 3.14159265
#endif
// Taps needs to be power-of-two.
#define TAPS (2048)
static const float lp_freq = 5000.0;
static const float hp_freq = 500.0;
static const float bp_freq = 300.0;
static const unsigned bp_q = 500;
#ifdef USE_SSE3
typedef union
{
__m128 vec[TAPS / 4 + 1]; // Wraparound for unaligned reads.
float f[TAPS + 4];
} vec_filt;
#else
typedef float vec_filt[TAPS + 4];
#endif
typedef struct
{
vec_filt buffer[2];
vec_filt iir_buffer[2];
vec_filt fir_coeff;
vec_filt iir_coeff;
float out_buffer[4096];
unsigned buf_ptr;
} dsp_state;
// Convolve polynoms.
static void conv(float * restrict a, const float * restrict b, unsigned a_size, unsigned b_size)
{
float output[a_size + b_size - 1];
// Lead-in
for (int i = 0; i < b_size - 1; i++)
{
output[i] = 0.0;
for (int j = 0; j < b_size; j++)
{
if ((i - j) >= 0)
output[i] += a[i - j] * b[j];
}
}
// Mid-section
for (unsigned i = b_size - 1; i < a_size; i++)
{
output[i] = 0.0;
for (unsigned j = 0; j < b_size; j++)
output[i] += a[i - j] * b[j];
}
// Lead-out
for (unsigned i = a_size; i < a_size + b_size - 1; i++)
{
output[i] = 0.0;
for (unsigned j = 0; j < b_size; j++)
{
if ((i - j) < a_size)
output[i] += a[i - j] * b[j];
}
}
memcpy(a, output, sizeof(output));
}
#ifdef LOG
static void print_coeff(const char *key, const float *coeff, unsigned elem)
{
for (unsigned i = 0; i < elem; i++)
fprintf(stderr, "%4s [%3u] = %9.5f\n", key, i, coeff[i]);
}
static void print_filter_coeffs(const float *fir, const float *iir, unsigned elem)
{
print_coeff("FIR", fir, elem);
print_coeff("IIR", iir, elem);
}
#endif
// Simulate plain 1-pole RC circuit.
// dVc/dt = (Vin - Vc) / RC =>
// y[n] = y[n - 1] * (1 - Ts/RC) + x[n] * Ts/RC
// RCw = 1 => RC = 1/(2*pi*fc)
static void generate_low_pass(float fir_out[1], float iir_out[2], float freq, float input_rate)
{
float ts = 1.0 / input_rate;
float t = 1.0 / (2 * M_PI * freq);
fir_out[0] = ts / t;
iir_out[0] = 1.0;
iir_out[1] = -(1.0 - ts / t);
#ifdef LOG
print_coeff("FLOW", fir_out, 1);
print_coeff("ILOW", iir_out, 2);
#endif
}
// 1-pole RC circuit (Vo taken over R).
static void generate_high_pass(float fir_out[2], float iir_out[2], float freq, float input_rate)
{
float ts = 1.0 / input_rate;
float t = 1.0 / (2 * M_PI * freq);
fir_out[0] = 1.0;
fir_out[1] = -1.0;
iir_out[0] = 1.0;
iir_out[1] = -(1.0 - ts / t);
#ifdef LOG
print_coeff("FHI", fir_out, 2);
print_coeff("IHI", iir_out, 2);
#endif
}
static void generate_band_pass(float *fir_out, unsigned num_fir, float freq, float input_rate)
{
float w_norm = 2.0 * M_PI * freq / input_rate;
for (unsigned i = 0; i < num_fir; i++)
fir_out[i] = cosf(i * w_norm);
complex float amp = 0.0;
for (unsigned i = 0; i < num_fir; i++)
amp += cosf(i * w_norm) * cexp(-I * w_norm * i);
float abs = cabs(amp);
for (unsigned i = 0; i < num_fir; i++)
fir_out[i] /= abs;
}
// Generic low-pass. Differential equation.
static void generate_filter_coeffs(float * restrict fir_out, float * restrict iir_out, float input_rate)
{
fir_out[0] = 1.0;
iir_out[0] = 1.0;
unsigned fir_length = 1;
unsigned iir_length = 1;
/*
// Low pass
float lp_fir[1];
float lp_iir[2];
generate_low_pass(lp_fir, lp_iir, lp_freq, input_rate);
conv(fir_out, lp_fir, fir_length, 1);
conv(iir_out, lp_iir, iir_length, 2);
fir_length += 0;
iir_length += 1;
// High pass
float hp_fir[2];
float hp_iir[2];
generate_high_pass(hp_fir, hp_iir, hp_freq, input_rate);
conv(fir_out, hp_fir, fir_length, 2);
conv(iir_out, hp_iir, iir_length, 2);
fir_length += 1;
iir_length += 1;
*/
// Band pass
float bp_fir[bp_q];
generate_band_pass(bp_fir, bp_q, bp_freq, input_rate);
conv(fir_out, bp_fir, fir_length, bp_q);
fir_length += bp_q - 1;
iir_length += 0;
// Adjust from Z rational polynomial model to discrete domain.
// We don't care about first param as it's implicitly 1.
for (unsigned i = 0; i < TAPS; i++)
iir_out[i] = -1.0 * iir_out[i + 1];
}
static void* dsp_init(const ssnes_dsp_info_t *info)
{
(void)info;
dsp_state *state = calloc(1, sizeof(*state));
if (!state)
return NULL;
fprintf(stderr, "Input rate = %.2f\n", (float)info->input_rate);
#ifdef USE_SSE3
generate_filter_coeffs(state->fir_coeff.f, state->iir_coeff.f, info->input_rate);
#ifdef LOG
print_filter_coeffs(state->fir_coeff.f, state->iir_coeff.f, 3);
#endif
#else
generate_filter_coeffs(state->fir_coeff, state->iir_coeff, info->input_rate);
#ifdef LOG
print_filter_coeffs(state->fir_coeff, state->iir_coeff, 3);
#endif
#endif
#ifdef USE_SSE3
memcpy(state->fir_coeff.f + TAPS, state->fir_coeff.f, 4 * sizeof(float));
memcpy(state->iir_coeff.f + TAPS, state->iir_coeff.f, 4 * sizeof(float));
#endif
return state;
}
#ifdef USE_SSE3
static void calculate_iir(float *out, dsp_state *dsp)
{
unsigned buf_ptr = (dsp->buf_ptr - 1) & (TAPS - 1);
unsigned iir_ptr = (TAPS - dsp->buf_ptr) & (TAPS - 1);
const float * restrict samples_left = dsp->buffer[0].f;
const float * restrict samples_right = dsp->buffer[1].f;
const float * restrict iir_left = dsp->iir_buffer[0].f;
const float * restrict iir_right = dsp->iir_buffer[1].f;
__m128 sum_left = _mm_setzero_ps();
__m128 sum_right = _mm_setzero_ps();
for (unsigned i = 0; i < TAPS; i += 4)
{
__m128 left = _mm_load_ps(samples_left + i);
__m128 right = _mm_load_ps(samples_right + i);
const __m128 ileft = _mm_load_ps(iir_left + i);
const __m128 iright = _mm_load_ps(iir_right + i);
// Need unaligned reads here.
const __m128 fir = _mm_loadu_ps(dsp->fir_coeff.f + iir_ptr);
const __m128 iir = _mm_loadu_ps(dsp->iir_coeff.f + iir_ptr);
const __m128 fir_res_left = _mm_mul_ps(fir, left);
const __m128 fir_res_right = _mm_mul_ps(fir, right);
const __m128 iir_res_left = _mm_mul_ps(iir, ileft);
const __m128 iir_res_right = _mm_mul_ps(iir, iright);
left = _mm_add_ps(fir_res_left, iir_res_left);
right = _mm_add_ps(fir_res_right, iir_res_right);
sum_left = _mm_add_ps(sum_left, left);
sum_right = _mm_add_ps(sum_right, right);
iir_ptr = (iir_ptr + 4) & (TAPS - 1);
}
__m128 res = _mm_hadd_ps(sum_left, sum_right);
res = _mm_hadd_ps(res, res);
union
{
__m128 vec;
float f[4];
} u;
u.vec = res;
out[0] = u.f[0];
out[1] = u.f[1];
dsp->iir_buffer[0].f[buf_ptr] = u.f[0];
dsp->iir_buffer[1].f[buf_ptr] = u.f[1];
}
#else
static void calculate_iir(float *out, dsp_state *dsp)
{
const float * restrict samples_left = dsp->buffer[0];
const float * restrict samples_right = dsp->buffer[1];
const float * restrict iir_left = dsp->iir_buffer[0];
const float * restrict iir_right = dsp->iir_buffer[1];
const float * restrict fir = dsp->fir_coeff;
const float * restrict iir = dsp->iir_coeff;
unsigned iir_ptr = 0;
unsigned sample_ptr = dsp->buf_ptr;
float sum[2] = { 0.0f, 0.0f };
for (unsigned i = 0; i < TAPS; i++)
{
sum[0] += fir[iir_ptr] * samples_left[sample_ptr] + iir[iir_ptr] * iir_left[sample_ptr];
sum[1] += fir[iir_ptr] * samples_right[sample_ptr] + iir[iir_ptr] * iir_right[sample_ptr];
iir_ptr++;
sample_ptr = (sample_ptr + 1) & (TAPS - 1);
}
// Stick our output value in the IIR buffer.
for (unsigned i = 0; i < 2; i++)
{
out[i] = sum[i];
dsp->iir_buffer[i][(dsp->buf_ptr - 1) & (TAPS - 1)] = sum[i];
}
}
#endif
static void dsp_process(void *data, ssnes_dsp_output_t *output, const ssnes_dsp_input_t *input)
{
dsp_state *dsp = data;
output->should_resample = SSNES_TRUE;
output->frames = input->frames;
output->samples = dsp->out_buffer;
for (unsigned i = 0; i < input->frames; i++)
{
#ifdef USE_SSE3
dsp->buffer[0].f[dsp->buf_ptr] = input->samples[(i << 1) + 0];
dsp->buffer[1].f[dsp->buf_ptr] = input->samples[(i << 1) + 1];
#else
dsp->buffer[0][dsp->buf_ptr] = input->samples[(i << 1) + 0];
dsp->buffer[1][dsp->buf_ptr] = input->samples[(i << 1) + 1];
#endif
calculate_iir(&dsp->out_buffer[i << 1], dsp);
dsp->buf_ptr = (dsp->buf_ptr - 1) & (TAPS - 1);
}
}
static void dsp_config(void *data)
{
(void)data;
// Normally we unhide a GUI window or something,
// but we're just going to print to the log instead.
fprintf(stderr, "DSP_CONFIG\n");
}
static void dsp_free(void *data)
{
free(data);
}
const ssnes_dsp_plugin_t dsp_plug = {
.init = dsp_init,
.process = dsp_process,
.free = dsp_free,
.config = dsp_config,
.api_version = SSNES_DSP_API_VERSION,
.ident = "IIR filter"
};
SSNES_API_EXPORT const ssnes_dsp_plugin_t*
SSNES_API_CALLTYPE ssnes_dsp_plugin_init(void)
{
return &dsp_plug;
}
#ifdef TEST
int main(void)
{
const ssnes_dsp_plugin_t *plug = ssnes_dsp_plugin_init();
assert(plug);
ssnes_dsp_info_t info = {
.input_rate = 44100,
.output_rate = 44100
};
void *handle = plug->init(&info); // Info isn't used.
assert(handle);
int16_t buf[64];
float fbuf[64];
for (;;)
{
size_t rd = fread(buf, sizeof(int16_t), 64, stdin);
for (unsigned i = 0; i < rd; i++)
fbuf[i] = (float)buf[i];
ssnes_dsp_input_t input = {
.samples = fbuf,
.frames = rd >> 1
};
ssnes_dsp_output_t output;
plug->process(handle, &output, &input);
for (unsigned i = 0; i < output.frames << 1; i++)
{
int32_t sample = (int32_t)output.samples[i];
buf[i] = (sample > 0x7fff) ? 0x7fff : ((sample < -0x8000) ? -0x8000 : (int16_t)sample);
}
fwrite(buf, sizeof(int16_t), output.frames << 1, stdout);
if (rd < 64)
break;
}
plug->free(handle);
}
#endif
+29 -28
View File
@@ -1,5 +1,5 @@
/* SSNES - A Super Nintendo Entertainment System (SNES) Emulator frontend for libsnes.
* Copyright (C) 2010-2011 - Hans-Kristian Arntzen
* Copyright (C) 2010-2012 - Hans-Kristian Arntzen
*
* Some code herein may be based on code found in BSNES.
*
@@ -16,12 +16,12 @@
*/
#include "ext/ssnes_audio.h"
#include <stdbool.h>
#include "../boolean.h"
#include <stdlib.h>
#include <stdint.h>
#include "driver.h"
#include "dynamic.h"
#include "general.h"
#include "../driver.h"
#include "../dynamic.h"
#include "../general.h"
#include <sys/types.h>
typedef struct audio_ext
@@ -34,7 +34,7 @@ typedef struct audio_ext
static void audio_ext_free(void *data)
{
audio_ext_t *ext = data;
audio_ext_t *ext = (audio_ext_t*)data;
if (ext)
{
if (ext->driver && ext->handle)
@@ -45,7 +45,7 @@ static void audio_ext_free(void *data)
}
}
static void* audio_ext_init(const char *device, unsigned rate, unsigned latency)
static void *audio_ext_init(const char *device, unsigned rate, unsigned latency)
{
if (!(*g_settings.audio.external_driver))
{
@@ -53,10 +53,13 @@ static void* audio_ext_init(const char *device, unsigned rate, unsigned latency)
return NULL;
}
audio_ext_t *ext = calloc(1, sizeof(*ext));
audio_ext_t *ext = (audio_ext_t*)calloc(1, sizeof(*ext));
if (!ext)
return NULL;
ssnes_audio_driver_info_t info = {0};
const ssnes_audio_driver_t *(*plugin_load)(void) = NULL;
ext->lib = dylib_load(g_settings.audio.external_driver);
if (!ext->lib)
{
@@ -64,7 +67,7 @@ static void* audio_ext_init(const char *device, unsigned rate, unsigned latency)
goto error;
}
const ssnes_audio_driver_t* (*plugin_load)(void) = (const ssnes_audio_driver_t* (*)(void))dylib_proc(ext->lib, "ssnes_audio_driver_init");
plugin_load = (const ssnes_audio_driver_t *(*)(void))dylib_proc(ext->lib, "ssnes_audio_driver_init");
if (!plugin_load)
{
@@ -87,11 +90,9 @@ static void* audio_ext_init(const char *device, unsigned rate, unsigned latency)
goto error;
}
ssnes_audio_driver_info_t info = {
.device = device,
.sample_rate = rate,
.latency = latency
};
info.device = device;
info.sample_rate = rate;
info.latency = latency;
ext->handle = ext->driver->init(&info);
if (!ext->handle)
@@ -115,7 +116,7 @@ error:
static ssize_t audio_ext_write(void *data, const void *buf, size_t size)
{
audio_ext_t *ext = data;
audio_ext_t *ext = (audio_ext_t*)data;
unsigned frame_size = ext->is_float ? (2 * sizeof(float)) : (2 * sizeof(int16_t));
size /= frame_size;
@@ -127,37 +128,37 @@ static ssize_t audio_ext_write(void *data, const void *buf, size_t size)
static bool audio_ext_start(void *data)
{
audio_ext_t *ext = data;
audio_ext_t *ext = (audio_ext_t*)data;
return ext->driver->start(ext->handle);
}
static bool audio_ext_stop(void *data)
{
audio_ext_t *ext = data;
audio_ext_t *ext = (audio_ext_t*)data;
return ext->driver->stop(ext->handle);
}
static void audio_ext_set_nonblock_state(void *data, bool toggle)
{
audio_ext_t *ext = data;
audio_ext_t *ext = (audio_ext_t*)data;
ext->driver->set_nonblock_state(ext->handle, toggle);
}
static bool audio_ext_use_float(void *data)
{
audio_ext_t *ext = data;
audio_ext_t *ext = (audio_ext_t*)data;
ext->is_float = ext->driver->use_float(ext->handle);
return ext->is_float;
}
const audio_driver_t audio_ext = {
.init = audio_ext_init,
.write = audio_ext_write,
.stop = audio_ext_stop,
.start = audio_ext_start,
.set_nonblock_state = audio_ext_set_nonblock_state,
.use_float = audio_ext_use_float,
.free = audio_ext_free,
.ident = "ext"
audio_ext_init,
audio_ext_write,
audio_ext_stop,
audio_ext_start,
audio_ext_set_nonblock_state,
audio_ext_free,
audio_ext_use_float,
"ext"
};
+37 -39
View File
@@ -1,5 +1,5 @@
/* SSNES - A Super Nintendo Entertainment System (SNES) Emulator frontend for libsnes.
* Copyright (C) 2010-2011 - Hans-Kristian Arntzen
* Copyright (C) 2010-2012 - Hans-Kristian Arntzen
*
* Some code herein may be based on code found in BSNES.
*
@@ -17,18 +17,31 @@
// Hermite resampler based on bsnes' audio library.
#include "hermite.h"
#include "resampler.h"
#include <stdlib.h>
#include <math.h>
#include "../boolean.h"
#define MAX_CHANS 8
#define CHANNELS 2
struct hermite_resampler
struct ssnes_resampler
{
float chan_data[MAX_CHANS][4];
float chan_data[CHANNELS][4];
double r_frac;
unsigned chans;
};
void resampler_preinit(ssnes_resampler_t *re, double omega, double *samples_offset)
{
*samples_offset = 2.0;
for (int i = 0; i < 4; i++)
{
re->chan_data[0][i] = (float)cos((i - 2) * omega);
re->chan_data[1][i] = re->chan_data[0][i];
}
re->r_frac = 0.0;
}
static inline float hermite_kernel(float mu1, float a, float b, float c, float d)
{
float mu2, mu3, m0, m1, a0, a1, a2, a3;
@@ -36,8 +49,8 @@ static inline float hermite_kernel(float mu1, float a, float b, float c, float d
mu2 = mu1 * mu1;
mu3 = mu2 * mu1;
m0 = (c - a) * 0.5;
m1 = (d - b) * 0.5;
m0 = (c - a) * 0.5f;
m1 = (d - b) * 0.5f;
a0 = +2 * mu3 - 3 * mu2 + 1;
a1 = mu3 - 2 * mu2 + mu1;
@@ -47,63 +60,48 @@ static inline float hermite_kernel(float mu1, float a, float b, float c, float d
return (a0 * b) + (a1 * m0) + (a2 * m1) + (a3 * c);
}
hermite_resampler_t *hermite_new(unsigned channels)
ssnes_resampler_t *resampler_new(void)
{
if (channels > MAX_CHANS)
return NULL;
hermite_resampler_t *re = calloc(1, sizeof(*re));
if (!re)
return NULL;
re->chans = channels;
return re;
return (ssnes_resampler_t*)calloc(1, sizeof(ssnes_resampler_t));
}
void hermite_process(hermite_resampler_t *re, struct hermite_data *data)
void resampler_process(ssnes_resampler_t *re, struct resampler_data *data)
{
double r_step = 1.0 / data->src_ratio;
double r_step = 1.0 / data->ratio;
size_t processed_out = 0;
size_t processed_in = 0;
size_t in_frames = data->input_frames;
size_t out_frames = data->output_frames;
const float *in_data = data->data_in;
float *out_data = data->data_out;
while (processed_in < in_frames && processed_out < out_frames)
for (size_t i = 0; i < in_frames; i++)
{
while (re->r_frac <= 1.0 && processed_out < out_frames)
while (re->r_frac <= 1.0)
{
re->r_frac += r_step;
for (unsigned i = 0; i < re->chans; i++)
for (unsigned i = 0; i < CHANNELS; i++)
{
float res = hermite_kernel(re->r_frac,
float res = hermite_kernel((float)re->r_frac,
re->chan_data[i][0], re->chan_data[i][1], re->chan_data[i][2], re->chan_data[i][3]);
*out_data++ = res;
}
processed_out++;
}
if (re->r_frac >= 1.0)
re->r_frac -= 1.0;
for (unsigned i = 0; i < CHANNELS; i++)
{
re->r_frac -= 1.0;
for (unsigned i = 0; i < re->chans; i++)
{
re->chan_data[i][0] = re->chan_data[i][1];
re->chan_data[i][1] = re->chan_data[i][2];
re->chan_data[i][2] = re->chan_data[i][3];
re->chan_data[i][3] = *in_data++;
}
processed_in++;
re->chan_data[i][0] = re->chan_data[i][1];
re->chan_data[i][1] = re->chan_data[i][2];
re->chan_data[i][2] = re->chan_data[i][3];
re->chan_data[i][3] = *in_data++;
}
}
data->input_frames_used = processed_in;
data->output_frames_gen = processed_out;
data->output_frames = processed_out;
}
void hermite_free(hermite_resampler_t *re)
void resampler_free(ssnes_resampler_t *re)
{
free(re);
}
+60 -42
View File
@@ -1,5 +1,5 @@
/* SSNES - A Super Nintendo Entertainment System (SNES) Emulator frontend for libsnes.
* Copyright (C) 2010-2011 - Hans-Kristian Arntzen
* Copyright (C) 2010-2012 - Hans-Kristian Arntzen
*
* Some code herein may be based on code found in BSNES.
*
@@ -16,16 +16,16 @@
*/
#include "driver.h"
#include "../driver.h"
#include <stdlib.h>
#include "general.h"
#include "../general.h"
#include <jack/jack.h>
#include <jack/types.h>
#include <jack/ringbuffer.h>
#include <pthread.h>
#include <stdint.h>
#include <stdbool.h>
#include "../boolean.h"
#include <string.h>
#include <assert.h>
@@ -41,11 +41,12 @@ typedef struct jack
pthread_cond_t cond;
pthread_mutex_t cond_lock;
size_t buffer_size;
} jack_t;
static int process_cb(jack_nframes_t nframes, void *data)
{
jack_t *jd = data;
jack_t *jd = (jack_t*)data;
if (nframes <= 0)
{
pthread_cond_signal(&jd->cond);
@@ -62,7 +63,7 @@ static int process_cb(jack_nframes_t nframes, void *data)
for (int i = 0; i < 2; i++)
{
jack_default_audio_sample_t *out = jack_port_get_buffer(jd->ports[i], nframes);
jack_default_audio_sample_t *out = (jack_default_audio_sample_t*)jack_port_get_buffer(jd->ports[i], nframes);
assert(out);
jack_ringbuffer_read(jd->buffer[i], (char*)out, min_avail * sizeof(jack_default_audio_sample_t));
@@ -77,7 +78,7 @@ static int process_cb(jack_nframes_t nframes, void *data)
static void shutdown_cb(void *data)
{
jack_t *jd = data;
jack_t *jd = (jack_t*)data;
jd->shutdown = true;
pthread_cond_signal(&jd->cond);
}
@@ -108,7 +109,7 @@ static size_t find_buffersize(jack_t *jd, int latency)
for (int i = 0; i < 2; i++)
{
jack_port_get_latency_range(jd->ports[i], JackPlaybackLatency, &range);
if (range.max > jack_latency)
if ((int)range.max > jack_latency)
jack_latency = range.max;
}
@@ -124,9 +125,9 @@ static size_t find_buffersize(jack_t *jd, int latency)
return buffer_frames * sizeof(jack_default_audio_sample_t);
}
static void* __jack_init(const char* device, unsigned rate, unsigned latency)
static void *ja_init(const char *device, unsigned rate, unsigned latency)
{
jack_t *jd = calloc(1, sizeof(jack_t));
jack_t *jd = (jack_t*)calloc(1, sizeof(jack_t));
if (!jd)
return NULL;
@@ -134,6 +135,9 @@ static void* __jack_init(const char* device, unsigned rate, unsigned latency)
pthread_mutex_init(&jd->cond_lock, NULL);
const char **jports = NULL;
char *dest_ports[2];
size_t bufsize = 0;
int parsed = 0;
jd->client = jack_client_open("SSNES", JackNullOption, NULL);
if (jd->client == NULL)
@@ -152,7 +156,6 @@ static void* __jack_init(const char* device, unsigned rate, unsigned latency)
goto error;
}
char *dest_ports[2];
jports = jack_get_ports(jd->client, NULL, NULL, JackPortIsPhysical | JackPortIsInput);
if (jports == NULL)
{
@@ -160,7 +163,9 @@ static void* __jack_init(const char* device, unsigned rate, unsigned latency)
goto error;
}
size_t bufsize = find_buffersize(jd, latency);
bufsize = find_buffersize(jd, latency);
jd->buffer_size = bufsize;
SSNES_LOG("JACK: Internal buffer size: %d frames.\n", (int)(bufsize / sizeof(jack_default_audio_sample_t)));
for (int i = 0; i < 2; i++)
{
@@ -172,7 +177,7 @@ static void* __jack_init(const char* device, unsigned rate, unsigned latency)
}
}
int parsed = parse_ports(dest_ports, jports);
parsed = parse_ports(dest_ports, jports);
if (jack_activate(jd->client) < 0)
{
@@ -191,7 +196,6 @@ static void* __jack_init(const char* device, unsigned rate, unsigned latency)
for (int i = 0; i < parsed; i++)
free(dest_ports[i]);
jack_free(jports);
return jd;
@@ -204,7 +208,7 @@ error:
static size_t write_buffer(jack_t *jd, const float *buf, size_t size)
{
jack_default_audio_sample_t out_deinterleaved_buffer[2][FRAMES(size)];
jack_default_audio_sample_t out_deinterleaved_buffer[2][AUDIO_CHUNK_SIZE_NONBLOCKING];
for (int i = 0; i < 2; i++)
for (size_t j = 0; j < FRAMES(size); j++)
@@ -218,9 +222,11 @@ static size_t write_buffer(jack_t *jd, const float *buf, size_t size)
if (jd->shutdown)
return 0;
size_t avail[2];
avail[0] = jack_ringbuffer_write_space(jd->buffer[0]);
avail[1] = jack_ringbuffer_write_space(jd->buffer[1]);
size_t avail[2] = {
jack_ringbuffer_write_space(jd->buffer[0]),
jack_ringbuffer_write_space(jd->buffer[1]),
};
size_t min_avail = avail[0] < avail[1] ? avail[0] : avail[1];
min_avail /= sizeof(float);
@@ -229,7 +235,10 @@ static size_t write_buffer(jack_t *jd, const float *buf, size_t size)
if (write_frames > 0)
{
for (int i = 0; i < 2; i++)
jack_ringbuffer_write(jd->buffer[i], (const char*)&out_deinterleaved_buffer[i][written], write_frames * sizeof(jack_default_audio_sample_t));
{
jack_ringbuffer_write(jd->buffer[i], (const char*)&out_deinterleaved_buffer[i][written],
write_frames * sizeof(jack_default_audio_sample_t));
}
written += write_frames;
}
else
@@ -246,34 +255,34 @@ static size_t write_buffer(jack_t *jd, const float *buf, size_t size)
return written * sizeof(float) * 2;
}
static ssize_t __jack_write(void* data, const void* buf, size_t size)
static ssize_t ja_write(void *data, const void *buf, size_t size)
{
jack_t *jd = data;
jack_t *jd = (jack_t*)data;
return write_buffer(jd, buf, size);
return write_buffer(jd, (const float*)buf, size);
}
static bool __jack_stop(void *data)
static bool ja_stop(void *data)
{
(void)data;
return true;
}
static void __jack_set_nonblock_state(void *data, bool state)
static void ja_set_nonblock_state(void *data, bool state)
{
jack_t *jd = data;
jack_t *jd = (jack_t*)data;
jd->nonblock = state;
}
static bool __jack_start(void *data)
static bool ja_start(void *data)
{
(void)data;
return true;
}
static void __jack_free(void *data)
static void ja_free(void *data)
{
jack_t *jd = data;
jack_t *jd = (jack_t*)data;
jd->shutdown = true;
@@ -292,25 +301,34 @@ static void __jack_free(void *data)
free(jd);
}
static bool __jack_use_float(void *data)
static bool ja_use_float(void *data)
{
(void)data;
return true;
}
static size_t ja_write_avail(void *data)
{
jack_t *jd = (jack_t*)data;
return jack_ringbuffer_write_space(jd->buffer[0]);
}
static size_t ja_buffer_size(void *data)
{
jack_t *jd = (jack_t*)data;
return jd->buffer_size;
}
const audio_driver_t audio_jack = {
.init = __jack_init,
.write = __jack_write,
.stop = __jack_stop,
.start = __jack_start,
.set_nonblock_state = __jack_set_nonblock_state,
.free = __jack_free,
.use_float = __jack_use_float,
.ident = "jack"
ja_init,
ja_write,
ja_stop,
ja_start,
ja_set_nonblock_state,
ja_free,
ja_use_float,
"jack",
ja_write_avail,
ja_buffer_size,
};
+30 -32
View File
@@ -1,5 +1,5 @@
/* SSNES - A Super Nintendo Entertainment System (SNES) Emulator frontend for libsnes.
* Copyright (C) 2010-2011 - Hans-Kristian Arntzen
* Copyright (C) 2010-2012 - Hans-Kristian Arntzen
*
* Some code herein may be based on code found in BSNES.
*
@@ -15,8 +15,7 @@
* If not, see <http://www.gnu.org/licenses/>.
*/
#include "driver.h"
#include "../driver.h"
#ifdef __APPLE__
#include <OpenAL/al.h>
@@ -56,11 +55,11 @@ typedef struct al
} al_t;
static void* __al_init(const char* device, unsigned rate, unsigned latency)
static void *al_init(const char *device, unsigned rate, unsigned latency)
{
(void)device;
al_t *al = calloc(1, sizeof(al_t));
if ( al == NULL )
al_t *al = (al_t*)calloc(1, sizeof(al_t));
if (!al)
return NULL;
al->handle = alcOpenDevice(NULL);
@@ -76,8 +75,8 @@ static void* __al_init(const char* device, unsigned rate, unsigned latency)
al->rate = rate;
al->num_buffers = (latency * rate * 2 * 2) / (1000 * BUFSIZE);
al->buffers = calloc(al->num_buffers, sizeof(ALuint));
al->res_buf = calloc(al->num_buffers, sizeof(ALuint));
al->buffers = (ALuint*)calloc(al->num_buffers, sizeof(ALuint));
al->res_buf = (ALuint*)calloc(al->num_buffers, sizeof(ALuint));
if (al->buffers == NULL || al->res_buf == NULL)
goto error;
@@ -127,13 +126,12 @@ static bool al_get_buffer(al_t *al, ALuint *buffer)
if (al->res_ptr == 0)
{
#ifndef _WIN32
struct timespec tv = {
.tv_sec = 0,
.tv_nsec = 1000000
};
struct timespec tv = {0};
tv.tv_sec = 0;
tv.tv_nsec = 1000000;
#endif
for(;;)
for (;;)
{
if (al_unqueue_buffers(al))
break;
@@ -153,17 +151,17 @@ static bool al_get_buffer(al_t *al, ALuint *buffer)
return true;
}
static size_t al_fill_internal_buf(al_t *al, const void* buf, size_t size)
static size_t al_fill_internal_buf(al_t *al, const void *buf, size_t size)
{
size_t read_size = (BUFSIZE - al->tmpbuf_ptr > size) ? size : (BUFSIZE - al->tmpbuf_ptr);
size_t read_size = (BUFSIZE - al->tmpbuf_ptr > (ssize_t)size) ? size : (BUFSIZE - al->tmpbuf_ptr);
memcpy(al->tmpbuf + al->tmpbuf_ptr, buf, read_size);
al->tmpbuf_ptr += read_size;
return read_size;
}
static ssize_t __al_write(void* data, const void* buf, size_t size)
static ssize_t al_write(void *data, const void *buf, size_t size)
{
al_t *al = data;
al_t *al = (al_t*)data;
size_t written = 0;
while (written < size)
@@ -196,32 +194,32 @@ static ssize_t __al_write(void* data, const void* buf, size_t size)
return size;
}
static bool __al_stop(void *data)
static bool al_stop(void *data)
{
(void)data;
return true;
}
static void __al_set_nonblock_state(void *data, bool state)
static void al_set_nonblock_state(void *data, bool state)
{
al_t *al = data;
al_t *al = (al_t*)data;
al->nonblock = state;
}
static bool __al_start(void *data)
static bool al_start(void *data)
{
(void)data;
return true;
}
static void __al_free(void *data)
static void al_free(void *data)
{
al_t *al= data;
al_t *al = (al_t*)data;
if (al)
{
alSourceStop(al->source);
alDeleteSources(1, &al->source);
if ( al->buffers )
if (al->buffers)
{
alDeleteBuffers(al->num_buffers, al->buffers);
free(al->buffers);
@@ -235,13 +233,13 @@ static void __al_free(void *data)
}
const audio_driver_t audio_openal = {
.init = __al_init,
.write = __al_write,
.stop = __al_stop,
.start = __al_start,
.set_nonblock_state = __al_set_nonblock_state,
.free = __al_free,
.ident = "openal"
al_init,
al_write,
al_stop,
al_start,
al_set_nonblock_state,
al_free,
NULL,
"openal"
};
+67 -29
View File
@@ -1,5 +1,5 @@
/* SSNES - A Super Nintendo Entertainment System (SNES) Emulator frontend for libsnes.
* Copyright (C) 2010-2011 - Hans-Kristian Arntzen
* Copyright (C) 2010-2012 - Hans-Kristian Arntzen
*
* Some code herein may be based on code found in BSNES.
*
@@ -41,9 +41,9 @@
#define DEFAULT_OSS_DEV "/dev/dsp"
#endif
static void* __oss_init(const char* device, unsigned rate, unsigned latency)
static void *oss_init(const char *device, unsigned rate, unsigned latency)
{
int *fd = calloc(1, sizeof(int));
int *fd = (int*)calloc(1, sizeof(int));
if (fd == NULL)
return NULL;
@@ -55,18 +55,15 @@ static void* __oss_init(const char* device, unsigned rate, unsigned latency)
if ((*fd = open(oss_device, O_WRONLY)) < 0)
{
free(fd);
perror("open");
return NULL;
}
int frags = (latency * rate * 4)/(1000 * (1 << 9));
int frag = (frags << 16) | 9;
int frags = (latency * rate * 4) / (1000 * (1 << 10));
int frag = (frags << 16) | 10;
if (ioctl(*fd, SNDCTL_DSP_SETFRAGMENT, &frag) < 0)
{
close(*fd);
free(fd);
return NULL;
}
SSNES_WARN("Cannot set fragment sizes. Latency might not be as expected ...\n");
int channels = 2;
int format = is_little_endian() ?
@@ -76,6 +73,7 @@ static void* __oss_init(const char* device, unsigned rate, unsigned latency)
{
close(*fd);
free(fd);
perror("ioctl");
return NULL;
}
@@ -83,22 +81,31 @@ static void* __oss_init(const char* device, unsigned rate, unsigned latency)
{
close(*fd);
free(fd);
perror("ioctl");
return NULL;
}
if (ioctl(*fd, SNDCTL_DSP_SPEED, &rate) < 0)
int new_rate = rate;
if (ioctl(*fd, SNDCTL_DSP_SPEED, &new_rate) < 0)
{
close(*fd);
free(fd);
perror("ioctl");
return NULL;
}
if (new_rate != (int)rate)
{
SSNES_WARN("Requested sample rate not supported. Adjusting output rate to %d Hz.\n", new_rate);
g_settings.audio.out_rate = new_rate;
}
return fd;
}
static ssize_t __oss_write(void* data, const void* buf, size_t size)
static ssize_t oss_write(void *data, const void *buf, size_t size)
{
int *fd = data;
int *fd = (int*)data;
if (size == 0)
return 0;
@@ -114,46 +121,77 @@ static ssize_t __oss_write(void* data, const void* buf, size_t size)
return ret;
}
static bool __oss_stop(void *data)
static bool oss_stop(void *data)
{
int *fd = data;
int *fd = (int*)data;
ioctl(*fd, SNDCTL_DSP_RESET, 0);
return true;
}
static bool __oss_start(void *data)
static bool oss_start(void *data)
{
return true;
}
static void __oss_set_nonblock_state(void *data, bool state)
static void oss_set_nonblock_state(void *data, bool state)
{
int *fd = data;
int *fd = (int*)data;
int rc;
if (state)
rc = fcntl(*fd, F_SETFL, fcntl(*fd, F_GETFL) | O_NONBLOCK);
else
rc = fcntl(*fd, F_SETFL, fcntl(*fd, F_GETFL) & (~O_NONBLOCK));
if (rc != 0)
fprintf(stderr, "SSNES [ERROR]: Could not set nonblocking on OSS file descriptor. Will not be able to fast-forward.\n");
SSNES_WARN("Could not set nonblocking on OSS file descriptor. Will not be able to fast-forward.\n");
}
static void __oss_free(void *data)
static void oss_free(void *data)
{
int *fd = data;
int *fd = (int*)data;
ioctl(*fd, SNDCTL_DSP_RESET, 0);
close(*fd);
free(fd);
}
static size_t oss_write_avail(void *data)
{
int *fd = (int*)data;
audio_buf_info info;
if (ioctl(*fd, SNDCTL_DSP_GETOSPACE, &info) < 0)
{
SSNES_ERR("SNDCTL_DSP_GETOSPACE failed ...\n");
return 0;
}
return info.bytes;
}
static size_t oss_buffer_size(void *data)
{
int *fd = (int*)data;
audio_buf_info info;
if (ioctl(*fd, SNDCTL_DSP_GETOSPACE, &info) < 0)
{
SSNES_ERR("SNDCTL_DSP_GETOSPACE failed ...\n");
return 1; // Return something non-zero to avoid SIGFPE.
}
return info.fragsize * info.fragstotal;
}
const audio_driver_t audio_oss = {
.init = __oss_init,
.write = __oss_write,
.stop = __oss_stop,
.start = __oss_start,
.set_nonblock_state = __oss_set_nonblock_state,
.free = __oss_free,
.ident = "oss"
oss_init,
oss_write,
oss_stop,
oss_start,
oss_set_nonblock_state,
oss_free,
NULL,
"oss",
oss_write_avail,
oss_buffer_size,
};
+60 -44
View File
@@ -1,5 +1,5 @@
/* SSNES - A Super Nintendo Entertainment System (SNES) Emulator frontend for libsnes.
* Copyright (C) 2010-2011 - Hans-Kristian Arntzen
* Copyright (C) 2010-2012 - Hans-Kristian Arntzen
*
* Some code herein may be based on code found in BSNES.
*
@@ -19,7 +19,7 @@
#include "driver.h"
#include "general.h"
#include <pulse/pulseaudio.h>
#include <stdbool.h>
#include "../boolean.h"
#include <string.h>
#include <stdio.h>
@@ -30,11 +30,12 @@ typedef struct
pa_context *context;
pa_stream *stream;
bool nonblock;
size_t buffer_size;
} pa_t;
static void __pulse_free(void *data)
static void pulse_free(void *data)
{
pa_t *pa = data;
pa_t *pa = (pa_t*)data;
if (pa)
{
if (pa->mainloop)
@@ -61,7 +62,7 @@ static void __pulse_free(void *data)
static void context_state_cb(pa_context *c, void *data)
{
pa_t *pa = data;
pa_t *pa = (pa_t*)data;
switch (pa_context_get_state(c))
{
case PA_CONTEXT_READY:
@@ -76,7 +77,7 @@ static void context_state_cb(pa_context *c, void *data)
static void stream_state_cb(pa_stream *s, void *data)
{
pa_t *pa = data;
pa_t *pa = (pa_t*)data;
switch (pa_stream_get_state(s)) {
case PA_STREAM_READY:
case PA_STREAM_FAILED:
@@ -92,20 +93,24 @@ static void stream_request_cb(pa_stream *s, size_t length, void *data)
{
(void)length;
(void)s;
pa_t *pa = data;
pa_t *pa = (pa_t*)data;
pa_threaded_mainloop_signal(pa->mainloop, 0);
}
static void stream_latency_update_cb(pa_stream *s, void *data)
{
(void)s;
pa_t *pa = data;
pa_t *pa = (pa_t*)data;
pa_threaded_mainloop_signal(pa->mainloop, 0);
}
static void* __pulse_init(const char* device, unsigned rate, unsigned latency)
static void *pulse_init(const char *device, unsigned rate, unsigned latency)
{
pa_t *pa = calloc(1, sizeof(*pa));
pa_sample_spec spec;
memset(&spec, 0, sizeof(spec));
pa_buffer_attr buffer_attr = {0};
pa_t *pa = (pa_t*)calloc(1, sizeof(*pa));
if (!pa)
goto error;
@@ -131,11 +136,9 @@ static void* __pulse_init(const char* device, unsigned rate, unsigned latency)
if (pa_context_get_state(pa->context) != PA_CONTEXT_READY)
goto unlock_error;
pa_sample_spec spec = {
.format = is_little_endian() ? PA_SAMPLE_FLOAT32LE : PA_SAMPLE_FLOAT32BE,
.channels = 2,
.rate = rate
};
spec.format = is_little_endian() ? PA_SAMPLE_FLOAT32LE : PA_SAMPLE_FLOAT32BE;
spec.channels = 2;
spec.rate = rate;
pa->stream = pa_stream_new(pa->context, "audio", &spec, NULL);
if (!pa->stream)
@@ -145,13 +148,13 @@ static void* __pulse_init(const char* device, unsigned rate, unsigned latency)
pa_stream_set_write_callback(pa->stream, stream_request_cb, pa);
pa_stream_set_latency_update_callback(pa->stream, stream_latency_update_cb, pa);
pa_buffer_attr buffer_attr = {
.maxlength = -1,
.tlength = pa_usec_to_bytes(latency * PA_USEC_PER_MSEC, &spec),
.prebuf = -1,
.minreq = -1,
.fragsize = -1
};
buffer_attr.maxlength = -1;
buffer_attr.tlength = pa_usec_to_bytes(latency * PA_USEC_PER_MSEC, &spec);
buffer_attr.prebuf = -1;
buffer_attr.minreq = -1;
buffer_attr.fragsize = -1;
pa->buffer_size = buffer_attr.tlength;
if (pa_stream_connect_playback(pa->stream, NULL, &buffer_attr, PA_STREAM_ADJUST_LATENCY, NULL, NULL) < 0)
goto error;
@@ -168,17 +171,18 @@ static void* __pulse_init(const char* device, unsigned rate, unsigned latency)
unlock_error:
pa_threaded_mainloop_unlock(pa->mainloop);
error:
__pulse_free(pa);
pulse_free(pa);
return NULL;
}
static ssize_t __pulse_write(void* data, const void* buf, size_t size)
static ssize_t pulse_write(void *data, const void *buf, size_t size)
{
pa_t *pa = data;
pa_t *pa = (pa_t*)data;
pa_threaded_mainloop_lock(pa->mainloop);
unsigned length = pa_stream_writable_size(pa->stream);
size_t length = pa_stream_writable_size(pa->stream);
pa_threaded_mainloop_unlock(pa->mainloop);
while (length < size)
{
pa_threaded_mainloop_wait(pa->mainloop);
@@ -198,43 +202,55 @@ static ssize_t __pulse_write(void* data, const void* buf, size_t size)
return write_size;
}
static bool __pulse_stop(void *data)
static bool pulse_stop(void *data)
{
(void)data;
return true;
}
static bool __pulse_start(void *data)
static bool pulse_start(void *data)
{
(void)data;
return true;
}
static void __pulse_set_nonblock_state(void *data, bool state)
static void pulse_set_nonblock_state(void *data, bool state)
{
pa_t *pa = data;
pa_t *pa = (pa_t*)data;
pa->nonblock = state;
}
static bool __pulse_use_float(void *data)
static bool pulse_use_float(void *data)
{
(void)data;
return true;
}
static size_t pulse_write_avail(void *data)
{
pa_t *pa = (pa_t*)data;
pa_threaded_mainloop_lock(pa->mainloop);
size_t length = pa_stream_writable_size(pa->stream);
pa_threaded_mainloop_unlock(pa->mainloop);
return length;
}
static size_t pulse_buffer_size(void *data)
{
pa_t *pa = (pa_t*)data;
return pa->buffer_size;
}
const audio_driver_t audio_pulse = {
.init = __pulse_init,
.write = __pulse_write,
.stop = __pulse_stop,
.start = __pulse_start,
.set_nonblock_state = __pulse_set_nonblock_state,
.use_float = __pulse_use_float,
.free = __pulse_free,
.ident = "pulse"
pulse_init,
pulse_write,
pulse_stop,
pulse_start,
pulse_set_nonblock_state,
pulse_free,
pulse_use_float,
"pulse",
pulse_write_avail,
pulse_buffer_size,
};
+17 -16
View File
@@ -1,5 +1,5 @@
/* SSNES - A Super Nintendo Entertainment System (SNES) Emulator frontend for libsnes.
* Copyright (C) 2010-2011 - Hans-Kristian Arntzen
* Copyright (C) 2010-2012 - Hans-Kristian Arntzen
*
* Some code herein may be based on code found in BSNES.
*
@@ -15,20 +15,21 @@
* If not, see <http://www.gnu.org/licenses/>.
*/
// Hermite resampler based on bsnes' audio library.
// Attempts to be similiar to the libsamplerate process interface.
#ifndef __SSNES_HERMITE_H
#define __SSNES_HERMITE_H
#ifndef __SSNES_RESAMPLER_H
#define __SSNES_RESAMPLER_H
#include <stddef.h>
#include <stdbool.h>
#include <math.h>
typedef struct hermite_resampler hermite_resampler_t;
// M_PI is left out of ISO C99 :(
#ifndef M_PI
#define M_PI 3.14159265358979323846264338327
#endif
hermite_resampler_t *hermite_new(unsigned channels);
typedef struct ssnes_resampler ssnes_resampler_t;
struct hermite_data
struct resampler_data
{
const float *data_in;
float *data_out;
@@ -36,15 +37,15 @@ struct hermite_data
size_t input_frames;
size_t output_frames;
size_t input_frames_used;
size_t output_frames_gen;
bool end_of_input; // Just used to clone the SRC API.
double src_ratio;
double ratio;
};
void hermite_process(hermite_resampler_t *re, struct hermite_data *data);
void hermite_free(hermite_resampler_t *re);
ssnes_resampler_t *resampler_new(void);
void resampler_process(ssnes_resampler_t *re, struct resampler_data *data);
void resampler_free(ssnes_resampler_t *re);
// Generate a starting cosine pulse with given frequency for testing (SNR, etc) purposes.
void resampler_preinit(ssnes_resampler_t *re, double omega, double *samples_offset);
#endif
+21 -24
View File
@@ -1,5 +1,5 @@
/* SSNES - A Super Nintendo Entertainment System (SNES) Emulator frontend for libsnes.
* Copyright (C) 2010-2011 - Hans-Kristian Arntzen
* Copyright (C) 2010-2012 - Hans-Kristian Arntzen
*
* Some code herein may be based on code found in BSNES.
*
@@ -21,7 +21,7 @@
#include <roaraudio.h>
#include <errno.h>
#include <stdio.h>
#include <stdbool.h>
#include "../boolean.h"
#include "general.h"
typedef struct
@@ -30,10 +30,11 @@ typedef struct
bool nonblocking;
} roar_t;
static void* __roar_init(const char* device, unsigned rate, unsigned latency)
static void *ra_init(const char *device, unsigned rate, unsigned latency)
{
(void)latency;
int err;
roar_t *roar = calloc(1, sizeof(roar_t));
roar_t *roar = (roar_t*)calloc(1, sizeof(roar_t));
if (roar == NULL)
return NULL;
@@ -51,9 +52,9 @@ static void* __roar_init(const char* device, unsigned rate, unsigned latency)
return roar;
}
static ssize_t __roar_write(void* data, const void* buf, size_t size)
static ssize_t ra_write(void *data, const void *buf, size_t size)
{
roar_t *roar = data;
roar_t *roar = (roar_t*)data;
ssize_t rc;
if (size == 0)
@@ -77,45 +78,41 @@ static ssize_t __roar_write(void* data, const void* buf, size_t size)
return size;
}
static bool __roar_stop(void *data)
static bool ra_stop(void *data)
{
(void)data;
return true;
}
static void __roar_set_nonblock_state(void *data, bool state)
static void ra_set_nonblock_state(void *data, bool state)
{
roar_t *roar = data;
roar_t *roar = (roar_t*)data;
if (roar_vs_blocking(roar->vss, (state) ? ROAR_VS_FALSE : ROAR_VS_TRUE, NULL) < 0)
fprintf(stderr, "SSNES [ERROR]: Can't set nonblocking. Will not be able to fast-forward.\n");
roar->nonblocking = state;
}
static bool __roar_start(void *data)
static bool ra_start(void *data)
{
(void)data;
return true;
}
static void __roar_free(void *data)
static void ra_free(void *data)
{
roar_t *roar = data;
roar_t *roar = (roar_t*)data;
roar_vs_close(roar->vss, ROAR_VS_TRUE, NULL);
free(data);
}
const audio_driver_t audio_roar = {
.init = __roar_init,
.write = __roar_write,
.stop = __roar_stop,
.start = __roar_start,
.set_nonblock_state = __roar_set_nonblock_state,
.free = __roar_free,
.ident = "roar"
ra_init,
ra_write,
ra_stop,
ra_start,
ra_set_nonblock_state,
ra_free,
NULL,
"roar"
};
+66 -41
View File
@@ -1,5 +1,5 @@
/* SSNES - A Super Nintendo Entertainment System (SNES) Emulator frontend for libsnes.
* Copyright (C) 2010-2011 - Hans-Kristian Arntzen
* Copyright (C) 2010-2012 - Hans-Kristian Arntzen
*
* Some code herein may be based on code found in BSNES.
*
@@ -16,12 +16,16 @@
*/
#include "driver.h"
#include "../driver.h"
#include <stdlib.h>
#ifdef SSNES_CONSOLE
#include "../console/librsound/rsound.h"
#else
#include <rsound.h>
#endif
#include "fifo_buffer.h"
#include <stdbool.h>
#include "SDL.h"
#include "../boolean.h"
#include "../thread.h"
typedef struct rsd
{
@@ -31,45 +35,45 @@ typedef struct rsd
fifo_buffer_t *buffer;
SDL_mutex *cond_lock;
SDL_cond *cond;
slock_t *cond_lock;
scond_t *cond;
} rsd_t;
static ssize_t audio_cb(void *data, size_t bytes, void *userdata)
{
rsd_t *rsd = userdata;
rsd_t *rsd = (rsd_t*)userdata;
size_t avail = fifo_read_avail(rsd->buffer);
size_t write_size = bytes > avail ? avail : bytes;
fifo_read(rsd->buffer, data, write_size);
SDL_CondSignal(rsd->cond);
scond_signal(rsd->cond);
return write_size;
}
static void err_cb(void *userdata)
{
rsd_t *rsd = userdata;
rsd_t *rsd = (rsd_t*)userdata;
rsd->has_error = true;
SDL_CondSignal(rsd->cond);
scond_signal(rsd->cond);
}
static void* __rsd_init(const char* device, unsigned rate, unsigned latency)
static void *rs_init(const char *device, unsigned rate, unsigned latency)
{
rsd_t *rsd = calloc(1, sizeof(rsd_t));
if ( rsd == NULL )
rsd_t *rsd = (rsd_t*)calloc(1, sizeof(rsd_t));
if (!rsd)
return NULL;
rsound_t *rd;
if ( rsd_init(&rd) < 0 )
if (rsd_init(&rd) < 0)
{
free(rsd);
return NULL;
}
rsd->cond_lock = SDL_CreateMutex();
rsd->cond = SDL_CreateCond();
rsd->cond_lock = slock_new();
rsd->cond = scond_new();
rsd->buffer = fifo_new(1024 * 4);
@@ -80,14 +84,14 @@ static void* __rsd_init(const char* device, unsigned rate, unsigned latency)
rsd_set_param(rd, RSD_SAMPLERATE, &rate);
rsd_set_param(rd, RSD_LATENCY, &latency);
if ( device != NULL )
if (device)
rsd_set_param(rd, RSD_HOST, (void*)device);
rsd_set_param(rd, RSD_FORMAT, &format);
rsd_set_callback(rd, audio_cb, err_cb, 256, rsd);
if ( rsd_start(rd) < 0 )
if (rsd_start(rd) < 0)
{
free(rsd);
rsd_free(rd);
@@ -98,9 +102,9 @@ static void* __rsd_init(const char* device, unsigned rate, unsigned latency)
return rsd;
}
static ssize_t __rsd_write(void* data, const void* buf, size_t size)
static ssize_t rs_write(void *data, const void *buf, size_t size)
{
rsd_t *rsd = data;
rsd_t *rsd = (rsd_t*)data;
if (rsd->has_error)
return -1;
@@ -127,9 +131,9 @@ static ssize_t __rsd_write(void* data, const void* buf, size_t size)
rsd_callback_unlock(rsd->rd);
if (!rsd->has_error)
{
SDL_mutexP(rsd->cond_lock);
SDL_CondWait(rsd->cond, rsd->cond_lock);
SDL_mutexV(rsd->cond_lock);
slock_lock(rsd->cond_lock);
scond_wait(rsd->cond, rsd->cond_lock);
slock_unlock(rsd->cond_lock);
}
}
else
@@ -144,50 +148,71 @@ static ssize_t __rsd_write(void* data, const void* buf, size_t size)
}
}
static bool __rsd_stop(void *data)
static bool rs_stop(void *data)
{
rsd_t *rsd = data;
rsd_t *rsd = (rsd_t*)data;
rsd_stop(rsd->rd);
return true;
}
static void __rsd_set_nonblock_state(void *data, bool state)
static void rs_set_nonblock_state(void *data, bool state)
{
rsd_t *rsd = data;
rsd_t *rsd = (rsd_t*)data;
rsd->nonblock = state;
}
static bool __rsd_start(void *data)
static bool rs_start(void *data)
{
rsd_t *rsd = data;
if ( rsd_start(rsd->rd) < 0)
rsd_t *rsd = (rsd_t*)data;
if (rsd_start(rsd->rd) < 0)
return false;
return true;
}
static void __rsd_free(void *data)
static void rs_free(void *data)
{
rsd_t *rsd = data;
rsd_t *rsd = (rsd_t*)data;
rsd_stop(rsd->rd);
rsd_free(rsd->rd);
fifo_free(rsd->buffer);
SDL_DestroyMutex(rsd->cond_lock);
SDL_DestroyCond(rsd->cond);
slock_free(rsd->cond_lock);
scond_free(rsd->cond);
free(rsd);
}
static size_t rs_write_avail(void *data)
{
rsd_t *rsd = (rsd_t*)data;
if (rsd->has_error)
return 0;
rsd_callback_lock(rsd->rd);
size_t val = fifo_write_avail(rsd->buffer);
rsd_callback_unlock(rsd->rd);
return val;
}
static size_t rs_buffer_size(void *data)
{
(void)data;
return 1024 * 4;
}
const audio_driver_t audio_rsound = {
.init = __rsd_init,
.write = __rsd_write,
.stop = __rsd_stop,
.start = __rsd_start,
.set_nonblock_state = __rsd_set_nonblock_state,
.free = __rsd_free,
.ident = "rsound"
rs_init,
rs_write,
rs_stop,
rs_start,
rs_set_nonblock_state,
rs_free,
NULL,
"rsound",
rs_write_avail,
rs_buffer_size,
};
+40 -39
View File
@@ -1,5 +1,5 @@
/* SSNES - A Super Nintendo Entertainment System (SNES) Emulator frontend for libsnes.
* Copyright (C) 2010-2011 - Hans-Kristian Arntzen
* Copyright (C) 2010-2012 - Hans-Kristian Arntzen
*
* Some code herein may be based on code found in BSNES.
*
@@ -16,36 +16,37 @@
*/
#include "driver.h"
#include "../driver.h"
#include <stdlib.h>
#include <stdbool.h>
#include "../boolean.h"
#include <stddef.h>
#include <stdint.h>
#include <string.h>
#include "SDL.h"
#include "SDL_audio.h"
#include "SDL_thread.h"
#include "general.h"
#include "fifo_buffer.h"
#include "../thread.h"
#include "../general.h"
#include "../fifo_buffer.h"
typedef struct sdl_audio
{
bool nonblock;
SDL_mutex *lock;
SDL_cond *cond;
slock_t *lock;
scond_t *cond;
fifo_buffer_t *buffer;
} sdl_audio_t;
static void sdl_audio_cb(void *data, Uint8 *stream, int len)
{
sdl_audio_t *sdl = data;
sdl_audio_t *sdl = (sdl_audio_t*)data;
size_t avail = fifo_read_avail(sdl->buffer);
size_t write_size = len > avail ? avail : len;
size_t write_size = len > (int)avail ? avail : len;
fifo_read(sdl->buffer, stream, write_size);
SDL_CondSignal(sdl->cond);
scond_signal(sdl->cond);
// If underrun, fill rest with silence.
memset(stream + write_size, 0, len - write_size);
@@ -58,27 +59,26 @@ static inline int find_num_frames(int rate, int latency)
return next_pow2(frames);
}
static void* sdl_audio_init(const char* device, unsigned rate, unsigned latency)
static void *sdl_audio_init(const char *device, unsigned rate, unsigned latency)
{
(void)device;
if (SDL_InitSubSystem(SDL_INIT_AUDIO) < 0)
return NULL;
sdl_audio_t *sdl = calloc(1, sizeof(*sdl));
sdl_audio_t *sdl = (sdl_audio_t*)calloc(1, sizeof(*sdl));
if (!sdl)
return NULL;
// We have to buffer up some data ourselves, so we let SDL carry approx half of the latency. SDL double buffers audio and we do as well.
int frames = find_num_frames(rate, latency / 4);
SDL_AudioSpec spec = {
.freq = rate,
.format = AUDIO_S16SYS,
.channels = 2,
.samples = frames, // This is in audio frames, not samples ... :(
.callback = sdl_audio_cb,
.userdata = sdl
};
SDL_AudioSpec spec = {0};
spec.freq = rate;
spec.format = AUDIO_S16SYS;
spec.channels = 2;
spec.samples = frames; // This is in audio frames, not samples ... :(
spec.callback = sdl_audio_cb;
spec.userdata = sdl;
SDL_AudioSpec out;
@@ -90,8 +90,8 @@ static void* sdl_audio_init(const char* device, unsigned rate, unsigned latency)
}
g_settings.audio.out_rate = out.freq;
sdl->lock = SDL_CreateMutex();
sdl->cond = SDL_CreateCond();
sdl->lock = slock_new();
sdl->cond = scond_new();
SSNES_LOG("SDL audio: Requested %d ms latency, got %d ms\n", latency, (int)(out.samples * 4 * 1000 / g_settings.audio.out_rate));
@@ -109,9 +109,9 @@ static void* sdl_audio_init(const char* device, unsigned rate, unsigned latency)
return sdl;
}
static ssize_t sdl_audio_write(void* data, const void* buf, size_t size)
static ssize_t sdl_audio_write(void *data, const void *buf, size_t size)
{
sdl_audio_t *sdl = data;
sdl_audio_t *sdl = (sdl_audio_t*)data;
ssize_t ret = 0;
if (sdl->nonblock)
@@ -134,9 +134,9 @@ static ssize_t sdl_audio_write(void* data, const void* buf, size_t size)
if (avail == 0)
{
SDL_UnlockAudio();
SDL_mutexP(sdl->lock);
SDL_CondWait(sdl->cond, sdl->lock);
SDL_mutexV(sdl->lock);
slock_lock(sdl->lock);
scond_wait(sdl->cond, sdl->lock);
slock_unlock(sdl->lock);
}
else
{
@@ -168,7 +168,7 @@ static bool sdl_audio_start(void *data)
static void sdl_audio_set_nonblock_state(void *data, bool state)
{
sdl_audio_t *sdl = data;
sdl_audio_t *sdl = (sdl_audio_t*)data;
sdl->nonblock = state;
}
@@ -177,23 +177,24 @@ static void sdl_audio_free(void *data)
SDL_CloseAudio();
SDL_QuitSubSystem(SDL_INIT_AUDIO);
sdl_audio_t *sdl = data;
sdl_audio_t *sdl = (sdl_audio_t*)data;
if (sdl)
{
fifo_free(sdl->buffer);
SDL_DestroyMutex(sdl->lock);
SDL_DestroyCond(sdl->cond);
slock_free(sdl->lock);
scond_free(sdl->cond);
}
free(sdl);
}
const audio_driver_t audio_sdl = {
.init = sdl_audio_init,
.write = sdl_audio_write,
.stop = sdl_audio_stop,
.start = sdl_audio_start,
.set_nonblock_state = sdl_audio_set_nonblock_state,
.free = sdl_audio_free,
.ident = "sdl"
sdl_audio_init,
sdl_audio_write,
sdl_audio_stop,
sdl_audio_start,
sdl_audio_set_nonblock_state,
sdl_audio_free,
NULL,
"sdl"
};
+279
View File
@@ -0,0 +1,279 @@
/* SSNES - A Super Nintendo Entertainment System (SNES) Emulator frontend for libsnes.
* Copyright (C) 2010-2012 - Hans-Kristian Arntzen
*
* Some code herein may be based on code found in BSNES.
*
* SSNES is free software: you can redistribute it and/or modify it under the terms
* of the GNU General Public License as published by the Free Software Found-
* ation, either version 3 of the License, or (at your option) any later version.
*
* SSNES is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
* without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
* PURPOSE. See the GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License along with SSNES.
* If not, see <http://www.gnu.org/licenses/>.
*/
// Bog-standard windowed SINC implementation.
// Only suitable as an upsampler, as there is no low-pass filter stage.
#include "resampler.h"
#include <math.h>
#include <stdint.h>
#include <stdlib.h>
#include <string.h>
#ifndef RESAMPLER_TEST
#include "../general.h"
#else
#define SSNES_LOG(...)
#endif
#if __SSE__
#include <xmmintrin.h>
#endif
#define PHASE_BITS 8
#define SUBPHASE_BITS 16
#define PHASES (1 << PHASE_BITS)
#define PHASES_SHIFT (SUBPHASE_BITS)
#define SUBPHASES (1 << SUBPHASE_BITS)
#define SUBPHASES_SHIFT 0
#define SUBPHASES_MASK ((1 << SUBPHASE_BITS) - 1)
#define PHASES_WRAP (1 << (PHASE_BITS + SUBPHASE_BITS))
#define FRAMES_SHIFT (PHASE_BITS + SUBPHASE_BITS)
#define SIDELOBES 16
#define TAPS (SIDELOBES * 2)
#define CUTOFF 0.9
#define PHASE_INDEX 0
#define DELTA_INDEX 1
struct ssnes_resampler
{
float phase_table[PHASES][2][TAPS];
float buffer_l[2 * TAPS];
float buffer_r[2 * TAPS];
unsigned ptr;
uint32_t time;
};
void resampler_preinit(ssnes_resampler_t *re, double omega, double *samples_offset)
{
*samples_offset = SIDELOBES + 1;
for (int i = 0; i < 2 * SIDELOBES; i++)
{
re->buffer_l[i] = re->buffer_l[i + TAPS] = cos((i - (SIDELOBES - 1)) * omega);
re->buffer_r[i] = re->buffer_r[i + TAPS] = re->buffer_l[i];
}
re->time = 0;
re->ptr = 0;
}
static inline double sinc(double val)
{
if (fabs(val) < 0.00001)
return 1.0;
else
return sin(val) / val;
}
static inline double lanzcos(double index)
{
return sinc(index);
}
static void init_sinc_table(ssnes_resampler_t *resamp)
{
// Sinc phases: [..., p + 3, p + 2, p + 1, p + 0, p - 1, p - 2, p - 3, p - 4, ...]
for (int i = 0; i < PHASES; i++)
{
for (int j = 0; j < TAPS; j++)
{
double p = (double)i / PHASES;
double sinc_phase = M_PI * (p + (SIDELOBES - 1 - j));
resamp->phase_table[i][PHASE_INDEX][j] = CUTOFF * sinc(CUTOFF * sinc_phase) *
lanzcos(sinc_phase / SIDELOBES);
}
}
// Optimize linear interpolation.
for (int i = 0; i < PHASES - 1; i++)
{
for (int j = 0; j < TAPS; j++)
{
resamp->phase_table[i][DELTA_INDEX][j] =
(resamp->phase_table[i + 1][PHASE_INDEX][j] - resamp->phase_table[i][PHASE_INDEX][j]) / SUBPHASES;
}
}
// Interpolation between [PHASES - 1] => [PHASES]
for (int j = 0; j < TAPS; j++)
{
double p = 1.0;
double sinc_phase = M_PI * (p + (SIDELOBES - 1 - j));
double phase = CUTOFF * sinc(CUTOFF * sinc_phase) * lanzcos(sinc_phase / SIDELOBES);
float result = (phase - resamp->phase_table[PHASES - 1][PHASE_INDEX][j]) / SUBPHASES;
resamp->phase_table[PHASES - 1][DELTA_INDEX][j] = result;
}
}
// No memalign() for us on Win32 ...
static void *aligned_alloc(size_t boundary, size_t size)
{
void *ptr = malloc(boundary + size + sizeof(uintptr_t));
if (!ptr)
return NULL;
uintptr_t addr = ((uintptr_t)ptr + sizeof(uintptr_t) + boundary) & ~(boundary - 1);
void **place = (void**)addr;
place[-1] = ptr;
return (void*)addr;
}
static void aligned_free(void *ptr)
{
void **p = (void**)ptr;
free(p[-1]);
}
ssnes_resampler_t *resampler_new(void)
{
ssnes_resampler_t *re = (ssnes_resampler_t*)aligned_alloc(16, sizeof(*re));
if (!re)
return NULL;
memset(re, 0, sizeof(*re));
init_sinc_table(re);
#if __SSE__
SSNES_LOG("Sinc resampler [SSE]\n");
#else
SSNES_LOG("Sinc resampler [C]\n");
#endif
return re;
}
#if __SSE__
static void process_sinc(ssnes_resampler_t *resamp, float *out_buffer)
{
__m128 sum_l = _mm_setzero_ps();
__m128 sum_r = _mm_setzero_ps();
const float *buffer_l = resamp->buffer_l + resamp->ptr;
const float *buffer_r = resamp->buffer_r + resamp->ptr;
unsigned phase = resamp->time >> PHASES_SHIFT;
unsigned delta = (resamp->time >> SUBPHASES_SHIFT) & SUBPHASES_MASK;
__m128 delta_f = _mm_set1_ps(delta);
const float *phase_table = resamp->phase_table[phase][PHASE_INDEX];
const float *delta_table = resamp->phase_table[phase][DELTA_INDEX];
for (unsigned i = 0; i < TAPS; i += 4)
{
__m128 buf_l = _mm_loadu_ps(buffer_l + i);
__m128 buf_r = _mm_loadu_ps(buffer_r + i);
__m128 phases = _mm_load_ps(phase_table + i);
__m128 deltas = _mm_load_ps(delta_table + i);
__m128 sinc = _mm_add_ps(phases, _mm_mul_ps(deltas, delta_f));
sum_l = _mm_add_ps(sum_l, _mm_mul_ps(buf_l, sinc));
sum_r = _mm_add_ps(sum_r, _mm_mul_ps(buf_r, sinc));
}
// Them annoying shuffles :V
// sum_l = { l3, l2, l1, l0 }
// sum_r = { r3, r2, r1, r0 }
__m128 sum = _mm_add_ps(_mm_shuffle_ps(sum_l, sum_r, _MM_SHUFFLE(1, 0, 1, 0)),
_mm_shuffle_ps(sum_l, sum_r, _MM_SHUFFLE(3, 2, 3, 2)));
// sum = { r1, r0, l1, l0 } + { r3, r2, l3, l2 }
// sum = { R1, R0, L1, L0 }
sum = _mm_add_ps(_mm_shuffle_ps(sum, sum, _MM_SHUFFLE(3, 3, 1, 1)), sum);
// sum = {R1, R1, L1, L1 } + { R1, R0, L1, L0 }
// sum = { X, R, X, L }
// Store L
_mm_store_ss(out_buffer + 0, sum);
// movehl { X, R, X, L } == { X, R, X, R }
_mm_store_ss(out_buffer + 1, _mm_movehl_ps(sum, sum));
}
#else // Plain ol' C99
static void process_sinc(ssnes_resampler_t *resamp, float *out_buffer)
{
float sum_l = 0.0f;
float sum_r = 0.0f;
const float *buffer_l = resamp->buffer_l + resamp->ptr;
const float *buffer_r = resamp->buffer_r + resamp->ptr;
unsigned phase = resamp->time >> PHASES_SHIFT;
unsigned delta = (resamp->time >> SUBPHASES_SHIFT) & SUBPHASES_MASK;
float delta_f = (float)delta;
const float *phase_table = resamp->phase_table[phase][PHASE_INDEX];
const float *delta_table = resamp->phase_table[phase][DELTA_INDEX];
for (unsigned i = 0; i < TAPS; i++)
{
float sinc_val = phase_table[i] + delta_f * delta_table[i];
sum_l += buffer_l[i] * sinc_val;
sum_r += buffer_r[i] * sinc_val;
}
out_buffer[0] = sum_l;
out_buffer[1] = sum_r;
}
#endif
void resampler_process(ssnes_resampler_t *re, struct resampler_data *data)
{
uint32_t ratio = PHASES_WRAP / data->ratio;
const float *input = data->data_in;
float *output = data->data_out;
size_t frames = data->input_frames;
size_t out_frames = 0;
while (frames)
{
process_sinc(re, output);
output += 2;
out_frames++;
re->time += ratio;
while (re->time >= PHASES_WRAP)
{
re->buffer_l[re->ptr + TAPS] = re->buffer_l[re->ptr] = *input++;
re->buffer_r[re->ptr + TAPS] = re->buffer_r[re->ptr] = *input++;
re->ptr = (re->ptr + 1) & (TAPS - 1);
re->time -= PHASES_WRAP;
frames--;
}
}
data->output_frames = out_frames;
}
void resampler_free(ssnes_resampler_t *re)
{
aligned_free(re);
}
+29
View File
@@ -0,0 +1,29 @@
TESTS := test-hermite test-sinc test-snr-sinc test-snr-hermite
CFLAGS += -O3 -g -Wall -pedantic -std=gnu99 -DRESAMPLER_TEST -march=native
LDFLAGS += -lm
all: $(TESTS)
test-hermite: ../hermite.o ../utils.o main.o
$(CC) -o $@ $^ $(LDFLAGS)
test-sinc: ../sinc.o ../utils.o main.o
$(CC) -o $@ $^ $(LDFLAGS)
test-snr-sinc: ../sinc.o ../utils.o snr.o
$(CC) -o $@ $^ $(LDFLAGS)
test-snr-hermite: ../hermite.o ../utils.o snr.o
$(CC) -o $@ $^ $(LDFLAGS)
%.o: %.c
$(CC) -c -o $@ $< $(CFLAGS)
clean:
rm -f $(TESTS)
rm -f *.o
rm -f ../*.o
.PHONY: clean
+81
View File
@@ -0,0 +1,81 @@
/* SSNES - A Super Nintendo Entertainment System (SNES) Emulator frontend for libsnes.
* Copyright (C) 2010-2012 - Hans-Kristian Arntzen
*
* Some code herein may be based on code found in BSNES.
*
* SSNES is free software: you can redistribute it and/or modify it under the terms
* of the GNU General Public License as published by the Free Software Found-
* ation, either version 3 of the License, or (at your option) any later version.
*
* SSNES is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
* without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
* PURPOSE. See the GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License along with SSNES.
* If not, see <http://www.gnu.org/licenses/>.
*/
// Resampler that reads raw S16NE/stereo from stdin and outputs to stdout in S16NE/stereo.
// Used for testing and performance benchmarking.
#include "../resampler.h"
#include "../utils.h"
#include <stdio.h>
#include <stdlib.h>
int main(int argc, char *argv[])
{
int16_t input_i[1024];
float input_f[1024];
int16_t output_i[1024 * 8];
float output_f[1024 * 8];
if (argc != 3)
{
fprintf(stderr, "Usage: %s <in-rate> <out-rate> (max ratio: 8.0)\n", argv[0]);
return 1;
}
double in_rate = strtod(argv[1], NULL);
double out_rate = strtod(argv[2], NULL);
double ratio = out_rate / in_rate;
if (ratio >= 7.99)
{
fprintf(stderr, "Ratio is too high.\n");
return 1;
}
ssnes_resampler_t *resamp = resampler_new();
if (!resamp)
{
fprintf(stderr, "Failed to allocate resampler ...\n");
return 1;
}
for (;;)
{
if (fread(input_i, sizeof(int16_t), 1024, stdin) != 1024)
break;
audio_convert_s16_to_float(input_f, input_i, 1024);
struct resampler_data data = {
.data_in = input_f,
.data_out = output_f,
.input_frames = sizeof(input_f) / (2 * sizeof(float)),
.ratio = ratio,
};
resampler_process(resamp, &data);
size_t output_samples = data.output_frames * 2;
audio_convert_float_to_s16(output_i, output_f, output_samples);
if (fwrite(output_i, sizeof(int16_t), output_samples, stdout) != output_samples)
break;
}
resampler_free(resamp);
}
+288
View File
@@ -0,0 +1,288 @@
/* SSNES - A Super Nintendo Entertainment System (SNES) Emulator frontend for libsnes.
* Copyright (C) 2010-2012 - Hans-Kristian Arntzen
*
* Some code herein may be based on code found in BSNES.
*
* SSNES is free software: you can redistribute it and/or modify it under the terms
* of the GNU General Public License as published by the Free Software Found-
* ation, either version 3 of the License, or (at your option) any later version.
*
* SSNES is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
* without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
* PURPOSE. See the GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License along with SSNES.
* If not, see <http://www.gnu.org/licenses/>.
*/
#include "../resampler.h"
#include "../utils.h"
#include <stdio.h>
#include <stdlib.h>
#include <math.h>
#include <complex.h>
#include <string.h>
#include <assert.h>
#include <stdbool.h>
static void gen_signal(float *out, double omega, double bias_samples, size_t samples)
{
for (size_t i = 0; i < samples; i += 2)
{
out[i + 0] = cos(((i >> 1) + bias_samples) * omega);
out[i + 1] = out[i + 0];
}
}
struct snr_result
{
double snr;
double gain;
};
static unsigned bitrange(unsigned len)
{
unsigned ret = 0;
while ((len >>= 1))
ret++;
return ret;
}
static unsigned bitswap(unsigned i, unsigned range)
{
unsigned ret = 0;
for (unsigned shifts = 0; shifts < range; shifts++)
ret |= i & (1 << (range - shifts - 1)) ? (1 << shifts) : 0;
return ret;
}
// When interleaving the butterfly buffer, addressing puts bits in reverse.
// [0, 1, 2, 3, 4, 5, 6, 7] => [0, 4, 2, 6, 1, 5, 3, 7]
static void interleave(complex double *butterfly_buf, size_t samples)
{
unsigned range = bitrange(samples);
for (unsigned i = 0; i < samples; i++)
{
unsigned target = bitswap(i, range);
if (target > i)
{
complex double tmp = butterfly_buf[target];
butterfly_buf[target] = butterfly_buf[i];
butterfly_buf[i] = tmp;
}
}
}
static complex double gen_phase(double index)
{
return cexp(M_PI * I * index);
}
static void butterfly(complex double *a, complex double *b, complex double mod)
{
mod *= *b;
complex double a_ = *a + mod;
complex double b_ = *a - mod;
*a = a_;
*b = b_;
}
static void butterflies(complex double *butterfly_buf, double phase_dir, size_t step_size, size_t samples)
{
for (unsigned i = 0; i < samples; i += 2 * step_size)
for (unsigned j = i; j < i + step_size; j++)
butterfly(&butterfly_buf[j], &butterfly_buf[j + step_size], gen_phase((phase_dir * (j - i)) / step_size));
}
static void calculate_fft(const float *data, complex double *butterfly_buf, size_t samples)
{
// Enforce POT.
assert((samples & (samples - 1)) == 0);
for (unsigned i = 0; i < samples; i++)
butterfly_buf[i] = data[2 * i];
// Interleave buffer to work with FFT.
interleave(butterfly_buf, samples);
// Fly, lovely butterflies! :D
for (unsigned step_size = 1; step_size < samples; step_size *= 2)
butterflies(butterfly_buf, -1.0, step_size, samples);
}
static void calculate_fft_adjust(complex double *butterfly_buf, double gain, bool merge_high, size_t samples)
{
if (merge_high)
{
for (unsigned i = 1; i < samples / 2; i++)
butterfly_buf[i] += conj(butterfly_buf[samples - i]);
}
// Normalize amplitudes.
for (unsigned i = 0; i < samples; i++)
butterfly_buf[i] *= gain;
}
static void calculate_ifft(complex double *butterfly_buf, size_t samples, bool normalize)
{
// Enforce POT.
assert((samples & (samples - 1)) == 0);
interleave(butterfly_buf, samples);
// Fly, lovely butterflies! In opposite direction! :D
for (unsigned step_size = 1; step_size < samples; step_size *= 2)
butterflies(butterfly_buf, 1.0, step_size, samples);
if (normalize)
calculate_fft_adjust(butterfly_buf, 1.0 / samples, false, samples);
}
static void test_fft(void)
{
fprintf(stderr, "Sanity checking FFT ...\n");
float signal[32];
complex double butterfly_buf[16];
complex double buf_tmp[16];
const float cos_freqs[] = {
1.0, 4.0, 6.0,
};
const float sin_freqs[] = {
-2.0, 5.0, 7.0,
};
for (unsigned i = 0; i < 16; i++)
{
signal[2 * i] = 0.0;
for (unsigned j = 0; j < sizeof(cos_freqs) / sizeof(cos_freqs[0]); j++)
signal[2 * i] += cos(2.0 * M_PI * i * cos_freqs[j] / 16.0);
for (unsigned j = 0; j < sizeof(sin_freqs) / sizeof(sin_freqs[0]); j++)
signal[2 * i] += sin(2.0 * M_PI * i * sin_freqs[j] / 16.0);
}
calculate_fft(signal, butterfly_buf, 16);
memcpy(buf_tmp, butterfly_buf, sizeof(buf_tmp));
calculate_fft_adjust(buf_tmp, 1.0 / 16, true, 16);
printf("FFT: { ");
for (unsigned i = 0; i < 7; i++)
printf("(%4.2lf, %4.2lf), ", creal(buf_tmp[i]), cimag(buf_tmp[i]));
printf("(%4.2lf, %4.2lf) }\n", creal(buf_tmp[7]), cimag(buf_tmp[7]));
calculate_ifft(butterfly_buf, 16, true);
printf("Original: { ");
for (unsigned i = 0; i < 15; i++)
printf("%5.2f, ", signal[2 * i]);
printf("%5.2f }\n", signal[2 * 15]);
printf("FFT => IFFT: { ");
for (unsigned i = 0; i < 15; i++)
printf("%5.2lf, ", creal(butterfly_buf[i]));
printf("%5.2lf }\n", creal(butterfly_buf[15]));
}
// This doesn't yet take account for slight phase distortions,
// so reported SNR is lower than reality.
static void calculate_snr(struct snr_result *res,
unsigned in_rate,
const float *resamp, complex double *butterfly_buf, size_t samples)
{
samples >>= 1;
calculate_fft(resamp, butterfly_buf, samples);
calculate_fft_adjust(butterfly_buf, 1.0 / samples, true, samples);
double signal = cabs(butterfly_buf[in_rate] * butterfly_buf[in_rate]);
butterfly_buf[in_rate] = 0.0;
double noise = 0.0;
for (unsigned i = 0; i < samples / 2; i++)
noise += cabs(butterfly_buf[i] * butterfly_buf[i]);
res->snr = 10.0 * log10(signal / noise);
res->gain = 10.0 * log10(signal);
}
int main(int argc, char *argv[])
{
if (argc != 2)
{
fprintf(stderr, "Usage: %s <ratio> (out-rate is fixed for FFT).\n", argv[0]);
return 1;
}
double ratio = strtod(argv[1], NULL);
const unsigned fft_samples = 1024 * 128;
unsigned out_rate = fft_samples;
unsigned in_rate = out_rate / ratio;
ratio = (double)out_rate / in_rate;
if (ratio <= 1.0)
{
fprintf(stderr, "Ratio too low ...\n");
return 1;
}
static const float freq_list[] = {
0.001, 0.002, 0.003, 0.004, 0.005, 0.008,
0.010, 0.015, 0.020, 0.025, 0.030, 0.035, 0.040, 0.045, 0.050,
0.10, 0.15, 0.20, 0.25, 0.30, 0.35, 0.40, 0.45,
0.46, 0.47, 0.48, 0.49, 0.495,
};
unsigned samples = in_rate * 2;
float *input = calloc(sizeof(float), samples);
float *output = calloc(sizeof(float), (fft_samples + 1) * 2);
complex double *butterfly_buf = calloc(sizeof(complex double), fft_samples);
bool warned = false;
assert(input);
assert(output);
ssnes_resampler_t *re = resampler_new();
assert(re);
test_fft();
for (unsigned i = 0; i < sizeof(freq_list) / sizeof(freq_list[0]); i++)
{
unsigned freq = freq_list[i] * in_rate;
double omega = 2.0 * M_PI * freq / in_rate;
double sample_offset;
resampler_preinit(re, omega, &sample_offset);
gen_signal(input, omega, sample_offset, samples);
struct resampler_data data = {
.data_in = input,
.data_out = output,
.input_frames = in_rate,
.ratio = ratio,
};
resampler_process(re, &data);
unsigned out_samples = data.output_frames * 2;
if (out_samples != fft_samples * 2 && !warned)
{
fprintf(stderr, "Out samples != fft_samples ... %u / %u\n", out_samples, fft_samples * 2);
warned = true;
}
struct snr_result res;
calculate_snr(&res, freq, output, butterfly_buf, fft_samples * 2);
printf("SNR @ w = %5.3f : %6.2lf dB, Gain: %6.1lf dB\n",
freq_list[i], res.snr, res.gain);
}
resampler_free(re);
free(input);
free(output);
free(butterfly_buf);
}
+119
View File
@@ -0,0 +1,119 @@
#include "utils.h"
#if __SSE2__
#include <emmintrin.h>
#elif __ALTIVEC__
#include <altivec.h>
#endif
void audio_convert_s16_to_float_C(float *out,
const int16_t *in, size_t samples)
{
for (size_t i = 0; i < samples; i++)
out[i] = (float)in[i] / 0x8000;
}
void audio_convert_float_to_s16_C(int16_t *out,
const float *in, size_t samples)
{
for (size_t i = 0; i < samples; i++)
{
int32_t val = (int32_t)(in[i] * 0x8000);
out[i] = (val > 0x7FFF) ? 0x7FFF : (val < -0x8000 ? -0x8000 : (int16_t)val);
}
}
#if __SSE2__
void audio_convert_s16_to_float_SSE2(float *out,
const int16_t *in, size_t samples)
{
__m128 factor = _mm_set1_ps(1.0f / (0x7fff * 0x10000));
size_t i;
for (i = 0; i + 8 <= samples; i += 8, in += 8, out += 8)
{
__m128i input = _mm_loadu_si128((const __m128i *)in);
__m128i regs[2] = {
_mm_unpacklo_epi16(_mm_setzero_si128(), input),
_mm_unpackhi_epi16(_mm_setzero_si128(), input),
};
__m128 output[2] = {
_mm_mul_ps(_mm_cvtepi32_ps(regs[0]), factor),
_mm_mul_ps(_mm_cvtepi32_ps(regs[1]), factor),
};
_mm_storeu_ps(out + 0, output[0]);
_mm_storeu_ps(out + 4, output[1]);
}
audio_convert_s16_to_float_C(out, in, samples - i);
}
void audio_convert_float_to_s16_SSE2(int16_t *out,
const float *in, size_t samples)
{
__m128 factor = _mm_set1_ps((float)0x7fff);
size_t i;
for (i = 0; i + 8 <= samples; i += 8, in += 8, out += 8)
{
__m128 input[2] = { _mm_loadu_ps(in + 0), _mm_loadu_ps(in + 4) };
__m128 res[2] = { _mm_mul_ps(input[0], factor), _mm_mul_ps(input[1], factor) };
__m128i ints[2] = { _mm_cvtps_epi32(res[0]), _mm_cvtps_epi32(res[1]) };
__m128i packed = _mm_packs_epi32(ints[0], ints[1]);
_mm_storeu_si128((__m128i *)out, packed);
}
audio_convert_float_to_s16_C(out, in, samples - i);
}
#elif __ALTIVEC__
void audio_convert_s16_to_float_altivec(float *out,
const int16_t *in, size_t samples)
{
// Unaligned loads/store is a bit expensive, so we optimize for the good path (very likely).
if (((uintptr_t)out & 15) + ((uintptr_t)in & 15) == 0)
{
size_t i;
for (i = 0; i + 8 <= samples; i += 8, in += 8, out += 8)
{
vector signed short input = vec_ld(0, in);
vector signed int hi = vec_unpackh(input);
vector signed int lo = vec_unpackl(input);
vector float out_hi = vec_ctf(hi, 15);
vector float out_lo = vec_ctf(lo, 15);
vec_st(out_hi, 0, out);
vec_st(out_lo, 16, out);
}
audio_convert_s16_to_float_C(out, in, samples - i);
}
else
audio_convert_s16_to_float_C(out, in, samples);
}
void audio_convert_float_to_s16_altivec(int16_t *out,
const float *in, size_t samples)
{
// Unaligned loads/store is a bit expensive, so we optimize for the good path (very likely).
if (((uintptr_t)out & 15) + ((uintptr_t)in & 15) == 0)
{
size_t i;
for (i = 0; i + 8 <= samples; i += 8, in += 8, out += 8)
{
vector float input0 = vec_ld( 0, in);
vector float input1 = vec_ld(16, in);
vector signed int result0 = vec_cts(input0, 15);
vector signed int result1 = vec_cts(input1, 15);
vec_st(vec_packs(result0, result1), 0, out);
}
audio_convert_float_to_s16_C(out, in, samples - i);
}
else
audio_convert_float_to_s16_C(out, in, samples);
}
#endif
+38
View File
@@ -0,0 +1,38 @@
#ifndef AUDIO_UTILS_H
#define AUDIO_UTILS_H
#include <stdint.h>
#include <stddef.h>
#if __SSE2__
#define audio_convert_s16_to_float audio_convert_s16_to_float_SSE2
#define audio_convert_float_to_s16 audio_convert_float_to_s16_SSE2
void audio_convert_s16_to_float_SSE2(float *out,
const int16_t *in, size_t samples);
void audio_convert_float_to_s16_SSE2(int16_t *out,
const float *in, size_t samples);
#elif __ALTIVEC__
#define audio_convert_s16_to_float audio_convert_s16_to_float_altivec
#define audio_convert_float_to_s16 audio_convert_float_to_s16_altivec
void audio_convert_s16_to_float_altivec(float *out,
const int16_t *in, size_t samples);
void audio_convert_float_to_s16_altivec(int16_t *out,
const float *in, size_t samples);
#else
#define audio_convert_s16_to_float audio_convert_s16_to_float_C
#define audio_convert_float_to_s16 audio_convert_float_to_s16_C
#endif
void audio_convert_s16_to_float_C(float *out,
const int16_t *in, size_t samples);
void audio_convert_float_to_s16_C(int16_t *out,
const float *in, size_t samples);
#endif
+187
View File
@@ -0,0 +1,187 @@
/*
Simple C interface for XAudio2
Author: Hans-Kristian Arntzen
License: Public Domain
*/
#include "xaudio.h"
#include "xaudio-c.h"
#include <stdint.h>
#include <stdio.h>
#include "../../msvc/msvc_compat.h"
#define MAX_BUFFERS 16
#define MAX_BUFFERS_MASK (MAX_BUFFERS - 1)
#undef min
#undef max
#define min(a, b) ((a) < (b) ? (a) : (b))
#define max(a, b) ((a) > (b) ? (a) : (b))
struct xaudio2
{
const IXAudio2VoiceCallbackVtbl *lpVtbl;
uint8_t *buf;
IXAudio2 *pXAudio2;
IXAudio2MasteringVoice *pMasterVoice;
IXAudio2SourceVoice *pSourceVoice;
HANDLE hEvent;
volatile long buffers;
unsigned bufsize;
unsigned bufptr;
unsigned write_buffer;
};
static void WINAPI voice_on_buffer_end(void *handle_, void *data)
{
(void)data;
xaudio2_t *handle = (xaudio2_t*)handle_;
InterlockedDecrement(&handle->buffers);
SetEvent(handle->hEvent);
}
static void WINAPI dummy_voidp(void *handle, void *data) { (void)handle; (void)data; }
static void WINAPI dummy_nil(void *handle) { (void)handle; }
static void WINAPI dummy_uint32(void *handle, UINT32 dummy) { (void)handle; (void)dummy; }
static void WINAPI dummy_voidp_hresult(void *handle, void *data, HRESULT dummy) { (void)handle; (void)data; (void)dummy; }
const struct IXAudio2VoiceCallbackVtbl voice_vtable = {
dummy_uint32,
dummy_nil,
dummy_nil,
dummy_voidp,
voice_on_buffer_end,
dummy_voidp,
dummy_voidp_hresult,
};
void xaudio2_enumerate_devices(xaudio2_t *xa)
{
UINT32 dev_count;
IXAudio2_GetDeviceCount(xa->pXAudio2, &dev_count);
fprintf(stderr, "XAudio2 devices:\n");
for (unsigned i = 0; i < dev_count; i++)
{
XAUDIO2_DEVICE_DETAILS dev_detail;
IXAudio2_GetDeviceDetails(xa->pXAudio2, i, &dev_detail);
fwprintf(stderr, L"\t%u: %s\n", i, dev_detail.DisplayName);
}
}
xaudio2_t *xaudio2_new(unsigned samplerate, unsigned channels,
size_t size, unsigned device)
{
xaudio2_t *handle = (xaudio2_t*)calloc(1, sizeof(*handle));
if (!handle)
return NULL;
handle->lpVtbl = &voice_vtable;
CoInitializeEx(0, COINIT_MULTITHREADED);
WAVEFORMATEX wfx = {0};
if (FAILED(XAudio2Create(&handle->pXAudio2)))
goto error;
if (FAILED(IXAudio2_CreateMasteringVoice(handle->pXAudio2,
&handle->pMasterVoice, channels, samplerate, 0, device, NULL)))
goto error;
wfx.wFormatTag = WAVE_FORMAT_IEEE_FLOAT;
wfx.nChannels = channels;
wfx.nSamplesPerSec = samplerate;
wfx.nBlockAlign = channels * sizeof(float);
wfx.wBitsPerSample = sizeof(float) * 8;
wfx.nAvgBytesPerSec = wfx.nSamplesPerSec * wfx.nBlockAlign;
wfx.cbSize = 0;
if (FAILED(IXAudio2_CreateSourceVoice(handle->pXAudio2,
&handle->pSourceVoice, &wfx,
XAUDIO2_VOICE_NOSRC, XAUDIO2_DEFAULT_FREQ_RATIO,
(IXAudio2VoiceCallback*)handle, 0, 0)))
goto error;
handle->hEvent = CreateEvent(0, FALSE, FALSE, 0);
if (!handle->hEvent)
goto error;
handle->bufsize = size / MAX_BUFFERS;
handle->buf = (uint8_t*)calloc(1, handle->bufsize * MAX_BUFFERS);
if (!handle->buf)
goto error;
if (FAILED(IXAudio2SourceVoice_Start(handle->pSourceVoice, 0, XAUDIO2_COMMIT_NOW)))
goto error;
return handle;
error:
xaudio2_free(handle);
return NULL;
}
size_t xaudio2_write_avail(xaudio2_t *handle)
{
return handle->bufsize * (MAX_BUFFERS - handle->buffers - 1);
}
size_t xaudio2_write(xaudio2_t *handle, const void *buf, size_t bytes_)
{
unsigned bytes = bytes_;
const uint8_t *buffer = (const uint8_t*)buf;
while (bytes)
{
unsigned need = min(bytes, handle->bufsize - handle->bufptr);
memcpy(handle->buf + handle->write_buffer * handle->bufsize + handle->bufptr,
buffer, need);
handle->bufptr += need;
buffer += need;
bytes -= need;
if (handle->bufptr == handle->bufsize)
{
while (handle->buffers == MAX_BUFFERS - 1)
WaitForSingleObject(handle->hEvent, INFINITE);
XAUDIO2_BUFFER xa2buffer = {0};
xa2buffer.AudioBytes = handle->bufsize;
xa2buffer.pAudioData = handle->buf + handle->write_buffer * handle->bufsize;
if (FAILED(IXAudio2SourceVoice_SubmitSourceBuffer(handle->pSourceVoice, &xa2buffer, NULL)))
return 0;
InterlockedIncrement(&handle->buffers);
handle->bufptr = 0;
handle->write_buffer = (handle->write_buffer + 1) & MAX_BUFFERS_MASK;
}
}
return bytes_;
}
void xaudio2_free(xaudio2_t *handle)
{
if (handle)
{
if (handle->pSourceVoice)
{
IXAudio2SourceVoice_Stop(handle->pSourceVoice, 0, XAUDIO2_COMMIT_NOW);
IXAudio2SourceVoice_DestroyVoice(handle->pSourceVoice);
}
if (handle->pMasterVoice)
IXAudio2MasteringVoice_DestroyVoice(handle->pMasterVoice);
if (handle->pXAudio2)
IXAudio2_Release(handle->pXAudio2);
if (handle->hEvent)
CloseHandle(handle->hEvent);
free(handle->buf);
free(handle);
}
}
-164
View File
@@ -1,164 +0,0 @@
/*
Simple C interface for XAudio2
Author: Hans-Kristian Arntzen
License: Public Domain
*/
#include "xaudio-c.h"
#include "xaudio2.hpp"
#include <stdint.h>
#include <algorithm>
struct xaudio2 : public IXAudio2VoiceCallback
{
xaudio2(unsigned samplerate, unsigned channels, unsigned size) :
buf(0), pXAudio2(0), pMasterVoice(0), pSourceVoice(0),
buffers(0), bufptr(0)
{
CoInitializeEx(0, COINIT_MULTITHREADED);
if (FAILED(XAudio2Create(&pXAudio2, 0)))
throw -1;
if (FAILED(pXAudio2->CreateMasteringVoice(
&pMasterVoice, channels, samplerate, 0, 0, 0)))
throw -1;
WAVEFORMATEX wfx;
wfx.wFormatTag = WAVE_FORMAT_IEEE_FLOAT;
wfx.nChannels = channels;
wfx.nSamplesPerSec = samplerate;
wfx.nBlockAlign = channels * sizeof(float);
wfx.wBitsPerSample = sizeof(float) * 8;
wfx.nAvgBytesPerSec = wfx.nSamplesPerSec * wfx.nBlockAlign;
wfx.cbSize = 0;
if (FAILED(pXAudio2->CreateSourceVoice(
&pSourceVoice, &wfx, XAUDIO2_VOICE_NOSRC, XAUDIO2_DEFAULT_FREQ_RATIO, this, 0, 0)))
throw -1;
hEvent = CreateEvent(0, FALSE, FALSE, 0);
if (!hEvent)
throw -1;
pSourceVoice->Start(0);
bufsize = size / max_buffers;
buf = new uint8_t[bufsize * max_buffers];
write_buffer = 0;
}
virtual ~xaudio2()
{
if (pSourceVoice)
{
pSourceVoice->Stop(0);
pSourceVoice->DestroyVoice();
}
if (pMasterVoice)
pMasterVoice->DestroyVoice();
if (pXAudio2)
pXAudio2->Release();
if (hEvent)
CloseHandle(hEvent);
if (buf)
delete[] buf;
}
size_t write_avail() const
{
return bufsize * (max_buffers - buffers - 1);
}
size_t write(const void *buffer_, size_t bytes_)
{
unsigned bytes = bytes_;
const uint8_t *buffer = reinterpret_cast<const uint8_t*>(buffer_);
while (bytes > 0)
{
unsigned need = std::min(bytes, bufsize - bufptr);
memcpy(buf + write_buffer * bufsize + bufptr,
buffer, need);
bufptr += need;
buffer += need;
bytes -= need;
if (bufptr == bufsize)
{
WaitForSingleObject(hEvent, 0); // Clear out ready state.
while (buffers == max_buffers - 1)
WaitForSingleObject(hEvent, INFINITE);
XAUDIO2_BUFFER xa2buffer = {0};
xa2buffer.AudioBytes = bufsize;
xa2buffer.pAudioData = buf + write_buffer * bufsize;
xa2buffer.pContext = 0;
if (FAILED(pSourceVoice->SubmitSourceBuffer(&xa2buffer)))
return 0;
InterlockedIncrement(&buffers);
bufptr = 0;
write_buffer = (write_buffer + 1) & (max_buffers_mask);
}
}
return bytes_;
}
enum { max_buffers = 16, max_buffers_mask = max_buffers - 1 };
STDMETHOD_(void, OnBufferStart) (void *) {}
STDMETHOD_(void, OnBufferEnd) (void *)
{
InterlockedDecrement(&buffers);
SetEvent(hEvent);
}
STDMETHOD_(void, OnLoopEnd) (void *) {}
STDMETHOD_(void, OnStreamEnd) () {}
STDMETHOD_(void, OnVoiceError) (void *, HRESULT) {}
STDMETHOD_(void, OnVoiceProcessingPassEnd) () {}
STDMETHOD_(void, OnVoiceProcessingPassStart) (UINT32) {}
uint8_t *buf;
IXAudio2 *pXAudio2;
IXAudio2MasteringVoice *pMasterVoice;
IXAudio2SourceVoice *pSourceVoice;
HANDLE hEvent;
volatile long buffers;
unsigned bufsize;
unsigned bufptr;
unsigned write_buffer;
};
xaudio2_t *xaudio2_new(unsigned samplerate, unsigned channels, size_t size)
{
xaudio2 *handle = 0;
try {
handle = new xaudio2(samplerate, channels, size);
} catch(...) { delete handle; return 0; }
return handle;
}
size_t xaudio2_write_avail(xaudio2_t *handle)
{
try {
return handle->write_avail();
} catch(...) { return 0; }
}
size_t xaudio2_write(xaudio2_t *handle, const void *buf, size_t bytes)
{
try {
return handle->write(buf, bytes);
} catch(...) { return 0; }
}
void xaudio2_free(xaudio2_t *handle)
{
delete handle;
}
+2 -1
View File
@@ -15,10 +15,11 @@ extern "C" {
typedef struct xaudio2 xaudio2_t;
xaudio2_t* xaudio2_new(unsigned samplerate, unsigned channels, size_t bufsize);
xaudio2_t* xaudio2_new(unsigned samplerate, unsigned channels, size_t bufsize, unsigned device);
size_t xaudio2_write_avail(xaudio2_t *handle);
size_t xaudio2_write(xaudio2_t *handle, const void *data, size_t bytes);
void xaudio2_free(xaudio2_t *handle);
void xaudio2_enumerate_devices(xaudio2_t *handle);
#ifdef __cplusplus
}
+70 -159
View File
@@ -1,35 +1,37 @@
/*
xaudio2.hpp (2010-08-14)
author: OV2
xaudio.h (2010-08-14) / (2012-12-04)
authors: OV2, Themaister
*/
// Kinda stripped down. Only contains the bare essentials used in SSNES.
#ifndef XAUDIO2_MINGW_H
#define XAUDIO2_MINGW_H
#ifdef __cplusplus
#define CINTERFACE
#endif
#define WIN32_LEAN_AND_MEAN
#include <windows.h>
#undef min
#undef max
#include <basetyps.h>
#include <objbase.h>
#include <mmreg.h>
// 64-bit GCC fix
#define GUID_EXT EXTERN_C
#define GUID_SECT
#define DEFINE_GUID_X(n,l,w1,w2,b1,b2,b3,b4,b5,b6,b7,b8) GUID_EXT const GUID n GUID_SECT = {l,w1,w2,{b1,b2,b3,b4,b5,b6,b7,b8}}
#define DEFINE_GUID_X(n, l, w1, w2, b1, b2, b3, b4, b5, b6, b7, b8) \
static const GUID n = { l, w1, w2, { b1, b2, b3, b4, b5, b6, b7, b8 } }
#define DEFINE_CLSID_X(className, l, w1, w2, b1, b2, b3, b4, b5, b6, b7, b8) \
DEFINE_GUID_X(CLSID_##className, 0x##l, 0x##w1, 0x##w2, 0x##b1, 0x##b2, 0x##b3, 0x##b4, 0x##b5, 0x##b6, 0x##b7, 0x##b8)
#define DEFINE_IID_X(interfaceName, l, w1, w2, b1, b2, b3, b4, b5, b6, b7, b8) \
DEFINE_GUID_X(IID_##interfaceName, 0x##l, 0x##w1, 0x##w2, 0x##b1, 0x##b2, 0x##b3, 0x##b4, 0x##b5, 0x##b6, 0x##b7, 0x##b8)
#define X2DEFAULT(x) =x
#define X2DEFAULT(x)
DEFINE_CLSID_X(XAudio2, e21a7345, eb21, 468e, be, 50, 80, 4d, b9, 7c, f7, 08);
DEFINE_CLSID_X(XAudio2_Debug, f7a76c21, 53d4, 46bb, ac, 53, 8b, 45, 9c, ae, 46, bd);
DEFINE_IID_X(IXAudio2, 8bcf1f58, 9fe7, 4583, 8a, c6, e2, ad, c4, 65, c8, bb);
DECLARE_INTERFACE(IXAudio2Voice);
#ifndef INTERFACE
#define INTERFACE void
#endif
#define XAUDIO2_COMMIT_NOW 0
#define XAUDIO2_DEFAULT_CHANNELS 0
@@ -46,9 +48,21 @@ typedef enum XAUDIO2_DEVICE_ROLE
DefaultCommunicationsDevice = 0x4,
DefaultGameDevice = 0x8,
GlobalDefaultDevice = 0xf,
InvalidDeviceRole = ~GlobalDefaultDevice
InvalidDeviceRole = ~GlobalDefaultDevice
} XAUDIO2_DEVICE_ROLE;
typedef enum XAUDIO2_WINDOWS_PROCESSOR_SPECIFIER
{
XAUDIO2_ANY_PROCESSOR = 0xffffffff,
XAUDIO2_DEFAULT_PROCESSOR = XAUDIO2_ANY_PROCESSOR
} XAUDIO2_WINDOWS_PROCESSOR_SPECIFIER, XAUDIO2_PROCESSOR;
typedef enum XAUDIO2_FILTER_TYPE {
LowPassFilter,
BandPassFilter,
HighPassFilter
} XAUDIO2_FILTER_TYPE;
typedef struct XAUDIO2_DEVICE_DETAILS
{
WCHAR DeviceID[256];
@@ -57,84 +71,17 @@ typedef struct XAUDIO2_DEVICE_DETAILS
WAVEFORMATEXTENSIBLE OutputFormat;
} XAUDIO2_DEVICE_DETAILS;
typedef struct XAUDIO2_VOICE_DETAILS
{
UINT32 CreationFlags;
UINT32 InputChannels;
UINT32 InputSampleRate;
} XAUDIO2_VOICE_DETAILS;
typedef enum XAUDIO2_WINDOWS_PROCESSOR_SPECIFIER
{
Processor1 = 0x00000001,
Processor2 = 0x00000002,
Processor3 = 0x00000004,
Processor4 = 0x00000008,
Processor5 = 0x00000010,
Processor6 = 0x00000020,
Processor7 = 0x00000040,
Processor8 = 0x00000080,
Processor9 = 0x00000100,
Processor10 = 0x00000200,
Processor11 = 0x00000400,
Processor12 = 0x00000800,
Processor13 = 0x00001000,
Processor14 = 0x00002000,
Processor15 = 0x00004000,
Processor16 = 0x00008000,
Processor17 = 0x00010000,
Processor18 = 0x00020000,
Processor19 = 0x00040000,
Processor20 = 0x00080000,
Processor21 = 0x00100000,
Processor22 = 0x00200000,
Processor23 = 0x00400000,
Processor24 = 0x00800000,
Processor25 = 0x01000000,
Processor26 = 0x02000000,
Processor27 = 0x04000000,
Processor28 = 0x08000000,
Processor29 = 0x10000000,
Processor30 = 0x20000000,
Processor31 = 0x40000000,
Processor32 = 0x80000000,
XAUDIO2_ANY_PROCESSOR = 0xffffffff,
XAUDIO2_DEFAULT_PROCESSOR = XAUDIO2_ANY_PROCESSOR
} XAUDIO2_WINDOWS_PROCESSOR_SPECIFIER, XAUDIO2_PROCESSOR;
typedef struct XAUDIO2_VOICE_SENDS
{
UINT32 OutputCount;
IXAudio2Voice** pOutputVoices;
} XAUDIO2_VOICE_SENDS;
typedef struct XAUDIO2_EFFECT_DESCRIPTOR
{
IUnknown* pEffect;
BOOL InitialState;
UINT32 OutputChannels;
} XAUDIO2_EFFECT_DESCRIPTOR;
typedef struct XAUDIO2_EFFECT_CHAIN
{
UINT32 EffectCount;
const XAUDIO2_EFFECT_DESCRIPTOR* pEffectDescriptors;
} XAUDIO2_EFFECT_CHAIN;
typedef enum XAUDIO2_FILTER_TYPE
{
LowPassFilter,
BandPassFilter,
HighPassFilter
} XAUDIO2_FILTER_TYPE;
typedef struct XAUDIO2_FILTER_PARAMETERS
{
XAUDIO2_FILTER_TYPE Type;
float Frequency;
float OneOverQ;
} XAUDIO2_FILTER_PARAMETERS;
typedef struct XAUDIO2_VOICE_DETAILS XAUDIO2_VOICE_DETAILS;
typedef struct XAUDIO2_VOICE_SENDS XAUDIO2_VOICE_SENDS;
typedef struct XAUDIO2_EFFECT_DESCRIPTOR XAUDIO2_EFFECT_DESCRIPTOR;
typedef struct XAUDIO2_EFFECT_CHAIN XAUDIO2_EFFECT_CHAIN;
typedef struct XAUDIO2_FILTER_PARAMETERS XAUDIO2_FILTER_PARAMETERS;
typedef struct XAUDIO2_BUFFER_WMA XAUDIO2_BUFFER_WMA;
typedef struct XAUDIO2_VOICE_STATE XAUDIO2_VOICE_STATE;
typedef struct XAUDIO2_PERFORMANCE_DATA XAUDIO2_PERFORMANCE_DATA;
typedef struct XAUDIO2_DEBUG_CONFIGURATION XAUDIO2_DEBUG_CONFIGURATION;
typedef struct IXAudio2EngineCallback IXAudio2EngineCallback;
typedef struct IXAudio2SubmixVoice IXAudio2SubmixVoice;
typedef struct XAUDIO2_BUFFER
{
@@ -146,65 +93,18 @@ typedef struct XAUDIO2_BUFFER
UINT32 LoopBegin;
UINT32 LoopLength;
UINT32 LoopCount;
void* pContext;
void *pContext;
} XAUDIO2_BUFFER;
typedef struct XAUDIO2_BUFFER_WMA
{
const UINT32* pDecodedPacketCumulativeBytes;
UINT32 PacketCount;
} XAUDIO2_BUFFER_WMA;
typedef struct XAUDIO2_VOICE_STATE
{
void* pCurrentBufferContext;
UINT32 BuffersQueued;
UINT64 SamplesPlayed;
} XAUDIO2_VOICE_STATE;
typedef struct XAUDIO2_PERFORMANCE_DATA
{
UINT64 AudioCyclesSinceLastQuery;
UINT64 TotalCyclesSinceLastQuery;
UINT32 MinimumCyclesPerQuantum;
UINT32 MaximumCyclesPerQuantum;
UINT32 MemoryUsageInBytes;
UINT32 CurrentLatencyInSamples;
UINT32 GlitchesSinceEngineStarted;
UINT32 ActiveSourceVoiceCount;
UINT32 TotalSourceVoiceCount;
UINT32 ActiveSubmixVoiceCount;
UINT32 TotalSubmixVoiceCount;
UINT32 ActiveXmaSourceVoices;
UINT32 ActiveXmaStreams;
} XAUDIO2_PERFORMANCE_DATA;
typedef struct XAUDIO2_DEBUG_CONFIGURATION
{
UINT32 TraceMask;
UINT32 BreakMask;
BOOL LogThreadID;
BOOL LogFileline;
BOOL LogFunctionName;
BOOL LogTiming;
} XAUDIO2_DEBUG_CONFIGURATION;
DECLARE_INTERFACE(IXAudio2EngineCallback)
{
STDMETHOD_(void, OnProcessingPassStart) (THIS) PURE;
STDMETHOD_(void, OnProcessingPassEnd) (THIS) PURE;
STDMETHOD_(void, OnCriticalError) (THIS_ HRESULT Error) PURE;
};
DECLARE_INTERFACE(IXAudio2VoiceCallback)
{
STDMETHOD_(void, OnVoiceProcessingPassStart) (THIS_ UINT32 BytesRequired) PURE;
STDMETHOD_(void, OnVoiceProcessingPassEnd) (THIS) PURE;
STDMETHOD_(void, OnStreamEnd) (THIS) PURE;
STDMETHOD_(void, OnBufferStart) (THIS_ void* pBufferContext) PURE;
STDMETHOD_(void, OnBufferEnd) (THIS_ void* pBufferContext) PURE;
STDMETHOD_(void, OnLoopEnd) (THIS_ void* pBufferContext) PURE;
STDMETHOD_(void, OnVoiceError) (THIS_ void* pBufferContext, HRESULT Error) PURE;
STDMETHOD_(void, OnBufferStart) (THIS_ void *pBufferContext) PURE;
STDMETHOD_(void, OnBufferEnd) (THIS_ void *pBufferContext) PURE;
STDMETHOD_(void, OnLoopEnd) (THIS_ void *pBufferContext) PURE;
STDMETHOD_(void, OnVoiceError) (THIS_ void *pBufferContext, HRESULT Error) PURE;
};
DECLARE_INTERFACE(IXAudio2Voice)
@@ -219,10 +119,10 @@ DECLARE_INTERFACE(IXAudio2Voice)
UINT32 OperationSet X2DEFAULT(XAUDIO2_COMMIT_NOW)) PURE; \
STDMETHOD_(void, GetEffectState) (THIS_ UINT32 EffectIndex, BOOL* pEnabled) PURE; \
STDMETHOD(SetEffectParameters) (THIS_ UINT32 EffectIndex, \
const void* pParameters, \
const void *pParameters, \
UINT32 ParametersByteSize, \
UINT32 OperationSet X2DEFAULT(XAUDIO2_COMMIT_NOW)) PURE; \
STDMETHOD(GetEffectParameters) (THIS_ UINT32 EffectIndex, void* pParameters, \
STDMETHOD(GetEffectParameters) (THIS_ UINT32 EffectIndex, void *pParameters, \
UINT32 ParametersByteSize) PURE; \
STDMETHOD(SetFilterParameters) (THIS_ const XAUDIO2_FILTER_PARAMETERS* pParameters, \
UINT32 OperationSet X2DEFAULT(XAUDIO2_COMMIT_NOW)) PURE; \
@@ -245,17 +145,11 @@ DECLARE_INTERFACE(IXAudio2Voice)
Declare_IXAudio2Voice_Methods();
};
DECLARE_INTERFACE_(IXAudio2MasteringVoice, IXAudio2Voice)
{
Declare_IXAudio2Voice_Methods();
};
DECLARE_INTERFACE_(IXAudio2SubmixVoice, IXAudio2Voice)
{
Declare_IXAudio2Voice_Methods();
};
DECLARE_INTERFACE_(IXAudio2SourceVoice, IXAudio2Voice)
{
Declare_IXAudio2Voice_Methods();
@@ -304,23 +198,40 @@ DECLARE_INTERFACE_(IXAudio2, IUnknown)
STDMETHOD(CommitChanges) (THIS_ UINT32 OperationSet) PURE;
STDMETHOD_(void, GetPerformanceData) (THIS_ XAUDIO2_PERFORMANCE_DATA* pPerfData) PURE;
STDMETHOD_(void, SetDebugConfiguration) (THIS_ const XAUDIO2_DEBUG_CONFIGURATION* pDebugConfiguration,
void* pReserved X2DEFAULT(NULL)) PURE;
void *pReserved X2DEFAULT(NULL)) PURE;
};
static inline HRESULT XAudio2Create(IXAudio2** ppXAudio2, UINT32 Flags X2DEFAULT(0),
XAUDIO2_PROCESSOR XAudio2Processor X2DEFAULT(XAUDIO2_DEFAULT_PROCESSOR))
// C hooks.
#define IXAudio2_Initialize(THIS, ...) (THIS)->lpVtbl->Initialize(THIS, __VA_ARGS__)
#define IXAudio2_Release(THIS) (THIS)->lpVtbl->Release(THIS)
#define IXAudio2_CreateSourceVoice(THIS, ...) (THIS)->lpVtbl->CreateSourceVoice(THIS, __VA_ARGS__)
#define IXAudio2_CreateMasteringVoice(THIS, ...) (THIS)->lpVtbl->CreateMasteringVoice(THIS, __VA_ARGS__)
#define IXAudio2_GetDeviceCount(THIS, ...) (THIS)->lpVtbl->GetDeviceCount(THIS, __VA_ARGS__)
#define IXAudio2_GetDeviceDetails(THIS, ...) (THIS)->lpVtbl->GetDeviceDetails(THIS, __VA_ARGS__)
#define IXAudio2SourceVoice_Start(THIS, ...) (THIS)->lpVtbl->Start(THIS, __VA_ARGS__)
#define IXAudio2SourceVoice_Stop(THIS, ...) (THIS)->lpVtbl->Stop(THIS, __VA_ARGS__)
#define IXAudio2SourceVoice_SubmitSourceBuffer(THIS, ...) (THIS)->lpVtbl->SubmitSourceBuffer(THIS, __VA_ARGS__)
#define IXAudio2SourceVoice_DestroyVoice(THIS) (THIS)->lpVtbl->DestroyVoice(THIS)
#define IXAudio2MasteringVoice_DestroyVoice(THIS) (THIS)->lpVtbl->DestroyVoice(THIS)
static inline HRESULT XAudio2Create(IXAudio2 **ppXAudio2)
{
IXAudio2* pXAudio2;
HRESULT hr = CoCreateInstance((Flags & XAUDIO2_DEBUG_ENGINE) ? CLSID_XAudio2_Debug : CLSID_XAudio2,
NULL, CLSCTX_INPROC_SERVER, IID_IXAudio2, reinterpret_cast<void**>(&pXAudio2));
IXAudio2 *pXAudio2;
#ifdef __cplusplus
HRESULT hr = CoCreateInstance(CLSID_XAudio2, NULL, CLSCTX_INPROC_SERVER, IID_IXAudio2, (void**)&pXAudio2);
#else
HRESULT hr = CoCreateInstance(&CLSID_XAudio2, NULL, CLSCTX_INPROC_SERVER, &IID_IXAudio2, (void**)&pXAudio2);
#endif
if (SUCCEEDED(hr))
{
hr = pXAudio2->Initialize(Flags, XAudio2Processor);
hr = IXAudio2_Initialize(pXAudio2, 0, XAUDIO2_DEFAULT_PROCESSOR);
if (SUCCEEDED(hr))
*ppXAudio2 = pXAudio2;
else
pXAudio2->Release();
IXAudio2_Release(pXAudio2);
}
return hr;
}
+51 -26
View File
@@ -1,5 +1,5 @@
/* SSNES - A Super Nintendo Entertainment System (SNES) Emulator frontend for libsnes.
* Copyright (C) 2010-2011 - Hans-Kristian Arntzen
* Copyright (C) 2010-2012 - Hans-Kristian Arntzen
*
* Some code herein may be based on code found in BSNES.
*
@@ -15,43 +15,54 @@
* If not, see <http://www.gnu.org/licenses/>.
*/
#include "driver.h"
#include "../driver.h"
#include <stdlib.h>
#include "xaudio-c/xaudio-c.h"
#include "general.h"
#include "../general.h"
typedef struct
{
xaudio2_t *xa;
bool nonblock;
size_t bufsize;
} xa_t;
static void* __xa_init(const char* device, unsigned rate, unsigned latency)
static void *xa_init(const char *device, unsigned rate, unsigned latency)
{
if (latency < 8)
latency = 8; // Do not allow shenanigans.
xa_t *xa = calloc(1, sizeof(xa_t));
if (xa == NULL)
xa_t *xa = (xa_t*)calloc(1, sizeof(*xa));
if (!xa)
return NULL;
size_t bufsize = latency * rate / 1000;
SSNES_LOG("XAudio2: Requesting %d ms latency, using %d ms latency.\n", latency, (int)bufsize * 1000 / rate);
xa->xa = xaudio2_new(rate, 2, bufsize * 2 * sizeof(float));
xa->bufsize = bufsize * 2 * sizeof(float);
unsigned device_index = 0;
if (device)
device_index = strtoul(device, NULL, 0);
xa->xa = xaudio2_new(rate, 2, xa->bufsize, device_index);
if (!xa->xa)
{
SSNES_ERR("Failed to init XAudio2.\n");
free(xa);
return NULL;
}
if (g_extern.verbose)
xaudio2_enumerate_devices(xa->xa);
return xa;
}
static ssize_t __xa_write(void* data, const void* buf, size_t size)
static ssize_t xa_write(void *data, const void *buf, size_t size)
{
xa_t *xa = data;
xa_t *xa = (xa_t*)data;
if (xa->nonblock)
{
size_t avail = xaudio2_write_avail(xa->xa);
@@ -60,39 +71,40 @@ static ssize_t __xa_write(void* data, const void* buf, size_t size)
if (avail < size)
size = avail;
}
size_t ret = xaudio2_write(xa->xa, buf, size);
if (ret == 0)
if (ret == 0 && size > 0)
return -1;
return ret;
}
static bool __xa_stop(void *data)
static bool xa_stop(void *data)
{
(void)data;
return true;
}
static void __xa_set_nonblock_state(void *data, bool state)
static void xa_set_nonblock_state(void *data, bool state)
{
xa_t *xa = data;
xa_t *xa = (xa_t*)data;
xa->nonblock = state;
}
static bool __xa_start(void *data)
static bool xa_start(void *data)
{
(void)data;
return true;
}
static bool __xa_use_float(void *data)
static bool xa_use_float(void *data)
{
(void)data;
return true;
}
static void __xa_free(void *data)
static void xa_free(void *data)
{
xa_t *xa = data;
xa_t *xa = (xa_t*)data;
if (xa)
{
if (xa->xa)
@@ -101,14 +113,27 @@ static void __xa_free(void *data)
}
}
static size_t xa_write_avail(void *data)
{
xa_t *xa = (xa_t*)data;
return xaudio2_write_avail(xa->xa);
}
static size_t xa_buffer_size(void *data)
{
xa_t *xa = (xa_t*)data;
return xa->bufsize;
}
const audio_driver_t audio_xa = {
.init = __xa_init,
.write = __xa_write,
.stop = __xa_stop,
.start = __xa_start,
.set_nonblock_state = __xa_set_nonblock_state,
.use_float = __xa_use_float,
.free = __xa_free,
.ident = "xaudio"
xa_init,
xa_write,
xa_stop,
xa_start,
xa_set_nonblock_state,
xa_free,
xa_use_float,
"xaudio",
xa_write_avail,
xa_buffer_size,
};
+49 -43
View File
@@ -1,5 +1,5 @@
/* SSNES - A Super Nintendo Entertainment System (SNES) Emulator frontend for libsnes.
* Copyright (C) 2010-2011 - Hans-Kristian Arntzen
* Copyright (C) 2010-2012 - Hans-Kristian Arntzen
*
* Some code herein may be based on code found in BSNES.
*
@@ -16,9 +16,9 @@
*/
#include "autosave.h"
#include "SDL.h"
#include "thread.h"
#include <stdlib.h>
#include <stdbool.h>
#include "boolean.h"
#include <string.h>
#include <stdio.h>
#include "general.h"
@@ -26,11 +26,11 @@
struct autosave
{
volatile bool quit;
SDL_mutex *lock;
slock_t *lock;
SDL_mutex *cond_lock;
SDL_cond *cond;
SDL_Thread *thread;
slock_t *cond_lock;
scond_t *cond;
sthread_t *thread;
void *buffer;
const void *snes_buffer;
@@ -39,49 +39,54 @@ struct autosave
unsigned interval;
};
static int autosave_thread(void *data)
static void autosave_thread(void *data)
{
autosave_t *save = data;
autosave_t *save = (autosave_t*)data;
bool first_log = true;
while (!save->quit)
{
autosave_lock(save);
memcpy(save->buffer, save->snes_buffer, save->bufsize);
bool differ = memcmp(save->buffer, save->snes_buffer, save->bufsize) != 0;
if (differ)
memcpy(save->buffer, save->snes_buffer, save->bufsize);
autosave_unlock(save);
// Should probably deal with this more elegantly.
FILE *file = fopen(save->path, "wb");
if (file)
if (differ)
{
// Avoid spamming down stderr ... :)
if (first_log)
// Should probably deal with this more elegantly.
FILE *file = fopen(save->path, "wb");
if (file)
{
SSNES_LOG("Autosaving SRAM to \"%s\", will continue to autosave every %u seconds ...\n", save->path, save->interval);
first_log = false;
}
// Avoid spamming down stderr ... :)
if (first_log)
{
SSNES_LOG("Autosaving SRAM to \"%s\", will continue to check every %u seconds ...\n", save->path, save->interval);
first_log = false;
}
else
SSNES_LOG("SRAM changed ... autosaving ...\n");
bool failed = false;
failed |= fwrite(save->buffer, 1, save->bufsize, file) != save->bufsize;
failed |= fflush(file) != 0;
failed |= fclose(file) != 0;
if (failed)
SSNES_WARN("Failed to autosave SRAM! Disk might be full.\n");
bool failed = false;
failed |= fwrite(save->buffer, 1, save->bufsize, file) != save->bufsize;
failed |= fflush(file) != 0;
failed |= fclose(file) != 0;
if (failed)
SSNES_WARN("Failed to autosave SRAM. Disk might be full.\n");
}
}
SDL_mutexP(save->cond_lock);
slock_lock(save->cond_lock);
if (!save->quit)
SDL_CondWaitTimeout(save->cond, save->cond_lock, save->interval * 1000);
SDL_mutexV(save->cond_lock);
scond_wait_timeout(save->cond, save->cond_lock, save->interval * 1000);
slock_unlock(save->cond_lock);
}
return 0;
}
autosave_t *autosave_new(const char *path, const void *data, size_t size, unsigned interval)
{
autosave_t *handle = calloc(1, sizeof(*handle));
autosave_t *handle = (autosave_t*)calloc(1, sizeof(*handle));
if (!handle)
return NULL;
@@ -96,37 +101,38 @@ autosave_t *autosave_new(const char *path, const void *data, size_t size, unsign
free(handle);
return NULL;
}
memcpy(handle->buffer, handle->snes_buffer, handle->bufsize);
handle->lock = SDL_CreateMutex();
handle->cond_lock = SDL_CreateMutex();
handle->cond = SDL_CreateCond();
handle->lock = slock_new();
handle->cond_lock = slock_new();
handle->cond = scond_new();
handle->thread = SDL_CreateThread(autosave_thread, handle);
handle->thread = sthread_create(autosave_thread, handle);
return handle;
}
void autosave_lock(autosave_t *handle)
{
SDL_mutexP(handle->lock);
slock_lock(handle->lock);
}
void autosave_unlock(autosave_t *handle)
{
SDL_mutexV(handle->lock);
slock_unlock(handle->lock);
}
void autosave_free(autosave_t *handle)
{
SDL_mutexP(handle->cond_lock);
slock_lock(handle->cond_lock);
handle->quit = true;
SDL_mutexV(handle->cond_lock);
SDL_CondSignal(handle->cond);
SDL_WaitThread(handle->thread, NULL);
slock_unlock(handle->cond_lock);
scond_signal(handle->cond);
sthread_join(handle->thread);
SDL_DestroyMutex(handle->lock);
SDL_DestroyMutex(handle->cond_lock);
SDL_DestroyCond(handle->cond);
slock_free(handle->lock);
slock_free(handle->cond_lock);
scond_free(handle->cond);
free(handle->buffer);
free(handle);
+1 -1
View File
@@ -1,5 +1,5 @@
/* SSNES - A Super Nintendo Entertainment System (SNES) Emulator frontend for libsnes.
* Copyright (C) 2010-2011 - Hans-Kristian Arntzen
* Copyright (C) 2010-2012 - Hans-Kristian Arntzen
*
* Some code herein may be based on code found in BSNES.
*
+26
View File
@@ -0,0 +1,26 @@
/* SSNES - A Super Nintendo Entertainment System (SNES) Emulator frontend for libsnes.
* Copyright (C) 2010-2012 - Hans-Kristian Arntzen
*
* Some code herein may be based on code found in BSNES.
*
* SSNES is free software: you can redistribute it and/or modify it under the terms
* of the GNU General Public License as published by the Free Software Found-
* ation, either version 3 of the License, or (at your option) any later version.
*
* SSNES is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
* without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
* PURPOSE. See the GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License along with SSNES.
* If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef __SSNES_BOOLEAN_H
#define __SSNES_BOOLEAN_H
#ifndef __cplusplus
#include <stdbool.h>
#endif
#endif
-175
View File
@@ -1,175 +0,0 @@
/* SSNES - A Super Nintendo Entertainment System (SNES) Emulator frontend for libsnes.
* Copyright (C) 2010-2011 - Hans-Kristian Arntzen
*
* Some code herein may be based on code found in BSNES.
*
* SSNES is free software: you can redistribute it and/or modify it under the terms
* of the GNU General Public License as published by the Free Software Found-
* ation, either version 3 of the License, or (at your option) any later version.
*
* SSNES is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
* without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
* PURPOSE. See the GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License along with SSNES.
* If not, see <http://www.gnu.org/licenses/>.
*/
#include "bps.h"
#include "movie.h"
#include <stdint.h>
#include <stdbool.h>
enum bps_mode
{
SOURCE_READ = 0,
TARGET_READ,
SOURCE_COPY,
TARGET_COPY
};
struct bps_data
{
const uint8_t *modify_data, *source_data;
uint8_t *target_data;
size_t modify_length, source_length, target_length;
size_t modify_offset, source_offset, target_offset;
uint32_t modify_checksum, source_checksum, target_checksum;
size_t source_relative_offset, target_relative_offset, output_offset;
};
static uint8_t bps_read(struct bps_data *bps)
{
uint8_t data = bps->modify_data[bps->modify_offset++];
bps->modify_checksum = crc32_adjust(bps->modify_checksum, data);
return data;
}
static uint64_t bps_decode(struct bps_data *bps)
{
uint64_t data = 0, shift = 1;
for (;;)
{
uint8_t x = bps_read(bps);
data += (x & 0x7f) * shift;
if (x & 0x80)
break;
shift <<= 7;
data += shift;
}
return data;
}
static void bps_write(struct bps_data *bps, uint8_t data)
{
bps->target_data[bps->output_offset++] = data;
bps->target_checksum = crc32_adjust(bps->target_checksum, data);
}
bps_error_t bps_apply_patch(
const uint8_t *modify_data, size_t modify_length,
const uint8_t *source_data, size_t source_length,
uint8_t *target_data, size_t *target_length)
{
if (modify_length < 19)
return BPS_PATCH_TOO_SMALL;
struct bps_data bps = {
.modify_data = modify_data,
.modify_length = modify_length,
.target_data = target_data,
.target_length = *target_length,
.source_data = source_data,
.source_length = source_length,
.modify_checksum = ~0,
.target_checksum = ~0,
};
if ((bps_read(&bps) != 'B') || (bps_read(&bps) != 'P') || (bps_read(&bps) != 'S') || (bps_read(&bps) != '1'))
return BPS_PATCH_INVALID_HEADER;
size_t modify_source_size = bps_decode(&bps);
size_t modify_target_size = bps_decode(&bps);
size_t modify_markup_size = bps_decode(&bps);
for (size_t i = 0; i < modify_markup_size; i++)
bps_read(&bps);
if (modify_source_size > bps.source_length)
return BPS_SOURCE_TOO_SMALL;
if (modify_target_size > bps.target_length)
return BPS_TARGET_TOO_SMALL;
while (bps.modify_offset < bps.modify_length - 12)
{
size_t length = bps_decode(&bps);
unsigned mode = length & 3;
length = (length >> 2) + 1;
switch (mode)
{
case SOURCE_READ:
while (length--)
bps_write(&bps, bps.source_data[bps.output_offset]);
break;
case TARGET_READ:
while (length--)
bps_write(&bps, bps_read(&bps));
break;
case SOURCE_COPY:
case TARGET_COPY:
{
int offset = bps_decode(&bps);
bool negative = offset & 1;
offset >>= 1;
if (negative)
offset = -offset;
if (mode == SOURCE_COPY)
{
bps.source_offset += offset;
while (length--)
bps_write(&bps, bps.source_data[bps.source_offset++]);
}
else
{
bps.target_offset += offset;
while (length--)
bps_write(&bps, bps.target_data[bps.target_offset++]);
break;
}
break;
}
}
}
uint32_t modify_source_checksum = 0, modify_target_checksum = 0, modify_modify_checksum = 0;
for (unsigned i = 0; i < 32; i += 8)
modify_source_checksum |= bps_read(&bps) << i;
for (unsigned i = 0; i < 32; i += 8)
modify_target_checksum |= bps_read(&bps) << i;
uint32_t checksum = ~bps.modify_checksum;
for (unsigned i = 0; i < 32; i += 8)
modify_modify_checksum |= bps_read(&bps) << i;
bps.source_checksum = crc32_calculate(bps.source_data, bps.source_length);
bps.target_checksum = ~bps.target_checksum;
if (bps.source_checksum != modify_source_checksum)
return BPS_SOURCE_CHECKSUM_INVALID;
if (bps.target_checksum != modify_target_checksum)
return BPS_TARGET_CHECKSUM_INVALID;
if (checksum != modify_modify_checksum)
return BPS_PATCH_CHECKSUM_INVALID;
*target_length = modify_target_size;
return BPS_SUCCESS;
}
+123 -20
View File
@@ -1,5 +1,5 @@
/* SSNES - A Super Nintendo Entertainment System (SNES) Emulator frontend for libsnes.
* Copyright (C) 2010-2011 - Hans-Kristian Arntzen
* Copyright (C) 2010-2012 - Hans-Kristian Arntzen
*
* Some code herein may be based on code found in BSNES.
*
@@ -16,10 +16,18 @@
*/
#include "cheats.h"
#include "sha256.h"
#include "hash.h"
#include "dynamic.h"
#include "general.h"
#include "strl.h"
#include "compat/strl.h"
#ifdef HAVE_CONFIG_H
#include "config.h"
#endif
#ifdef HAVE_CONFIGFILE
#include "conf/config_file.h"
#endif
#include <stdlib.h>
#include <stddef.h>
@@ -43,13 +51,13 @@ struct cheat_manager
unsigned buf_size;
};
static char* strcat_alloc(char *dest, const char *input)
static char *strcat_alloc(char *dest, const char *input)
{
size_t dest_len = dest ? strlen(dest) : 0;
size_t input_len = strlen(input);
size_t required_len = dest_len + input_len + 1;
char *output = realloc(dest, required_len);
char *output = (char*)realloc(dest, required_len);
if (!output)
return NULL;
@@ -118,7 +126,7 @@ static bool xml_grab_cheats(cheat_manager_t *handle, xmlNodePtr ptr)
if (handle->size == handle->buf_size)
{
handle->buf_size *= 2;
handle->cheats = realloc(handle->cheats, handle->buf_size * sizeof(struct cheat));
handle->cheats = (struct cheat*)realloc(handle->cheats, handle->buf_size * sizeof(struct cheat));
if (!handle->cheats)
return false;
}
@@ -131,18 +139,118 @@ static bool xml_grab_cheats(cheat_manager_t *handle, xmlNodePtr ptr)
return true;
}
static void cheat_manager_apply_cheats(cheat_manager_t *handle)
{
unsigned index = 0;
psnes_cheat_reset();
for (unsigned i = 0; i < handle->size; i++)
{
if (handle->cheats[i].state)
psnes_cheat_set(index++, true, handle->cheats[i].code);
}
}
static void cheat_manager_load_config(cheat_manager_t *handle, const char *path, const char *sha256)
{
#ifdef HAVE_CONFIGFILE
if (!(*path))
return;
config_file_t *conf = config_file_new(path);
if (!conf)
return;
char *str;
if (!config_get_string(conf, sha256, &str))
{
config_file_free(conf);
return;
}
const char *num = strtok(str, ";");
while (num)
{
unsigned index = strtoul(num, NULL, 0);
if (index < handle->size)
handle->cheats[index].state = true;
num = strtok(NULL, ";");
}
free(str);
config_file_free(conf);
cheat_manager_apply_cheats(handle);
#else
(void)handle;
(void)path;
(void)sha256;
#endif
}
static void cheat_manager_save_config(cheat_manager_t *handle, const char *path, const char *sha256)
{
#ifdef HAVE_CONFIGFILE
if (!(*path))
return;
config_file_t *conf = config_file_new(path);
if (!conf)
conf = config_file_new(NULL);
if (!conf)
{
SSNES_ERR("Cannot save XML cheat settings.\n");
return;
}
char conf_str[512] = {0};
char tmp[32] = {0};
for (unsigned i = 0; i < handle->size; i++)
{
if (handle->cheats[i].state)
{
snprintf(tmp, sizeof(tmp), "%u;", i);
strlcat(conf_str, tmp, sizeof(conf_str));
}
}
if (*conf_str)
conf_str[strlen(conf_str) - 1] = '\0'; // Remove the trailing ';'
config_set_string(conf, sha256, conf_str);
if (!config_file_write(conf, path))
SSNES_ERR("Failed to write XML cheat settings to \"%s\". Check permissions.\n", path);
config_file_free(conf);
#else
(void)handle;
(void)path;
(void)sha256;
#endif
}
cheat_manager_t* cheat_manager_new(const char *path)
{
LIBXML_TEST_VERSION;
psnes_cheat_reset();
xmlParserCtxtPtr ctx = NULL;
xmlDocPtr doc = NULL;
cheat_manager_t *handle = calloc(1, sizeof(struct cheat_manager));
cheat_manager_t *handle = (cheat_manager_t*)calloc(1, sizeof(struct cheat_manager));
if (!handle)
return NULL;
xmlNodePtr head = NULL;
xmlNodePtr cur = NULL;
handle->buf_size = 1;
handle->cheats = calloc(handle->buf_size, sizeof(struct cheat));
handle->cheats = (struct cheat*)calloc(handle->buf_size, sizeof(struct cheat));
if (!handle->cheats)
{
handle->buf_size = 0;
@@ -166,8 +274,7 @@ cheat_manager_t* cheat_manager_new(const char *path)
goto error;
}
xmlNodePtr head = xmlDocGetRootElement(doc);
xmlNodePtr cur = NULL;
head = xmlDocGetRootElement(doc);
for (cur = head; cur; cur = cur->next)
{
if (cur->type == XML_ELEMENT_NODE && strcmp((const char*)cur->name, "database") == 0)
@@ -188,7 +295,7 @@ cheat_manager_t* cheat_manager_new(const char *path)
if (!sha256)
continue;
if (memcmp(sha256, g_extern.sha256, 64) == 0)
if (strcmp((const char*)sha256, g_extern.sha256) == 0)
{
xmlFree(sha256);
break;
@@ -213,6 +320,8 @@ cheat_manager_t* cheat_manager_new(const char *path)
goto error;
}
cheat_manager_load_config(handle, g_settings.cheat_settings_path, g_extern.sha256);
xmlFreeDoc(doc);
xmlFreeParserCtxt(ctx);
return handle;
@@ -233,6 +342,7 @@ void cheat_manager_free(cheat_manager_t *handle)
if (handle->cheats)
{
cheat_manager_save_config(handle, g_settings.cheat_settings_path, g_extern.sha256);
for (unsigned i = 0; i < handle->size; i++)
{
xmlFree(handle->cheats[i].desc);
@@ -254,18 +364,11 @@ static void cheat_manager_update(cheat_manager_t *handle)
SSNES_LOG("%s\n", msg);
}
void cheat_manager_toggle(cheat_manager_t *handle)
{
handle->cheats[handle->ptr].state ^= true;
unsigned index = 0;
psnes_cheat_reset();
for (unsigned i = 0; i < handle->size; i++)
{
if (handle->cheats[handle->ptr].state)
psnes_cheat_set(index++, true, handle->cheats[handle->ptr].code);
}
cheat_manager_apply_cheats(handle);
cheat_manager_update(handle);
}
+1 -1
View File
@@ -1,5 +1,5 @@
/* SSNES - A Super Nintendo Entertainment System (SNES) Emulator frontend for libsnes.
* Copyright (C) 2010-2011 - Hans-Kristian Arntzen
* Copyright (C) 2010-2012 - Hans-Kristian Arntzen
*
* Some code herein may be based on code found in BSNES.
*
+284
View File
@@ -0,0 +1,284 @@
/* SSNES - A Super Nintendo Entertainment System (SNES) Emulator frontend for libsnes.
* Copyright (C) 2010-2012 - Hans-Kristian Arntzen
*
* Some code herein may be based on code found in BSNES.
*
* SSNES is free software: you can redistribute it and/or modify it under the terms
* of the GNU General Public License as published by the Free Software Found-
* ation, either version 3 of the License, or (at your option) any later version.
*
* SSNES is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
* without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
* PURPOSE. See the GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License along with SSNES.
* If not, see <http://www.gnu.org/licenses/>.
*/
#include "getopt_ssnes.h"
#include "strl.h"
#include "posix_string.h"
#ifndef HAVE_GETOPT_LONG
#include <string.h>
#include "../boolean.h"
#include <stddef.h>
#include <stdlib.h>
#ifdef _MSC_VER
#include "../msvc/msvc_compat.h"
#endif
#include "../general.h"
char *optarg;
int optind, opterr, optopt;
static bool is_short_option(const char *str)
{
return str[0] == '-' && str[1] != '-';
}
static bool is_long_option(const char *str)
{
return str[0] == '-' && str[1] == '-';
}
static int find_short_index(char * const *argv)
{
for (int index = 0; argv[index]; index++)
{
if (is_short_option(argv[index]))
return index;
}
return -1;
}
static int find_long_index(char * const *argv)
{
for (int index = 0; argv[index]; index++)
{
if (is_long_option(argv[index]))
return index;
}
return -1;
}
static int parse_short(const char *optstring, char * const *argv)
{
char arg = argv[0][1];
if (arg == ':')
return '?';
const char *opt = strchr(optstring, arg);
if (!opt)
return '?';
bool extra_opt = argv[0][2];
bool takes_arg = opt[1] == ':';
// If we take an argument, and we see additional characters,
// this is in fact the argument (i.e. -cfoo is same as -c foo).
bool embedded_arg = extra_opt && takes_arg;
if (takes_arg)
{
if (embedded_arg)
{
optarg = argv[0] + 2;
optind++;
}
else
{
optarg = argv[1];
optind += 2;
}
return optarg ? opt[0] : '?';
}
else if (embedded_arg) // If we see additional characters, and they don't take arguments, this means we have multiple flags in one.
{
memmove(&argv[0][1], &argv[0][2], strlen(&argv[0][2]) + 1);
return opt[0];
}
else
{
optind++;
return opt[0];
}
}
static int parse_long(const struct option *longopts, char * const *argv)
{
const struct option *opt = NULL;
for (size_t indice = 0; longopts[indice].name; indice++)
{
if (strcmp(longopts[indice].name, &argv[0][2]) == 0)
{
opt = &longopts[indice];
break;
}
}
if (!opt)
return '?';
// getopt_long has an "optional" arg, but we don't bother with that.
if (opt->has_arg && !argv[1])
return '?';
if (opt->has_arg)
{
optarg = argv[1];
optind += 2;
}
else
optind++;
if (opt->flag)
{
*opt->flag = opt->val;
return 0;
}
else
return opt->val;
}
static void shuffle_block(char **begin, char **last, char **end)
{
ptrdiff_t len = last - begin;
const char **tmp = (const char**)calloc(len, sizeof(const char*));
ssnes_assert(tmp);
memcpy(tmp, begin, sizeof(tmp));
memmove(begin, last, (end - last) * sizeof(char*));
memcpy(end - len, tmp, sizeof(tmp));
free(tmp);
}
int getopt_long(int argc, char *argv[],
const char *optstring, const struct option *longopts, int *longindex)
{
(void)longindex;
if (argc == 1)
return -1;
if (optind == 0)
optind = 1;
int short_index = find_short_index(&argv[optind]);
int long_index = find_long_index(&argv[optind]);
// We're done here.
if (short_index == -1 && long_index == -1)
return -1;
// Reorder argv so that non-options come last.
// Non-POSIXy, but that's what getopt does by default.
if ((short_index > 0) && ((short_index < long_index) || (long_index == -1)))
{
shuffle_block(&argv[optind], &argv[optind + short_index], &argv[argc]);
short_index = 0;
}
else if ((long_index > 0) && ((long_index < short_index) || (short_index == -1)))
{
shuffle_block(&argv[optind], &argv[optind + long_index], &argv[argc]);
long_index = 0;
}
ssnes_assert(short_index == 0 || long_index == 0);
if (short_index == 0)
return parse_short(optstring, &argv[optind]);
else if (long_index == 0)
return parse_long(longopts, &argv[optind]);
else
return '?';
}
#endif
#ifndef HAVE_STRL
// Implementation of strlcpy()/strlcat() based on OpenBSD.
size_t strlcpy(char *dest, const char *source, size_t size)
{
size_t src_size = 0;
size_t n = size;
if (n)
while (--n && (*dest++ = *source++)) src_size++;
if (!n)
{
if (size) *dest = '\0';
while (*source++) src_size++;
}
return src_size;
}
size_t strlcat(char *dest, const char *source, size_t size)
{
size_t len = strlen(dest);
dest += len;
if (len > size)
size = 0;
else
size -= len;
return len + strlcpy(dest, source, size);
}
#endif
#ifdef _WIN32
#undef strcasecmp
#undef strdup
#undef isblank
#include <ctype.h>
#include <stdlib.h>
#include <stddef.h>
#include "strl.h"
#include <string.h>
int strcasecmp_ssnes__(const char *a, const char *b)
{
while (*a && *b)
{
int a_ = tolower(*a);
int b_ = tolower(*b);
if (a_ != b_)
return a_ - b_;
a++;
b++;
}
return tolower(*a) - tolower(*b);
}
char *strdup_ssnes__(const char *orig)
{
size_t len = strlen(orig) + 1;
char *ret = (char*)malloc(len);
if (!ret)
return NULL;
strlcpy(ret, orig, len);
return ret;
}
int isblank_ssnes__(int c)
{
return (c == ' ') || (c == '\t');
}
#endif
+59
View File
@@ -0,0 +1,59 @@
/* SSNES - A Super Nintendo Entertainment System (SNES) Emulator frontend for libsnes.
* Copyright (C) 2010-2012 - Hans-Kristian Arntzen
*
* Some code herein may be based on code found in BSNES.
*
* SSNES is free software: you can redistribute it and/or modify it under the terms
* of the GNU General Public License as published by the Free Software Found-
* ation, either version 3 of the License, or (at your option) any later version.
*
* SSNES is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
* without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
* PURPOSE. See the GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License along with SSNES.
* If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef __SSNES_GETOPT_H
#define __SSNES_GETOPT_H
#ifdef HAVE_CONFIG_H
#include "config.h"
#endif
// Custom implementation of the GNU getopt_long for portability.
// Not designed to be fully compatible,
// but compatible with the features SSNES uses.
#ifdef HAVE_GETOPT_LONG
#include <getopt.h>
#else
// Avoid possible naming collitions during link since we prefer to use the actual name.
#define getopt_long(argc, argv, optstring, longopts, longindex) __getopt_long_ssnes(argc, argv, optstring, longopts, longindex)
#ifdef __cplusplus
extern "C" {
#endif
struct option
{
const char *name;
int has_arg;
int *flag;
int val;
};
// argv[] is declared with char * const argv[] in GNU,
// but this makes no sense, as non-POSIX getopt_long mutates argv (non-opts are moved to the end).
int getopt_long(int argc, char *argv[],
const char *optstring, const struct option *longopts, int *longindex);
extern char *optarg;
extern int optind, opterr, optopt;
#ifdef __cplusplus
}
#endif
#endif
#endif
+41
View File
@@ -0,0 +1,41 @@
/* SSNES - A Super Nintendo Entertainment System (SNES) Emulator frontend for libsnes.
* Copyright (C) 2010-2012 - Hans-Kristian Arntzen
*
* Some code herein may be based on code found in BSNES.
*
* SSNES is free software: you can redistribute it and/or modify it under the terms
* of the GNU General Public License as published by the Free Software Found-
* ation, either version 3 of the License, or (at your option) any later version.
*
* SSNES is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
* without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
* PURPOSE. See the GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License along with SSNES.
* If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef __SSNES_POSIX_STRING_H
#define __SSNES_POSIX_STRING_H
#ifdef _WIN32
#ifdef __cplusplus
extern "C" {
#endif
#undef strcasecmp
#define strcasecmp(a, b) strcasecmp_ssnes__(a, b)
#define strdup(orig) strdup_ssnes__(orig)
#define isblank(c) isblank_ssnes__(c)
int strcasecmp(const char *a, const char *b);
char *strdup(const char *orig);
int isblank(int c);
#ifdef __cplusplus
}
#endif
#endif
#endif
+12 -6
View File
@@ -1,5 +1,5 @@
/* SSNES - A Super Nintendo Entertainment System (SNES) Emulator frontend for libsnes.
* Copyright (C) 2010-2011 - Hans-Kristian Arntzen
* Copyright (C) 2010-2012 - Hans-Kristian Arntzen
*
* Some code herein may be based on code found in BSNES.
*
@@ -21,18 +21,24 @@
#include <string.h>
#include <stddef.h>
#ifdef HAVE_CONFIG
#ifdef HAVE_CONFIG_H
#include "config.h"
#endif
#ifndef HAVE_STRL
// Avoid possible naming collitions during link since we prefer to use the actual name.
#define strlcpy(dst, src, size) __strlcpy_ssnes(dst, src, size)
#define strlcat(dst, src, size) __strlcat_ssnes(dst, src, size)
#ifdef __cplusplus
extern "C" {
#endif
// Avoid possible naming collisions during link since we prefer to use the actual name.
#define strlcpy(dst, src, size) strlcpy_ssnes__(dst, src, size)
#define strlcat(dst, src, size) strlcat_ssnes__(dst, src, size)
size_t strlcpy(char *dest, const char *source, size_t size);
size_t strlcat(char *dest, const char *source, size_t size);
#ifdef __cplusplus
}
#endif
#endif
#endif
+436 -85
View File
@@ -1,5 +1,5 @@
/* SSNES - A Super Nintendo Entertainment System (SNES) Emulator frontend for libsnes.
* Copyright (C) 2010-2011 - Hans-Kristian Arntzen
* Copyright (C) 2010-2012 - Hans-Kristian Arntzen
*
* Some code herein may be based on code found in BSNES.
*
@@ -21,23 +21,61 @@
#include <string.h>
#include <stdio.h>
#include <ctype.h>
#include "strl.h"
#include <errno.h>
#include "../compat/strl.h"
#include "../compat/posix_string.h"
#include "../msvc/msvc_compat.h"
#if !defined(_WIN32) && !defined(__CELLOS_LV2__) && !defined(_XBOX)
#include <sys/param.h> // PATH_MAX
#elif defined(_WIN32) && !defined(_XBOX)
#define WIN32_LEAN_AND_MEAN
#include <windows.h>
#elif defined(_XBOX)
#define NOD3D
#define NONET
#include <xtl.h>
#endif
#ifndef PATH_MAX
#ifdef PATH_MAX
#define PATH_MAX PATH_MAX
#else
#define PATH_MAX 512
#endif
#endif
#define MAX_INCLUDE_DEPTH 16
struct entry_list
{
bool readonly; // If we got this from an #include, do not allow write.
char *key;
char *value;
struct entry_list *next;
};
struct include_list
{
char *path;
struct include_list *next;
};
struct config_file
{
char *path;
struct entry_list *entries;
struct entry_list *tail;
unsigned include_depth;
struct include_list *includes;
};
static config_file_t *config_file_new_internal(const char *path, unsigned depth);
static char *getaline(FILE *file)
{
char *newline = malloc(9);
char *newline = (char*)malloc(9);
size_t cur_size = 8;
size_t index = 0;
@@ -47,7 +85,7 @@ static char *getaline(FILE *file)
if (index == cur_size)
{
cur_size *= 2;
newline = realloc(newline, cur_size + 1);
newline = (char*)realloc(newline, cur_size + 1);
}
newline[index++] = in;
@@ -57,18 +95,198 @@ static char *getaline(FILE *file)
return newline;
}
static bool parse_line(struct entry_list *list, char *line)
static char *extract_value(char *line, bool is_value)
{
if (is_value)
{
while (isspace(*line))
line++;
// If we don't have an equal sign here, we've got an invalid string...
if (*line != '=')
return NULL;
line++;
}
while (isspace(*line))
line++;
// We have a full string. Read until next ".
if (*line == '"')
{
line++;
char *tok = strtok(line, "\"");
if (!tok)
return NULL;
return strdup(tok);
}
else if (*line == '\0') // Nothing :(
return NULL;
else // We don't have that... Read till next space.
{
char *tok = strtok(line, " \n\t\f\r\v");
if (tok)
return strdup(tok);
else
return NULL;
}
}
static void set_list_readonly(struct entry_list *list)
{
while (list)
{
list->readonly = true;
list = list->next;
}
}
// Move semantics? :)
static void add_child_list(config_file_t *parent, config_file_t *child)
{
if (parent->entries)
{
struct entry_list *head = parent->entries;
while (head->next)
head = head->next;
set_list_readonly(child->entries);
head->next = child->entries;
}
else
{
set_list_readonly(child->entries);
parent->entries = child->entries;
}
child->entries = NULL;
// Rebase tail.
if (parent->entries)
{
struct entry_list *head = parent->entries;
while (head->next)
head = head->next;
parent->tail = head;
}
else
parent->tail = NULL;
}
static void add_include_list(config_file_t *conf, const char *path)
{
struct include_list *head = conf->includes;
struct include_list *node = (struct include_list*)calloc(1, sizeof(*node));
node->path = strdup(path);
if (head)
{
while (head->next)
head = head->next;
head->next = node;
}
else
conf->includes = node;
}
static void add_sub_conf(config_file_t *conf, char *line)
{
char *path = extract_value(line, false);
if (!path)
return;
add_include_list(conf, path);
char real_path[PATH_MAX];
#ifdef _WIN32
// Accomodate POSIX systems on Win32.
bool is_full_path = *path == '/';
if (is_full_path)
strlcpy(real_path, path, sizeof(real_path));
else
{
// Workaround GetFullPathName not existing on XDK.
// : is not a valid element in a path name. (NTFS streams?)
if (strchr(path, ':') == NULL)
{
strlcpy(real_path, conf->path, sizeof(real_path));
char *split = strrchr(real_path, '/');
if (!split)
split = strrchr(real_path, '\\');
split[1] = '\0';
strlcat(real_path, path, sizeof(real_path));
}
else
strlcpy(real_path, path, sizeof(real_path));
}
#else
if (*path == '/')
strlcpy(real_path, path, sizeof(real_path));
#ifndef __CELLOS_LV2__
else if (*path == '~')
{
const char *home = getenv("HOME");
strlcpy(real_path, home ? home : "/", sizeof(real_path));
strlcat(real_path, path + 1, sizeof(real_path));
}
#endif
else
{
strlcpy(real_path, conf->path, sizeof(real_path));
char *split = strrchr(real_path, '/');
if (split)
{
split[1] = '\0';
strlcat(real_path, path, sizeof(real_path));
}
else
strlcpy(real_path, path, sizeof(real_path));
}
#endif
config_file_t *sub_conf = config_file_new_internal(real_path, conf->include_depth + 1);
if (!sub_conf)
{
free(path);
return;
}
// Pilfer internal list. :D
add_child_list(conf, sub_conf);
config_file_free(sub_conf);
free(path);
}
static bool parse_line(config_file_t *conf, struct entry_list *list, char *line)
{
// Remove everything after comment.
char *comment = strchr(line, '#');
if (comment)
*comment = '\0';
// Starting line with # and include includes config files. :)
if ((comment == line) && (conf->include_depth < MAX_INCLUDE_DEPTH))
{
comment++;
if (strstr(comment, "include ") == comment)
{
add_sub_conf(conf, comment + strlen("include "));
return false;
}
}
else if (conf->include_depth >= MAX_INCLUDE_DEPTH)
fprintf(stderr, "!!! #include depth exceeded for config. Might be a cycle.\n");
// Skips to first character.
while (isspace(*line))
line++;
char *key = malloc(9);
char *key = (char*)malloc(9);
size_t cur_size = 8;
size_t index = 0;
@@ -77,7 +295,7 @@ static bool parse_line(struct entry_list *list, char *line)
if (index == cur_size)
{
cur_size *= 2;
key = realloc(key, cur_size + 1);
key = (char*)realloc(key, cur_size + 1);
}
key[index++] = *line++;
@@ -85,118 +303,113 @@ static bool parse_line(struct entry_list *list, char *line)
key[index] = '\0';
list->key = key;
while (isspace(*line))
line++;
// If we don't have an equal sign here, we've got an invalid string...
if (*line != '=')
list->value = extract_value(line, true);
if (!list->value)
{
list->key = NULL;
free(key);
return false;
}
line++;
while (isspace(*line))
line++;
// We have a full string. Read until next ".
if (*line == '"')
{
char *tok = strtok(line + 1, "\"");
if (tok == NULL)
{
list->key = NULL;
free(key);
return false;
}
list->value = strdup(tok);
}
else // We don't have that... Read till next space.
{
char *tok = strtok(line, " \t\f");
if (tok == NULL)
{
list->key = NULL;
free(key);
return false;
}
list->value = strdup(tok);
}
return true;
}
config_file_t *config_file_new(const char *path)
static config_file_t *config_file_new_internal(const char *path, unsigned depth)
{
struct config_file *conf = calloc(1, sizeof(*conf));
if (conf == NULL)
struct config_file *conf = (struct config_file*)calloc(1, sizeof(*conf));
if (!conf)
return NULL;
if (path == NULL)
if (!path)
return conf;
FILE *file = fopen(path, "r");
if (!file)
conf->path = strdup(path);
if (!conf->path)
{
free(conf);
return NULL;
}
struct entry_list *tail = conf->entries;
conf->include_depth = depth;
FILE *file = fopen(path, "r");
if (!file)
{
free(conf->path);
free(conf);
return NULL;
}
while (!feof(file))
{
struct entry_list *list = calloc(1, sizeof(*list));
struct entry_list *list = (struct entry_list*)calloc(1, sizeof(*list));
char *line = getaline(file);
if (line)
{
if (parse_line(list, line))
if (parse_line(conf, list, line))
{
if (conf->entries == NULL)
if (conf->entries)
{
conf->entries = list;
tail = list;
conf->tail->next = list;
conf->tail = list;
}
else
{
tail->next = list;
tail = list;
conf->entries = list;
conf->tail = list;
}
}
free(line);
}
if (list != conf->tail)
free(list);
}
fclose(file);
return conf;
}
config_file_t *config_file_new(const char *path)
{
return config_file_new_internal(path, 0);
}
void config_file_free(config_file_t *conf)
{
if (conf != NULL)
if (!conf)
return;
struct entry_list *tmp = conf->entries;
while (tmp)
{
struct entry_list *tmp = conf->entries;
struct entry_list *old = tmp;
while (tmp != NULL)
{
free(tmp->key);
free(tmp->value);
old = tmp;
tmp = tmp->next;
free(old);
}
free(conf);
free(tmp->key);
free(tmp->value);
struct entry_list *hold = tmp;
tmp = tmp->next;
free(hold);
}
struct include_list *inc_tmp = conf->includes;
while (inc_tmp)
{
free(inc_tmp->path);
struct include_list *hold = inc_tmp;
inc_tmp = inc_tmp->next;
free(hold);
}
free(conf->path);
free(conf);
}
bool config_get_double(config_file_t *conf, const char *key, double *in)
{
struct entry_list *list = conf->entries;
while (list != NULL)
while (list)
{
if (strcmp(key, list->key) == 0)
{
@@ -208,15 +421,20 @@ bool config_get_double(config_file_t *conf, const char *key, double *in)
return false;
}
bool config_get_int(config_file_t *conf, const char *key, int *in)
bool config_get_float(config_file_t *conf, const char *key, float *in)
{
struct entry_list *list = conf->entries;
while (list != NULL)
while (list)
{
if (strcmp(key, list->key) == 0)
{
*in = strtol(list->value, NULL, 0);
#ifdef __cplusplus
// strtof() is C99/POSIX.
*in = (float)strtod(list->value, NULL);
#else
*in = strtof(list->value, NULL);
#endif
return true;
}
list = list->next;
@@ -224,16 +442,87 @@ bool config_get_int(config_file_t *conf, const char *key, int *in)
return false;
}
bool config_get_int(config_file_t *conf, const char *key, int *in)
{
struct entry_list *list = conf->entries;
while (list)
{
if (strcmp(key, list->key) == 0)
{
errno = 0;
int val = strtol(list->value, NULL, 0);
if (errno == 0)
{
*in = val;
return true;
}
return
false;
}
list = list->next;
}
return false;
}
bool config_get_uint64(config_file_t *conf, const char *key, uint64_t *in)
{
struct entry_list *list = conf->entries;
while (list)
{
if (strcmp(key, list->key) == 0)
{
errno = 0;
uint64_t val = strtoull(list->value, NULL, 0);
if (errno == 0)
{
*in = val;
return true;
}
return
false;
}
list = list->next;
}
return false;
}
bool config_get_uint(config_file_t *conf, const char *key, unsigned *in)
{
struct entry_list *list = conf->entries;
while (list != NULL)
{
if (strcmp(key, list->key) == 0)
{
*in = strtol(list->value, NULL, 0);
return true;
}
list = list->next;
}
return false;
}
bool config_get_hex(config_file_t *conf, const char *key, unsigned *in)
{
struct entry_list *list = conf->entries;
while (list != NULL)
while (list)
{
if (strcmp(key, list->key) == 0)
{
*in = strtol(list->value, NULL, 16);
return true;
errno = 0;
unsigned val = strtoul(list->value, NULL, 16);
if (errno == 0)
{
*in = val;
return true;
}
else
return false;
}
list = list->next;
}
@@ -244,7 +533,7 @@ bool config_get_char(config_file_t *conf, const char *key, char *in)
{
struct entry_list *list = conf->entries;
while (list != NULL)
while (list)
{
if (strcmp(key, list->key) == 0)
{
@@ -262,7 +551,7 @@ bool config_get_string(config_file_t *conf, const char *key, char **str)
{
struct entry_list *list = conf->entries;
while (list != NULL)
while (list)
{
if (strcmp(key, list->key) == 0)
{
@@ -278,7 +567,7 @@ bool config_get_array(config_file_t *conf, const char *key, char *buf, size_t si
{
struct entry_list *list = conf->entries;
while (list != NULL)
while (list)
{
if (strcmp(key, list->key) == 0)
{
@@ -294,7 +583,7 @@ bool config_get_bool(config_file_t *conf, const char *key, bool *in)
{
struct entry_list *list = conf->entries;
while (list != NULL)
while (list)
{
if (strcmp(key, list->key) == 0)
{
@@ -320,19 +609,20 @@ void config_set_string(config_file_t *conf, const char *key, const char *val)
{
struct entry_list *list = conf->entries;
struct entry_list *last = list;
while (list != NULL)
while (list)
{
if (strcmp(key, list->key) == 0)
if (!list->readonly && (strcmp(key, list->key) == 0))
{
free(list->value);
list->value = strdup(val);
return;
}
last = list;
list = list->next;
}
struct entry_list *elem = calloc(1, sizeof(*elem));
struct entry_list *elem = (struct entry_list*)calloc(1, sizeof(*elem));
elem->key = strdup(key);
elem->value = strdup(val);
@@ -345,7 +635,18 @@ void config_set_string(config_file_t *conf, const char *key, const char *val)
void config_set_double(config_file_t *conf, const char *key, double val)
{
char buf[128];
#ifdef __cplusplus
snprintf(buf, sizeof(buf), "%f", (float)val);
#else
snprintf(buf, sizeof(buf), "%lf", val);
#endif
config_set_string(conf, key, buf);
}
void config_set_float(config_file_t *conf, const char *key, float val)
{
char buf[128];
snprintf(buf, sizeof(buf), "%f", val);
config_set_string(conf, key, buf);
}
@@ -356,6 +657,17 @@ void config_set_int(config_file_t *conf, const char *key, int val)
config_set_string(conf, key, buf);
}
void config_set_uint64(config_file_t *conf, const char *key, uint64_t val)
{
char buf[128];
#ifdef _WIN32
snprintf(buf, sizeof(buf), "%I64u", val);
#else
snprintf(buf, sizeof(buf), "%llu", (long long unsigned)val);
#endif
config_set_string(conf, key, buf);
}
void config_set_char(config_file_t *conf, const char *key, char val)
{
char buf[2];
@@ -391,11 +703,50 @@ bool config_file_write(config_file_t *conf, const char *path)
void config_file_dump(config_file_t *conf, FILE *file)
{
struct entry_list *list = conf->entries;
while (list != NULL)
struct include_list *includes = conf->includes;
while (includes)
{
fprintf(file, "%s = \"%s\"\n", list->key, list->value);
fprintf(file, "#include \"%s\"\n", includes->path);
includes = includes->next;
}
struct entry_list *list = conf->entries;
while (list)
{
if (!list->readonly)
fprintf(file, "%s = \"%s\"\n", list->key, list->value);
list = list->next;
}
}
void config_file_dump_all(config_file_t *conf, FILE *file)
{
struct include_list *includes = conf->includes;
while (includes)
{
fprintf(file, "#include \"%s\"\n", includes->path);
includes = includes->next;
}
struct entry_list *list = conf->entries;
while (list)
{
fprintf(file, "%s = \"%s\" %s\n", list->key, list->value, list->readonly ? "(included)" : "");
list = list->next;
}
}
bool config_entry_exists(config_file_t *conf, const char *entry)
{
struct entry_list *list = conf->entries;
while (list)
{
if (strcmp(entry, list->key) == 0)
return true;
list = list->next;
}
return false;
}
+26 -8
View File
@@ -1,5 +1,5 @@
/* SSNES - A Super Nintendo Entertainment System (SNES) Emulator frontend for libsnes.
* Copyright (C) 2010-2011 - Hans-Kristian Arntzen
* Copyright (C) 2010-2012 - Hans-Kristian Arntzen
*
* Some code herein may be based on code found in BSNES.
*
@@ -20,7 +20,7 @@
#define __CONFIG_FILE_H
#include <stdint.h>
#include <stdbool.h>
#include "../boolean.h"
#include <stdio.h>
#include <stddef.h>
@@ -31,19 +31,33 @@ typedef struct config_file config_file_t;
// - # are treated as comments. Rest of the line is ignored.
// - Format is: key = value. There can be as many spaces as you like in-between.
// - Value can be wrapped inside "" for multiword strings. (foo = "hai u")
//
// - #include includes a config file in-place.
// Path is relative to where config file was loaded unless an absolute path is chosen.
// Key/value pairs from an #include are read-only, and cannot be modified.
// Loads a config file. Returns NULL if file doesn't exist. NULL path will create an empty config file.
// Loads a config file. Returns NULL if file doesn't exist.
// NULL path will create an empty config file.
config_file_t *config_file_new(const char *path);
// Frees config file.
void config_file_free(config_file_t *conf);
// All extract functions return true when value is valid and exists. Returns false otherwise.
// All extract functions return true when value is valid and exists.
// Returns false otherwise.
bool config_entry_exists(config_file_t *conf, const char *entry);
// Extracts a double from config file.
bool config_get_double(config_file_t *conf, const char *entry, double *in);
// Extracts a float from config file.
bool config_get_float(config_file_t *conf, const char *entry, float *in);
// Extracts an int from config file.
bool config_get_int(config_file_t *conf, const char *entry, int *in);
// Extracts an int from config file. (Hexadecimal)
// Extracts an uint from config file.
bool config_get_uint(config_file_t *conf, const char *entry, unsigned *in);
// Extracts an uint64 from config file.
bool config_get_uint64(config_file_t *conf, const char *entry, uint64_t *in);
// Extracts an unsigned int from config file treating input as hex.
bool config_get_hex(config_file_t *conf, const char *entry, unsigned *in);
// Extracts a single char. If value consists of several chars, this is an error.
bool config_get_char(config_file_t *conf, const char *entry, char *in);
@@ -54,9 +68,12 @@ bool config_get_array(config_file_t *conf, const char *entry, char *in, size_t s
// Extracts a boolean from config. Valid boolean true are "true" and "1". Valid false are "false" and "0". Other values will be treated as an error.
bool config_get_bool(config_file_t *conf, const char *entry, bool *in);
// Setters. Similiar to the getters.
// Setters. Similar to the getters. Will not write to entry if the entry
// was obtained from an #include.
void config_set_double(config_file_t *conf, const char *entry, double value);
void config_set_float(config_file_t *conf, const char *entry, float value);
void config_set_int(config_file_t *conf, const char *entry, int val);
void config_set_uint64(config_file_t *conf, const char *entry, uint64_t val);
void config_set_char(config_file_t *conf, const char *entry, char val);
void config_set_string(config_file_t *conf, const char *entry, const char *val);
void config_set_bool(config_file_t *conf, const char *entry, bool val);
@@ -66,7 +83,8 @@ bool config_file_write(config_file_t *conf, const char *path);
// Dump the current config to an already opened file. Does not close the file.
void config_file_dump(config_file_t *conf, FILE *file);
// Also dumps inherited values, useful for logging.
void config_file_dump_all(config_file_t *conf, FILE *file);
#endif
+71
View File
@@ -0,0 +1,71 @@
/* SSNES - A Super Nintendo Entertainment System (SNES) Emulator frontend for libsnes.
* Copyright (C) 2010-2012 - Hans-Kristian Arntzen
* Copyright (C) 2011-2012 - Daniel De Matteis
*
* Some code herein may be based on code found in BSNES.
*
* SSNES is free software: you can redistribute it and/or modify it under the terms
* of the GNU General Public License as published by the Free Software Found-
* ation, either version 3 of the License, or (at your option) any later version.
*
* SSNES is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
* without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
* PURPOSE. See the GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License along with SSNES.
* If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef CONFIG_FILE_MACROS_H__
#define CONFIG_FILE_MACROS_H__
// Macros to ease config getting.
#include <stdint.h>
#define CONFIG_GET_BOOL_BASE(conf, base, var, key) do { \
bool tmp = false; \
if (config_get_bool(conf, key, &tmp)) \
base.var = tmp; \
} while(0)
#define CONFIG_GET_INT_BASE(conf, base, var, key) do { \
int tmp = 0; \
if (config_get_int(conf, key, &tmp)) \
base.var = tmp; \
} while(0)
#define CONFIG_GET_UINT64_BASE(conf, base, var, key) do { \
uint64_t tmp = 0; \
if (config_get_int(conf, key, &tmp)) \
base.var = tmp; \
} while(0)
#define CONFIG_GET_FLOAT_BASE(conf, base, var, key) do { \
float tmp = 0.0f; \
if (config_get_float(conf, key, &tmp)) \
base.var = tmp; \
} while(0)
#define CONFIG_GET_STRING_BASE(conf, base, var, key) \
config_get_array(conf, key, base.var, sizeof(base.var))
#define CONFIG_GET_BOOL(var, key) CONFIG_GET_BOOL_BASE(conf, g_settings, var, key)
#define CONFIG_GET_INT(var, key) CONFIG_GET_INT_BASE(conf, g_settings, var, key)
#define CONFIG_GET_UINT64(var, key) CONFIG_GET_UINT64_BASE(conf, g_settings, var, key)
#define CONFIG_GET_FLOAT(var, key) CONFIG_GET_FLOAT_BASE(conf, g_settings, var, key)
#define CONFIG_GET_STRING(var, key) CONFIG_GET_STRING_BASE(conf, g_settings, var, key)
#define CONFIG_GET_BOOL_EXTERN(var, key) CONFIG_GET_BOOL_BASE(conf, g_extern, var, key)
#define CONFIG_GET_INT_EXTERN(var, key) CONFIG_GET_INT_BASE(conf, g_extern, var, key)
#define CONFIG_GET_FLOAT_EXTERN(var, key) CONFIG_GET_FLOAT_BASE(conf, g_extern, var, key)
#define CONFIG_GET_STRING_EXTERN(var, key) CONFIG_GET_STRING_BASE(conf, g_extern, var, key)
#ifdef SSNES_CONSOLE
#define CONFIG_GET_BOOL_CONSOLE(var, key) CONFIG_GET_BOOL_BASE(conf, g_console, var, key)
#define CONFIG_GET_INT_CONSOLE(var, key) CONFIG_GET_INT_BASE(conf, g_console, var, key)
#define CONFIG_GET_FLOAT_CONSOLE(var, key) CONFIG_GET_FLOAT_BASE(conf, g_console, var, key)
#define CONFIG_GET_STRING_CONSOLE(var, key) CONFIG_GET_STRING_BASE(conf, g_console, var, key)
#endif
#endif
+147 -81
View File
@@ -1,5 +1,5 @@
/* SSNES - A Super Nintendo Entertainment System (SNES) Emulator frontend for libsnes.
* Copyright (C) 2010-2011 - Hans-Kristian Arntzen
* Copyright (C) 2010-2012 - Hans-Kristian Arntzen
*
* Some code herein may be based on code found in BSNES.
*
@@ -22,7 +22,7 @@
#ifndef __CONFIG_DEF_H
#define __CONFIG_DEF_H
#include <stdbool.h>
#include "boolean.h"
#include "libsnes.hpp"
#include "driver.h"
@@ -30,22 +30,16 @@
#include "config.h"
#endif
#ifdef HAVE_SDL
#include "SDL.h"
#else
#error "HAVE_SDL is not defined!"
#endif
#ifdef HAVE_SRC
#include <samplerate.h>
#endif
#include "input/keysym.h"
///////////////// Drivers
#define VIDEO_GL 0
#define VIDEO_XVIDEO 11
#define VIDEO_SDL 13
#define VIDEO_EXT 14
#define VIDEO_WII 24
#define VIDEO_XENON360 25
#define VIDEO_XDK360 28
////////////////////////
#define AUDIO_RSOUND 1
#define AUDIO_OSS 2
@@ -59,13 +53,27 @@
#define AUDIO_EXT 15
#define AUDIO_DSOUND 16
#define AUDIO_COREAUDIO 17
#define AUDIO_PS3 18
#define AUDIO_XENON360 20
#define AUDIO_WII 22
#define AUDIO_XDK360 27
////////////////////////
#define INPUT_SDL 7
#define INPUT_X 12
#define INPUT_PS3 19
#define INPUT_XENON360 21
#define INPUT_WII 23
#define INPUT_XDK360 26
////////////////////////
#if defined(HAVE_SDL)
#if defined(HAVE_OPENGL) || defined(__CELLOS_LV2__)
#define VIDEO_DEFAULT_DRIVER VIDEO_GL
#elif defined(GEKKO)
#define VIDEO_DEFAULT_DRIVER VIDEO_WII
#elif defined(XENON)
#define VIDEO_DEFAULT_DRIVER VIDEO_XENON360
#elif defined(_XBOX)
#define VIDEO_DEFAULT_DRIVER VIDEO_XDK360
#elif defined(HAVE_XVIDEO)
#define VIDEO_DEFAULT_DRIVER VIDEO_XVIDEO
#elif defined(HAVE_SDL)
@@ -73,10 +81,18 @@
#elif defined(HAVE_DYLIB)
#define VIDEO_DEFAULT_DRIVER VIDEO_EXT
#else
#error "Need at least one video driver!"
#error "Need at least one video driver."
#endif
#if defined(HAVE_ALSA)
#if defined(__CELLOS_LV2__)
#define AUDIO_DEFAULT_DRIVER AUDIO_PS3
#elif defined(XENON)
#define AUDIO_DEFAULT_DRIVER AUDIO_XENON360
#elif defined(_XBOX)
#define AUDIO_DEFAULT_DRIVER AUDIO_XDK360
#elif defined(GEKKO)
#define AUDIO_DEFAULT_DRIVER AUDIO_WII
#elif defined(HAVE_ALSA)
#define AUDIO_DEFAULT_DRIVER AUDIO_ALSA
#elif defined(HAVE_PULSE)
#define AUDIO_DEFAULT_DRIVER AUDIO_PULSE
@@ -101,15 +117,23 @@
#elif defined(HAVE_DYLIB)
#define AUDIO_DEFAULT_DRIVER AUDIO_EXT
#else
#error "Need at least one audio driver!"
#error "Need at least one audio driver."
#endif
#if defined(HAVE_SDL)
#if defined(XENON)
#define INPUT_DEFAULT_DRIVER INPUT_XENON360
#elif defined(_XBOX)
#define INPUT_DEFAULT_DRIVER INPUT_XDK360
#elif defined(HAVE_SDL)
#define INPUT_DEFAULT_DRIVER INPUT_SDL
#elif defined(__CELLOS_LV2__)
#define INPUT_DEFAULT_DRIVER INPUT_PS3
#elif defined(GEKKO)
#define INPUT_DEFAULT_DRIVER INPUT_WII
#elif defined(HAVE_XVIDEO)
#define INPUT_DEFAULT_DRIVER INPUT_X
#else
#error "Need at least one input driver!"
#error "Need at least one input driver."
#endif
@@ -118,8 +142,8 @@
////////////////
// Windowed
static const float xscale = 3.0; // Real x res = 296 * xscale
static const float yscale = 3.0; // Real y res = 224 * yscale
static const float xscale = 3.0; // Real x res = aspect * base_size * xscale
static const float yscale = 3.0; // Real y res = base_size * yscale
// Fullscreen
static const bool fullscreen = false; // To start in Fullscreen or not
@@ -142,14 +166,19 @@ static const bool video_smooth = true;
static const bool force_aspect = true;
// Crop overscanned frames (7/8 or 15/15 for interlaced frames).
static const bool crop_overscan = false;
static const bool crop_overscan = true;
// Font size for on-screen messages.
static const unsigned font_size = 48;
// Attempt to scale the font size.
// The scale factor will be window_size / desktop_size.
static const bool font_scale = true;
// Offset for where messages will be placed on-screen. Values are in range [0.0, 1.0].
static const float message_pos_offset_x = 0.05;
static const float message_pos_offset_y = 0.05;
// Color of the message.
static const uint32_t message_color = 0xffff00; // RGB hex value.
// Render-to-texture before rendering to screen (multi-pass shaders)
static const bool render_to_texture = false;
@@ -160,10 +189,32 @@ static const bool second_pass_smooth = true;
// Record video assuming game runs hi-res.
static const bool hires_record = false;
// Enables lossless RGB H.264 recording if possible (if not, FFV1 is used).
static const bool h264_record = true;
// Record post-filtered (CPU filter) video rather than raw SNES output.
static const bool post_filter_record = false;
#define SNES_ASPECT_RATIO (4.0/3)
// OSD-messages
static const bool font_enable = true;
// The accurate refresh rate of your monitor (Hz).
// This is used to calculate audio input rate with the formula:
// audio_input_rate = game_input_rate * display_refresh_rate / game_refresh_rate.
// If the implementation does not report any values,
// SNES NTSC defaults will be assumed for compatibility.
// This value should stay close to 60Hz to avoid large pitch changes.
// If your monitor does not run at 60Hz, or something close to it, disable VSync,
// and leave this at its default.
#if defined(__CELLOS_LV2__) || defined(XENON) || defined(GEKKO)
static const float refresh_rate = 59.92;
#else
static const float refresh_rate = 59.95;
#endif
// Allow games to set rotation. If false, rotation requests are honored, but ignored.
// Used for setups where one manually rotates the monitor.
static const bool allow_rotate = true;
////////////////
// Audio
@@ -175,15 +226,11 @@ static const bool audio_enable = true;
// Output samplerate
static const unsigned out_rate = 48000;
// Input samplerate from libSNES.
// Lower this (slightly) if you are experiencing frequent audio dropouts while vsync is enabled.
static const float in_rate = 31980.0;
// When changing input rate on-the-fly
static const float audio_rate_step = 0.25;
// Audio device (e.g. hw:0,0 or /dev/audio). If NULL, will use defaults.
static const char* audio_device = NULL;
static const char *audio_device = NULL;
// Desired audio latency in milliseconds. Might not be honored if driver can't provide given latency.
static const int out_latency = 64;
@@ -191,10 +238,15 @@ static const int out_latency = 64;
// Will sync audio. (recommended)
static const bool audio_sync = true;
// Defines the quality (and cpu reqirements) of samplerate conversion.
#ifdef HAVE_SRC
#define SAMPLERATE_QUALITY SRC_LINEAR
#endif
// Experimental rate control
static const bool rate_control = false;
// Rate control delta. Defines how much rate_control is allowed to adjust input rate.
static const float rate_control_delta = 0.005;
//////////////
// Misc
//////////////
// Enables use of rewind. This will incur some memory footprint depending on the save state buffer.
// This rewind only works when using bSNES core atm.
@@ -207,7 +259,7 @@ static const unsigned rewind_buffer_size = 20 << 20; // 20MiB
static const unsigned rewind_granularity = 1;
// Pause gameplay when gameplay loses focus.
static const bool pause_nonactive = true;
static const bool pause_nonactive = false;
// Saves non-volatile SRAM at a regular interval. It is measured in seconds. A value of 0 disables autosave.
static const unsigned autosave_interval = 0;
@@ -215,6 +267,17 @@ static const unsigned autosave_interval = 0;
// When being client over netplay, use keybinds for player 1 rather than player 2.
static const bool netplay_client_swap_input = true;
// On save state load, block SRAM from being overwritten.
// This could potentially lead to buggy games.
static const bool block_sram_overwrite = false;
// When saving savestates, state index is automatically incremented before saving.
// When the ROM is loaded, state index will be set to the highest existing value.
static const bool savestate_auto_index = false;
// Slowmotion ratio.
static const float slowmotion_ratio = 3.0;
////////////////////
// Keybinds, Joypad
@@ -222,65 +285,68 @@ static const bool netplay_client_swap_input = true;
// Axis threshold (between 0.0 and 1.0)
// How far an axis must be tilted to result in a button press
#define AXIS_THRESHOLD 0.5
static const float axis_threshold = 0.5;
// To figure out which joypad buttons to use, check jstest or similar.
// SDL sometimes reverses the axes for some odd reason, but hey. :D
// Player 1
static const struct snes_keybind snes_keybinds_1[] = {
// SNES button | keyboard key | js btn | js axis |
{ SNES_DEVICE_ID_JOYPAD_A, SDLK_x, NO_BTN, AXIS_NONE },
{ SNES_DEVICE_ID_JOYPAD_B, SDLK_z, NO_BTN, AXIS_NONE },
{ SNES_DEVICE_ID_JOYPAD_X, SDLK_s, NO_BTN, AXIS_NONE },
{ SNES_DEVICE_ID_JOYPAD_Y, SDLK_a, NO_BTN, AXIS_NONE },
{ SNES_DEVICE_ID_JOYPAD_L, SDLK_q, NO_BTN, AXIS_NONE },
{ SNES_DEVICE_ID_JOYPAD_R, SDLK_w, NO_BTN, AXIS_NONE },
{ SNES_DEVICE_ID_JOYPAD_LEFT, SDLK_LEFT, NO_BTN, AXIS_NONE },
{ SNES_DEVICE_ID_JOYPAD_RIGHT, SDLK_RIGHT, NO_BTN, AXIS_NONE },
{ SNES_DEVICE_ID_JOYPAD_UP, SDLK_UP, NO_BTN, AXIS_NONE },
{ SNES_DEVICE_ID_JOYPAD_DOWN, SDLK_DOWN, NO_BTN, AXIS_NONE },
{ SNES_DEVICE_ID_JOYPAD_START, SDLK_RETURN, NO_BTN, AXIS_NONE },
{ SNES_DEVICE_ID_JOYPAD_SELECT, SDLK_RSHIFT, NO_BTN, AXIS_NONE },
{ SSNES_FAST_FORWARD_KEY, SDLK_SPACE, NO_BTN, AXIS_NONE },
{ SSNES_FAST_FORWARD_HOLD_KEY, SDLK_l, NO_BTN, AXIS_NONE },
{ SSNES_SAVE_STATE_KEY, SDLK_F2, NO_BTN, AXIS_NONE },
{ SSNES_LOAD_STATE_KEY, SDLK_F4, NO_BTN, AXIS_NONE },
{ SSNES_FULLSCREEN_TOGGLE_KEY, SDLK_f, NO_BTN, AXIS_NONE },
{ SSNES_QUIT_KEY, SDLK_ESCAPE, NO_BTN, AXIS_NONE },
{ SSNES_STATE_SLOT_MINUS, SDLK_F6, NO_BTN, AXIS_NONE },
{ SSNES_STATE_SLOT_PLUS, SDLK_F7, NO_BTN, AXIS_NONE },
{ SSNES_AUDIO_INPUT_RATE_PLUS, SDLK_KP_PLUS, NO_BTN, AXIS_NONE },
{ SSNES_AUDIO_INPUT_RATE_MINUS, SDLK_KP_MINUS, NO_BTN, AXIS_NONE },
{ SSNES_REWIND, SDLK_r, NO_BTN, AXIS_NONE },
{ SSNES_MOVIE_RECORD_TOGGLE, SDLK_o, NO_BTN, AXIS_NONE },
{ SSNES_PAUSE_TOGGLE, SDLK_p, NO_BTN, AXIS_NONE },
{ SSNES_RESET, SDLK_h, NO_BTN, AXIS_NONE },
{ SSNES_SHADER_NEXT, SDLK_m, NO_BTN, AXIS_NONE },
{ SSNES_SHADER_PREV, SDLK_n, NO_BTN, AXIS_NONE },
{ SSNES_CHEAT_INDEX_PLUS, SDLK_y, NO_BTN, AXIS_NONE },
{ SSNES_CHEAT_INDEX_MINUS, SDLK_t, NO_BTN, AXIS_NONE },
{ SSNES_CHEAT_TOGGLE, SDLK_u, NO_BTN, AXIS_NONE },
{ SSNES_SCREENSHOT, SDLK_PRINT, NO_BTN, AXIS_NONE },
{ SSNES_DSP_CONFIG, SDLK_c, NO_BTN, AXIS_NONE },
{ -1 }
// SNES button | keyboard key | js btn | js axis |
{ true, SNES_DEVICE_ID_JOYPAD_B, SK_z, NO_BTN, AXIS_NONE },
{ true, SNES_DEVICE_ID_JOYPAD_Y, SK_a, NO_BTN, AXIS_NONE },
{ true, SNES_DEVICE_ID_JOYPAD_SELECT, SK_RSHIFT, NO_BTN, AXIS_NONE },
{ true, SNES_DEVICE_ID_JOYPAD_START, SK_RETURN, NO_BTN, AXIS_NONE },
{ true, SNES_DEVICE_ID_JOYPAD_UP, SK_UP, NO_BTN, AXIS_NONE },
{ true, SNES_DEVICE_ID_JOYPAD_DOWN, SK_DOWN, NO_BTN, AXIS_NONE },
{ true, SNES_DEVICE_ID_JOYPAD_LEFT, SK_LEFT, NO_BTN, AXIS_NONE },
{ true, SNES_DEVICE_ID_JOYPAD_RIGHT, SK_RIGHT, NO_BTN, AXIS_NONE },
{ true, SNES_DEVICE_ID_JOYPAD_A, SK_x, NO_BTN, AXIS_NONE },
{ true, SNES_DEVICE_ID_JOYPAD_X, SK_s, NO_BTN, AXIS_NONE },
{ true, SNES_DEVICE_ID_JOYPAD_L, SK_q, NO_BTN, AXIS_NONE },
{ true, SNES_DEVICE_ID_JOYPAD_R, SK_w, NO_BTN, AXIS_NONE },
{ true, SSNES_FAST_FORWARD_KEY, SK_SPACE, NO_BTN, AXIS_NONE },
{ true, SSNES_FAST_FORWARD_HOLD_KEY, SK_l, NO_BTN, AXIS_NONE },
{ true, SSNES_LOAD_STATE_KEY, SK_F4, NO_BTN, AXIS_NONE },
{ true, SSNES_SAVE_STATE_KEY, SK_F2, NO_BTN, AXIS_NONE },
{ true, SSNES_FULLSCREEN_TOGGLE_KEY, SK_f, NO_BTN, AXIS_NONE },
{ true, SSNES_QUIT_KEY, SK_ESCAPE, NO_BTN, AXIS_NONE },
{ true, SSNES_STATE_SLOT_PLUS, SK_F7, NO_BTN, AXIS_NONE },
{ true, SSNES_STATE_SLOT_MINUS, SK_F6, NO_BTN, AXIS_NONE },
{ true, SSNES_AUDIO_INPUT_RATE_PLUS, SK_KP_PLUS, NO_BTN, AXIS_NONE },
{ true, SSNES_AUDIO_INPUT_RATE_MINUS, SK_KP_MINUS, NO_BTN, AXIS_NONE },
{ true, SSNES_REWIND, SK_r, NO_BTN, AXIS_NONE },
{ true, SSNES_MOVIE_RECORD_TOGGLE, SK_o, NO_BTN, AXIS_NONE },
{ true, SSNES_PAUSE_TOGGLE, SK_p, NO_BTN, AXIS_NONE },
{ true, SSNES_FRAMEADVANCE, SK_k, NO_BTN, AXIS_NONE },
{ true, SSNES_RESET, SK_h, NO_BTN, AXIS_NONE },
{ true, SSNES_SHADER_NEXT, SK_m, NO_BTN, AXIS_NONE },
{ true, SSNES_SHADER_PREV, SK_n, NO_BTN, AXIS_NONE },
{ true, SSNES_CHEAT_INDEX_PLUS, SK_y, NO_BTN, AXIS_NONE },
{ true, SSNES_CHEAT_INDEX_MINUS, SK_t, NO_BTN, AXIS_NONE },
{ true, SSNES_CHEAT_TOGGLE, SK_u, NO_BTN, AXIS_NONE },
{ true, SSNES_SCREENSHOT, SK_PRINT, NO_BTN, AXIS_NONE },
{ true, SSNES_DSP_CONFIG, SK_c, NO_BTN, AXIS_NONE },
{ true, SSNES_MUTE, SK_F9, NO_BTN, AXIS_NONE },
{ true, SSNES_NETPLAY_FLIP, SK_i, NO_BTN, AXIS_NONE },
{ true, SSNES_SLOWMOTION, SK_e, NO_BTN, AXIS_NONE },
};
// Player 2-5
static const struct snes_keybind snes_keybinds_rest[] = {
{ SNES_DEVICE_ID_JOYPAD_A, SDLK_UNKNOWN, NO_BTN, AXIS_NONE },
{ SNES_DEVICE_ID_JOYPAD_B, SDLK_UNKNOWN, NO_BTN, AXIS_NONE },
{ SNES_DEVICE_ID_JOYPAD_X, SDLK_UNKNOWN, NO_BTN, AXIS_NONE },
{ SNES_DEVICE_ID_JOYPAD_Y, SDLK_UNKNOWN, NO_BTN, AXIS_NONE },
{ SNES_DEVICE_ID_JOYPAD_L, SDLK_UNKNOWN, NO_BTN, AXIS_NONE },
{ SNES_DEVICE_ID_JOYPAD_R, SDLK_UNKNOWN, NO_BTN, AXIS_NONE },
{ SNES_DEVICE_ID_JOYPAD_LEFT, SDLK_UNKNOWN, NO_BTN, AXIS_NONE },
{ SNES_DEVICE_ID_JOYPAD_RIGHT, SDLK_UNKNOWN, NO_BTN, AXIS_NONE },
{ SNES_DEVICE_ID_JOYPAD_UP, SDLK_UNKNOWN, NO_BTN, AXIS_NONE },
{ SNES_DEVICE_ID_JOYPAD_DOWN, SDLK_UNKNOWN, NO_BTN, AXIS_NONE },
{ SNES_DEVICE_ID_JOYPAD_START, SDLK_UNKNOWN, NO_BTN, AXIS_NONE },
{ SNES_DEVICE_ID_JOYPAD_SELECT, SDLK_UNKNOWN, NO_BTN, AXIS_NONE },
{ -1 }
{ true, SNES_DEVICE_ID_JOYPAD_B, SK_UNKNOWN, NO_BTN, AXIS_NONE },
{ true, SNES_DEVICE_ID_JOYPAD_Y, SK_UNKNOWN, NO_BTN, AXIS_NONE },
{ true, SNES_DEVICE_ID_JOYPAD_SELECT, SK_UNKNOWN, NO_BTN, AXIS_NONE },
{ true, SNES_DEVICE_ID_JOYPAD_START, SK_UNKNOWN, NO_BTN, AXIS_NONE },
{ true, SNES_DEVICE_ID_JOYPAD_UP, SK_UNKNOWN, NO_BTN, AXIS_NONE },
{ true, SNES_DEVICE_ID_JOYPAD_DOWN, SK_UNKNOWN, NO_BTN, AXIS_NONE },
{ true, SNES_DEVICE_ID_JOYPAD_LEFT, SK_UNKNOWN, NO_BTN, AXIS_NONE },
{ true, SNES_DEVICE_ID_JOYPAD_RIGHT, SK_UNKNOWN, NO_BTN, AXIS_NONE },
{ true, SNES_DEVICE_ID_JOYPAD_A, SK_UNKNOWN, NO_BTN, AXIS_NONE },
{ true, SNES_DEVICE_ID_JOYPAD_X, SK_UNKNOWN, NO_BTN, AXIS_NONE },
{ true, SNES_DEVICE_ID_JOYPAD_L, SK_UNKNOWN, NO_BTN, AXIS_NONE },
{ true, SNES_DEVICE_ID_JOYPAD_R, SK_UNKNOWN, NO_BTN, AXIS_NONE },
};
#endif
+22 -4
View File
@@ -2,7 +2,7 @@
#define __SSNES_FEATURES_H
#include <stddef.h>
#include <stdbool.h>
#include "boolean.h"
#ifdef HAVE_CONFIG_H
#include "config.h"
@@ -14,6 +14,18 @@ static const bool _sdl_supp = true;
static const bool _sdl_supp = false;
#endif
#ifdef HAVE_THREADS
static const bool _thread_supp = true;
#else
static const bool _thread_supp = false;
#endif
#ifdef HAVE_OPENGL
static const bool _opengl_supp = true;
#else
static const bool _opengl_supp = false;
#endif
#ifdef HAVE_XVIDEO
static const bool _xvideo_supp = true;
#else
@@ -62,6 +74,12 @@ static const bool _pulse_supp = true;
static const bool _pulse_supp = false;
#endif
#ifdef HAVE_DSOUND
static const bool _dsound_supp = true;
#else
static const bool _dsound_supp = false;
#endif
#ifdef HAVE_XAUDIO
static const bool _xaudio_supp = true;
#else
@@ -110,10 +128,10 @@ static const bool _ffmpeg_supp = true;
static const bool _ffmpeg_supp = false;
#endif
#ifdef HAVE_SRC
static const bool _src_supp = true;
#ifdef HAVE_X264RGB
static const bool _x264rgb_supp = true;
#else
static const bool _src_supp = false;
static const bool _x264rgb_supp = false;
#endif
#ifdef HAVE_CONFIGFILE
+487
View File
@@ -0,0 +1,487 @@
/* SSNES - A Super Nintendo Entertainment System (SNES) Emulator frontend for libsnes.
* Copyright (C) 2010-2012 - Hans-Kristian Arntzen
* Copyright (C) 2011-2012 - Daniel De Matteis
*
* Some code herein may be based on code found in BSNES.
*
* SSNES is free software: you can redistribute it and/or modify it under the terms
* of the GNU General Public License as published by the Free Software Found-
* ation, either version 3 of the License, or (at your option) any later version.
*
* SSNES is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
* without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
* PURPOSE. See the GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License along with SSNES.
* If not, see <http://www.gnu.org/licenses/>.
*/
#include <stdio.h>
#include <stdlib.h>
#include <stddef.h>
#include <string.h>
#include <ctype.h>
#include "../boolean.h"
#include "../compat/strl.h"
#include "../libsnes.hpp"
#include "../general.h"
#include "../compat/strl.h"
#include "main_wrap.h"
#ifdef HAVE_ZLIB
#include "szlib/zlib.h"
#define WRITEBUFFERSIZE (1024 * 512)
#endif
#ifdef _WIN32
#include "../compat/posix_string.h"
#endif
#define MAX_ARGS 32
/*============================================================
ROM EXTENSIONS
============================================================ */
static char g_rom_ext[1024];
void ssnes_console_set_rom_ext(const char *ext)
{
strlcpy(g_rom_ext, ext, sizeof(g_rom_ext));
}
const char *ssnes_console_get_rom_ext(void)
{
const char *retval = NULL;
if (*g_rom_ext)
retval = g_rom_ext;
else
retval = "ZIP|zip";
return retval;
}
void ssnes_console_name_from_id(char *name, size_t size)
{
if (size == 0)
return;
const char *id = snes_library_id();
if (!id || strlen(id) >= size)
{
name[0] = '\0';
return;
}
name[strlen(id)] = '\0';
for (size_t i = 0; id[i] != '\0'; i++)
{
char c = id[i];
if (isspace(c) || isblank(c))
name[i] = '_';
else
name[i] = tolower(c);
}
}
#ifdef HAVE_ZLIB
static int ssnes_extract_currentfile_in_zip(unzFile uf)
{
char filename_inzip[PATH_MAX];
FILE *fout = NULL;
unz_file_info file_info;
int err = unzGetCurrentFileInfo(uf,
&file_info, filename_inzip, sizeof(filename_inzip),
NULL, 0, NULL, 0);
if (err != UNZ_OK)
{
SSNES_ERR("Error %d with zipfile in unzGetCurrentFileInfo.\n", err);
return err;
}
size_t size_buf = WRITEBUFFERSIZE;
void *buf = malloc(size_buf);
if (!buf)
{
SSNES_ERR("Error allocating memory\n");
return UNZ_INTERNALERROR;
}
char write_filename[PATH_MAX];
#if defined(__CELLOS_LV2__)
snprintf(write_filename, sizeof(write_filename), "/dev_hdd1/%s", filename_inzip);
#elif defined(_XBOX)
snprintf(write_filename, sizeof(write_filename), "cache:\\%s", filename_inzip);
#endif
err = unzOpenCurrentFile(uf);
if (err != UNZ_OK)
SSNES_ERR("Error %d with zipfile in unzOpenCurrentFile.\n", err);
else
{
/* success */
fout = fopen(write_filename, "wb");
if (!fout)
SSNES_ERR("Error opening %s.\n", write_filename);
}
if (fout)
{
SSNES_LOG("Extracting: %s\n", write_filename);
do
{
err = unzReadCurrentFile(uf, buf, size_buf);
if (err < 0)
{
SSNES_ERR("error %d with zipfile in unzReadCurrentFile.\n", err);
break;
}
if (err > 0)
{
if (fwrite(buf, err, 1, fout) != 1)
{
SSNES_ERR("Error in writing extracted file.\n");
err = UNZ_ERRNO;
break;
}
}
} while (err > 0);
if (fout)
fclose(fout);
}
if (err == UNZ_OK)
{
err = unzCloseCurrentFile (uf);
if (err != UNZ_OK)
SSNES_ERR("Error %d with zipfile in unzCloseCurrentFile.\n", err);
}
else
unzCloseCurrentFile(uf);
free(buf);
return err;
}
int ssnes_extract_zipfile(const char *zip_path)
{
unzFile uf = unzOpen(zip_path);
unz_global_info gi;
int err = unzGetGlobalInfo(uf, &gi);
if (err != UNZ_OK)
SSNES_ERR("error %d with zipfile in unzGetGlobalInfo \n",err);
for (unsigned i = 0; i < gi.number_entry; i++)
{
if (ssnes_extract_currentfile_in_zip(uf) != UNZ_OK)
break;
if ((i + 1) < gi.number_entry)
{
err = unzGoToNextFile(uf);
if (err != UNZ_OK)
{
SSNES_ERR("error %d with zipfile in unzGoToNextFile\n",err);
break;
}
}
}
return 0;
}
#endif
int ssnes_main_init_wrap(const struct ssnes_main_wrap *args)
{
int argc = 0;
char *argv[MAX_ARGS] = {NULL};
argv[argc++] = strdup("ssnes");
if (args->rom_path)
argv[argc++] = strdup(args->rom_path);
if (args->sram_path)
{
argv[argc++] = strdup("-s");
argv[argc++] = strdup(args->sram_path);
}
if (args->state_path)
{
argv[argc++] = strdup("-S");
argv[argc++] = strdup(args->state_path);
}
if (args->config_path)
{
argv[argc++] = strdup("-c");
argv[argc++] = strdup(args->config_path);
}
if (args->verbose)
argv[argc++] = strdup("-v");
int ret = ssnes_main_init(argc, argv);
char **tmp = argv;
while (*tmp)
{
free(*tmp);
tmp++;
}
return ret;
}
/*============================================================
INPUT EXTENSIONS
============================================================ */
#include "console_ext_input.h"
struct platform_bind
{
uint64_t joykey;
const char *label;
};
uint64_t ssnes_default_keybind_lut[SSNES_FIRST_META_KEY];
char ssnes_default_libsnes_keybind_name_lut[SSNES_FIRST_META_KEY][256] = {
"B Button", /* SNES_DEVICE_ID_JOYPAD_B */
"Y Button", /* SNES_DEVICE_ID_JOYPAD_Y */
"Select button", /* SNES_DEVICE_ID_JOYPAD_SELECT */
"Start button", /* SNES_DEVICE_ID_JOYPAD_START */
"D-Pad Up", /* SNES_DEVICE_ID_JOYPAD_UP */
"D-Pad Down", /* SNES_DEVICE_ID_JOYPAD_DOWN */
"D-Pad Left", /* SNES_DEVICE_ID_JOYPAD_LEFT */
"D-Pad Right", /* SNES_DEVICE_ID_JOYPAD_RIGHT */
"A Button", /* SNES_DEVICE_ID_JOYPAD_A */
"X Button", /* SNES_DEVICE_ID_JOYPAD_X */
"L Button", /* SNES_DEVICE_ID_JOYPAD_L */
"R Button", /* SNES_DEVICE_ID_JOYPAD_R */
};
#if defined(__CELLOS_LV2__)
uint64_t ssnes_platform_keybind_lut[SSNES_LAST_PLATFORM_KEY] = {
CTRL_CIRCLE_MASK,
CTRL_CROSS_MASK,
CTRL_TRIANGLE_MASK,
CTRL_SQUARE_MASK,
CTRL_UP_MASK,
CTRL_DOWN_MASK,
CTRL_LEFT_MASK,
CTRL_RIGHT_MASK,
CTRL_SELECT_MASK,
CTRL_START_MASK,
CTRL_L1_MASK,
CTRL_L2_MASK,
CTRL_L3_MASK,
CTRL_R1_MASK,
CTRL_R2_MASK,
CTRL_R3_MASK,
CTRL_LSTICK_LEFT_MASK,
CTRL_LSTICK_RIGHT_MASK,
CTRL_LSTICK_UP_MASK,
CTRL_LSTICK_DOWN_MASK,
CTRL_LEFT_MASK | CTRL_LSTICK_LEFT_MASK,
CTRL_RIGHT_MASK | CTRL_LSTICK_RIGHT_MASK,
CTRL_UP_MASK | CTRL_LSTICK_UP_MASK,
CTRL_DOWN_MASK | CTRL_LSTICK_DOWN_MASK,
CTRL_RSTICK_LEFT_MASK,
CTRL_RSTICK_RIGHT_MASK,
CTRL_RSTICK_UP_MASK,
CTRL_RSTICK_DOWN_MASK,
CTRL_LEFT_MASK | CTRL_RSTICK_LEFT_MASK,
CTRL_RIGHT_MASK | CTRL_RSTICK_RIGHT_MASK,
CTRL_UP_MASK | CTRL_RSTICK_UP_MASK,
CTRL_DOWN_MASK | CTRL_RSTICK_DOWN_MASK,
};
static const struct platform_bind platform_keys[] = {
{ CTRL_CIRCLE_MASK, "Circle button" },
{ CTRL_CROSS_MASK, "Cross button" },
{ CTRL_TRIANGLE_MASK, "Triangle button" },
{ CTRL_SQUARE_MASK, "Square button" },
{ CTRL_UP_MASK, "D-Pad Up" },
{ CTRL_DOWN_MASK, "D-Pad Down" },
{ CTRL_LEFT_MASK, "D-Pad Left" },
{ CTRL_RIGHT_MASK, "D-Pad Right" },
{ CTRL_SELECT_MASK, "Select button" },
{ CTRL_START_MASK, "Start button" },
{ CTRL_L1_MASK, "L1 button" },
{ CTRL_L2_MASK, "L2 button" },
{ CTRL_L3_MASK, "L3 button" },
{ CTRL_R1_MASK, "R1 button" },
{ CTRL_R2_MASK, "R2 button" },
{ CTRL_R3_MASK, "R3 button" },
{ CTRL_LSTICK_LEFT_MASK, "LStick Left" },
{ CTRL_LSTICK_RIGHT_MASK, "LStick Right" },
{ CTRL_LSTICK_UP_MASK, "LStick Up" },
{ CTRL_LSTICK_DOWN_MASK, "LStick Down" },
{ CTRL_LEFT_MASK | CTRL_LSTICK_LEFT_MASK, "LStick D-Pad Left" },
{ CTRL_RIGHT_MASK | CTRL_LSTICK_RIGHT_MASK, "LStick D-Pad Right" },
{ CTRL_UP_MASK | CTRL_LSTICK_UP_MASK, "LStick D-Pad Up" },
{ CTRL_DOWN_MASK | CTRL_LSTICK_DOWN_MASK, "LStick D-Pad Down" },
{ CTRL_RSTICK_LEFT_MASK, "RStick Left" },
{ CTRL_RSTICK_RIGHT_MASK, "RStick Right" },
{ CTRL_RSTICK_UP_MASK, "RStick Up" },
{ CTRL_RSTICK_DOWN_MASK, "RStick Down" },
{ CTRL_LEFT_MASK | CTRL_RSTICK_LEFT_MASK, "RStick D-Pad Left" },
{ CTRL_RIGHT_MASK | CTRL_RSTICK_RIGHT_MASK, "RStick D-Pad Right" },
{ CTRL_UP_MASK | CTRL_RSTICK_UP_MASK, "RStick D-Pad Up" },
{ CTRL_DOWN_MASK | CTRL_RSTICK_DOWN_MASK, "RStick D-Pad Down" },
};
#elif defined(_XBOX)
uint64_t ssnes_platform_keybind_lut[SSNES_LAST_PLATFORM_KEY] = {
XINPUT_GAMEPAD_B,
XINPUT_GAMEPAD_A,
XINPUT_GAMEPAD_Y,
XINPUT_GAMEPAD_X,
XINPUT_GAMEPAD_DPAD_UP,
XINPUT_GAMEPAD_DPAD_DOWN,
XINPUT_GAMEPAD_DPAD_LEFT,
XINPUT_GAMEPAD_DPAD_RIGHT,
XINPUT_GAMEPAD_BACK,
XINPUT_GAMEPAD_START,
XINPUT_GAMEPAD_LEFT_SHOULDER,
XINPUT_GAMEPAD_LEFT_TRIGGER,
XINPUT_GAMEPAD_LEFT_THUMB,
XINPUT_GAMEPAD_RIGHT_SHOULDER,
XINPUT_GAMEPAD_RIGHT_TRIGGER,
XINPUT_GAMEPAD_RIGHT_THUMB,
XINPUT_GAMEPAD_LSTICK_LEFT_MASK,
XINPUT_GAMEPAD_LSTICK_RIGHT_MASK,
XINPUT_GAMEPAD_LSTICK_UP_MASK,
XINPUT_GAMEPAD_LSTICK_DOWN_MASK,
XINPUT_GAMEPAD_DPAD_LEFT | XINPUT_GAMEPAD_LSTICK_LEFT_MASK,
XINPUT_GAMEPAD_DPAD_RIGHT | XINPUT_GAMEPAD_LSTICK_RIGHT_MASK,
XINPUT_GAMEPAD_DPAD_UP | XINPUT_GAMEPAD_LSTICK_UP_MASK,
XINPUT_GAMEPAD_DPAD_DOWN | XINPUT_GAMEPAD_LSTICK_DOWN_MASK,
XINPUT_GAMEPAD_RSTICK_LEFT_MASK,
XINPUT_GAMEPAD_RSTICK_RIGHT_MASK,
XINPUT_GAMEPAD_RSTICK_UP_MASK,
XINPUT_GAMEPAD_RSTICK_DOWN_MASK,
XINPUT_GAMEPAD_DPAD_LEFT | XINPUT_GAMEPAD_RSTICK_LEFT_MASK,
XINPUT_GAMEPAD_DPAD_RIGHT | XINPUT_GAMEPAD_RSTICK_RIGHT_MASK,
XINPUT_GAMEPAD_DPAD_UP | XINPUT_GAMEPAD_RSTICK_UP_MASK,
XINPUT_GAMEPAD_DPAD_DOWN | XINPUT_GAMEPAD_RSTICK_DOWN_MASK,
};
static const struct platform_bind platform_keys[] = {
{ XINPUT_GAMEPAD_B, "B button" },
{ XINPUT_GAMEPAD_A, "A button" },
{ XINPUT_GAMEPAD_Y, "Y button" },
{ XINPUT_GAMEPAD_X, "X button" },
{ XINPUT_GAMEPAD_DPAD_UP, "D-Pad Up" },
{ XINPUT_GAMEPAD_DPAD_DOWN, "D-Pad Down" },
{ XINPUT_GAMEPAD_DPAD_LEFT, "D-Pad Left" },
{ XINPUT_GAMEPAD_DPAD_RIGHT, "D-Pad Right" },
{ XINPUT_GAMEPAD_BACK, "Back button" },
{ XINPUT_GAMEPAD_START, "Start button" },
{ XINPUT_GAMEPAD_LEFT_SHOULDER, "Left Shoulder" },
{ XINPUT_GAMEPAD_LEFT_TRIGGER, "Left Trigger" },
{ XINPUT_GAMEPAD_LEFT_THUMB, "Left Thumb" },
{ XINPUT_GAMEPAD_RIGHT_SHOULDER, "Right Shoulder" },
{ XINPUT_GAMEPAD_RIGHT_TRIGGER, "Right Trigger" },
{ XINPUT_GAMEPAD_RIGHT_THUMB, "Right Thumb" },
{ XINPUT_GAMEPAD_LSTICK_LEFT_MASK, "LStick Left" },
{ XINPUT_GAMEPAD_LSTICK_RIGHT_MASK, "LStick Right" },
{ XINPUT_GAMEPAD_LSTICK_UP_MASK, "LStick Up" },
{ XINPUT_GAMEPAD_LSTICK_DOWN_MASK, "LStick Down" },
{ XINPUT_GAMEPAD_DPAD_LEFT | XINPUT_GAMEPAD_LSTICK_LEFT_MASK, "LStick D-Pad Left" },
{ XINPUT_GAMEPAD_DPAD_RIGHT | XINPUT_GAMEPAD_LSTICK_RIGHT_MASK, "LStick D-Pad Right" },
{ XINPUT_GAMEPAD_DPAD_UP | XINPUT_GAMEPAD_LSTICK_UP_MASK, "LStick D-Pad Up" },
{ XINPUT_GAMEPAD_DPAD_DOWN | XINPUT_GAMEPAD_LSTICK_DOWN_MASK, "LStick D-Pad Down" },
{ XINPUT_GAMEPAD_RSTICK_LEFT_MASK, "RStick Left" },
{ XINPUT_GAMEPAD_RSTICK_RIGHT_MASK, "RStick Right" },
{ XINPUT_GAMEPAD_RSTICK_UP_MASK, "RStick Up" },
{ XINPUT_GAMEPAD_RSTICK_DOWN_MASK, "RStick Down" },
{ XINPUT_GAMEPAD_DPAD_LEFT | XINPUT_GAMEPAD_RSTICK_LEFT_MASK, "RStick D-Pad Left" },
{ XINPUT_GAMEPAD_DPAD_RIGHT | XINPUT_GAMEPAD_RSTICK_RIGHT_MASK, "RStick D-Pad Right" },
{ XINPUT_GAMEPAD_DPAD_UP | XINPUT_GAMEPAD_RSTICK_UP_MASK, "RStick D-Pad Up" },
{ XINPUT_GAMEPAD_DPAD_DOWN | XINPUT_GAMEPAD_RSTICK_DOWN_MASK, "RStick D-Pad Down" },
};
#endif
uint64_t ssnes_input_find_previous_platform_key(uint64_t joykey)
{
size_t arr_size = sizeof(platform_keys) / sizeof(platform_keys[0]);
if (platform_keys[0].joykey == joykey)
return joykey;
for (size_t i = 1; i < arr_size; i++)
{
if (platform_keys[i].joykey == joykey)
return platform_keys[i - 1].joykey;
}
return NO_BTN;
}
uint64_t ssnes_input_find_next_platform_key(uint64_t joykey)
{
size_t arr_size = sizeof(platform_keys) / sizeof(platform_keys[0]);
if (platform_keys[arr_size - 1].joykey == joykey)
return joykey;
for (size_t i = 0; i < arr_size - 1; i++)
{
if (platform_keys[i].joykey == joykey)
return platform_keys[i + 1].joykey;
}
return NO_BTN;
}
const char *ssnes_input_find_platform_key_label(uint64_t joykey)
{
if (joykey == NO_BTN)
return "No button";
size_t arr_size = sizeof(platform_keys) / sizeof(platform_keys[0]);
for (size_t i = 0; i < arr_size; i++)
{
if (platform_keys[i].joykey == joykey)
return platform_keys[i].label;
}
return "Unknown";
}
void ssnes_input_set_default_keybind_names_for_emulator(void)
{
const char *id = snes_library_id();
// Genesis Plus GX/Next
if (strstr(id, "Genesis Plus GX"))
{
strlcpy(ssnes_default_libsnes_keybind_name_lut[SNES_DEVICE_ID_JOYPAD_B],
"B button", sizeof(ssnes_default_libsnes_keybind_name_lut[SNES_DEVICE_ID_JOYPAD_B]));
strlcpy(ssnes_default_libsnes_keybind_name_lut[SNES_DEVICE_ID_JOYPAD_A],
"C button", sizeof(ssnes_default_libsnes_keybind_name_lut[SNES_DEVICE_ID_JOYPAD_A]));
strlcpy(ssnes_default_libsnes_keybind_name_lut[SNES_DEVICE_ID_JOYPAD_X],
"Y button", sizeof(ssnes_default_libsnes_keybind_name_lut[SNES_DEVICE_ID_JOYPAD_X]));
strlcpy(ssnes_default_libsnes_keybind_name_lut[SNES_DEVICE_ID_JOYPAD_Y],
"A button", sizeof(ssnes_default_libsnes_keybind_name_lut[SNES_DEVICE_ID_JOYPAD_Y]));
strlcpy(ssnes_default_libsnes_keybind_name_lut[SNES_DEVICE_ID_JOYPAD_L],
"X button", sizeof(ssnes_default_libsnes_keybind_name_lut[SNES_DEVICE_ID_JOYPAD_L]));
strlcpy(ssnes_default_libsnes_keybind_name_lut[SNES_DEVICE_ID_JOYPAD_R],
"Z button", sizeof(ssnes_default_libsnes_keybind_name_lut[SNES_DEVICE_ID_JOYPAD_R]));
strlcpy(ssnes_default_libsnes_keybind_name_lut[SNES_DEVICE_ID_JOYPAD_SELECT],
"Mode button", sizeof(ssnes_default_libsnes_keybind_name_lut[SNES_DEVICE_ID_JOYPAD_SELECT]));
}
}
+53
View File
@@ -0,0 +1,53 @@
/* SSNES - A Super Nintendo Entertainment System (SNES) Emulator frontend for libsnes.
* Copyright (C) 2010-2012 - Hans-Kristian Arntzen
* Copyright (C) 2011-2012 - Daniel De Matteis
*
* Some code herein may be based on code found in BSNES.
*
* SSNES is free software: you can redistribute it and/or modify it under the terms
* of the GNU General Public License as published by the Free Software Found-
* ation, either version 3 of the License, or (at your option) any later version.
*
* SSNES is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
* without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
* PURPOSE. See the GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License along with SSNES.
* If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef ROM_EXT_H__
#define ROM_EXT_H__
#include "console_ext_input.h"
/*============================================================
ROM EXTENSIONS
============================================================ */
void ssnes_console_set_rom_ext(const char *ext);
// Get rom extensions for current library.
// Returns NULL if library doesn't have any preferences in particular.
const char *ssnes_console_get_rom_ext(void);
// Transforms a library id to a name suitable as a pathname.
void ssnes_console_name_from_id(char *name, size_t size);
#ifdef HAVE_ZLIB
int ssnes_extract_zipfile(const char *zip_path);
#endif
/*============================================================
INPUT EXTENSIONS
============================================================ */
const char *ssnes_input_find_platform_key_label(uint64_t joykey);
uint64_t ssnes_input_find_previous_platform_key(uint64_t joykey);
uint64_t ssnes_input_find_next_platform_key(uint64_t joykey);
// Sets custom default keybind names (some systems emulated by the emulator
// will need different keybind names for buttons, etc.)
void ssnes_input_set_default_keybind_names_for_emulator(void);
#endif
+110
View File
@@ -0,0 +1,110 @@
/* SSNES - A Super Nintendo Entertainment System (SNES) Emulator frontend for libsnes.
* Copyright (C) 2010-2012 - Hans-Kristian Arntzen
* Copyright (C) 2011-2012 - Daniel De Matteis
*
* Some code herein may be based on code found in BSNES.
*
* SSNES is free software: you can redistribute it and/or modify it under the terms
* of the GNU General Public License as published by the Free Software Found-
* ation, either version 3 of the License, or (at your option) any later version.
*
* SSNES is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
* without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
* PURPOSE. See the GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License along with SSNES.
* If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef ROM_EXT_INPUT_H__
#define ROM_EXT_INPUT_H__
#include "../driver.h"
#if defined(__CELLOS_LV2__)
#include "../ps3/ps3_input.h"
enum ps3_device_id
{
PS3_DEVICE_ID_JOYPAD_CIRCLE = 0,
PS3_DEVICE_ID_JOYPAD_CROSS,
PS3_DEVICE_ID_JOYPAD_TRIANGLE,
PS3_DEVICE_ID_JOYPAD_SQUARE,
PS3_DEVICE_ID_JOYPAD_UP,
PS3_DEVICE_ID_JOYPAD_DOWN,
PS3_DEVICE_ID_JOYPAD_LEFT,
PS3_DEVICE_ID_JOYPAD_RIGHT,
PS3_DEVICE_ID_JOYPAD_SELECT,
PS3_DEVICE_ID_JOYPAD_START,
PS3_DEVICE_ID_JOYPAD_L1,
PS3_DEVICE_ID_JOYPAD_L2,
PS3_DEVICE_ID_JOYPAD_L3,
PS3_DEVICE_ID_JOYPAD_R1,
PS3_DEVICE_ID_JOYPAD_R2,
PS3_DEVICE_ID_JOYPAD_R3,
PS3_DEVICE_ID_LSTICK_LEFT,
PS3_DEVICE_ID_LSTICK_RIGHT,
PS3_DEVICE_ID_LSTICK_UP,
PS3_DEVICE_ID_LSTICK_DOWN,
PS3_DEVICE_ID_LSTICK_LEFT_DPAD,
PS3_DEVICE_ID_LSTICK_RIGHT_DPAD,
PS3_DEVICE_ID_LSTICK_UP_DPAD,
PS3_DEVICE_ID_LSTICK_DOWN_DPAD,
PS3_DEVICE_ID_RSTICK_LEFT,
PS3_DEVICE_ID_RSTICK_RIGHT,
PS3_DEVICE_ID_RSTICK_UP,
PS3_DEVICE_ID_RSTICK_DOWN,
PS3_DEVICE_ID_RSTICK_LEFT_DPAD,
PS3_DEVICE_ID_RSTICK_RIGHT_DPAD,
PS3_DEVICE_ID_RSTICK_UP_DPAD,
PS3_DEVICE_ID_RSTICK_DOWN_DPAD,
SSNES_LAST_PLATFORM_KEY
};
#elif defined(_XBOX)
#include "../360/xdk360_input.h"
enum xdk360_device_id
{
XDK360_DEVICE_ID_JOYPAD_B = 0,
XDK360_DEVICE_ID_JOYPAD_A,
XDK360_DEVICE_ID_JOYPAD_Y,
XDK360_DEVICE_ID_JOYPAD_X,
XDK360_DEVICE_ID_JOYPAD_UP,
XDK360_DEVICE_ID_JOYPAD_DOWN,
XDK360_DEVICE_ID_JOYPAD_LEFT,
XDK360_DEVICE_ID_JOYPAD_RIGHT,
XDK360_DEVICE_ID_JOYPAD_BACK,
XDK360_DEVICE_ID_JOYPAD_START,
XDK360_DEVICE_ID_JOYPAD_LB,
XDK360_DEVICE_ID_JOYPAD_LEFT_TRIGGER,
XDK360_DEVICE_ID_LSTICK_THUMB,
XDK360_DEVICE_ID_JOYPAD_RB,
XDK360_DEVICE_ID_JOYPAD_RIGHT_TRIGGER,
XDK360_DEVICE_ID_RSTICK_THUMB,
XDK360_DEVICE_ID_LSTICK_LEFT,
XDK360_DEVICE_ID_LSTICK_RIGHT,
XDK360_DEVICE_ID_LSTICK_UP,
XDK360_DEVICE_ID_LSTICK_DOWN,
XDK360_DEVICE_ID_LSTICK_LEFT_DPAD,
XDK360_DEVICE_ID_LSTICK_RIGHT_DPAD,
XDK360_DEVICE_ID_LSTICK_UP_DPAD,
XDK360_DEVICE_ID_LSTICK_DOWN_DPAD,
XDK360_DEVICE_ID_RSTICK_LEFT,
XDK360_DEVICE_ID_RSTICK_RIGHT,
XDK360_DEVICE_ID_RSTICK_UP,
XDK360_DEVICE_ID_RSTICK_DOWN,
XDK360_DEVICE_ID_RSTICK_LEFT_DPAD,
XDK360_DEVICE_ID_RSTICK_RIGHT_DPAD,
XDK360_DEVICE_ID_RSTICK_UP_DPAD,
XDK360_DEVICE_ID_RSTICK_DOWN_DPAD,
SSNES_LAST_PLATFORM_KEY
};
#endif
extern uint64_t ssnes_default_keybind_lut[SSNES_FIRST_META_KEY];
extern uint64_t ssnes_platform_keybind_lut[SSNES_LAST_PLATFORM_KEY];
extern char ssnes_default_libsnes_keybind_name_lut[SSNES_FIRST_META_KEY][256];
#endif
+252
View File
@@ -0,0 +1,252 @@
/* SSNES - A Super Nintendo Entertainment System (SNES) Emulator frontend for libsnes.
* Copyright (C) 2010-2012 - Hans-Kristian Arntzen
* Copyright (C) 2011-2012 - Daniel De Matteis
*
* Some code herein may be based on code found in BSNES.
*
* SSNES is free software: you can redistribute it and/or modify it under the terms
* of the GNU General Public License as published by the Free Software Found-
* ation, either version 3 of the License, or (at your option) any later version.
*
* SSNES is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
* without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
* PURPOSE. See the GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License along with SSNES.
* If not, see <http://www.gnu.org/licenses/>.
*/
#ifdef _XBOX
#include <xtl.h>
#endif
#include "file_browser.h"
static int less_than_key(const void * a, const void * b)
{
#ifdef __CELLOS_LV2__
DirectoryEntry * a_dir = (DirectoryEntry*)a;
DirectoryEntry * b_dir = (DirectoryEntry*)b;
/* compare a directory to a file directory is always lesser than*/
if ((a_dir->d_type == CELL_FS_TYPE_DIRECTORY && b_dir->d_type == CELL_FS_TYPE_REGULAR))
return -1;
else if (a_dir->d_type == CELL_FS_TYPE_REGULAR && b_dir->d_type == CELL_FS_TYPE_DIRECTORY)
return 1;
return strcasecmp(a_dir->d_name, b_dir->d_name);
#else
return 0;
#endif
}
static const char * filebrowser_get_extension(const char * filename)
{
const char * ext = strrchr(filename, '.');
if (ext)
return ext+1;
else
return "";
}
static void filebrowser_clear_current_entries(filebrowser_t * filebrowser)
{
for(uint32_t i = 0; i < MAX_FILE_LIMIT; i++)
{
filebrowser->cur[filebrowser->file_count].d_type = 0;
filebrowser->cur[filebrowser->file_count].d_namlen = 0;
strcpy(filebrowser->cur[filebrowser->file_count].d_name, "\0");
}
}
static void filebrowser_parse_directory(filebrowser_t * filebrowser,
const char * path, const char * extensions)
{
int error = 0;
#if defined(_XBOX)
filebrowser->file_count = 0;
WIN32_FIND_DATA ffd;
HANDLE hFind = INVALID_HANDLE_VALUE;
char path_buf[PATH_MAX];
if (strlcpy(path_buf, path, sizeof(path_buf)) >= sizeof(path_buf))
{
error = 1;
goto error;
}
if (strlcat(path_buf, "\\*", sizeof(path_buf)) >= sizeof(path_buf))
{
error = 1;
goto error;
}
hFind = FindFirstFile(path_buf, &ffd);
if (hFind == INVALID_HANDLE_VALUE)
{
error = 1;
goto error;
}
do
{
strcpy(filebrowser->dir[filebrowser->directory_stack_size], path);
bool found_dir = false;
if(!(ffd.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY))
{
char tmp_extensions[512];
strncpy(tmp_extensions, extensions, sizeof(tmp_extensions));
const char * current_extension = filebrowser_get_extension(ffd.cFileName);
bool found_rom = false;
if(current_extension)
{
char * pch = strtok(tmp_extensions, "|");
while (pch != NULL)
{
if(strcmp(current_extension, pch) == 0)
{
found_rom = true;
break;
}
pch = strtok(NULL, "|");
}
}
if(!found_rom)
continue;
}
else if (ffd.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY)
found_dir = true;
filebrowser->cur[filebrowser->file_count].d_type = found_dir ? FILE_ATTRIBUTE_DIRECTORY : FILE_ATTRIBUTE_NORMAL;
sprintf(filebrowser->cur[filebrowser->file_count].d_name, ffd.cFileName);
filebrowser->file_count++;
}while (FindNextFile(hFind, &ffd) != 0 && (filebrowser->file_count + 1) < MAX_FILE_LIMIT);
#elif defined(__CELLOS_LV2__)
int fd;
/* bad path*/
if (strcmp(path,"") == 0)
{
error = 1;
goto error;
}
/* delete old path*/
filebrowser_clear_current_entries(filebrowser);
if (cellFsOpendir(path, &fd) == CELL_FS_SUCCEEDED)
{
uint64_t nread = 0;
strcpy(filebrowser->dir[filebrowser->directory_stack_size], path);
filebrowser->file_count = 0;
filebrowser->currently_selected = 0;
CellFsDirent dirent;
while (cellFsReaddir(fd, &dirent, &nread) == CELL_FS_SUCCEEDED)
{
if (nread == 0)
break;
if ((dirent.d_type != CELL_FS_TYPE_REGULAR) && (dirent.d_type != CELL_FS_TYPE_DIRECTORY))
continue;
if (dirent.d_type == CELL_FS_TYPE_DIRECTORY && !(strcmp(dirent.d_name, ".")))
continue;
if (dirent.d_type == CELL_FS_TYPE_REGULAR)
{
char tmp_extensions[512];
strncpy(tmp_extensions, extensions, sizeof(tmp_extensions));
const char * current_extension = filebrowser_get_extension(dirent.d_name);
bool found_rom = false;
if(current_extension)
{
char * pch = strtok(tmp_extensions, "|");
while (pch != NULL)
{
if(strcmp(current_extension, pch) == 0)
{
found_rom = true;
break;
}
pch = strtok(NULL, "|");
}
}
if(!found_rom)
continue;
}
filebrowser->cur[filebrowser->file_count].d_type = dirent.d_type;
filebrowser->cur[filebrowser->file_count].d_namlen = dirent.d_namlen;
strcpy(filebrowser->cur[filebrowser->file_count].d_name, dirent.d_name);
++filebrowser->file_count;
}
cellFsClosedir(fd);
}
else
{
error = 1;
goto error;
}
qsort(filebrowser->cur, filebrowser->file_count, sizeof(DirectoryEntry), less_than_key);
#endif
error:
if(error)
{
SSNES_ERR("Failed to open directory: \"%s\"\n", path);
}
#ifdef _XBOX
FindClose(hFind);
#endif
}
void filebrowser_new(filebrowser_t * filebrowser, const char * start_dir,
const char * extensions)
{
filebrowser_clear_current_entries(filebrowser);
filebrowser->directory_stack_size = 0;
strlcpy(filebrowser->extensions, extensions, sizeof(filebrowser->extensions));
filebrowser_parse_directory(filebrowser, start_dir, filebrowser->extensions);
}
void filebrowser_reset_start_directory(filebrowser_t * filebrowser, const char * start_dir,
const char * extensions)
{
filebrowser->directory_stack_size = 0;
strlcpy(filebrowser->extensions, extensions, sizeof(filebrowser->extensions));
filebrowser_parse_directory(filebrowser, start_dir, filebrowser->extensions);
}
void filebrowser_push_directory(filebrowser_t * filebrowser, const char * path,
bool with_extension)
{
filebrowser->directory_stack_size++;
if(with_extension)
filebrowser_parse_directory(filebrowser, path, filebrowser->extensions);
else
filebrowser_parse_directory(filebrowser, path, "empty");
}
void filebrowser_pop_directory (filebrowser_t * filebrowser)
{
if (filebrowser->directory_stack_size > 0)
filebrowser->directory_stack_size--;
filebrowser_parse_directory(filebrowser, filebrowser->dir[filebrowser->directory_stack_size],
filebrowser->extensions);
}
+99
View File
@@ -0,0 +1,99 @@
/* SSNES - A Super Nintendo Entertainment System (SNES) Emulator frontend for libsnes.
* Copyright (C) 2010-2012 - Hans-Kristian Arntzen
* Copyright (C) 2011-2012 - Daniel De Matteis
*
* Some code herein may be based on code found in BSNES.
*
* SSNES is free software: you can redistribute it and/or modify it under the terms
* of the GNU General Public License as published by the Free Software Found-
* ation, either version 3 of the License, or (at your option) any later version.
*
* SSNES is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
* without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
* PURPOSE. See the GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License along with SSNES.
* If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef FILEBROWSER_H_
#define FILEBROWSER_H_
#define MAXJOLIET 255
#define MAX_PATH_LENGTH 1024
#include <stdint.h>
#include <stdlib.h>
#ifdef __CELLOS_LV2__
#include <stdbool.h>
#include <cell/cell_fs.h>
#include <sys/types.h>
#define FS_MAX_PATH 256
#define FS_MAX_FS_PATH_LENGTH 255
#define MAX_FILE_LIMIT 30000
#elif defined(_XBOX)
#define FS_MAX_PATH MAX_PATH
#define FS_MAX_FS_PATH_LENGTH 2048
#define MAX_FILE_LIMIT 4096
#endif
typedef struct {
uint8_t d_type;
uint8_t d_namlen;
char d_name[FS_MAX_PATH];
} DirectoryEntry;
typedef struct
{
uint32_t file_count; /* amount of files in current dir*/
uint32_t currently_selected; /* currently select browser entry*/
uint32_t directory_stack_size;
char dir[128][FS_MAX_FS_PATH_LENGTH]; /* info of the current directory*/
DirectoryEntry cur[MAX_FILE_LIMIT]; /* current file listing*/
char extensions[512]; /* allowed extensions*/
} filebrowser_t;
void filebrowser_new(filebrowser_t * filebrowser, const char * start_dir, const char * extensions);
void filebrowser_reset_start_directory(filebrowser_t * filebrowser, const char * start_dir, const char * extensions);
void filebrowser_push_directory(filebrowser_t * filebrowser, const char * path, bool with_extension);
void filebrowser_pop_directory (filebrowser_t * filebrowser);
#define FILEBROWSER_GET_CURRENT_DIRECTORY_NAME(filebrowser) (filebrowser.dir[filebrowser.directory_stack_size])
#define FILEBROWSER_GET_CURRENT_DIRECTORY_FILE_COUNT(filebrowser) (filebrowser.file_count)
#define FILEBROWSER_GOTO_ENTRY(filebrowser, i) filebrowser.currently_selected = i;
#define FILEBROWSER_INCREMENT_ENTRY(filebrowser) \
{ \
filebrowser.currently_selected++; \
if (filebrowser.currently_selected >= filebrowser.file_count) \
filebrowser.currently_selected = 0; \
}
#define FILEBROWSER_INCREMENT_ENTRY_POINTER(filebrowser) \
{ \
filebrowser->currently_selected++; \
if (filebrowser->currently_selected >= filebrowser->file_count) \
filebrowser->currently_selected = 0; \
}
#define FILEBROWSER_DECREMENT_ENTRY(filebrowser) \
{ \
filebrowser.currently_selected--; \
if (filebrowser.currently_selected >= filebrowser.file_count) \
filebrowser.currently_selected = filebrowser.file_count - 1; \
}
#define FILEBROWSER_DECREMENT_ENTRY_POINTER(filebrowser) \
{ \
filebrowser->currently_selected--; \
if (filebrowser->currently_selected >= filebrowser->file_count) \
filebrowser->currently_selected = filebrowser->file_count - 1; \
}
#define FILEBROWSER_GET_CURRENT_FILENAME(filebrowser) (filebrowser.cur[filebrowser.currently_selected].d_name)
#define FILEBROWSER_GET_CURRENT_ENTRY_INDEX(filebrowser) (filebrowser.currently_selected)
#define FILEBROWSER_IS_CURRENT_A_FILE(filebrowser) (filebrowser.cur[filebrowser.currently_selected].d_type == CELL_FS_TYPE_REGULAR)
#define FILEBROWSER_IS_CURRENT_A_DIRECTORY(filebrowser) (filebrowser.cur[filebrowser.currently_selected].d_type == CELL_FS_TYPE_DIRECTORY)
#endif /* FILEBROWSER_H_ */
+32
View File
@@ -0,0 +1,32 @@
/* SSNES - A Super Nintendo Entertainment System (SNES) Emulator frontend for libsnes.
* Copyright (C) 2010-2012 - Hans-Kristian Arntzen
* Copyright (C) 2011-2012 - Daniel De Matteis
*
* Some code herein may be based on code found in BSNES.
*
* SSNES is free software: you can redistribute it and/or modify it under the terms
* of the GNU General Public License as published by the Free Software Found-
* ation, either version 3 of the License, or (at your option) any later version.
*
* SSNES is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
* without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
* PURPOSE. See the GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License along with SSNES.
* If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef _FUNC_HOOKS_H
#define _FUNC_HOOKS_H
/*============================================================
GENERAL
============================================================ */
#if defined(__CELLOS_LV2__) || defined(_XBOX)
#define HAVE_GRIFFIN_OVERRIDE_VIDEO_FRAME_FUNC 1
#endif
#define ssnes_render_cached_frame() \
const char *msg = msg_queue_pull(g_extern.msg_queue); \
video_frame_func(g_extern.frame_cache.data, g_extern.frame_cache.width, g_extern.frame_cache.height, lines_to_pitch(g_extern.frame_cache.height), msg);
#endif
+173
View File
@@ -0,0 +1,173 @@
/* SSNES - A Super Nintendo Entertainment System (SNES) Emulator frontend for libsnes.
* Copyright (C) 2010-2012 - Hans-Kristian Arntzen
* Copyright (C) 2011-2012 - Daniel De Matteis
*
* Some code herein may be based on code found in BSNES.
*
* SSNES is free software: you can redistribute it and/or modify it under the terms
* of the GNU General Public License as published by the Free Software Found-
* ation, either version 3 of the License, or (at your option) any later version.
*
* SSNES is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
* without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
* PURPOSE. See the GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License along with SSNES.
* If not, see <http://www.gnu.org/licenses/>.
*/
#if defined(_XBOX)
#include "../../msvc/msvc_compat.h"
#endif
/*============================================================
CONSOLE EXTENSIONS
============================================================ */
#include "../console_ext.c"
/*============================================================
COMPATIBILITY
============================================================ */
#include "../../compat/compat.c"
/*============================================================
CONFIG FILE
============================================================ */
#ifdef _XBOX
#undef __SSNES_POSIX_STRING_H
#undef __SSNES_MSVC_COMPAT_H
#undef strcasecmp
#endif
#include "../../conf/config_file.c"
#include "func_hooks.h"
/*============================================================
VIDEO
============================================================ */
#if defined(__CELLOS_LV2__)
#include "../../ps3/ps3_video_psgl.c"
#include "../../ps3/image.c"
#elif defined(_XBOX)
#include "../../360/xdk360_video.cpp"
#include "../../360/fonts.cpp"
#endif
/*============================================================
INPUT
============================================================ */
#if defined(__CELLOS_LV2__)
#include "../../ps3/ps3_input.c"
#elif defined(_XBOX)
#include "../../360/xdk360_input.c"
#endif
/*============================================================
SNES STATE
============================================================ */
#include "../../gfx/snes_state.c"
/*============================================================
DRIVERS
============================================================ */
#include "../../driver.c"
/*============================================================
FIFO BUFFER
============================================================ */
#include "../../fifo_buffer.c"
/*============================================================
AUDIO HERMITE
============================================================ */
#include "../../audio/hermite.c"
/*============================================================
RSOUND
============================================================ */
#ifdef __CELLOS_LV2__
#include "../../console/librsound/librsound.c"
#include "../../audio/rsound.c"
#endif
/*============================================================
AUDIO UTILS
============================================================ */
#include "../../audio/utils.c"
/*============================================================
AUDIO
============================================================ */
#if defined(__CELLOS_LV2__)
#include "../../ps3/ps3_audio.c"
#elif defined(_XBOX)
#include "../../360/xdk360_audio.cpp"
#endif
/*============================================================
DYNAMIC
============================================================ */
#include "../../dynamic.c"
/*============================================================
FILE
============================================================ */
#if defined(__CELLOS_LV2__) || defined(_XBOX)
#include "../fileio/file_browser.c"
#endif
#include "../../file.c"
/*============================================================
MESSAGE
============================================================ */
#include "../../message.c"
/*============================================================
PATCH
============================================================ */
#include "../../patch.c"
/*============================================================
SETTINGS
============================================================ */
#include "../../settings.c"
/*============================================================
REWIND
============================================================ */
#include "../../rewind.c"
/*============================================================
MAIN
============================================================ */
#if defined(__CELLOS_LV2__)
#include "../../ps3/main.c"
#elif defined(_XBOX)
#include "../../360/main.c"
#endif
/*============================================================
SSNES
============================================================ */
#include "../../ssnes.c"
/*============================================================
THREAD
============================================================ */
#include "../../thread.c"
/*============================================================
NETPLAY
============================================================ */
#include "../../netplay.c"
/*============================================================
MENU
============================================================ */
#if defined(__CELLOS_LV2__)
#include "../../ps3/menu.c"
#elif defined(_XBOX)
#include "../../360/menu.cpp"
#endif
+74
View File
@@ -0,0 +1,74 @@
/* SSNES - A Super Nintendo Entertainment System (SNES) Emulator frontend for libsnes.
* Copyright (C) 2010-2012 - Hans-Kristian Arntzen
* Copyright (C) 2011-2012 - Daniel De Matteis
*
* Some code herein may be based on code found in BSNES.
*
* SSNES is free software: you can redistribute it and/or modify it under the terms
* of the GNU General Public License as published by the Free Software Found-
* ation, either version 3 of the License, or (at your option) any later version.
*
* SSNES is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
* without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
* PURPOSE. See the GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License along with SSNES.
* If not, see <http://www.gnu.org/licenses/>.
*/
#define audio_init_func(device, rate, latency) driver.audio->init(device, rate, latency)
#define audio_write_func(buf, size) driver.audio->write(driver.audio_data, buf, size)
#define audio_stop_func() driver.audio->stop(driver.audio_data)
#define audio_start_func() driver.audio->start(driver.audio_data)
#define audio_set_nonblock_state_func(state) driver.audio->set_nonblock_state(driver.audio_data, state)
#define audio_free_func() driver.audio->free(driver.audio_data)
#define audio_use_float_func() driver.audio->use_float(driver.audio_data)
#define audio_write_avail_func() driver.audio->write_avail(driver.audio_data)
#define audio_buffer_size_func() driver.audio->buffer_size(driver.audio_data)
/*============================================================
PLAYSTATION3
============================================================ */
#ifdef __CELLOS_LV2__
#define video_init_func(video_info, input, input_data) \
gl_init(video_info, input, input_data)
#define video_frame_func(data, width, height, pitch, msg) \
gl_frame(driver.video_data, data, width, height, pitch, msg)
#define video_set_nonblock_state_func(state) driver.video->set_nonblock_state(driver.video_data, state)
#define video_alive_func() gl_alive(driver.video_data)
#define video_focus_func() gl_focus(driver.video_data)
#define video_xml_shader_func(path) driver.video->xml_shader(driver.video_data, path)
#define video_free_func() gl_free(driver.video_data)
#define video_set_rotation_func(orientation) ps3graphics_set_orientation(driver.video_data, orientation)
#define input_init_func() ps3_input_initialize()
#define input_poll_func() ps3_input_poll(driver.input_data)
#define input_input_state_func(snes_keybinds, port, device, index, id) \
ps3_input_state(driver.input_data, snes_keybinds, port, device, index, id)
#define input_key_pressed_func(key) ps3_key_pressed(driver.input_data, key)
#define input_free_func() ps3_free_input(driver.input_data)
/*============================================================
XBOX 360
============================================================ */
#elif defined(_XBOX)
#define video_init_func(video_info, input, input_data) \
xdk360_gfx_init(video_info, input, input_data)
#define video_frame_func(data, width, height, pitch, msg) \
xdk360_gfx_frame(driver.video_data, data, width, height, pitch, msg)
#define video_set_nonblock_state_func(state) driver.video->set_nonblock_state(driver.video_data, state)
#define video_alive_func() xdk360_gfx_alive(driver.video_data)
#define video_focus_func() xdk360_gfx_focus(driver.video_data)
#define video_xml_shader_func(path) driver.video->xml_shader(driver.video_data, path)
#define video_free_func() xdk360_gfx_free(driver.video_data)
#define video_set_rotation_func(orientation) xdk360_set_orientation(driver.video_data, orientation)
#define input_init_func() xdk360_input_initialize()
#define input_poll_func() xdk360_input_poll(driver.input_data)
#define input_input_state_func(snes_keybinds, port, device, index, id) \
xdk360_input_state(driver.input_data, snes_keybinds, port, device, index, id)
#define input_key_pressed_func(key) xdk360_key_pressed(driver.input_data, key)
#define input_free_func() xdk360_free_input(driver.input_data)
#endif
+60
View File
@@ -0,0 +1,60 @@
/* SSNES - A Super Nintendo Entertainment System (SNES) Emulator frontend for libsnes.
* Copyright (C) 2010-2012 - Hans-Kristian Arntzen
* Copyright (C) 2011-2012 - Daniel De Matteis
*
* Some code herein may be based on code found in BSNES.
*
* SSNES is free software: you can redistribute it and/or modify it under the terms
* of the GNU General Public License as published by the Free Software Found-
* ation, either version 3 of the License, or (at your option) any later version.
*
* SSNES is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
* without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
* PURPOSE. See the GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License along with SSNES.
* If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef _SSNES_FUNC_HOOKS_H
#define _SSNES_FUNC_HOOKS_H
/*============================================================
PLAYSTATION3
============================================================ */
#ifdef __CELLOS_LV2__
#define HAVE_GRIFFIN_OVERRIDE_AUDIO_FLUSH_FUNC 1
static bool audio_flush(const int16_t *data, size_t samples)
{
const float *output_data = NULL;
unsigned output_frames = 0;
audio_convert_s16_to_float(g_extern.audio_data.data, data, samples);
struct resampler_data src_data = {0};
src_data.data_in = g_extern.audio_data.data;
src_data.data_out = g_extern.audio_data.outsamples;
src_data.input_frames = (samples / 2);
src_data.ratio = g_extern.audio_data.src_ratio;
if (g_extern.is_slowmotion)
src_data.ratio *= g_settings.slowmotion_ratio;
resampler_process(g_extern.audio_data.source, &src_data);
output_data = g_extern.audio_data.outsamples;
output_frames = src_data.output_frames;
if (audio_write_func(output_data, output_frames * sizeof(float) * 2) < 0)
return false;
return true;
}
#endif
#endif
File diff suppressed because it is too large. Load diff
+339
View File
@@ -0,0 +1,339 @@
/* RSound - A PCM audio client/server
* Copyright (C) 2010 - Hans-Kristian Arntzen
*
* RSound is free software: you can redistribute it and/or modify it under the terms
* of the GNU General Public License as published by the Free Software Found-
* ation, either version 3 of the License, or (at your option) any later version.
*
* RSound is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
* without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
* PURPOSE. See the GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License along with RSound.
* If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef __RSOUND_H
#define __RSOUND_H
#ifdef __cplusplus
extern "C" {
#endif
#ifdef RSD_EXPOSE_STRUCT
#include <sys/types.h>
#include <unistd.h>
#include <pthread.h>
#include <sys/time.h>
#include <time.h>
#include <stdint.h>
#include <stddef.h>
#else
#include <stddef.h>
#include <sys/types.h>
#endif
#include "../../fifo_buffer.h"
#ifdef _WIN32
#define RSD_DEFAULT_HOST "127.0.0.1" // Stupid Windows.
#else
#define RSD_DEFAULT_HOST "localhost"
#endif
#define RSD_DEFAULT_PORT "12345"
#define RSD_DEFAULT_UNIX_SOCK "/tmp/rsound"
#define RSD_DEFAULT_OBJECT "rsound"
#ifndef RSD_VERSION
#define RSD_VERSION "1.1"
#endif
/* Feature tests */
#define RSD_SAMPLERATE RSD_SAMPLERATE
#define RSD_CHANNELS RSD_CHANNELS
#define RSD_HOST RSD_HOST
#define RSD_PORT RSD_PORT
#define RSD_BUFSIZE RSD_BUFSIZE
#define RSD_LATENCY RSD_LATENCY
#define RSD_FORMAT RSD_FORMAT
#define RSD_IDENTITY RSD_IDENTITY
#define RSD_S16_LE RSD_S16_LE
#define RSD_S16_BE RSD_S16_BE
#define RSD_U16_LE RSD_U16_LE
#define RSD_U16_BE RSD_U16_BE
#define RSD_U8 RSD_U8
#define RSD_S8 RSD_S8
#define RSD_S16_NE RSD_S16_NE
#define RSD_U16_NE RSD_U16_NE
#define RSD_ALAW RSD_ALAW
#define RSD_MULAW RSD_MULAW
#define RSD_S32_LE RSD_S32_LE
#define RSD_S32_BE RSD_S32_BE
#define RSD_S32_NE RSD_S32_NE
#define RSD_U32_LE RSD_U32_LE
#define RSD_U32_BE RSD_U32_BE
#define RSD_U32_NE RSD_U32_NE
#define RSD_DELAY_MS RSD_DELAY_MS
#define RSD_SAMPLESIZE RSD_SAMPLESIZE
#define RSD_EXEC RSD_EXEC
#define RSD_SIMPLE_START RSD_SIMPLE_START
#define RSD_NO_FMT RSD_NO_FMT
#define RSD_USES_OPAQUE_TYPE RSD_USES_OPAQUE_TYPE
#define RSD_USES_SAMPLESIZE_MEMBER RSD_USES_SAMPLESIZE_MEMBER
#define RSD_AUDIO_CALLBACK_T RSD_AUDIO_CALLBACK_T
#define RSD_ERROR_CALLBACK_T RSD_ERROR_CALLBACK_T
#define RSD_SET_CALLBACK RSD_SET_CALLBACK
#define RSD_CALLBACK_LOCK RSD_CALLBACK_LOCK
#define RSD_CALLBACK_UNLOCK RSD_CALLBACK_UNLOCK
/* End feature tests */
/* Defines sample formats available. Defaults to S16_LE should it never be set. */
enum rsd_format
{
RSD_NO_FMT = 0x0000,
RSD_S16_LE = 0x0001,
RSD_S16_BE = 0x0002,
RSD_U16_LE = 0x0004,
RSD_U16_BE = 0x0008,
RSD_U8 = 0x0010,
RSD_S8 = 0x0020,
RSD_S16_NE = 0x0040,
RSD_U16_NE = 0x0080,
RSD_ALAW = 0x0100,
RSD_MULAW = 0x0200,
RSD_S32_LE = 0x0400,
RSD_S32_BE = 0x0800,
RSD_S32_NE = 0x1000,
RSD_U32_LE = 0x2000,
RSD_U32_BE = 0x4000,
RSD_U32_NE = 0x8000,
};
/* Defines operations that can be used with rsd_set_param() */
enum rsd_settings
{
RSD_SAMPLERATE = 0,
RSD_CHANNELS,
RSD_HOST,
RSD_PORT,
RSD_BUFSIZE,
RSD_LATENCY,
RSD_FORMAT,
RSD_IDENTITY
};
/* Audio callback for rsd_set_callback. Return -1 to trigger an error in the stream. */
typedef ssize_t (*rsd_audio_callback_t)(void *data, size_t bytes, void *userdata);
/* Error callback. Signals caller that stream has been stopped, either by audio callback returning -1 or stream was hung up. */
typedef void (*rsd_error_callback_t)(void *userdata);
#ifdef RSD_EXPOSE_STRUCT
/* Defines the main structure for use with the API. */
typedef struct rsound
{
struct {
volatile int socket;
volatile int ctl_socket;
} conn;
char *host;
char *port;
char *buffer; /* Obsolete, but kept for backwards header compatibility. */
int conn_type;
volatile int buffer_pointer; /* Obsolete, but kept for backwards header compatibility. */
size_t buffer_size;
fifo_buffer_t *fifo_buffer;
volatile int thread_active;
int64_t total_written;
int64_t start_time;
volatile int has_written;
int bytes_in_buffer;
int delay_offset;
int max_latency;
struct {
uint32_t latency;
uint32_t chunk_size;
} backend_info;
volatile int ready_for_data;
uint32_t rate;
uint32_t channels;
uint16_t format;
int samplesize;
struct {
pthread_t threadId;
pthread_mutex_t mutex;
pthread_mutex_t cond_mutex;
pthread_cond_t cond;
} thread;
char identity[256];
rsd_audio_callback_t audio_callback;
rsd_error_callback_t error_callback;
size_t cb_max_size;
void *cb_data;
pthread_mutex_t cb_lock;
} rsound_t;
#else
typedef struct rsound rsound_t;
#endif
/* -- API --
All functions (except for rsd_write() return 0 for success, and -1 for error. errno is currently not set. */
/* Initializes an rsound_t structure. To make sure no memory leaks occur, you need to rsd_free() it after use.
A typical use of the API is as follows:
rsound_t *rd;
rsd_init(&rd);
rsd_set_param(rd, RSD_HOST, "foohost");
*sets more params*
rsd_start(rd);
rsd_write(rd, buf, size);
rsd_stop(rd);
rsd_free(rd);
*/
int rsd_init (rsound_t **rd);
/* This is a simpler function that initializes an rsound struct, sets params as given,
and starts the stream. Should this function fail, the structure will stay uninitialized.
Should NULL be passed in either host, port or ident, defaults will be used. */
int rsd_simple_start (rsound_t **rd, const char* host, const char* port, const char* ident,
int rate, int channels, enum rsd_format format);
/* Sets params associated with an rsound_t. These options (int options) include:
RSD_HOST: Server to connect to. Expects (char *) in param.
If not set, will default to environmental variable RSD_SERVER or "localhost".
RSD_PORT: Set port. Expects (char *) in param.
If not set, will default to environmental variable RSD_PORT or "12345".
RSD_CHANNELS: Set number of audio channels. Expects (int *) in param. Mandatory.
RSD_SAMPLERATE: Set samplerate of audio stream. Expects (int *) in param. Mandatory.
RSD_BUFSIZE: Sets internal buffersize for the stream.
Might be overridden if too small.
Expects (int *) in param. Optional.
RSD_LATENCY: Sets maximum audio latency in milliseconds,
(must be used with rsd_delay_wait() or this will have no effect).
Most applications do not need this.
Might be overridden if too small.
Expects (int *) in param. Optional.
RSD_FORMAT: Sets sample format.
It defaults to S16_LE, so you probably will not use this.
Expects (int *) in param, with available values found in the format enum.
If invalid format is given, param might be changed to reflect the sample format the library will use.
RSD_IDENTITY: Sets an identity string associated with the client.
Takes a (char *) parameter with the stream name.
Will be truncated if longer than 256 bytes.
*/
int rsd_set_param (rsound_t *rd, enum rsd_settings option, void* param);
/* Enables use of the callback interface. This must be set when stream is not active.
When callback is active, use of the blocking interface is disabled.
Only valid functions to call after rsd_start() is stopping the stream with either rsd_pause() or rsd_stop(). Calling any other function is undefined.
The callback is called at regular intervals and is asynchronous, so thread safety must be ensured by the caller.
If not enough data can be given to the callback, librsound will fill the rest of the callback data with silence.
librsound will attempt to obey latency information given with RSD_LATENCY as given before calling rsd_start().
max_size signifies the maximum size that will ever be requested by librsound. Set this to 0 to let librsound decide the maximum size.
Should an error occur to the stream, err_callback will be called, and the stream will be stopped. The stream can be started again.
Callbacks can be disabled by setting callbacks to NULL. */
void rsd_set_callback (rsound_t *rd, rsd_audio_callback_t callback, rsd_error_callback_t err_callback, size_t max_size, void *userdata);
/* Lock and unlock the callback. When the callback lock is aquired, the callback is guaranteed to not be executing.
The lock has to be unlocked afterwards.
Attemping to call several rsd_callback_lock() in succession might cause a deadlock.
The lock should be held for as short period as possible.
Try to avoid calling code that may block when holding the lock. */
void rsd_callback_lock (rsound_t *rd);
void rsd_callback_unlock (rsound_t *rd);
/* Establishes connection to server. Might fail if connection can't be established or that one of
the mandatory options isn't set in rsd_set_param(). This needs to be called after params have been set
with rsd_set_param(), and before rsd_write(). */
int rsd_start (rsound_t *rd);
/* Shuts down the rsound data structures, but returns the file descriptor associated with the connection.
The control socket will be shut down. If this function returns a negative number, the exec failed,
but the data structures will not be teared down.
Should a valid file descriptor be returned, it will always be blocking.
This call will block until all internal buffers have been sent to the network. */
int rsd_exec (rsound_t *rd);
/* Disconnects from server. All audio data still in network buffer and other buffers will be dropped.
To continue playing, you will need to rsd_start() again. */
int rsd_stop (rsound_t *rd);
/* Writes from buf to the internal buffer. Might fail if no connection is established,
or there was an unexpected error. This function will block until all data has
been written to the buffer. This function will return the number of bytes written to the buffer,
or 0 should it fail (disconnection from server). You will have to restart the stream again should this occur. */
size_t rsd_write (rsound_t *rd, const void* buf, size_t size);
/* Gets the position of the buffer pointer.
Not really interesting for normal applications.
Might be useful for implementing rsound on top of other blocking APIs.
*NOTE* This function is deprecated, it should not be used in new applications. */
size_t rsd_pointer (rsound_t *rd);
/* Aquires how much data can be written to the buffer without blocking */
size_t rsd_get_avail (rsound_t *rd);
/* Aquires the latency at the moment for the audio stream. It is measured in bytes. Useful for syncing video and audio. */
size_t rsd_delay (rsound_t *rd);
/* Utility for returning latency in milliseconds. */
size_t rsd_delay_ms (rsound_t *rd);
/* Returns bytes per sample */
int rsd_samplesize(rsound_t *rd);
/* Will sleep until latency of stream reaches maximum allowed latency defined earlier by rsd_set_param - RSD_LATENCY
Useful for hard headed blocking I/O design where user defined latency is needed. If rsd_set_param hasn't been set
with RSD_LATENCY, this function will do nothing. */
void rsd_delay_wait(rsound_t *rd);
/* Pauses or unpauses a stream. pause -> enable = 1
This function essentially calls on start() and stop(). This behavior might be changed later. */
int rsd_pause (rsound_t *rd, int enable);
/* Frees an rsound_t struct. Make sure that the stream is properly closed down with rsd_stop() before calling rsd_free(). */
int rsd_free (rsound_t *rd);
#ifdef __cplusplus
}
#endif
#endif
+140
View File
@@ -0,0 +1,140 @@
/* SSNES - A Super Nintendo Entertainment System (SNES) Emulator frontend for libsnes.
* Copyright (C) 2010-2012 - Hans-Kristian Arntzen
* Copyright (C) 2011-2012 - Daniel De Matteis
*
* Some code herein may be based on code found in BSNES.
*
* SSNES is free software: you can redistribute it and/or modify it under the terms
* of the GNU General Public License as published by the Free Software Found-
* ation, either version 3 of the License, or (at your option) any later version.
*
* SSNES is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
* without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
* PURPOSE. See the GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License along with SSNES.
* If not, see <http://www.gnu.org/licenses/>.
*/
#ifdef __CELLOS_LV2__
#include <netex/net.h>
#include <cell/sysmodule.h>
#include <netex/libnetctl.h>
#include <sys/timer.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#endif
#ifdef HW_RVL
#include <network.h>
#endif
#include <stdio.h>
#include <stdlib.h>
#include <stdarg.h>
#include <string.h>
#include "../../netplay_compat.h"
#include "logger.h"
#if !defined(PC_DEVELOPMENT_IP_ADDRESS)
#define PC_DEVELOPMENT_IP_ADDRESS "192.168.1.7"
#endif
#if !defined(PC_DEVELOPMENT_UDP_PORT)
#define PC_DEVELOPMENT_UDP_PORT 3490
#endif
static int g_sid;
static int sock;
static struct sockaddr_in target;
static char sendbuf[4096];
#ifdef HW_RVL
#define sendto(s, msg, len, flags, addr, tolen) net_sendto(s, msg, len, flags, addr, tolen)
#define socket(domain, type, protocol) net_socket(domain, type, protocol)
static int inet_pton(int af, const char *src, void *dst)
{
if (af != AF_INET)
return -1;
return inet_aton (src, dst);
}
#endif
static int if_up_with(int index)
{
(void)index;
#ifdef __CELLOS_LV2__
int timeout_count = 10;
int state;
int ret;
ret = cellNetCtlInit();
if (ret < 0)
{
printf("cellNetCtlInit() failed(%x)\n", ret);
return (-1);
}
for (;;)
{
ret = cellNetCtlGetState(&state);
if (ret < 0)
{
printf("cellNetCtlGetState() failed(%x)\n", ret);
return (-1);
}
if (state == CELL_NET_CTL_STATE_IPObtained)
break;
sys_timer_usleep(500 * 1000);
timeout_count--;
if (index && timeout_count < 0)
{
printf("if_up_with(%d) timeout\n", index);
return (0);
}
}
#endif
sock=socket(AF_INET,SOCK_DGRAM ,0);
target.sin_family = AF_INET;
target.sin_port = htons(PC_DEVELOPMENT_UDP_PORT);
inet_pton(AF_INET, PC_DEVELOPMENT_IP_ADDRESS, &target.sin_addr);
return (0);
}
static int if_down(int sid)
{
(void)sid;
#ifdef __CELLOS_LV2__
cellNetCtlTerm();
#endif
return (0);
}
void logger_init (void)
{
g_sid = if_up_with(1);
}
void logger_shutdown (void)
{
if_down(g_sid);
}
void logger_send(const char *__format,...)
{
va_list args;
va_start(args,__format);
vsnprintf(sendbuf,4000,__format, args);
va_end(args);
int len=strlen(sendbuf);
sendto(sock,sendbuf,len,MSG_DONTWAIT,(struct sockaddr*)&target,sizeof(target));
}
+30
View File
@@ -0,0 +1,30 @@
/* SSNES - A Super Nintendo Entertainment System (SNES) Emulator frontend for libsnes.
* Copyright (C) 2010-2012 - Hans-Kristian Arntzen
* Copyright (C) 2011-2012 - Daniel De Matteis
*
* Some code herein may be based on code found in BSNES.
*
* SSNES is free software: you can redistribute it and/or modify it under the terms
* of the GNU General Public License as published by the Free Software Found-
* ation, either version 3 of the License, or (at your option) any later version.
*
* SSNES is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
* without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
* PURPOSE. See the GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License along with SSNES.
* If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef _LOGGER_H_
#define _LOGGER_H_
#define BUFSIZE (64 * 1024)
#define TCPDUMP_STACKSIZE (16 * 1024)
#define TCPDUMP_PRIO (2048)
void logger_init (void);
void logger_shutdown (void);
void logger_send (const char *__format,...);
#endif
+13 -22
View File
@@ -1,5 +1,6 @@
/* SSNES - A Super Nintendo Entertainment System (SNES) Emulator frontend for libsnes.
* Copyright (C) 2010-2011 - Hans-Kristian Arntzen
* Copyright (C) 2010-2012 - Hans-Kristian Arntzen
* Copyright (C) 2011-2012 - Daniel De Matteis
*
* Some code herein may be based on code found in BSNES.
*
@@ -15,30 +16,20 @@
* If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef __UPS_H
#define __UPS_H
// Builds argc/argv and calls ssnes_main_init().
#include <stdint.h>
#include <stddef.h>
#ifndef _SSNES_WRAP_H
#define _SSNES_WRAP_H
// UPS implementation from bSNES.
typedef enum ups_error
struct ssnes_main_wrap
{
UPS_UNKNOWN,
UPS_SUCCESS,
UPS_PATCH_INVALID,
UPS_SOURCE_INVALID,
UPS_TARGET_INVALID,
UPS_TARGET_TOO_SMALL,
UPS_PATCH_CHECKSUM_INVALID,
UPS_SOURCE_CHECKSUM_INVALID,
UPS_TARGET_CHECKSUM_INVALID
} ups_error_t;
const char *rom_path;
const char *sram_path;
const char *state_path;
const char *config_path;
bool verbose;
};
ups_error_t ups_apply_patch(
const uint8_t *patch_data, size_t patch_length,
const uint8_t *source_data, size_t source_length,
uint8_t *target_data, size_t *target_length);
int ssnes_main_init_wrap(const struct ssnes_main_wrap *args);
#endif
BIN
View File
Binary file not shown.

After

Width:  |  Height:  |  Size: 192 KiB

+118
View File
@@ -0,0 +1,118 @@
/* SSNES - A Super Nintendo Entertainment System (SNES) Emulator frontend for libsnes.
* Copyright (C) 2010-2012 - Hans-Kristian Arntzen
*
* Some code herein may be based on code found in BSNES.
*
* SSNES is free software: you can redistribute it and/or modify it under the terms
* of the GNU General Public License as published by the Free Software Found-
* ation, either version 3 of the License, or (at your option) any later version.
*
* SSNES is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
* without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
* PURPOSE. See the GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License along with SSNES.
* If not, see <http://www.gnu.org/licenses/>.
*/
#include "list.h"
#include <stddef.h>
#include <stdlib.h>
#include <string.h>
struct sgui_file
{
char *path;
sgui_file_type_t type;
};
struct sgui_list
{
struct sgui_file *list;
size_t capacity;
size_t ptr;
};
sgui_list_t *sgui_list_new(void)
{
return (sgui_list_t*)calloc(1, sizeof(sgui_list_t));
}
bool sgui_list_empty(const sgui_list_t *list)
{
return list->ptr == 0;
}
void sgui_list_push(sgui_list_t *list, const char *path, sgui_file_type_t type)
{
if (list->ptr >= list->capacity)
{
list->capacity++;
list->capacity *= 2;
list->list = (struct sgui_file*)realloc(list->list, list->capacity * sizeof(struct sgui_file));
}
list->list[list->ptr].path = strdup(path);
list->list[list->ptr].type = type;
list->ptr++;
}
void sgui_list_pop(sgui_list_t *list)
{
if (!sgui_list_empty(list))
free(list->list[--list->ptr].path);
}
void sgui_list_free(sgui_list_t *list)
{
for (size_t i = 0; i < list->ptr; i++)
free(list->list[i].path);
free(list->list);
free(list);
}
void sgui_list_clear(sgui_list_t *list)
{
for (size_t i = 0; i < list->ptr; i++)
free(list->list[i].path);
list->ptr = 0;
}
void sgui_list_back(const sgui_list_t *list,
const char **path, sgui_file_type_t *file_type)
{
if (sgui_list_size(list) > 0)
sgui_list_at(list, sgui_list_size(list) - 1, path, file_type);
}
size_t sgui_list_size(const sgui_list_t *list)
{
return list->ptr;
}
void sgui_list_at(const sgui_list_t *list, size_t index,
const char **path, sgui_file_type_t *file_type)
{
if (path)
*path = list->list[index].path;
if (file_type)
*file_type = list->list[index].type;
}
static int list_comp(const void *a_, const void *b_)
{
const struct sgui_file *a = (const struct sgui_file*)a_;
const struct sgui_file *b = (const struct sgui_file*)b_;
if (a->type != b->type)
return a->type == SGUI_FILE_DIRECTORY ? -1 : 1;
return strcmp(a->path, b->path);
}
void sgui_list_sort(sgui_list_t *list)
{
qsort(list->list, list->ptr, sizeof(struct sgui_file), list_comp);
}
Loaded 100 of 224 files, more files were not shown because too many files have changed in this diff. Show more