Compare commits

..

2 commits

Author SHA1 Message Date
Ilari Liusvaara
d91b20d430 Movie downloading 2013-11-11 01:49:36 +02:00
Ilari Liusvaara
2a14872ae7 Upload UI 2013-11-11 01:49:36 +02:00
614 changed files with 27286 additions and 69210 deletions

7
.gitignore vendored
View file

@ -3,7 +3,6 @@
*.lib
*.obj
*.exe
*.dep
*.ldflags
*.files
docs
@ -15,9 +14,3 @@ lsnes
/gambatte
src/fonts/font.cpp
src/core/version.cpp
src/cmdhelp/*.cpp
include/cmdhelp/*.hpp
src/emulation/make-ports
src/cmdhelp/mkstubs
src/cmdhelp/mkstubsi
buildaux/mkdeps

6
.gitmodules vendored
View file

@ -1,6 +0,0 @@
[submodule "bsnes"]
path = bsnes
url = .
[submodule "gambatte"]
path = gambatte
url = .

731
CHANGELOG
View file

@ -1457,734 +1457,3 @@ rr2-β12 [Monday October 14th 2013]
* Fix more bugs in rerecord counting
* Fix bug that caused save slots always to be semi-text in projects
* Speed up binary savestate saving
rr2-β13 [Thursday November 28th 2013]
=====================================
* If libgcrypt is available but /dev/urandom is not, use libgcrypt for RNG* Allow setting AVI scale factors
* JSON-based controller descriptions
* Fix compile for Mac OS X
* Optimize generic controllers using dynamically generated code
* Make regex thread-safe
* JSON: Reduce internal exception spam
* Recent Lua scripts
* Support latch notifications on SNES
* Wxwidgets: Command line history
* Oops, forgot to update patchseries for latch notification support
* Add on_latch to Lua docs
* Try to autodect I386/amd64
* Save bitmaps as PNG
* Lua: gui.bitmap_hash/gui.palete_hash
* Lua: bsnes.dump_sprite: Allow overriding row stride
* Fix recent movies menu
* Fix output if core tries to output wider than buffer (currently 4096)
* Win32 compile fixes
* Don't crash if setting game name & authors outside project context
* Support in-memory saves and use those for wxwidgets ROM loading
* Fix in-memory slots
* Improve randomness of get_random_hexstring (on I386)
* Zip: Allow output to arbitrary ostream
* HTTP request code
* Support stream compression
* File upload code
* Add command-line file uploader
* Upload UI
* Movie downloading
* Strip path when autofilling filename
* httpauth: Use the no-protocol mode
* Gambatte: Expose CPU registers
* Fix compilation on Win32
* BSNES: Compile with accuracy core
* Fix WWW-Autheticate parsing
* Rewrite parse_authenticate in saner way
* Lua: Fix a typo in error message
* Fix writing movie data
* Nuke the helper executables on make clean
* Print proper error message if Lua expression parse fails
* Allow resizing messages window
* Oops, remove some crap lines
* Messages panel: copy to clipboard / save to file
* Messages window: Scroll with wheel
* Fold audio device controls to VU meter window
* Unified support for breakpoints & cheats
rr2-β14 [Tuesday December 31st 2013]
====================================
* Fix printing of errors from some notifications
* Don't require to specify bsnes version when building
* Null core: Set the hidden flag
* Attempt to save if emulator is crashing
* Gameboy disasembler
* Fix compile with Gambatte not supporting debug hooks
* Gambatte: Do not lose colors when ROM is reloaded
* Command to set current slot
* Optional background sound autodisable
* Gambatte: DC levels fixes
* Don't crash if loaded dynamic library contains a new core
* Fix compile for bsnes accuracy for real
* Add bsnes alternate poll timings patch
* Fix http_request::_progress
* Make parse_value be able to parse 0x notation
* Bitmap font to custom font conversion
* Also catch terminate() for autosave
* Initialize some vars in messages window
* Release regexps before finally exiting
* Lua: random.*
* Lua: Zip create / enumerate
* Lua: gui.screenshot_bitmap()
* Clean up filesystem stuff
* Move binarystream functions to dedicated namespace
* Refactor library command functions to dedicated namespace
* Refactor library keyboard to dedicated namespace
* Refactor library dispatch stuff to dedicated namespace
* Build: Fast global need-rebuild detection
* Remove some crazy dependencies to keymapper
* Extra framebuffer methods
* Refactor library framebuffer to dedicated namespace
* Further framebuffer refactoring (pixel formats)
* Remove some dead files
* Refactor custom_font into framebuffer namespace
* Refactor library gamepad to dedicated namespace
* Refactor library ogg functions to dedicated namespace
* Refactor library zip functions to dedicated namespace
* Refactor library serialization to dedicated namespace
* loadlib refactoring, add program modules
* Move opus_packet_tick_count() to main opus library code
* Move routines from oggopus to opus namespace
* keyboard-mapper: Get rid of command.hpp include
* Get rid of DECLARE_LUACLASS
* Throw internal error instead of crashing if trying to use nonexistent class
* Refactor library Lua base to dedicated namespace
* Refactor library settings to dedicated namespace
* Refactor library png functions to dedicated namespace
* Refactor library UTF8 to dedicated namespace
* Clean up hexadecimal<->string conversion
* File upload: Behave like cancel was clicked on window close
* Fix compilation of make-ports helper
* Refactor library fileimage to dedicated namespace
* Refactor library filesystem code
* SNES: PPU registers
* Move library patch functions with file image functions
* Get rid of utf8::to32i2() and extract_token()
* Fix compile error on some systems
* Fix another compile error (constant in Connect())
* SNES: Make needed directories for build if missing
* Clean up some hash and RNG code
* Crash autosave: Don't try to save movies with NULL sysregion
* Lua: Bitmap/renderq object methods
* Framebuffer: Set unused color bits to 1 instead of 0
* Fix a bug applying delta gaps on render queue
* Lua: RENDERQUEUE:render: Render queue to DBITMAP
* Allow color names as color specifications
* Some refactoring of the named colors stuff (and a lot more colors)
* Lua: HSL colors and color modifiers
* JSON Pretty printing support and pretty-print joystick configuration
* GB: Disassemble/Tracelog fixes for CB xx
* Wxwidgets: Plugin manager
* Lua: render_queue_function
* Fix off-by-one in counting number of objects in render queue
* Clean up error reporting on plugin load failure
* Plugin manager: Mark plugins that failed to load
* Plugin manager: Atomic overwrites, remove otherstate plugin on rename
* Also load plugins from location relative to the executable
* Fix compiling on Win32
* Plugin blacklist/killlist (needed on some toys)
rr1-Δ18ε3 [Sunday January 5th 2014]
===================================
* Backport bsnes/gambatte patches and make emu at least run
* Fix compiling gambatte binding with versions not supporting debug extensions
* Handle frame spanning movie page boundary
* Platform::wait(): Never wait on zero delay
rr2-β15 [Sunday January 5th 2014]
=================================
* options.build: Default to g++, not g++-4.6 (too old)
* Fix crash on canceling tracelog filename select
* Fix framebuffer::font::get_metrics
* Don't crash on certain invalid memory read/write commands
* Oops, GB(C) bus was missing
* Don't desync if loading a movie preserving input
* Fix rerecord count to reset on new movie
rr2-β16 [Friday February 14th 2014]
===================================
* PNG screenshots are bugged again...
* Fix typo in macosx platform makefile
* More advanced memory watches
* Fix core selection among multiple candidates for downloaded movies
* Allow -mt prefix for host boost
* Make frame count controller_frame_vector property
* Clean up internal name used to designate a save slot
* Move main movie compatiblity checking to controller_frame_vector
* Optimize controller_frame_vector::compatible()
* Fix lockup if exiting emulator with project active
* Lua: gui.set_video_scale()
* Slot branches
* Allow loading empty font and editing font after loading
* Lua interface to iconv(3), string.byteU and string.charU
* Rename ERROR to FAILED in evaluation status
* Lua: Byte order swapping
* Lua: Scaling blits, color priority blits, Porter-Duff blits
* Lua: Autogenerate sysrc.cpp from sysrc.lua
* Lua: identify_class
* Lua: Refactor lots of stuff
* Lua: Refactor classes
* Lua: Make static constructor methods for MMAP_STRUCT and ZIPWRITER
* Lua: Cleanup hostmemory and use static method for TILEMAP ctor
* Lua: Cleanup gui-rqueue.cpp
* Lua: Table of classes
* Lua: Refactor some documentation
* Lua: Some fixes related to sysrc.lua
* Lua: cleanup some more files
* Lua: More conversion to lua::parameters
* Lua: More refactoring
* Lua: Multi-argument parsing and unify color parsing
* Lua: Use multi-argument parsing in some more places
* Lua: use multi-argument parsing for more files
* Lua: Use multiarg in some more files
* Lua: Use multiarg for rest of gui-* stuff
* Lua: Multiarg refactoring for a few more files
* Lua: Refactor the two remaining files to use multiarg
* Lua: Convert some core-specific stuff and kill lua::fnptr
* Lua: Make class methods take lua::parameters
* PRNG: Don't try to access element -1 of array in some cases
* Make reference to certain library conditional
* Lua: Give the print method as pointer instead of assuming T::print
* Lua: all_classes()
* Lua: Support __pairs for classes
* Lua: Convert some functions to static-only classes
* Lua: Get rid of unneeded subclasses of lua::function
* lua_func_callback isn't used anymore, remove it
* Lua: bit.compose, bit.binary_{ld,st}_*, bit.quotent
* Fix some exception specifier mismatches
* Refactor some generic reading/writing routines out of moviefile.cpp
* wxwidgets: Use text render panel in messages window
* Make git diff --check happy
* Gambatte: New patch: Optional crash on SIGILL, fix MBC3
* Back movie data off movie file structure
* Fix initram handling with rewind to start type actions
* Upload: Don't send empty fields
* Dynamically allocate moviefile, rrdata and movie structures
* Support multi-branch movies
* moviefile.cpp is friggin' large, split it up
* Load some legacy memory watches
* Cleanup lua code by introducing lua::functions
* File upload: More usable game name selection
* Don't crash if exiting with trace log active
* Upload: Drop the system select, it isn't usable
* Fix kill_hooks()
* Gambatte: Some Trace/Disassemble fixes
* Hex editor: Properly erase past-the-end chars for non-mod16 regions
* Don't use framebuffer palettes
* Lua: memory.hash_region(), memory.store(), memory.storecmp()
* Lua docs: Replace "vma" by "memory area" or "marea"
* Trace logger / disassembler GUI
* Fix parsing of #nnnnnn color notation
* Lua: Cleanup & fix memory hash / storecmp functions
* Lua: memory2: More functions corresponding to memory.*
rr2-β17 [Friday February 28th 2014]
===================================
* Makefile: platclean: Only clean emulation files
* Lua: COMPARE_OBJ: Check strided memory block for modifications
* Some tweaks to Lua docs
* Show dialog if loading ROM/movie from command line fails
* Lua: Don't run Lua until the emulator has fully started up
* Lua: Run startup scripts after amode has been initialized
* wxwidgets: Allow entering fullscreen mode from commandline
* bsnes: redump sprite/palette functions
* Lua: Fix gui.repaint() when paused
* Lua: Clean up region bounds computation
* Some cleanup
* Wxwidgets: --unpause to auto-unpause on start
* Properly set Read-Only mode if rewinding
* Memory search: Fix display of unsigned dword and signed qword
* Tracelogger: Breakpoints
* Pass dummy object parameter to do_unregister
* Fix system plugins not getting loaded if user plugin enum failed
* Move library recentfiles to its own namespace
* Don't crash if recentfiles line fails to deserialize
* Recentfiles object: named object
* New projects menu
* C interface
* Fix exact core matching when loading projects
rr2-β18 [Wednesday March 19th 2014]
===================================
* bsnes core: Raise bus breaks against correct address
* C interface: Fix lag counting without LSNES_CORE_CAP1_PFLAG
* C interface: Check for value != 0, not for control != 0 for lag check
* Fix core callbacks being undefined if loading ROM from cmdline
* Fix compilation on Mac OS X
* Fix mouse electronics test
* Tweak new movie dialog layout a bit
* Add JSON linter utility
* Force some configuration windows to be larger
* Correctly show axes as disabled even if offline
* Don't double-close audio output
* Fix deleting executing breakpoint
* Lua: Get lag count function
* Allow bsnes tracelogger to trace execution in controller registers
* SNES: Fix disassembly of long offsets
* Make setting/unsetting non-bus breaks much faster.
* Optimize movie.find_frame()
rr2-β19 [Monday March 31st 2014]
================================
* Move one #ifdef BSNES_HAS_DEBUGGER to the proper place
* Some missing string conversions and headers
* Speed up font init
* Fix some memory leak complaints from Valgrind
* Free some more memory before quitting
* Fix potential dtor ordering crash in file hasher
* Fix another potential dtor order crash
* Refactor workthread.hpp and threadtypes.hpp (renamed to threads.hpp)
* Refactor streamcompress.hpp
* Lock/Unlock multiple locks at once function / class
* Gambatte: Mark system bus as I/O special
* Initialize project active_branch/next_branch
* Fix loading memory watches on project change
* GB: Fix read/write of A, PC and CycleCounter when executing
* GB: Fix tracelogger not to screw up breaks
* Refactor triple buffering logic to its own file
* Small tweak to previous (convert multiplication to bitshift)
* Lua: string.regex
* Lua: bit.multidiv
* Tweak description of bit.multidiv
* Lua: bit.test, bit.testn, string.hex, string.lpad, string.rpad
* Make redraw_framebuffer call update_movie_state();
* Only update emulator status from within update_movie_state()
* Fix the 0 movie length bug
* Don't crash if trying to load movie with unknown sysregion
* Work around compiler warning on -2^63 written as constant
* Make compiler more anal and fix what comes up
* Lua: bit.mul32
* Autosave settings immediately after closing settings
* Add base support for Lua object overcommit
* Use overcommit for palettes, bitmaps, dbitmaps and tilemaps
* Error out creating too large bitmaps / tilemaps instead of corrupting memory
* Fix compare objects
* Fix printing of tilemaps and compare objects
* Use overcommit in memory compares
* SNES: Support VRAM, OAM, CGRAM and APURAM breakpoints
* Refactor emulator status reporting (and fix the statusbar doesn't update bug)
rr2-β20 [Monday April 1st 2014]
===============================
* Fix typo in changelog
* Fix bug in printing MSU-1 track playback messages
* Add option to emulate fucked up GBC timings
* Coalesce UI events.
* Don't update statusbar fast outside paint event
rr2-β21 [Sunday May 4th 2014]
=============================
* Delete the now-unused emulator_status stuff
* Numeric range class, obsolete clip_range.
* Lua: gui.solidrectangle
* Lua: (D)BITMAP:draw_clip, (D)BITMAP:draw_outside, TILEMAP:draw_outside
* c-interface: Add some translation templates
* src/lua/gui-bitmap.cpp Initialize spal to avoid compiler warning
* Don't use -Werror
* Use open/read/write/close for binary saves instead of iostreams
* Select slot hotkeys
* Fix macros getting frame duplicated after loadstate
* Advance macros after frame is complete, not before frame starts
* SA1 tracing support + memorywatch/search SA1 IRAM
* Recognize SA1IRAM for purposes of breakpoints
* ZMBV full search mode
* SNES: SA1 registers for memory.getregister/setregister
* SNES: Pseudo-registers hcounter and vcounter
* Memory search: Resolve memory area if possible
* Merge multiple versions of get_read_address() into one
* Lua: Deprecate global addresses
* moviefile::get_movie_length: Use milliseconds, not nanoseconds
* Use curl-config instead of -lcurl
* Wipe all sorts of potentially sensitive stuff after use
* Memory peek/poke: Accept and show relative addresses
* Autodetect followed by undefined with multiple choices: Ask user
* Lua: Fix some includes
* Fix SA1 open bus
* Trace logger (Window): Show start of frame
* Trace logger: Allow deleting lines / clearing
* Fix potential crash on exit
* lsnes-dumpavi: Support downloading movies
* Trace logger: Don't double free trace hooks
* Support configurable URI shorthands
* Movie editor: Draw clear / fix current column
* Movie editor: Insert multiple lines at once
* Fix loading states with movie-ahead without ROM
* If loading ROM with multiple candidates, prompt before adding to recentrom
* Tweak the RNG a bit
* Some Win32 build fixes
* TAS input keyboard support
* Use urandom / rtlgenrandom
rr2-β22 [Saturday January 24th 2015]
====================================
* Lua: memory.getregisters()
* Zeroize: Don't crash if size=0
* Remove unused variable and some commented out debug code
* movb -> lsnes_instance.mlogic
* lsnes_memory -> lsnes_instance.memory
* Don't extern lsnes_lua_state, it is only used in one file
* lsnes_lua_state -> lsnes_instance.lua
* lsnes_memorywatch -> lsnes_instance.mwatch
* lsnes_vsetc -> lsnes_instance.setcache
* Get rid of lsnes_vset[foo]
* Instancefy inthread.cpp stuff
* Instancefy subtitles.cpp stuff
* Clean up some uses of lsnes_instance
* Instancefy mbranch.cpp stuff
* Kill unused generic_controller_name()
* Instancefy multitrack.cpp stuff
* Instancefy emustatus.cpp stuff
* Split random number functions from misc.cpp to dedicated file
* Move lsnes_kbd and lsnes_mapper to be instance vars
* Command sets WIP
* Simplify command::* memory management
* Use recursive locks to deal with the locking mess in command::*
* Delete some unused fields
* Fix valgrind warnings in inthread.cpp
* Inverse binding sets
* EVDEV: Select on joysticks
* Listener object is better than 3 lambdas + handle
* Initialize fdset before polling on it
* Setting sets
* Kill command::set::get_commands()
* Reduce dependicies between header files
* keyboard.cpp: Get rid of register_queue
* keyboard-mapper.cpp: Get rid of register_queue
* Lua.cpp: Get rid of register-queue
* settingvar.cpp: Get rid of register_queue
* Lua.cpp: Don't call unregister callbacks if nothing get unreg'd
* Kill off register-queue
* Rename some classes
* Move memorywatch stuff to dedicated namespace
* Namespacify mathexpr
* Move lua-framebuffer to lua namespace
* lua.hpp: Forward-declare keyboard::key
* controller_frame_vector: Use object instead of lambda for notify
* Scope listener base classes inside respective master classes
* Fix keyboard::keyboard::all_keys and all_modifiers
* Toggle sound mute command/hotkey
* Move directory stuff to dedicated namespace
* Move rename_overwrite from zip:: to directory::
* Change some terms in UI
* Don't crash if trying to select key without keys (shouldn't happen)
* Instancefy alias binds management
* Instancefy next rrdata
* Instancefy internal emulation thread execution queue
* Instancefy cart mappings
* Make main controllers state a instance variable
* Introduce run_show_error() and use it to clean up some code
* Instancefy project state
* Don't crash on exit with voice track loaded
* Get rid of most absolute refs to lsnes_instance in src/core
* run in emu thread: Throw exceptions over thread switches
* Gambatte: Fix bus write breaks
* Gambatte: Fix execute breaks on bus and IOAMHRAM
* Don't corrupt memory when trying to GC various items on exit
* Make the emulator harder to imporperly quit
* Fix all sort of Windows stupidities
* Add some test commands
* Refactor debugging into instance object
* Faster arithmetic modulo 2^255-19 on 64-bit
* Remove broken crap
* Some optimizations & fixes
* Some more optimization, some test code for this thing
* Move some debug stuff to be in class scope
* Instancefy framerate stuff
* Instancefy framebuffer stuff
* Make various instance stuff to take references to other instance objs
* Do some more stuff missed in last commit
* Factor queue stuff to its own file
* Make instance vars to be pointers
* Properly handle deletes if those behave oddly on some platform
* Remove unused dump_region_map()
* Rewrite basic video dumping framework
* Instancefy button manager stuff
* Make helper class for instance member allocation / deallocation
* Combine some small headers together
* Factor message stream stuff to its own files
* Some #include cleanup
* Move render_video_hud and killed_audio_length to master dumper class
* Refactor video dump framedrop handling
* Instancefy dispatch stuff
* Move action_update to be via dispatch
* Remove unused load_rom_from_commandline
* More include cleanups
* Instancefy base mmio stuff
* Get rid of direct references to emulation thread in branchesmenu.cpp
* Use variable obtained earlier for current branch
* Cleanup direct emulation thread references in editor-authors.cpp
* Get rid of direct references from dumpmenu.cpp to emulation thread
* Remove direct emulation thread references from keyboard.cpp
* Sweep instance variables upward in UI code
* Fix repainting status panel
* More sweeping instance variables up
* Eliminate settings_tab::call_window_fit(), nothing uses it
* Push instances up out from settings window code
* Push instance vars out of keyboard/mouse driver code
* Do not use CORE() multiple times in the same function, it is pointless
* Use helper class to simplify per-instance external vars
* Fix warnings from valgrind
* Refactor slotcache to be instance variable
* Make some values const, remove some unused stuff
* Lua: Memory address object
* Kill emulation_thread, nothing uses it
* lua::state::reset(): Use get instead of get_soft
* Instancefy lua core stuff
* Don't crash if exiting on panic
* When panicing, show last message (as it is presumably related)
* read_lua_fragment: Don't duplicate the script infinite number of times
* Actually don't start if sysrc.lua is bad
* Remove Lua 5.1 support
* Make some arrow magic constants in gui-arrow.cpp const
* Make render queue scratch variables instance variables
* Some non-instance variables cleanup
* Cleanup unused boost includes
* Instancefy audioapi core (but not driver) stuff
* Make some static variables in audioapi functions fields of audioapi class
* Instancefy currently loaded ROM
* Privatefy loaded_rom rtype, region and orig_region
* Refactor save jukebox handling into its own class
* Make class for emulator run mode
* Factor updating status to its own class
* Cleanup some symbols
* Fix updating statusbar on save slot change
* Clean up window-fileupload.cpp
* Clean up use of project->moviepath/otherpath
* Clean up instance usage in editor-voicesub.cpp
* Use UI_in_project_context() in branchesmenu.cpp
* bsnes: Fix on_latch in alttimings mode
* Fix build on GCC 4.9
* Fix memory.writeregion
* Fix compilation on Mac OS X
* Fix loading lz images with 128 or more colors
* Fix some accidentially mistyped variables in makefile
* Lua: Initialize some variables in address.cpp to make GCC happy
* Revert "Remove Lua 5.1 support"
* 25519: Add valgrind test mode
* Opus: Support some newly added stuff
* Small whitespace cleanup
* Commentary: Fix gain on oggopus export
* Fix emulator going out of whack after project load
* Add -pthread to flags
* Don't overdraw in outside draw
* Add few extra sound commands
* Fix jukebox slot select
* Remember sound device over sound restart
* Remember sound devices
* Oggopus: Complain about single-dpage streams with bad granulepos
* Lua: memory.action_flags
* Print messages about loaded libraries
* Library: Don't fail link without library support
* Wxwidgets: --library=<filename>
* C interface: render_text (version bump to v2)
* Music: Use all PSID LSIDs as implicit entrypoints (not just the first)
* Refactor controller runtime code generation
* Namespace library port-controller stuff
* Refactor library GC to its own namespace
* Refactor memory_region{,_direct} to be subclasses of memory_space
* Make workthread a class in top namespace and move some stuff under it
* Rename token_iterator_foreach to token_iterator::foreach
* Split audioapi to core interface and driver interface parts
* Fix crash if canceling load of other project
* Allow memory watch to read registers
* Show error dialog if project switch fails
* Add missing file
* gambatte fixes: Properly save MBC3 without RTC
* Don't try to do controller runtime codegen on X32, it won't work
* Memory watch fixes
* Rudimentary library unloading support
* Allow binding commands to class instance
* Module unloading: Small cleanup
* Module unloading: Small further cleanup
* Reinitialize gamepads command and fix EVDEV going bonkers on gamepad suddenly disconnecting
* Remove unused function
* Show VMA relative hex address when dumping debug hook list
* Tweak format of command help files and do some further command cleanup
* Don't try to unregister killed debug CBs
* bsnes: Add hcounter/vcounter registers
* Tracelogger: Unregister the frame callback even on hard kill
* Music playback: Guard against crazy pcmpos
* Wxwidgets: Fix loading ROM from commandline
* Fix most hotkeys to show up in configuration (were missing due to errant !)
* Fix error message if trying to load ROM with project active
* If project switch loads savestate, mark position at point of save
* Squash some wrong-thread bugs
* Memory editor: Squash another wrong-thread bug
* Add the UI thread checking code
* runuifun: Allow marking cb routine to run once at a time
* wxwidgets: Add some missing conversions for string arguments
* Oops from previous commit
* Portaudio: Don't blacklist ALSA default/sysdefault for input
* Redraw framebuffer when entering break pause
* Fix some nondeterminism (probably wouldn't cause desyncs)
* Lua: PALETTE:get()
* Fix some valgrind warnings
* Exit immediately on double fault
* Update the default build options
* Libao: Don't crash on quit
* Remove some utilities that should not be there anymore
* Use $DOT_EXECUTABLE_SUFFIX instead of hardcoding .exe
* Fattest? Really?
* Ignore some build helper programs, now that the .exe rule doesn't cover those
* Don't use arbitrary garbage as amount of samples to squash
* Show error from Lua if parsing Lua expression fails
* Don't let one unload currently used core (crashes the emulator)
* Lua 5.3 support
* Cleanup Lua multiversion support
* Add wide (64 bits) versions of bit functions if Lua 5.3 is used
* Fix Win32 build
* Fix compile error with Lua 5.1
* Clean up all build helper programs on make clean
* Add commands and Lua functions to manipulate running speed
* Remove target for font.cpp.dep
* Readd rule for font.cpp.dep in different way
* Pluginmanager: Autocreate directory instead of crashing
* Fix bad download crashing the emulator
* bsnes: DMA tracing
* bsnes: Support IRQ/NMI tracing
rr2-β23 [Thursday May 28th 2015]
================================
* Lua: Don't lua_error() out of context with pending dtors
* Add $LSNES_NO_SOUND_IN to disable sound input
* Makefile: Build cmdhelp before anything else
* keymapper: Verify gamepad config write before committing
* Remember volume settings across restarts
* Remember video settings
* Fix CUSTOMFONT text positioning
* Only exit poll advance on poll to non-00 control
* Show error instead silently failing tangent positive edge
* Fix race condition in makefile
* Fix scaling-related crashes
* NULL video dumper
* Fix some compilation errors on Mac OS X
* Move all regex matching to library/string.cpp
* Switch to std::regex by default
* Movie editor: Don't lock up on trying to display error messages
* Add a internal TODO list
* Lua: add gui.get_runmode()
* Movie editor: Fix unnamed branch to show properly in select branch
* If initsram/initstate points to LSS file, pull the matching member
* wxwidgets: Hide dumper called "NULL"
* Force game panel to window size in fullscreen mode
* Implicitly redirect cmdhelp includes to corresponding JSON files
* Fix movie length being wrong for imported binary tracks
* Lua: input.controller_info(): Don't crash with out-of-range port
* Lua: movie.rom_loaded()
* Lua: movie.get_rom_info()
* Force a repaint when becoming fullscreen
* wxwidgets: exit-fullscreen to forcibly exit fullscreen mode
* Make gitlinks for bsnes and gambatte
* Throw mic in to entropy pool
* Fix hostendian memory watches
* Fix race condition in do_mix_tsc()
* Lua: Don't run class destructor if constructor failed
* Fix typo in resolve_filename documentation
* bit.(r)flagdecode: Fix unicode in on/off strings
* Wxwidgets: Add keycode entries for å, ä and ö
* Wxwidgets: Fix §
* Wxwidgets: Fix some compile errors in editor-memorywatch.cpp
* Wxwidgets: Fix some compile errors in window-fileupload.cpp
* Lua: movie.get_game_info
* Don't callback to Lua in inconsistent state when loading a new ROM
* SNES: Functions for messing with clockrate (for debugging games)
* Remove some unnecressary casts
* Add back reload-rom and close-rom
* Add load-rom command
* Split overly large loaded_rom constructor
* Fix speed going out of whack after doing unsafe rewind
* Refactor loaded_rom to make public fields private
* Move NULL core code to its own file
* Internally refactor loaded ROM imageset out of loaded ROM code
* Refer to loaded ROM imagesets as handles
* A bit of code cleanup
* Mark the core methods that should be idempotent as const
* Refactor dynamic state to its own subobject
* Refactor unsafe rewinding a bit now that state is its own subobject
* Clean up dynamic state handling a bit
* Circle coordinates can go negative and thus must be signed
* Add dedicated method for resetting to poweron state
* Add description of PALETTE:get()
* Fix typo in Lua reference
* Don't leak open file descriptors to loaded ROMs
* Fix race between killing object and drawing object
* Fix a compiler warning
* Small rendering speedups
* Actually kill objects using palette about to be GC'd
* font rendering: Use ranges for bounding instead of buggy routine
* Have only one main Lua function trampoline
* Use master state for trampolines
* Lua: Memory usage limit
* Framework for memory usage tracking
* Redo text rendering (adds halo support to gui.text())
* Make git diff --check happier
* Clean up system font drawing
* Memory tracker: Add tracking of render objects
* Rework how memory tracking works
* Small whitespace cleanup
rr2-β24 [Monday December 31st 2018]
===================================
* Don't overflow buffers if bsnes goes bonkers* Lua: get_directory_contents & get_file_type
* Fix multiple problems with text drawing
* Fix load preserving movie displaying wrong screenshot
* Eliminate sloppy types from headers
* Don't crash on trying to create 0x0 bitmap or tilemap
* Lua: CUSTOMFONT:dump(): Dump font to file
* Fix build breakage on Win32
* Close the ROM on quit to avoid crashes
* Remove bogus comments in gui-tilemap.cpp
* Merge remote-tracking branch 'origin/master'
* Cleanup bitmap and tilemap rendering a bit
* Merge some common drawing code between bitmaps and tilemaps
* Use standard bitmap composition for rendered text bitmaps
* ss_int24_t and ss_uint24_t are integers
* Fix do_load_rom() in readonly case
* Add movie.subframe_to_frame
* movie::frame_subframes: Gracefully handle invalid frame numbers
* Fix crash on loading invalid PNG files
* Fix gamepad reset
* Fix bsnes compilation for GCC 5.X
* Fix MSU-1 bug where write to MSU1BASE+4 is mirred to MSUBASE+5
* When loading gamepaks, use #1 as MSU-1 base only if system has BIOS
* Fix help for +tangent/-tangent to be less obscure
* Fix disassembly of SNES BRL instruction
* Fix crash if loading type0 PNG without tRNS chunk
* Fix compilation with Lua 5.1
* Nuke last remains of boost::regex from outside string.cpp
* Add regex sanity checks on startup and add --sanity-check
* Fix Valgrind warning about uninitialized variable
* Add bit.fextract, bit.bfields
* bsnes: Add Lua function to dump 2bpp sprites (and allow 4-color palettes)
* Fix "empty path points to root" bug
* Don't try to uninstall handlers for active core
* Allow modifying button to be autofire/autohold/typed
* Lua Add getters for various paths
* Some new hotkeys
* Small cleanup: move up some lsnes_instance stuff
* Virtualize audio system for instances
* Fix crash if mouse_x or mouse_y are hooked
* Don't try to enter loadstate with loadstate already in progress
* Fix crash if text containing \n is printed at nonzero x
* PIX_FMT_* constants are deprecated, use AV_PIX_FMT_* instead
* Support uncompressing ZIP compression method 12 (bzip2)
* Lua: Fix type confusion between signed and unsigned
* When redrawing screen, read the last written frame
* Fix few uninitialized variables and a stack smash in AVI dumper
* Linear transformed texture sampling for (d)bitmap
* Specialize (D)BITMAP:sample_texture when s is power of two
* Lua (d)bitmap: add hflip and vflip functions
* Save: Fix issues with adding an extension if missing
* De-header SNES games with headers submultiple of 512 bytes correctly
* Make wrapper for boost::lexical_cast
* Bus fixes: Reading of CPU MMIO registers does not update MDR
* Add <functional> to files that use std::function
* Delay committing fullscreen until seeing window size change
* Track all window size changes while in fullscreen
* Fix bogus ROM type mismatch when using --rom
* movie.get_last_movie()

View file

@ -12,16 +12,14 @@ REALRANLIB = $(CROSS_PREFIX)$(RANLIB)
#Flags.
HOSTCCFLAGS = -std=gnu++0x
CFLAGS += -std=gnu++0x -pthread $(USER_CFLAGS)
CFLAGS += -std=gnu++0x $(USER_CFLAGS)
ifdef BOOST_NEEDS_MT
BOOST_LIB_POSTFIX=-mt
endif
ifdef HOST_BOOST_NEEDS_MT
HOST_BOOST_POSTFIX=-mt
else
BOOST_LIB_POSTFIX=
endif
LDFLAGS = -pthread -lboost_iostreams$(BOOST_LIB_POSTFIX) -lboost_filesystem$(BOOST_LIB_POSTFIX) -lboost_system$(BOOST_LIB_POSTFIX) -lz $(USER_LDFLAGS)
HOSTHELPER_LDFLAGS =
LDFLAGS = -lboost_iostreams$(BOOST_LIB_POSTFIX) -lboost_filesystem$(BOOST_LIB_POSTFIX) -lboost_system$(BOOST_LIB_POSTFIX) -lboost_regex$(BOOST_LIB_POSTFIX) -lz $(USER_LDFLAGS) -lcurl
ifeq ($(THREADS), NATIVE)
CFLAGS += -DNATIVE_THREADS
@ -34,18 +32,6 @@ $(error "Bad value for THREADS (expected NATIVE or BOOST)")
endif
endif
ifeq ($(REGEX), BOOST)
CFLAGS += -DUSE_BOOST_REGEX
LDFLAGS += -lboost_regex$(BOOST_LIB_POSTFIX)
HOSTHELPER_LDFLAGS += -lboost_regex$(HOST_BOOST_POSTFIX)
endif
HOSTHELPER_LDFLAGS += -lboost_system$(HOST_BOOST_POSTFIX)
ifdef NEED_LIBICONV
LDFLAGS += -liconv
endif
ifdef USE_LIBGCRYPT
CFLAGS += -DUSE_LIBGCRYPT_SHA256
LDFLAGS += -lgcrypt -lgpg-error
@ -68,8 +54,6 @@ all: src/__all_files__
CFLAGS += $(shell $(CROSS_PREFIX)pkg-config $(LUA) --cflags)
LDFLAGS += $(shell $(CROSS_PREFIX)pkg-config $(LUA) --libs)
CFLAGS += $(shell $(CROSS_PREFIX)curl-config --cflags)
LDFLAGS += $(shell $(CROSS_PREFIX)curl-config --libs)
compiler=$(subst ++,cc,$(REALCC))
gambatte_compiler=$(REALCC)
@ -79,28 +63,19 @@ bsnes/out/libsnes.$(ARCHIVE_SUFFIX): forcelook
$(REALRANLIB) bsnes/out/libsnes.$(ARCHIVE_SUFFIX)
src/__all_files__: src/core/version.cpp buildaux/mkdeps$(DOT_EXECUTABLE_SUFFIX) buildaux/txt2cstr$(DOT_EXECUTABLE_SUFFIX) forcelook
src/__all_files__: src/core/version.cpp forcelook
$(MAKE) -C src precheck
$(MAKE) -C src
cp src/lsnes$(DOT_EXECUTABLE_SUFFIX) .
buildaux/txt2cstr$(DOT_EXECUTABLE_SUFFIX): buildaux/txt2cstr.cpp
buildaux/version.exe: buildaux/version.cpp VERSION
$(HOSTCC) $(HOSTCCFLAGS) -o $@ $<
buildaux/version$(DOT_EXECUTABLE_SUFFIX): buildaux/version.cpp VERSION
$(HOSTCC) $(HOSTCCFLAGS) -o $@ $<
buildaux/mkdeps$(DOT_EXECUTABLE_SUFFIX): buildaux/mkdeps.cpp VERSION
$(HOSTCC) $(HOSTCCFLAGS) -o $@ $< -lboost_filesystem$(HOST_BOOST_POSTFIX) -lboost_system$(HOST_BOOST_POSTFIX)
src/core/version.cpp: buildaux/version$(DOT_EXECUTABLE_SUFFIX) forcelook
buildaux/version$(DOT_EXECUTABLE_SUFFIX) >$@
src/core/version.cpp: buildaux/version.exe forcelook
buildaux/version.exe >$@
platclean:
$(MAKE) -C src platclean
clean:
$(MAKE) -C src clean
rm -f buildaux/version$(DOT_EXECUTABLE_SUFFIX)
rm -f buildaux/mkdeps$(DOT_EXECUTABLE_SUFFIX)
rm -f buildaux/txt2cstr$(DOT_EXECUTABLE_SUFFIX)
forcelook:
@true

3
TODO
View file

@ -1,3 +0,0 @@
- Memory Tracking: Track dynamic state.
- Fix paths and filenames containing non-ASCII on Win32.
- Win64 build.

View file

@ -1 +1 @@
2-β24
2-β12

1
bsnes

@ -1 +0,0 @@
Subproject commit 4cfbbeadc3abe3e3911f7f59ce57b715edc76563

View file

@ -1,7 +1,7 @@
From 831e9614a7babbacf59935960fbaa6cfc8d49c08 Mon Sep 17 00:00:00 2001
From: Ilari Liusvaara <ilari.liusvaara@elisanet.fi>
Date: Wed, 9 Nov 2011 00:30:36 +0200
Subject: [PATCH 01/10] Make libsnes compile
Subject: [PATCH 1/9] Make libsnes compile
Changes between v083 and v084 had broken libsnes. Fix it so it at least
compiles.
@ -78,5 +78,5 @@ index fbb4482..5f5ded6 100755
}
SNES::cartridge.load(SNES::Cartridge::Mode::SuperGameBoy, xmlrom);
--
1.8.4.4
1.8.4.rc3

View file

@ -1,8 +1,7 @@
From df7851648e41ae6b6efd1a54cdcd32ac55a90131 Mon Sep 17 00:00:00 2001
From: Ilari Liusvaara <ilari.liusvaara@elisanet.fi>
Date: Wed, 9 Nov 2011 00:31:59 +0200
Subject: [PATCH 02/10] Fix bsnes version number in libsnes to be v084, not
v083
Subject: [PATCH 2/9] Fix bsnes version number in libsnes to be v084, not v083
---
ui-libsnes/libsnes.cpp | 2 +-
@ -22,5 +21,5 @@ index 5f5ded6..6b4ef12 100755
unsigned snes_library_revision_major(void) {
--
1.8.4.4
1.8.4.rc3

View file

@ -1,7 +1,7 @@
From b481e3d161d924cc5a4449329393c8d9f23b27ec Mon Sep 17 00:00:00 2001
From: Ilari Liusvaara <ilari.liusvaara@elisanet.fi>
Date: Wed, 9 Nov 2011 00:37:44 +0200
Subject: [PATCH 03/10] Don't use time() in emulating chips
Subject: [PATCH 3/9] Don't use time() in emulating chips
Instead of using time() in chip emulation, create new interface method
currentTime(), defaulting to time(0). This way frontend can cleanly
@ -80,5 +80,5 @@ index f1a48c0..df975e8 100755
extern Interface *interface;
--
1.8.4.4
1.8.4.rc3

View file

@ -1,7 +1,7 @@
From af7fdd9f73a3eb5e9266c59bfb4dd676679b2f7d Mon Sep 17 00:00:00 2001
From: Ilari Liusvaara <ilari.liusvaara@elisanet.fi>
Date: Wed, 9 Nov 2011 01:52:08 +0200
Subject: [PATCH 04/10] Save controller state when savestating
Subject: [PATCH 4/9] Save controller state when savestating
When savestating, save the controller state and restore it upon loadstate.
Prevents libsnes from mixing up buttons.
@ -341,5 +341,5 @@ index f7d6f3b..08e7051 100755
if(cartridge.mode() == Cartridge::Mode::SufamiTurbo) sufamiturbo.serialize(s);
if(cartridge.mode() == Cartridge::Mode::SuperGameBoy) icd2.serialize(s);
--
1.8.4.4
1.8.4.rc3

View file

@ -1,7 +1,7 @@
From aa1352516e38ff64f304d8831b357841c4795e43 Mon Sep 17 00:00:00 2001
From: Ilari Liusvaara <ilari.liusvaara@elisanet.fi>
Date: Fri, 11 Nov 2011 03:05:48 +0200
Subject: [PATCH 05/10] Fix unserialization of 64-bit signed integers
Subject: [PATCH 5/9] Fix unserialization of 64-bit signed integers
---
nall/serializer.hpp | 2 +-
@ -21,5 +21,5 @@ index ff2337a..e6bc8fa 100755
isize += size;
}
--
1.8.4.4
1.8.4.rc3

View file

@ -1,7 +1,7 @@
From 794d83cb28a93d9ae1e613598d3c7cf09090d6a3 Mon Sep 17 00:00:00 2001
From: Ilari Liusvaara <ilari.liusvaara@elisanet.fi>
Date: Fri, 11 Nov 2011 19:49:46 +0200
Subject: [PATCH 06/10] Allow frontend to control random number seed
Subject: [PATCH 6/9] Allow frontend to control random number seed
---
snes/interface/interface.cpp | 5 +++++
@ -49,5 +49,5 @@ index 6881810..8583595 100755
region = config.region;
expansion = config.expansion_port;
--
1.8.4.4
1.8.4.rc3

View file

@ -1,7 +1,7 @@
From 4f6981592e29038ad9f818399c0d5a48750cf28a Mon Sep 17 00:00:00 2001
From: Ilari Liusvaara <ilari.liusvaara@elisanet.fi>
Date: Wed, 7 Mar 2012 16:57:18 +0200
Subject: [PATCH 07/10] Fix mouse polling
Subject: [PATCH 7/9] Fix mouse polling
Don't poll for mouse motion excessive number of times (no need to poll it for
each bit!)
@ -59,5 +59,5 @@ index b66ea51..b07c8ab 100755
+ int _position_y;
};
--
1.8.4.4
1.8.4.rc3

View file

@ -1,8 +1,8 @@
From 7b09063fbcaf50c56b476a744f9f3d9634777740 Mon Sep 17 00:00:00 2001
From: Ilari Liusvaara <ilari.liusvaara@elisanet.fi>
Date: Mon, 24 Sep 2012 21:46:09 +0300
Subject: [PATCH 08/10] Add needed support for detecting true polls as opposed
to just autopolling
Subject: [PATCH 8/9] Add needed support for detecting true polls as opposed to
just autopolling
---
snes/cpu/cpu.hpp | 1 +
@ -65,5 +65,5 @@ index 8b6aaa6..c5ee930 100755
//DMAPx
uint8 CPU::mmio_r43x0(uint8 i) {
--
1.8.4.4
1.8.4.rc3

View file

@ -1,7 +1,7 @@
From 62f8a07104b57b75071318098145d99012dbc908 Mon Sep 17 00:00:00 2001
From: Ilari Liusvaara <ilari.liusvaara@elisanet.fi>
Date: Sun, 27 Oct 2013 10:52:45 +0200
Subject: [PATCH 09/10] Support notifying latches
Subject: [PATCH 9/9] Support notifying latches
---
snes/cpu/mmio/mmio.cpp | 1 +
@ -61,5 +61,5 @@ index 30ee7fd..203f7b0 100755
extern Interface *interface;
--
1.8.4.4
1.8.4.rc3

View file

@ -1,22 +0,0 @@
From 242efcc9cf10fa58c8e06f154c41db21e6aa2688 Mon Sep 17 00:00:00 2001
From: Ilari Liusvaara <ilari.liusvaara@elisanet.fi>
Date: Sat, 30 Nov 2013 10:26:59 +0200
Subject: [PATCH 10/10] Add support for auto-detecting bsnes version
---
bsnes.mk | 3 +++
1 file changed, 3 insertions(+)
create mode 100644 bsnes.mk
diff --git a/bsnes.mk b/bsnes.mk
new file mode 100644
index 0000000..11300e2
--- /dev/null
+++ b/bsnes.mk
@@ -0,0 +1,3 @@
+BSNES_SUPPORTS_DEBUGGER=yes
+LIBSNES_DIR=ui-libsnes
+BSNES_VERSION=084
--
1.8.4.4

View file

@ -1,7 +1,7 @@
From b19b3b2d1d7a522af695f4482abb28e52804326b Mon Sep 17 00:00:00 2001
From: Ilari Liusvaara <ilari.liusvaara@elisanet.fi>
Date: Wed, 9 Nov 2011 00:30:36 +0200
Subject: [PATCH 01/27] Make libsnes compile
Subject: [PATCH 01/11] Make libsnes compile
Changes between v083 and v084 had broken libsnes. Fix it so it at least
compiles.
@ -10,7 +10,7 @@ compiles.
1 file changed, 35 insertions(+), 2 deletions(-)
diff --git a/ui-libsnes/libsnes.cpp b/ui-libsnes/libsnes.cpp
index fbb4482c..5f5ded69 100755
index fbb4482..5f5ded6 100755
--- a/ui-libsnes/libsnes.cpp
+++ b/ui-libsnes/libsnes.cpp
@@ -1,5 +1,6 @@
@ -78,5 +78,5 @@ index fbb4482c..5f5ded69 100755
}
SNES::cartridge.load(SNES::Cartridge::Mode::SuperGameBoy, xmlrom);
--
2.15.0.rc1
1.8.4.rc3

View file

@ -1,7 +1,7 @@
From bb2fed04fbfe62a89e4bcfe90f44b4738f7c7c1a Mon Sep 17 00:00:00 2001
From: Ilari Liusvaara <ilari.liusvaara@elisanet.fi>
Date: Wed, 9 Nov 2011 00:31:59 +0200
Subject: [PATCH 02/27] Fix bsnes version number in libsnes to be v085, not
Subject: [PATCH 02/11] Fix bsnes version number in libsnes to be v085, not
v083
---
@ -9,7 +9,7 @@ Subject: [PATCH 02/27] Fix bsnes version number in libsnes to be v085, not
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/ui-libsnes/libsnes.cpp b/ui-libsnes/libsnes.cpp
index 5f5ded69..0e63075e 100755
index 5f5ded6..0e63075 100755
--- a/ui-libsnes/libsnes.cpp
+++ b/ui-libsnes/libsnes.cpp
@@ -112,7 +112,7 @@ struct Interface : public SNES::Interface {
@ -22,5 +22,5 @@ index 5f5ded69..0e63075e 100755
unsigned snes_library_revision_major(void) {
--
2.15.0.rc1
1.8.4.rc3

View file

@ -1,7 +1,7 @@
From 7379b4570e5755a5a1da25181ba4f5d1ca461a98 Mon Sep 17 00:00:00 2001
From: Ilari Liusvaara <ilari.liusvaara@elisanet.fi>
Date: Wed, 9 Nov 2011 00:37:44 +0200
Subject: [PATCH 03/27] Don't use time() in emulating chips
Subject: [PATCH 03/11] Don't use time() in emulating chips
Instead of using time() in chip emulation, create new interface method
currentTime(), defaulting to time(0). This way frontend can cleanly
@ -15,7 +15,7 @@ override the current time bsnes is using.
5 files changed, 9 insertions(+), 3 deletions(-)
diff --git a/snes/chip/bsx/satellaview/satellaview.cpp b/snes/chip/bsx/satellaview/satellaview.cpp
index 386fb628..3c980195 100755
index 386fb62..3c98019 100755
--- a/snes/chip/bsx/satellaview/satellaview.cpp
+++ b/snes/chip/bsx/satellaview/satellaview.cpp
@@ -38,7 +38,7 @@ uint8 BSXSatellaview::mmio_read(unsigned addr) {
@ -28,7 +28,7 @@ index 386fb628..3c980195 100755
regs.r2192_hour = t->tm_hour;
diff --git a/snes/chip/spc7110/spc7110.cpp b/snes/chip/spc7110/spc7110.cpp
index d2dc640b..74a817a6 100755
index d2dc640..74a817a 100755
--- a/snes/chip/spc7110/spc7110.cpp
+++ b/snes/chip/spc7110/spc7110.cpp
@@ -101,7 +101,7 @@ void SPC7110::set_data_adjust(unsigned addr) { r4814 = addr; r4815 = addr >> 8;
@ -41,7 +41,7 @@ index d2dc640b..74a817a6 100755
//sizeof(time_t) is platform-dependent; though rtc[] needs to be platform-agnostic.
//yet platforms with 32-bit signed time_t will overflow every ~68 years. handle this by
diff --git a/snes/chip/srtc/srtc.cpp b/snes/chip/srtc/srtc.cpp
index 1b2fd2aa..78fc4c1f 100755
index 1b2fd2a..78fc4c1 100755
--- a/snes/chip/srtc/srtc.cpp
+++ b/snes/chip/srtc/srtc.cpp
@@ -31,7 +31,7 @@ void SRTC::reset() {
@ -54,7 +54,7 @@ index 1b2fd2aa..78fc4c1f 100755
//sizeof(time_t) is platform-dependent; though rtc[] needs to be platform-agnostic.
//yet platforms with 32-bit signed time_t will overflow every ~68 years. handle this by
diff --git a/snes/interface/interface.cpp b/snes/interface/interface.cpp
index a0e3a81b..b3017c90 100755
index a0e3a81..b3017c9 100755
--- a/snes/interface/interface.cpp
+++ b/snes/interface/interface.cpp
@@ -18,4 +18,9 @@ void Interface::message(const string &text) {
@ -68,7 +68,7 @@ index a0e3a81b..b3017c90 100755
+
}
diff --git a/snes/interface/interface.hpp b/snes/interface/interface.hpp
index f1a48c0f..df975e83 100755
index f1a48c0..df975e8 100755
--- a/snes/interface/interface.hpp
+++ b/snes/interface/interface.hpp
@@ -5,6 +5,7 @@ struct Interface {
@ -80,5 +80,5 @@ index f1a48c0f..df975e83 100755
extern Interface *interface;
--
2.15.0.rc1
1.8.4.rc3

View file

@ -1,7 +1,7 @@
From efe1b5884c316ce070953edd87c6c9aeffffaa94 Mon Sep 17 00:00:00 2001
From: Ilari Liusvaara <ilari.liusvaara@elisanet.fi>
Date: Wed, 9 Nov 2011 01:52:08 +0200
Subject: [PATCH 04/27] Save controller state when savestating
Subject: [PATCH 04/11] Save controller state when savestating
When savestating, save the controller state and restore it upon loadstate.
Prevents libsnes from mixing up buttons.
@ -24,7 +24,7 @@ Prevents libsnes from mixing up buttons.
15 files changed, 142 insertions(+), 3 deletions(-)
diff --git a/snes/controller/controller.cpp b/snes/controller/controller.cpp
index 9091b21b..f254bedb 100755
index 9091b21..f254bed 100755
--- a/snes/controller/controller.cpp
+++ b/snes/controller/controller.cpp
@@ -46,8 +46,16 @@ void Controller::iobit(bool data) {
@ -45,7 +45,7 @@ index 9091b21b..f254bedb 100755
+
}
diff --git a/snes/controller/controller.hpp b/snes/controller/controller.hpp
index 73327129..827b2eb4 100755
index 7332712..827b2eb 100755
--- a/snes/controller/controller.hpp
+++ b/snes/controller/controller.hpp
@@ -13,12 +13,14 @@
@ -64,7 +64,7 @@ index 73327129..827b2eb4 100755
bool iobit();
void iobit(bool data);
diff --git a/snes/controller/gamepad/gamepad.cpp b/snes/controller/gamepad/gamepad.cpp
index 594020d2..4fa1c99e 100755
index 594020d..4fa1c99 100755
--- a/snes/controller/gamepad/gamepad.cpp
+++ b/snes/controller/gamepad/gamepad.cpp
@@ -13,6 +13,19 @@ void Gamepad::latch(bool data) {
@ -88,7 +88,7 @@ index 594020d2..4fa1c99e 100755
latched = 0;
counter = 0;
diff --git a/snes/controller/gamepad/gamepad.hpp b/snes/controller/gamepad/gamepad.hpp
index c5ca69ca..a2392d1e 100755
index c5ca69c..a2392d1 100755
--- a/snes/controller/gamepad/gamepad.hpp
+++ b/snes/controller/gamepad/gamepad.hpp
@@ -2,7 +2,7 @@ struct Gamepad : Controller {
@ -101,7 +101,7 @@ index c5ca69ca..a2392d1e 100755
bool latched;
unsigned counter;
diff --git a/snes/controller/justifier/justifier.cpp b/snes/controller/justifier/justifier.cpp
index 62079166..ad13a9bd 100755
index 6207916..ad13a9b 100755
--- a/snes/controller/justifier/justifier.cpp
+++ b/snes/controller/justifier/justifier.cpp
@@ -100,6 +100,42 @@ void Justifier::latch(bool data) {
@ -148,7 +148,7 @@ index 62079166..ad13a9bd 100755
create(Controller::Enter, 21477272);
latched = 0;
diff --git a/snes/controller/justifier/justifier.hpp b/snes/controller/justifier/justifier.hpp
index f927acf6..6b7bba07 100755
index f927acf..6b7bba0 100755
--- a/snes/controller/justifier/justifier.hpp
+++ b/snes/controller/justifier/justifier.hpp
@@ -2,6 +2,7 @@ struct Justifier : Controller {
@ -160,7 +160,7 @@ index f927acf6..6b7bba07 100755
//private:
diff --git a/snes/controller/mouse/mouse.cpp b/snes/controller/mouse/mouse.cpp
index c9f5d16b..6b26fae5 100755
index c9f5d16..6b26fae 100755
--- a/snes/controller/mouse/mouse.cpp
+++ b/snes/controller/mouse/mouse.cpp
@@ -61,6 +61,19 @@ void Mouse::latch(bool data) {
@ -184,7 +184,7 @@ index c9f5d16b..6b26fae5 100755
latched = 0;
counter = 0;
diff --git a/snes/controller/mouse/mouse.hpp b/snes/controller/mouse/mouse.hpp
index 95e24b65..b66ea513 100755
index 95e24b6..b66ea51 100755
--- a/snes/controller/mouse/mouse.hpp
+++ b/snes/controller/mouse/mouse.hpp
@@ -2,7 +2,7 @@ struct Mouse : Controller {
@ -197,7 +197,7 @@ index 95e24b65..b66ea513 100755
bool latched;
unsigned counter;
diff --git a/snes/controller/multitap/multitap.cpp b/snes/controller/multitap/multitap.cpp
index 3a6eb720..146c41d4 100755
index 3a6eb72..146c41d 100755
--- a/snes/controller/multitap/multitap.cpp
+++ b/snes/controller/multitap/multitap.cpp
@@ -30,6 +30,22 @@ void Multitap::latch(bool data) {
@ -224,7 +224,7 @@ index 3a6eb720..146c41d4 100755
latched = 0;
counter1 = 0;
diff --git a/snes/controller/multitap/multitap.hpp b/snes/controller/multitap/multitap.hpp
index 0540af71..e6324ac5 100755
index 0540af7..e6324ac 100755
--- a/snes/controller/multitap/multitap.hpp
+++ b/snes/controller/multitap/multitap.hpp
@@ -2,7 +2,7 @@ struct Multitap : Controller {
@ -237,7 +237,7 @@ index 0540af71..e6324ac5 100755
bool latched;
unsigned counter1;
diff --git a/snes/controller/superscope/superscope.cpp b/snes/controller/superscope/superscope.cpp
index 12068f05..1a1dfbff 100755
index 12068f0..1a1dfbf 100755
--- a/snes/controller/superscope/superscope.cpp
+++ b/snes/controller/superscope/superscope.cpp
@@ -100,6 +100,37 @@ void SuperScope::latch(bool data) {
@ -279,7 +279,7 @@ index 12068f05..1a1dfbff 100755
create(Controller::Enter, 21477272);
latched = 0;
diff --git a/snes/controller/superscope/superscope.hpp b/snes/controller/superscope/superscope.hpp
index a7a90b71..93509d79 100755
index a7a90b7..93509d7 100755
--- a/snes/controller/superscope/superscope.hpp
+++ b/snes/controller/superscope/superscope.hpp
@@ -2,6 +2,7 @@ struct SuperScope : Controller {
@ -291,7 +291,7 @@ index a7a90b71..93509d79 100755
//private:
diff --git a/snes/system/input.cpp b/snes/system/input.cpp
index 90503106..ec5559dc 100755
index 9050310..ec5559d 100755
--- a/snes/system/input.cpp
+++ b/snes/system/input.cpp
@@ -26,6 +26,22 @@ void Input::connect(bool port, Input::Device id) {
@ -318,7 +318,7 @@ index 90503106..ec5559dc 100755
connect(Controller::Port1, Input::Device::Joypad);
connect(Controller::Port2, Input::Device::Joypad);
diff --git a/snes/system/input.hpp b/snes/system/input.hpp
index 13ef46e1..6832e823 100755
index 13ef46e..6832e82 100755
--- a/snes/system/input.hpp
+++ b/snes/system/input.hpp
@@ -31,6 +31,7 @@ struct Input {
@ -330,7 +330,7 @@ index 13ef46e1..6832e823 100755
Input();
~Input();
diff --git a/snes/system/serialization.cpp b/snes/system/serialization.cpp
index f7d6f3b1..08e70510 100755
index f7d6f3b..08e7051 100755
--- a/snes/system/serialization.cpp
+++ b/snes/system/serialization.cpp
@@ -56,6 +56,7 @@ void System::serialize_all(serializer &s) {
@ -342,5 +342,5 @@ index f7d6f3b1..08e70510 100755
if(cartridge.mode() == Cartridge::Mode::SufamiTurbo) sufamiturbo.serialize(s);
if(cartridge.mode() == Cartridge::Mode::SuperGameBoy) icd2.serialize(s);
--
2.15.0.rc1
1.8.4.rc3

View file

@ -1,14 +1,14 @@
From cdf2f46490f128308eb7f399d03530936ebeda0a Mon Sep 17 00:00:00 2001
From: Ilari Liusvaara <ilari.liusvaara@elisanet.fi>
Date: Fri, 11 Nov 2011 03:05:48 +0200
Subject: [PATCH 05/27] Fix unserialization of 64-bit signed integers
Subject: [PATCH 05/11] Fix unserialization of 64-bit signed integers
---
nall/serializer.hpp | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/nall/serializer.hpp b/nall/serializer.hpp
index ff2337ab..e6bc8fad 100755
index ff2337a..e6bc8fa 100755
--- a/nall/serializer.hpp
+++ b/nall/serializer.hpp
@@ -58,7 +58,7 @@ namespace nall {
@ -21,5 +21,5 @@ index ff2337ab..e6bc8fad 100755
isize += size;
}
--
2.15.0.rc1
1.8.4.rc3

View file

@ -1,7 +1,7 @@
From 4dc46334ec175e26277632fee4aea80768749af9 Mon Sep 17 00:00:00 2001
From: Ilari Liusvaara <ilari.liusvaara@elisanet.fi>
Date: Fri, 11 Nov 2011 19:49:46 +0200
Subject: [PATCH 06/27] Allow frontend to control random number seed
Subject: [PATCH 06/11] Allow frontend to control random number seed
---
snes/interface/interface.cpp | 5 +++++
@ -10,7 +10,7 @@ Subject: [PATCH 06/27] Allow frontend to control random number seed
3 files changed, 7 insertions(+), 1 deletion(-)
diff --git a/snes/interface/interface.cpp b/snes/interface/interface.cpp
index b3017c90..0a21a132 100755
index b3017c9..0a21a13 100755
--- a/snes/interface/interface.cpp
+++ b/snes/interface/interface.cpp
@@ -23,4 +23,9 @@ time_t Interface::currentTime()
@ -24,7 +24,7 @@ index b3017c90..0a21a132 100755
+
}
diff --git a/snes/interface/interface.hpp b/snes/interface/interface.hpp
index df975e83..30ee7fde 100755
index df975e8..30ee7fd 100755
--- a/snes/interface/interface.hpp
+++ b/snes/interface/interface.hpp
@@ -6,6 +6,7 @@ struct Interface {
@ -36,7 +36,7 @@ index df975e83..30ee7fde 100755
extern Interface *interface;
diff --git a/snes/system/system.cpp b/snes/system/system.cpp
index c19a7c51..dbd912d8 100755
index c19a7c5..dbd912d 100755
--- a/snes/system/system.cpp
+++ b/snes/system/system.cpp
@@ -146,7 +146,7 @@ void System::unload() {
@ -49,5 +49,5 @@ index c19a7c51..dbd912d8 100755
region = config.region;
expansion = config.expansion_port;
--
2.15.0.rc1
1.8.4.rc3

View file

@ -1,7 +1,7 @@
From eeaf6dc52d39ca9c150ff61864c11297d200d968 Mon Sep 17 00:00:00 2001
From: Ilari Liusvaara <ilari.liusvaara@elisanet.fi>
Date: Wed, 7 Mar 2012 16:57:18 +0200
Subject: [PATCH 07/27] Fix mouse polling
Subject: [PATCH 07/11] Fix mouse polling
Don't poll for mouse motion excessive number of times (no need to poll it for
each bit!)
@ -11,7 +11,7 @@ each bit!)
2 files changed, 14 insertions(+), 2 deletions(-)
diff --git a/snes/controller/mouse/mouse.cpp b/snes/controller/mouse/mouse.cpp
index 6b26fae5..1a066b98 100755
index 6b26fae..1a066b9 100755
--- a/snes/controller/mouse/mouse.cpp
+++ b/snes/controller/mouse/mouse.cpp
@@ -3,9 +3,13 @@
@ -48,7 +48,7 @@ index 6b26fae5..1a066b98 100755
}
diff --git a/snes/controller/mouse/mouse.hpp b/snes/controller/mouse/mouse.hpp
index b66ea513..b07c8ab7 100755
index b66ea51..b07c8ab 100755
--- a/snes/controller/mouse/mouse.hpp
+++ b/snes/controller/mouse/mouse.hpp
@@ -6,4 +6,6 @@ struct Mouse : Controller {
@ -59,5 +59,5 @@ index b66ea513..b07c8ab7 100755
+ int _position_y;
};
--
2.15.0.rc1
1.8.4.rc3

View file

@ -1,7 +1,7 @@
From 7018377c93553071fc404db872b2746d40ac3bce Mon Sep 17 00:00:00 2001
From: Ilari Liusvaara <ilari.liusvaara@elisanet.fi>
Date: Sat, 1 Sep 2012 11:23:34 +0300
Subject: [PATCH 08/27] Fix uninitialized variables
Subject: [PATCH 08/11] Fix uninitialized variables
These uninitialized variables cause a lot of desyncs in Shadowrun.
---
@ -16,7 +16,7 @@ These uninitialized variables cause a lot of desyncs in Shadowrun.
8 files changed, 38 insertions(+)
diff --git a/snes/alt/dsp/dsp.cpp b/snes/alt/dsp/dsp.cpp
index d0c9e077..c6809f73 100755
index d0c9e07..c6809f7 100755
--- a/snes/alt/dsp/dsp.cpp
+++ b/snes/alt/dsp/dsp.cpp
@@ -40,6 +40,8 @@ void DSP::write(uint8 addr, uint8 data) {
@ -29,7 +29,7 @@ index d0c9e077..c6809f73 100755
spc_dsp.reset();
spc_dsp.set_output(samplebuffer, 8192);
diff --git a/snes/alt/ppu-compatibility/ppu.cpp b/snes/alt/ppu-compatibility/ppu.cpp
index 1a3835b3..a21e5e31 100755
index 1a3835b..a21e5e3 100755
--- a/snes/alt/ppu-compatibility/ppu.cpp
+++ b/snes/alt/ppu-compatibility/ppu.cpp
@@ -345,6 +345,17 @@ void PPU::power() {
@ -51,7 +51,7 @@ index 1a3835b3..a21e5e31 100755
}
diff --git a/snes/cpu/core/core.cpp b/snes/cpu/core/core.cpp
index 427176b0..a5b809b9 100755
index 427176b..a5b809b 100755
--- a/snes/cpu/core/core.cpp
+++ b/snes/cpu/core/core.cpp
@@ -86,4 +86,12 @@ CPUcore::CPUcore() {
@ -68,7 +68,7 @@ index 427176b0..a5b809b9 100755
+
}
diff --git a/snes/cpu/core/core.hpp b/snes/cpu/core/core.hpp
index 964bd128..7a685a8d 100755
index 964bd12..7a685a8 100755
--- a/snes/cpu/core/core.hpp
+++ b/snes/cpu/core/core.hpp
@@ -7,6 +7,8 @@ struct CPUcore {
@ -81,7 +81,7 @@ index 964bd128..7a685a8d 100755
virtual uint8_t op_read(uint32_t addr) = 0;
virtual void op_write(uint32_t addr, uint8_t data) = 0;
diff --git a/snes/cpu/cpu.cpp b/snes/cpu/cpu.cpp
index f6ae9754..2d7d3432 100755
index f6ae975..2d7d343 100755
--- a/snes/cpu/cpu.cpp
+++ b/snes/cpu/cpu.cpp
@@ -125,6 +125,7 @@ void CPU::power() {
@ -93,7 +93,7 @@ index f6ae9754..2d7d3432 100755
void CPU::reset() {
diff --git a/snes/smp/core/core.cpp b/snes/smp/core/core.cpp
index 9c94d00a..2fc29be1 100755
index 9c94d00..2fc29be 100755
--- a/snes/smp/core/core.cpp
+++ b/snes/smp/core/core.cpp
@@ -269,4 +269,15 @@ void SMPcore::op_step() {
@ -113,7 +113,7 @@ index 9c94d00a..2fc29be1 100755
+
}
diff --git a/snes/smp/core/core.hpp b/snes/smp/core/core.hpp
index 6adf6f6b..1489fcef 100755
index 6adf6f6..1489fce 100755
--- a/snes/smp/core/core.hpp
+++ b/snes/smp/core/core.hpp
@@ -11,6 +11,8 @@ struct SMPcore {
@ -126,7 +126,7 @@ index 6adf6f6b..1489fcef 100755
string disassemble_opcode(uint16 addr);
diff --git a/snes/smp/smp.cpp b/snes/smp/smp.cpp
index 90806245..d4ccf425 100755
index 9080624..d4ccf42 100755
--- a/snes/smp/smp.cpp
+++ b/snes/smp/smp.cpp
@@ -53,6 +53,7 @@ void SMP::power() {
@ -138,5 +138,5 @@ index 90806245..d4ccf425 100755
void SMP::reset() {
--
2.15.0.rc1
1.8.4.rc3

View file

@ -1,7 +1,7 @@
From 6e0364c9a86caa71623a188a720b2d68b304b89b Mon Sep 17 00:00:00 2001
From: Ilari Liusvaara <ilari.liusvaara@elisanet.fi>
Date: Mon, 24 Sep 2012 21:46:09 +0300
Subject: [PATCH 09/27] Add needed support for detecting true polls as opposed
Subject: [PATCH 09/11] Add needed support for detecting true polls as opposed
to just autopolling
---
@ -10,7 +10,7 @@ Subject: [PATCH 09/27] Add needed support for detecting true polls as opposed
2 files changed, 11 insertions(+), 8 deletions(-)
diff --git a/snes/cpu/cpu.hpp b/snes/cpu/cpu.hpp
index 3da865e2..49445773 100755
index 3da865e..4944577 100755
--- a/snes/cpu/cpu.hpp
+++ b/snes/cpu/cpu.hpp
@@ -25,6 +25,7 @@ struct CPU : public Processor, public CPUcore, public PPUcounter {
@ -22,7 +22,7 @@ index 3da865e2..49445773 100755
#include "dma/dma.hpp"
#include "memory/memory.hpp"
diff --git a/snes/cpu/mmio/mmio.cpp b/snes/cpu/mmio/mmio.cpp
index 8b6aaa6a..c5ee930f 100755
index 8b6aaa6..c5ee930 100755
--- a/snes/cpu/mmio/mmio.cpp
+++ b/snes/cpu/mmio/mmio.cpp
@@ -42,6 +42,7 @@ void CPU::mmio_w4016(uint8 data) {
@ -65,5 +65,5 @@ index 8b6aaa6a..c5ee930f 100755
//DMAPx
uint8 CPU::mmio_r43x0(uint8 i) {
--
2.15.0.rc1
1.8.4.rc3

View file

@ -1,14 +1,14 @@
From e397bd46f17d6ea00c8c96d5a8e0c5f5b4a6f642 Mon Sep 17 00:00:00 2001
From: Ilari Liusvaara <ilari.liusvaara@elisanet.fi>
Date: Sun, 14 Oct 2012 23:31:36 +0300
Subject: [PATCH 10/27] Fix compiling on GCC 4.7
Subject: [PATCH 10/11] Fix compiling on GCC 4.7
---
nall/string.hpp | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/nall/string.hpp b/nall/string.hpp
index 1b255ce2..07a64dfc 100755
index 1b255ce..07a64df 100755
--- a/nall/string.hpp
+++ b/nall/string.hpp
@@ -25,8 +25,8 @@
@ -22,5 +22,5 @@ index 1b255ce2..07a64dfc 100755
#include <nall/string/convert.hpp>
#include <nall/string/cstring.hpp>
--
2.15.0.rc1
1.8.4.rc3

View file

@ -1,7 +1,7 @@
From e047aa8eb9883f60e4141effba8128a4a555d8be Mon Sep 17 00:00:00 2001
From: Ilari Liusvaara <ilari.liusvaara@elisanet.fi>
Date: Sun, 27 Oct 2013 10:52:45 +0200
Subject: [PATCH 11/27] Support notifying latches
Subject: [PATCH 11/11] Support notifying latches
---
snes/cpu/mmio/mmio.cpp | 1 +
@ -11,7 +11,7 @@ Subject: [PATCH 11/27] Support notifying latches
4 files changed, 8 insertions(+)
diff --git a/snes/cpu/mmio/mmio.cpp b/snes/cpu/mmio/mmio.cpp
index c5ee930f..b7afff00 100755
index c5ee930..b7afff0 100755
--- a/snes/cpu/mmio/mmio.cpp
+++ b/snes/cpu/mmio/mmio.cpp
@@ -33,6 +33,7 @@ void CPU::mmio_w2183(uint8 data) {
@ -23,7 +23,7 @@ index c5ee930f..b7afff00 100755
input.port2->latch(data & 1);
}
diff --git a/snes/cpu/timing/joypad.cpp b/snes/cpu/timing/joypad.cpp
index 179df27d..6a98de00 100755
index 179df27..6a98de0 100755
--- a/snes/cpu/timing/joypad.cpp
+++ b/snes/cpu/timing/joypad.cpp
@@ -9,6 +9,7 @@ void CPU::step_auto_joypad_poll() {
@ -35,7 +35,7 @@ index 179df27d..6a98de00 100755
input.port2->latch(1);
input.port1->latch(0);
diff --git a/snes/interface/interface.cpp b/snes/interface/interface.cpp
index 0a21a132..6685556c 100755
index 0a21a13..6685556 100755
--- a/snes/interface/interface.cpp
+++ b/snes/interface/interface.cpp
@@ -28,4 +28,9 @@ time_t Interface::randomSeed()
@ -49,7 +49,7 @@ index 0a21a132..6685556c 100755
+
}
diff --git a/snes/interface/interface.hpp b/snes/interface/interface.hpp
index 30ee7fde..203f7b0c 100755
index 30ee7fd..203f7b0 100755
--- a/snes/interface/interface.hpp
+++ b/snes/interface/interface.hpp
@@ -7,6 +7,7 @@ struct Interface {
@ -61,5 +61,5 @@ index 30ee7fde..203f7b0c 100755
extern Interface *interface;
--
2.15.0.rc1
1.8.4.rc3

View file

@ -1,799 +0,0 @@
From a5b380757b086e3a00b47fe14e2a63c74683e8da Mon Sep 17 00:00:00 2001
From: Ilari Liusvaara <ilari.liusvaara@elisanet.fi>
Date: Thu, 28 Nov 2013 22:36:29 +0200
Subject: [PATCH 12/27] Support unlimited number of breakpoints
---
snes/alt/cpu/cpu.cpp | 22 +++++++-------
snes/alt/ppu-compatibility/ppu.cpp | 4 +--
snes/alt/ppu-parallel/ppu.cpp | 4 +--
snes/alt/ppu-performance/ppu.cpp | 4 +--
snes/cartridge/cartridge.hpp | 17 +++++++++++
snes/cartridge/markup.cpp | 11 +++++++
snes/cheat/cheat.cpp | 11 ++++---
snes/cheat/cheat.hpp | 1 +
snes/chip/bsx/satellaview/satellaview.cpp | 4 +--
snes/chip/hitachidsp/hitachidsp.cpp | 2 +-
snes/chip/hitachidsp/memory.cpp | 2 +-
snes/chip/nss/nss.cpp | 4 +--
snes/chip/sa1/memory/memory.cpp | 2 +-
snes/chip/sa1/memory/memory.hpp | 2 +-
snes/chip/sa1/sa1.cpp | 2 +-
snes/chip/sdd1/sdd1.cpp | 4 +--
snes/cpu/core/core.hpp | 2 +-
snes/cpu/core/disassembler/disassembler.cpp | 2 +-
snes/cpu/core/memory.hpp | 2 +-
snes/cpu/cpu.cpp | 26 ++++++++--------
snes/cpu/debugger/debugger.cpp | 4 +--
snes/cpu/debugger/debugger.hpp | 2 +-
snes/cpu/dma/dma.cpp | 4 +--
snes/cpu/memory/memory.cpp | 4 +--
snes/cpu/memory/memory.hpp | 2 +-
snes/cpu/mmio/mmio.cpp | 2 +-
snes/debugger/debugger.cpp | 2 +-
snes/memory/memory-inline.hpp | 21 +++++++++++--
snes/memory/memory.cpp | 47 ++++++++++++++++++++++++++---
snes/memory/memory.hpp | 13 +++++++-
snes/ppu/ppu.cpp | 4 +--
snes/smp/core/core.hpp | 2 +-
snes/snes.hpp | 1 +
33 files changed, 166 insertions(+), 70 deletions(-)
diff --git a/snes/alt/cpu/cpu.cpp b/snes/alt/cpu/cpu.cpp
index 814908d0..dcbb92d3 100755
--- a/snes/alt/cpu/cpu.cpp
+++ b/snes/alt/cpu/cpu.cpp
@@ -89,24 +89,24 @@ void CPU::enable() {
function<uint8 (unsigned)> read = { &CPU::mmio_read, (CPU*)&cpu };
function<void (unsigned, uint8)> write = { &CPU::mmio_write, (CPU*)&cpu };
- bus.map(Bus::MapMode::Direct, 0x00, 0x3f, 0x2140, 0x2183, read, write);
- bus.map(Bus::MapMode::Direct, 0x80, 0xbf, 0x2140, 0x2183, read, write);
+ bus.map(Bus::MapMode::Direct, 0x00, 0x3f, 0x2140, 0x2183, 0, read, write);
+ bus.map(Bus::MapMode::Direct, 0x80, 0xbf, 0x2140, 0x2183, 0, read, write);
- bus.map(Bus::MapMode::Direct, 0x00, 0x3f, 0x4016, 0x4017, read, write);
- bus.map(Bus::MapMode::Direct, 0x80, 0xbf, 0x4016, 0x4017, read, write);
+ bus.map(Bus::MapMode::Direct, 0x00, 0x3f, 0x4016, 0x4017, 0, read, write);
+ bus.map(Bus::MapMode::Direct, 0x80, 0xbf, 0x4016, 0x4017, 0, read, write);
- bus.map(Bus::MapMode::Direct, 0x00, 0x3f, 0x4200, 0x421f, read, write);
- bus.map(Bus::MapMode::Direct, 0x80, 0xbf, 0x4200, 0x421f, read, write);
+ bus.map(Bus::MapMode::Direct, 0x00, 0x3f, 0x4200, 0x421f, 0, read, write);
+ bus.map(Bus::MapMode::Direct, 0x80, 0xbf, 0x4200, 0x421f, 0, read, write);
- bus.map(Bus::MapMode::Direct, 0x00, 0x3f, 0x4300, 0x437f, read, write);
- bus.map(Bus::MapMode::Direct, 0x80, 0xbf, 0x4300, 0x437f, read, write);
+ bus.map(Bus::MapMode::Direct, 0x00, 0x3f, 0x4300, 0x437f, 0, read, write);
+ bus.map(Bus::MapMode::Direct, 0x80, 0xbf, 0x4300, 0x437f, 0, read, write);
read = [](unsigned addr) { return cpu.wram[addr]; };
write = [](unsigned addr, uint8 data) { cpu.wram[addr] = data; };
- bus.map(Bus::MapMode::Linear, 0x00, 0x3f, 0x0000, 0x1fff, read, write, 0x000000, 0x002000);
- bus.map(Bus::MapMode::Linear, 0x80, 0xbf, 0x0000, 0x1fff, read, write, 0x000000, 0x002000);
- bus.map(Bus::MapMode::Linear, 0x7e, 0x7f, 0x0000, 0xffff, read, write);
+ bus.map(Bus::MapMode::Linear, 0x00, 0x3f, 0x0000, 0x1fff, 3, read, write, 0x000000, 0x002000);
+ bus.map(Bus::MapMode::Linear, 0x80, 0xbf, 0x0000, 0x1fff, 3, read, write, 0x000000, 0x002000);
+ bus.map(Bus::MapMode::Linear, 0x7e, 0x7f, 0x0000, 0xffff, 3, read, write);
}
void CPU::power() {
diff --git a/snes/alt/ppu-compatibility/ppu.cpp b/snes/alt/ppu-compatibility/ppu.cpp
index a21e5e31..122b1430 100755
--- a/snes/alt/ppu-compatibility/ppu.cpp
+++ b/snes/alt/ppu-compatibility/ppu.cpp
@@ -126,8 +126,8 @@ void PPU::enable() {
function<uint8 (unsigned)> read = { &PPU::mmio_read, (PPU*)&ppu };
function<void (unsigned, uint8)> write = { &PPU::mmio_write, (PPU*)&ppu };
- bus.map(Bus::MapMode::Direct, 0x00, 0x3f, 0x2100, 0x213f, read, write);
- bus.map(Bus::MapMode::Direct, 0x80, 0xbf, 0x2100, 0x213f, read, write);
+ bus.map(Bus::MapMode::Direct, 0x00, 0x3f, 0x2100, 0x213f, 0, read, write);
+ bus.map(Bus::MapMode::Direct, 0x80, 0xbf, 0x2100, 0x213f, 0, read, write);
}
void PPU::power() {
diff --git a/snes/alt/ppu-parallel/ppu.cpp b/snes/alt/ppu-parallel/ppu.cpp
index 1c3dcb70..8dd118b2 100755
--- a/snes/alt/ppu-parallel/ppu.cpp
+++ b/snes/alt/ppu-parallel/ppu.cpp
@@ -36,8 +36,8 @@ void PPU::frame() {
}
void PPU::enable() {
- bus.map(Bus::MapMode::Direct, 0x00, 0x3f, 0x2100, 0x213f, { &PPU::mmio_read, this }, { &PPU::mmio_write, this });
- bus.map(Bus::MapMode::Direct, 0x80, 0xbf, 0x2100, 0x213f, { &PPU::mmio_read, this }, { &PPU::mmio_write, this });
+ bus.map(Bus::MapMode::Direct, 0x00, 0x3f, 0x2100, 0x213f, 0, { &PPU::mmio_read, this }, { &PPU::mmio_write, this });
+ bus.map(Bus::MapMode::Direct, 0x80, 0xbf, 0x2100, 0x213f, 0, { &PPU::mmio_read, this }, { &PPU::mmio_write, this });
}
void PPU::power() {
diff --git a/snes/alt/ppu-performance/ppu.cpp b/snes/alt/ppu-performance/ppu.cpp
index 7c231bc0..4b2b2948 100755
--- a/snes/alt/ppu-performance/ppu.cpp
+++ b/snes/alt/ppu-performance/ppu.cpp
@@ -90,8 +90,8 @@ void PPU::enable() {
function<uint8 (unsigned)> read = { &PPU::mmio_read, (PPU*)&ppu };
function<void (unsigned, uint8)> write = { &PPU::mmio_write, (PPU*)&ppu };
- bus.map(Bus::MapMode::Direct, 0x00, 0x3f, 0x2100, 0x213f, read, write);
- bus.map(Bus::MapMode::Direct, 0x80, 0xbf, 0x2100, 0x213f, read, write);
+ bus.map(Bus::MapMode::Direct, 0x00, 0x3f, 0x2100, 0x213f, 0, read, write);
+ bus.map(Bus::MapMode::Direct, 0x80, 0xbf, 0x2100, 0x213f, 0, read, write);
}
void PPU::power() {
diff --git a/snes/cartridge/cartridge.hpp b/snes/cartridge/cartridge.hpp
index 37555bc0..82e73c4c 100755
--- a/snes/cartridge/cartridge.hpp
+++ b/snes/cartridge/cartridge.hpp
@@ -12,6 +12,22 @@ struct Cartridge : property<Cartridge> {
PAL,
};
+ enum class MemoryClass : unsigned {
+ MISC = 0,
+ ROM = 1,
+ SRAM = 2,
+ WRAM = 3,
+ SUPERFXROM = 4,
+ SUPERFXRAM = 5,
+ SA1IRAM = 6,
+ SA1BWRAM = 7,
+ SUFAMITURBO_ROMA = 8,
+ SUFAMITURBO_ROMB = 9,
+ SUFAMITURBO_RAMA = 10,
+ SUFAMITURBO_RAMB = 11,
+ BSXFLASH = 12,
+ };
+
enum class Slot : unsigned {
Base,
Bsx,
@@ -68,6 +84,7 @@ struct Cartridge : property<Cartridge> {
unsigned addrhi;
unsigned offset;
unsigned size;
+ MemoryClass clazz;
Mapping();
Mapping(const function<uint8 (unsigned)>&, const function<void (unsigned, uint8)>&);
diff --git a/snes/cartridge/markup.cpp b/snes/cartridge/markup.cpp
index e639fe52..2dd0d646 100755
--- a/snes/cartridge/markup.cpp
+++ b/snes/cartridge/markup.cpp
@@ -74,6 +74,7 @@ void Cartridge::parse_markup_rom(XML::Node &root) {
for(auto &node : root) {
if(node.name != "map") continue;
Mapping m(rom);
+ m.clazz = MemoryClass::ROM;
parse_markup_map(m, node);
if(m.size == 0) m.size = rom.size();
mapping.append(m);
@@ -85,6 +86,7 @@ void Cartridge::parse_markup_ram(XML::Node &root) {
ram_size = parse_markup_integer(root["size"].data);
for(auto &node : root) {
Mapping m(ram);
+ m.clazz = MemoryClass::SRAM;
parse_markup_map(m, node);
if(m.size == 0) m.size = ram_size;
mapping.append(m);
@@ -133,6 +135,7 @@ void Cartridge::parse_markup_superfx(XML::Node &root) {
for(auto &leaf : node) {
if(leaf.name != "map") continue;
Mapping m(superfx.rom);
+ //m.clazz = MemoryClass::SUPERFXROM; -- Aliases ROM.
parse_markup_map(m, leaf);
mapping.append(m);
}
@@ -145,6 +148,7 @@ void Cartridge::parse_markup_superfx(XML::Node &root) {
}
if(leaf.name != "map") continue;
Mapping m(superfx.ram);
+ //m.clazz = MemoryClass::SUPERFXRAM; -- Aliases SRAM.
parse_markup_map(m, leaf);
if(m.size == 0) m.size = ram_size;
mapping.append(m);
@@ -188,6 +192,7 @@ void Cartridge::parse_markup_sa1(XML::Node &root) {
for(auto &node : iram) {
if(node.name != "map") continue;
Mapping m(sa1.cpuiram);
+ m.clazz = MemoryClass::SA1IRAM;
parse_markup_map(m, node);
if(m.size == 0) m.size = 2048;
mapping.append(m);
@@ -197,6 +202,7 @@ void Cartridge::parse_markup_sa1(XML::Node &root) {
for(auto &node : bwram) {
if(node.name != "map") continue;
Mapping m(sa1.cpubwram);
+ //m.clazz = MemoryClass::SA1BWRAM; -- Aliases SRAM
parse_markup_map(m, node);
if(m.size == 0) m.size = ram_size;
mapping.append(m);
@@ -341,6 +347,7 @@ void Cartridge::parse_markup_bsx(XML::Node &root) {
for(auto &node : root["slot"]) {
if(node.name != "map") continue;
Mapping m(bsxflash.memory);
+ m.clazz = MemoryClass::BSXFLASH;
parse_markup_map(m, node);
mapping.append(m);
}
@@ -373,6 +380,7 @@ void Cartridge::parse_markup_sufamiturbo(XML::Node &root) {
if(leaf.name != "map") continue;
Memory &memory = slotid == 0 ? sufamiturbo.slotA.rom : sufamiturbo.slotB.rom;
Mapping m(memory);
+ m.clazz = slotid ? MemoryClass::SUFAMITURBO_ROMB : MemoryClass::SUFAMITURBO_ROMA;
parse_markup_map(m, leaf);
if(m.size == 0) m.size = memory.size();
if(m.size) mapping.append(m);
@@ -384,6 +392,7 @@ void Cartridge::parse_markup_sufamiturbo(XML::Node &root) {
if(leaf.name != "map") continue;
Memory &memory = slotid == 0 ? sufamiturbo.slotA.ram : sufamiturbo.slotB.ram;
Mapping m(memory);
+ m.clazz = slotid ? MemoryClass::SUFAMITURBO_RAMB : MemoryClass::SUFAMITURBO_RAMA;
parse_markup_map(m, leaf);
if(m.size == 0) m.size = ram_size;
if(m.size) mapping.append(m);
@@ -536,11 +545,13 @@ void Cartridge::parse_markup_link(XML::Node &root) {
}
Cartridge::Mapping::Mapping() {
+ clazz = MemoryClass::MISC;
mode = Bus::MapMode::Direct;
banklo = bankhi = addrlo = addrhi = offset = size = 0;
}
Cartridge::Mapping::Mapping(Memory &memory) {
+ clazz = MemoryClass::MISC;
read = { &Memory::read, &memory };
write = { &Memory::write, &memory };
mode = Bus::MapMode::Direct;
diff --git a/snes/cheat/cheat.cpp b/snes/cheat/cheat.cpp
index 46c42d1c..3a269cc5 100755
--- a/snes/cheat/cheat.cpp
+++ b/snes/cheat/cheat.cpp
@@ -21,9 +21,9 @@ void Cheat::synchronize() {
for(unsigned i = 0; i < size(); i++) {
const CheatCode &code = operator[](i);
- unsigned addr = mirror(code.addr);
+ unsigned addr = code.nomirror ? code.addr : mirror(code.addr);
override[addr] = true;
- if((addr & 0xffe000) == 0x7e0000) {
+ if(!code.nomirror && (addr & 0xffe000) == 0x7e0000) {
//mirror $7e:0000-1fff to $00-3f|80-bf:0000-1fff
unsigned mirroraddr;
for(unsigned x = 0; x <= 0x3f; x++) {
@@ -40,11 +40,14 @@ void Cheat::synchronize() {
}
uint8 Cheat::read(unsigned addr) const {
- addr = mirror(addr);
+ unsigned raddr = mirror(addr);
for(unsigned i = 0; i < size(); i++) {
const CheatCode &code = operator[](i);
- if(addr == mirror(code.addr)) {
+ if(!code.nomirror && addr == mirror(code.addr)) {
+ return code.data;
+ }
+ if(code.nomirror && raddr == code.addr) {
return code.data;
}
}
diff --git a/snes/cheat/cheat.hpp b/snes/cheat/cheat.hpp
index 306b99b1..b4d2a42e 100755
--- a/snes/cheat/cheat.hpp
+++ b/snes/cheat/cheat.hpp
@@ -1,6 +1,7 @@
struct CheatCode {
unsigned addr;
unsigned data;
+ bool nomirror;
};
struct Cheat : public linear_vector<CheatCode> {
diff --git a/snes/chip/bsx/satellaview/satellaview.cpp b/snes/chip/bsx/satellaview/satellaview.cpp
index 3c980195..25af8e56 100755
--- a/snes/chip/bsx/satellaview/satellaview.cpp
+++ b/snes/chip/bsx/satellaview/satellaview.cpp
@@ -6,8 +6,8 @@ void BSXSatellaview::init() {
}
void BSXSatellaview::load() {
- bus.map(Bus::MapMode::Direct, 0x00, 0x3f, 0x2188, 0x219f, { &BSXSatellaview::mmio_read, &bsxsatellaview }, { &BSXSatellaview::mmio_write, &bsxsatellaview });
- bus.map(Bus::MapMode::Direct, 0x80, 0xbf, 0x2188, 0x219f, { &BSXSatellaview::mmio_read, &bsxsatellaview }, { &BSXSatellaview::mmio_write, &bsxsatellaview });
+ bus.map(Bus::MapMode::Direct, 0x00, 0x3f, 0x2188, 0x219f, 0, { &BSXSatellaview::mmio_read, &bsxsatellaview }, { &BSXSatellaview::mmio_write, &bsxsatellaview });
+ bus.map(Bus::MapMode::Direct, 0x80, 0xbf, 0x2188, 0x219f, 0, { &BSXSatellaview::mmio_read, &bsxsatellaview }, { &BSXSatellaview::mmio_write, &bsxsatellaview });
}
void BSXSatellaview::unload() {
diff --git a/snes/chip/hitachidsp/hitachidsp.cpp b/snes/chip/hitachidsp/hitachidsp.cpp
index 1042267e..3e5c5bdb 100755
--- a/snes/chip/hitachidsp/hitachidsp.cpp
+++ b/snes/chip/hitachidsp/hitachidsp.cpp
@@ -23,7 +23,7 @@ void HitachiDSP::enter() {
break;
case State::DMA:
for(unsigned n = 0; n < regs.dma_length; n++) {
- bus.write(regs.dma_target + n, bus.read(regs.dma_source + n));
+ bus.write(regs.dma_target + n, bus.read(regs.dma_source + n, false));
step(2);
}
state = State::Idle;
diff --git a/snes/chip/hitachidsp/memory.cpp b/snes/chip/hitachidsp/memory.cpp
index 3c9c3af1..36868e88 100755
--- a/snes/chip/hitachidsp/memory.cpp
+++ b/snes/chip/hitachidsp/memory.cpp
@@ -1,7 +1,7 @@
#ifdef HITACHIDSP_CPP
uint8 HitachiDSP::bus_read(unsigned addr) {
- if((addr & 0x408000) == 0x008000) return bus.read(addr);
+ if((addr & 0x408000) == 0x008000) return bus.read(addr, false);
return 0x00;
}
diff --git a/snes/chip/nss/nss.cpp b/snes/chip/nss/nss.cpp
index 964973d0..5946af3b 100755
--- a/snes/chip/nss/nss.cpp
+++ b/snes/chip/nss/nss.cpp
@@ -10,8 +10,8 @@ void NSS::init() {
void NSS::load() {
dip = 0x0000;
- bus.map(Bus::MapMode::Direct, 0x00, 0x3f, 0x4100, 0x4101, { &NSS::read, this }, { &NSS::write, this });
- bus.map(Bus::MapMode::Direct, 0x80, 0xbf, 0x4100, 0x4101, { &NSS::read, this }, { &NSS::write, this });
+ bus.map(Bus::MapMode::Direct, 0x00, 0x3f, 0x4100, 0x4101, 0, { &NSS::read, this }, { &NSS::write, this });
+ bus.map(Bus::MapMode::Direct, 0x80, 0xbf, 0x4100, 0x4101, 0, { &NSS::read, this }, { &NSS::write, this });
}
void NSS::unload() {
diff --git a/snes/chip/sa1/memory/memory.cpp b/snes/chip/sa1/memory/memory.cpp
index d13ac929..9bb4ff20 100755
--- a/snes/chip/sa1/memory/memory.cpp
+++ b/snes/chip/sa1/memory/memory.cpp
@@ -107,7 +107,7 @@ void SA1::op_io() {
tick();
}
-uint8 SA1::op_read(unsigned addr) {
+uint8 SA1::op_read(unsigned addr, bool exec) {
tick();
if(((addr & 0x40e000) == 0x006000) || ((addr & 0xd00000) == 0x400000)) tick();
return bus_read(addr);
diff --git a/snes/chip/sa1/memory/memory.hpp b/snes/chip/sa1/memory/memory.hpp
index ffb9e9f6..ab8e1edd 100755
--- a/snes/chip/sa1/memory/memory.hpp
+++ b/snes/chip/sa1/memory/memory.hpp
@@ -3,7 +3,7 @@ void bus_write(unsigned addr, uint8 data);
uint8 vbr_read(unsigned addr);
alwaysinline void op_io();
-alwaysinline uint8 op_read(unsigned addr);
+alwaysinline uint8 op_read(unsigned addr, bool exec);
alwaysinline void op_write(unsigned addr, uint8 data);
uint8 mmc_read(unsigned addr);
diff --git a/snes/chip/sa1/sa1.cpp b/snes/chip/sa1/sa1.cpp
index 71c6310a..30e00809 100755
--- a/snes/chip/sa1/sa1.cpp
+++ b/snes/chip/sa1/sa1.cpp
@@ -37,7 +37,7 @@ void SA1::enter() {
}
void SA1::op_irq() {
- op_read(regs.pc.d);
+ op_read(regs.pc.d, false);
op_io();
if(!regs.e) op_writestack(regs.pc.b);
op_writestack(regs.pc.h);
diff --git a/snes/chip/sdd1/sdd1.cpp b/snes/chip/sdd1/sdd1.cpp
index c9b8b1c4..5d6cc55f 100755
--- a/snes/chip/sdd1/sdd1.cpp
+++ b/snes/chip/sdd1/sdd1.cpp
@@ -14,8 +14,8 @@ void SDD1::init() {
void SDD1::load() {
//hook S-CPU DMA MMIO registers to gather information for struct dma[];
//buffer address and transfer size information for use in SDD1::mcu_read()
- bus.map(Bus::MapMode::Direct, 0x00, 0x3f, 0x4300, 0x437f, { &SDD1::mmio_read, &sdd1 }, { &SDD1::mmio_write, &sdd1 });
- bus.map(Bus::MapMode::Direct, 0x80, 0xbf, 0x4300, 0x437f, { &SDD1::mmio_read, &sdd1 }, { &SDD1::mmio_write, &sdd1 });
+ bus.map(Bus::MapMode::Direct, 0x00, 0x3f, 0x4300, 0x437f, 0, { &SDD1::mmio_read, &sdd1 }, { &SDD1::mmio_write, &sdd1 });
+ bus.map(Bus::MapMode::Direct, 0x80, 0xbf, 0x4300, 0x437f, 0, { &SDD1::mmio_read, &sdd1 }, { &SDD1::mmio_write, &sdd1 });
}
void SDD1::unload() {
diff --git a/snes/cpu/core/core.hpp b/snes/cpu/core/core.hpp
index 7a685a8d..9d77f3c5 100755
--- a/snes/cpu/core/core.hpp
+++ b/snes/cpu/core/core.hpp
@@ -10,7 +10,7 @@ struct CPUcore {
void powercycle();
virtual void op_io() = 0;
- virtual uint8_t op_read(uint32_t addr) = 0;
+ virtual uint8_t op_read(uint32_t addr, bool exec = false) = 0;
virtual void op_write(uint32_t addr, uint8_t data) = 0;
virtual void last_cycle() = 0;
virtual bool interrupt_pending() = 0;
diff --git a/snes/cpu/core/disassembler/disassembler.cpp b/snes/cpu/core/disassembler/disassembler.cpp
index 030b3ab5..ab8dde24 100755
--- a/snes/cpu/core/disassembler/disassembler.cpp
+++ b/snes/cpu/core/disassembler/disassembler.cpp
@@ -6,7 +6,7 @@ uint8 CPUcore::dreadb(uint32 addr) {
//do not read MMIO registers within debugger
return 0x00;
}
- return bus.read(addr);
+ return bus.read(addr, false);
}
uint16 CPUcore::dreadw(uint32 addr) {
diff --git a/snes/cpu/core/memory.hpp b/snes/cpu/core/memory.hpp
index 49926578..132501c1 100755
--- a/snes/cpu/core/memory.hpp
+++ b/snes/cpu/core/memory.hpp
@@ -1,5 +1,5 @@
alwaysinline uint8_t op_readpc() {
- return op_read((regs.pc.b << 16) + regs.pc.w++);
+ return op_read((regs.pc.b << 16) + regs.pc.w++, true);
}
alwaysinline uint8_t op_readstack() {
diff --git a/snes/cpu/cpu.cpp b/snes/cpu/cpu.cpp
index 2d7d3432..39da6b16 100755
--- a/snes/cpu/cpu.cpp
+++ b/snes/cpu/cpu.cpp
@@ -78,8 +78,8 @@ void CPU::enter() {
} else if(status.reset_pending) {
status.reset_pending = false;
add_clocks(186);
- regs.pc.l = bus.read(0xfffc);
- regs.pc.h = bus.read(0xfffd);
+ regs.pc.l = bus.read(0xfffc, false);
+ regs.pc.h = bus.read(0xfffd, false);
}
}
@@ -95,24 +95,24 @@ void CPU::enable() {
function<uint8 (unsigned)> read = { &CPU::mmio_read, (CPU*)&cpu };
function<void (unsigned, uint8)> write = { &CPU::mmio_write, (CPU*)&cpu };
- bus.map(Bus::MapMode::Direct, 0x00, 0x3f, 0x2140, 0x2183, read, write);
- bus.map(Bus::MapMode::Direct, 0x80, 0xbf, 0x2140, 0x2183, read, write);
+ bus.map(Bus::MapMode::Direct, 0x00, 0x3f, 0x2140, 0x2183, 0, read, write);
+ bus.map(Bus::MapMode::Direct, 0x80, 0xbf, 0x2140, 0x2183, 0, read, write);
- bus.map(Bus::MapMode::Direct, 0x00, 0x3f, 0x4016, 0x4017, read, write);
- bus.map(Bus::MapMode::Direct, 0x80, 0xbf, 0x4016, 0x4017, read, write);
+ bus.map(Bus::MapMode::Direct, 0x00, 0x3f, 0x4016, 0x4017, 0, read, write);
+ bus.map(Bus::MapMode::Direct, 0x80, 0xbf, 0x4016, 0x4017, 0, read, write);
- bus.map(Bus::MapMode::Direct, 0x00, 0x3f, 0x4200, 0x421f, read, write);
- bus.map(Bus::MapMode::Direct, 0x80, 0xbf, 0x4200, 0x421f, read, write);
+ bus.map(Bus::MapMode::Direct, 0x00, 0x3f, 0x4200, 0x421f, 0, read, write);
+ bus.map(Bus::MapMode::Direct, 0x80, 0xbf, 0x4200, 0x421f, 0, read, write);
- bus.map(Bus::MapMode::Direct, 0x00, 0x3f, 0x4300, 0x437f, read, write);
- bus.map(Bus::MapMode::Direct, 0x80, 0xbf, 0x4300, 0x437f, read, write);
+ bus.map(Bus::MapMode::Direct, 0x00, 0x3f, 0x4300, 0x437f, 0, read, write);
+ bus.map(Bus::MapMode::Direct, 0x80, 0xbf, 0x4300, 0x437f, 0, read, write);
read = [](unsigned addr) { return cpu.wram[addr]; };
write = [](unsigned addr, uint8 data) { cpu.wram[addr] = data; };
- bus.map(Bus::MapMode::Linear, 0x00, 0x3f, 0x0000, 0x1fff, read, write, 0x000000, 0x002000);
- bus.map(Bus::MapMode::Linear, 0x80, 0xbf, 0x0000, 0x1fff, read, write, 0x000000, 0x002000);
- bus.map(Bus::MapMode::Linear, 0x7e, 0x7f, 0x0000, 0xffff, read, write);
+ bus.map(Bus::MapMode::Linear, 0x00, 0x3f, 0x0000, 0x1fff, 3, read, write, 0x000000, 0x002000);
+ bus.map(Bus::MapMode::Linear, 0x80, 0xbf, 0x0000, 0x1fff, 3, read, write, 0x000000, 0x002000);
+ bus.map(Bus::MapMode::Linear, 0x7e, 0x7f, 0x0000, 0xffff, 3, read, write);
}
void CPU::power() {
diff --git a/snes/cpu/debugger/debugger.cpp b/snes/cpu/debugger/debugger.cpp
index a33518ed..8301bdb6 100755
--- a/snes/cpu/debugger/debugger.cpp
+++ b/snes/cpu/debugger/debugger.cpp
@@ -19,8 +19,8 @@ void CPUDebugger::op_step() {
synchronize_smp();
}
-uint8 CPUDebugger::op_read(uint32 addr) {
- uint8 data = CPU::op_read(addr);
+uint8 CPUDebugger::op_read(uint32 addr, bool exec) {
+ uint8 data = CPU::op_read(addr, exec);
usage[addr] |= UsageRead;
debugger.breakpoint_test(Debugger::Breakpoint::Source::CPUBus, Debugger::Breakpoint::Mode::Read, addr, data);
return data;
diff --git a/snes/cpu/debugger/debugger.hpp b/snes/cpu/debugger/debugger.hpp
index 579f6f03..c3d66db5 100755
--- a/snes/cpu/debugger/debugger.hpp
+++ b/snes/cpu/debugger/debugger.hpp
@@ -16,7 +16,7 @@ public:
bool opcode_edge; //true right before an opcode execues, used to skip over opcodes
void op_step();
- uint8 op_read(uint32 addr);
+ uint8 op_read(uint32 addr, bool exec = false);
void op_write(uint32 addr, uint8 data);
CPUDebugger();
diff --git a/snes/cpu/dma/dma.cpp b/snes/cpu/dma/dma.cpp
index e8cdb3ec..0a00bfea 100755
--- a/snes/cpu/dma/dma.cpp
+++ b/snes/cpu/dma/dma.cpp
@@ -26,7 +26,7 @@ bool CPU::dma_addr_valid(uint32 abus) {
uint8 CPU::dma_read(uint32 abus) {
if(dma_addr_valid(abus) == false) return 0x00;
- return bus.read(abus);
+ return bus.read(abus, false);
}
//simulate two-stage pipeline for DMA transfers; example:
@@ -49,7 +49,7 @@ void CPU::dma_transfer(bool direction, uint8 bbus, uint32 abus) {
dma_write(dma_transfer_valid(bbus, abus), 0x2100 | bbus, regs.mdr);
} else {
dma_add_clocks(4);
- regs.mdr = dma_transfer_valid(bbus, abus) ? bus.read(0x2100 | bbus) : 0x00;
+ regs.mdr = dma_transfer_valid(bbus, abus) ? bus.read(0x2100 | bbus, false) : 0x00;
dma_add_clocks(4);
dma_write(dma_addr_valid(abus), abus, regs.mdr);
}
diff --git a/snes/cpu/memory/memory.cpp b/snes/cpu/memory/memory.cpp
index c2c8f1fa..31f82c31 100755
--- a/snes/cpu/memory/memory.cpp
+++ b/snes/cpu/memory/memory.cpp
@@ -10,11 +10,11 @@ void CPU::op_io() {
alu_edge();
}
-uint8 CPU::op_read(uint32 addr) {
+uint8 CPU::op_read(uint32 addr, bool exec) {
status.clock_count = speed(addr);
dma_edge();
add_clocks(status.clock_count - 4);
- regs.mdr = bus.read(addr);
+ regs.mdr = bus.read(addr, exec);
add_clocks(4);
alu_edge();
return regs.mdr;
diff --git a/snes/cpu/memory/memory.hpp b/snes/cpu/memory/memory.hpp
index d33861d4..fd64ba8b 100755
--- a/snes/cpu/memory/memory.hpp
+++ b/snes/cpu/memory/memory.hpp
@@ -1,4 +1,4 @@
void op_io();
-debugvirtual uint8 op_read(uint32 addr);
+debugvirtual uint8 op_read(uint32 addr, bool exec);
debugvirtual void op_write(uint32 addr, uint8 data);
alwaysinline unsigned speed(unsigned addr) const;
diff --git a/snes/cpu/mmio/mmio.cpp b/snes/cpu/mmio/mmio.cpp
index b7afff00..30048c19 100755
--- a/snes/cpu/mmio/mmio.cpp
+++ b/snes/cpu/mmio/mmio.cpp
@@ -5,7 +5,7 @@ bool CPU::joylatch() { return status.joypad_strobe_latch; }
//WMDATA
uint8 CPU::mmio_r2180() {
- return bus.read(0x7e0000 | status.wram_addr++);
+ return bus.read(0x7e0000 | status.wram_addr++, false);
}
//WMDATA
diff --git a/snes/debugger/debugger.cpp b/snes/debugger/debugger.cpp
index b1312339..e8d0f5af 100755
--- a/snes/debugger/debugger.cpp
+++ b/snes/debugger/debugger.cpp
@@ -33,7 +33,7 @@ uint8 Debugger::read(Debugger::MemorySource source, unsigned addr) {
case MemorySource::CPUBus: {
//do not read from memory-mapped registers that could affect program behavior
if(((addr - 0x2000) & 0x40c000) == 0x000000) break; //$00-3f:2000-5fff MMIO
- return bus.read(addr & 0xffffff);
+ return bus.read(addr & 0xffffff, false);
} break;
case MemorySource::APUBus: {
diff --git a/snes/memory/memory-inline.hpp b/snes/memory/memory-inline.hpp
index 70503bea..45f150c9 100755
--- a/snes/memory/memory-inline.hpp
+++ b/snes/memory/memory-inline.hpp
@@ -51,11 +51,26 @@ MappedRAM::MappedRAM() : data_(0), size_(0), write_protect_(false) {}
//Bus
-uint8 Bus::read(unsigned addr) {
- if(cheat.override[addr]) return cheat.read(addr);
- return reader[lookup[addr]](target[addr]);
+uint8 Bus::read(unsigned addr, bool exec) {
+ uint8 emask = exec ? 0x24 : 0x09;
+ uint8 val;
+ if(__builtin_expect(cheat.override[addr], 0))
+ val = cheat.read(addr);
+ else
+ val = reader[lookup[addr]](target[addr]);
+ if(__builtin_expect((u_debugflags | debugflags[addr]) & emask, 0)) {
+ unsigned daddr = target[addr];
+ uint8 mclass = classmap[addr];
+ debug_read(mclass, daddr, addr, val, exec);
+ }
+ return val;
}
void Bus::write(unsigned addr, uint8 data) {
+ if(__builtin_expect((u_debugflags | debugflags[addr]) & 0x12, 0)) {
+ unsigned daddr = target[addr];
+ uint8 mclass = classmap[addr];
+ debug_write(mclass, daddr, addr, data);
+ }
return writer[lookup[addr]](target[addr], data);
}
diff --git a/snes/memory/memory.cpp b/snes/memory/memory.cpp
index ede9cbd0..a9a484a0 100755
--- a/snes/memory/memory.cpp
+++ b/snes/memory/memory.cpp
@@ -27,6 +27,7 @@ void Bus::map(
MapMode mode,
unsigned bank_lo, unsigned bank_hi,
unsigned addr_lo, unsigned addr_hi,
+ unsigned mclass,
const function<uint8 (unsigned)> &rd,
const function<void (unsigned, uint8)> &wr,
unsigned base, unsigned length
@@ -48,6 +49,7 @@ void Bus::map(
if(mode == MapMode::Shadow) destaddr = mirror(base + destaddr, length);
lookup[(bank << 16) | addr] = id;
target[(bank << 16) | addr] = destaddr;
+ if(mclass) classmap[(bank << 16) | addr] = mclass;
}
}
}
@@ -57,23 +59,58 @@ void Bus::map_reset() {
function<void (unsigned, uint8)> writer = [](unsigned, uint8) {};
idcount = 0;
- map(MapMode::Direct, 0x00, 0xff, 0x0000, 0xffff, reader, writer);
+ map(MapMode::Direct, 0x00, 0xff, 0x0000, 0xffff, 0xFF, reader, writer);
}
void Bus::map_xml() {
for(auto &m : cartridge.mapping) {
- map(m.mode, m.banklo, m.bankhi, m.addrlo, m.addrhi, m.read, m.write, m.offset, m.size);
+ map(m.mode, m.banklo, m.bankhi, m.addrlo, m.addrhi, (unsigned)m.clazz, m.read, m.write, m.offset, m.size);
}
}
+unsigned Bus::enumerateMirrors(uint8 clazz, uint32 offset, unsigned start)
+{
+ unsigned i;
+ for(i = start; i < 0x1000000; i++)
+ if((classmap[i] == clazz && target[i] == offset) || (i == offset && clazz == 255))
+ return i;
+ return i;
+}
+
+void Bus::clearDebugFlags()
+{
+ u_debugflags = 0;
+ memset(debugflags, 0, 0x1000000);
+}
+
+void Bus::debugFlags(uint8 setf, uint8 clrf)
+{
+ u_debugflags = (u_debugflags | setf) & ~clrf;
+}
+
+void Bus::debugFlags(uint8 setf, uint8 clrf, uint8 clazz, uint32 offset)
+{
+ if(clazz == 255) {
+ setf <<= 3;
+ clrf <<= 3;
+ debugflags[offset] = (debugflags[offset] | setf) & ~clrf;
+ } else
+ for(unsigned i = 0; i < 0x1000000; i++)
+ if(classmap[i] == clazz && target[i] == offset)
+ debugflags[i] = (debugflags[i] | setf) & ~clrf;
+}
+
Bus::Bus() {
- lookup = new uint8 [16 * 1024 * 1024];
- target = new uint32[16 * 1024 * 1024];
+ u_debugflags = 0;
+ lookup = new uint8 [112 * 1024 * 1024];
+ target = (uint32*)(lookup + 0x3000000);
+ classmap = lookup + 0x1000000;
+ debugflags = lookup + 0x2000000;
+ memset(debugflags, 0, 0x1000000);
}
Bus::~Bus() {
delete[] lookup;
- delete[] target;
}
}
diff --git a/snes/memory/memory.hpp b/snes/memory/memory.hpp
index 634e0717..c20e14db 100755
--- a/snes/memory/memory.hpp
+++ b/snes/memory/memory.hpp
@@ -44,10 +44,13 @@ private:
struct Bus {
unsigned mirror(unsigned addr, unsigned size);
- alwaysinline uint8 read(unsigned addr);
+ alwaysinline uint8 read(unsigned addr, bool exec);
alwaysinline void write(unsigned addr, uint8 data);
uint8 *lookup;
+ uint8 *classmap;
+ uint8 *debugflags;
+ uint8 u_debugflags;
uint32 *target;
unsigned idcount;
@@ -59,6 +62,7 @@ struct Bus {
MapMode mode,
unsigned bank_lo, unsigned bank_hi,
unsigned addr_lo, unsigned addr_hi,
+ unsigned mclass,
const function<uint8 (unsigned)> &read,
const function<void (unsigned, uint8)> &write,
unsigned base = 0, unsigned length = 0
@@ -67,6 +71,13 @@ struct Bus {
void map_reset();
void map_xml();
+ void clearDebugFlags();
+ void debugFlags(uint8 setf, uint8 clrf);
+ void debugFlags(uint8 setf, uint8 clrf, uint8 clazz, uint32 offset);
+ unsigned enumerateMirrors(uint8 clazz, uint32 offset, unsigned start);
+ function<void (uint8, unsigned, unsigned, uint8, bool)> debug_read;
+ function<void (uint8, unsigned, unsigned, uint8)> debug_write;
+
Bus();
~Bus();
};
diff --git a/snes/ppu/ppu.cpp b/snes/ppu/ppu.cpp
index 8545175f..13e231cf 100755
--- a/snes/ppu/ppu.cpp
+++ b/snes/ppu/ppu.cpp
@@ -87,8 +87,8 @@ void PPU::enable() {
function<uint8 (unsigned)> read = { &PPU::mmio_read, (PPU*)&ppu };
function<void (unsigned, uint8)> write = { &PPU::mmio_write, (PPU*)&ppu };
- bus.map(Bus::MapMode::Direct, 0x00, 0x3f, 0x2100, 0x213f, read, write);
- bus.map(Bus::MapMode::Direct, 0x80, 0xbf, 0x2100, 0x213f, read, write);
+ bus.map(Bus::MapMode::Direct, 0x00, 0x3f, 0x2100, 0x213f, 0, read, write);
+ bus.map(Bus::MapMode::Direct, 0x80, 0xbf, 0x2100, 0x213f, 0, read, write);
}
void PPU::power() {
diff --git a/snes/smp/core/core.hpp b/snes/smp/core/core.hpp
index 1489fcef..13d69364 100755
--- a/snes/smp/core/core.hpp
+++ b/snes/smp/core/core.hpp
@@ -2,7 +2,7 @@ struct SMPcore {
virtual void op_io() = 0;
virtual uint8 op_read(uint16 addr) = 0;
virtual void op_write(uint16 addr, uint8 data) = 0;
- void op_step();
+ virtual void op_step();
#include "registers.hpp"
#include "memory.hpp"
diff --git a/snes/snes.hpp b/snes/snes.hpp
index dffeeee3..37ed1feb 100755
--- a/snes/snes.hpp
+++ b/snes/snes.hpp
@@ -1,5 +1,6 @@
#ifndef SNES_HPP
#define SNES_HPP
+#define BSNES_SUPPORTS_ADV_BREAKPOINTS
namespace SNES {
namespace Info {
--
2.15.0.rc1

View file

@ -1,22 +0,0 @@
From 8bc6bb381e680616dcc843c99889799aedd43163 Mon Sep 17 00:00:00 2001
From: Ilari Liusvaara <ilari.liusvaara@elisanet.fi>
Date: Sat, 30 Nov 2013 10:27:37 +0200
Subject: [PATCH 13/27] Support auto-detecting bsnes version
---
bsnes.mk | 3 +++
1 file changed, 3 insertions(+)
create mode 100644 bsnes.mk
diff --git a/bsnes.mk b/bsnes.mk
new file mode 100644
index 00000000..20f22f61
--- /dev/null
+++ b/bsnes.mk
@@ -0,0 +1,3 @@
+BSNES_SUPPORTS_DEBUGGER=yes
+LIBSNES_DIR=ui-libsnes
+BSNES_VERSION=085
--
2.15.0.rc1

View file

@ -1,138 +0,0 @@
From 40c456dadd79cb2c94379fda8b41a4d0ba051ad1 Mon Sep 17 00:00:00 2001
From: Ilari Liusvaara <ilari.liusvaara@elisanet.fi>
Date: Sat, 7 Dec 2013 23:32:44 +0200
Subject: [PATCH 14/27] Support alternate (more accurate) poll timings
---
snes/config/config.cpp | 1 +
snes/config/config.hpp | 1 +
snes/cpu/timing/joypad.cpp | 40 ++++++++++++++++++++++++++++++++++++++++
snes/cpu/timing/timing.cpp | 16 ++++++++++++----
snes/cpu/timing/timing.hpp | 1 +
snes/snes.hpp | 1 +
6 files changed, 56 insertions(+), 4 deletions(-)
diff --git a/snes/config/config.cpp b/snes/config/config.cpp
index 701af94c..206daae0 100755
--- a/snes/config/config.cpp
+++ b/snes/config/config.cpp
@@ -13,6 +13,7 @@ Configuration::Configuration() {
cpu.ntsc_frequency = 21477272; //315 / 88 * 6000000
cpu.pal_frequency = 21281370;
cpu.wram_init_value = 0x55;
+ cpu.alt_poll_timings = false;
smp.ntsc_frequency = 24607104; //32040.5 * 768
smp.pal_frequency = 24607104;
diff --git a/snes/config/config.hpp b/snes/config/config.hpp
index 1f4d037c..dabde597 100755
--- a/snes/config/config.hpp
+++ b/snes/config/config.hpp
@@ -10,6 +10,7 @@ struct Configuration {
unsigned ntsc_frequency;
unsigned pal_frequency;
unsigned wram_init_value;
+ bool alt_poll_timings;
} cpu;
struct SMP {
diff --git a/snes/cpu/timing/joypad.cpp b/snes/cpu/timing/joypad.cpp
index 6a98de00..ae8e94f8 100755
--- a/snes/cpu/timing/joypad.cpp
+++ b/snes/cpu/timing/joypad.cpp
@@ -29,4 +29,44 @@ void CPU::step_auto_joypad_poll() {
}
}
+//called every 128 clocks; see CPU::add_clocks()
+void CPU::step_auto_joypad_poll_NEW(bool polarity) {
+ if(status.auto_joypad_counter > 0 && status.auto_joypad_counter <= 34) {
+ if(!status.auto_joypad_latch) {
+ //FIXME: Is this right, busy flag goes on even if not enabled???
+ if(status.auto_joypad_counter == 1)
+ status.auto_joypad_active = true;
+ if(status.auto_joypad_counter == 34)
+ status.auto_joypad_active = false;
+ } else {
+ if(status.auto_joypad_counter == 1) {
+ status.auto_joypad_active = true;
+ input.port1->latch(1);
+ input.port2->latch(1);
+ }
+ if(status.auto_joypad_counter == 3) {
+ input.port1->latch(0);
+ input.port2->latch(0);
+ }
+ if((status.auto_joypad_counter & 1) != 0 && status.auto_joypad_counter != 1) {
+ uint2 port0 = input.port1->data();
+ uint2 port1 = input.port2->data();
+
+ status.joy1 = (status.joy1 << 1) | (bool)(port0 & 1);
+ status.joy2 = (status.joy2 << 1) | (bool)(port1 & 1);
+ status.joy3 = (status.joy3 << 1) | (bool)(port0 & 2);
+ status.joy4 = (status.joy4 << 1) | (bool)(port1 & 2);
+ }
+ if(status.auto_joypad_counter == 34)
+ status.auto_joypad_active = false;
+ }
+ status.auto_joypad_counter++;
+ }
+ if(vcounter() >= (ppu.overscan() == false ? 225 : 240) && status.auto_joypad_counter == 0 && !polarity) {
+ status.auto_joypad_latch = status.auto_joypad_poll;
+ status.auto_joypad_counter = 1;
+ }
+}
+
+
#endif
diff --git a/snes/cpu/timing/timing.cpp b/snes/cpu/timing/timing.cpp
index f1378f0c..d7cf24f3 100755
--- a/snes/cpu/timing/timing.cpp
+++ b/snes/cpu/timing/timing.cpp
@@ -17,10 +17,18 @@ void CPU::add_clocks(unsigned clocks) {
step(clocks);
- status.auto_joypad_clock += clocks;
- if(status.auto_joypad_clock >= 256) {
- status.auto_joypad_clock -= 256;
- step_auto_joypad_poll();
+ if(config.cpu.alt_poll_timings) {
+ bool opolarity = (status.auto_joypad_clock & 128);
+ status.auto_joypad_clock = (status.auto_joypad_clock + clocks) & 0xFF;
+ bool npolarity = (status.auto_joypad_clock & 128);
+ if(opolarity != npolarity)
+ step_auto_joypad_poll_NEW(opolarity);
+ } else {
+ status.auto_joypad_clock += clocks;
+ if(status.auto_joypad_clock >= 256) {
+ status.auto_joypad_clock -= 256;
+ step_auto_joypad_poll();
+ }
}
if(status.dram_refreshed == false && hcounter() >= status.dram_refresh_position) {
diff --git a/snes/cpu/timing/timing.hpp b/snes/cpu/timing/timing.hpp
index 6c225dab..bf15a727 100755
--- a/snes/cpu/timing/timing.hpp
+++ b/snes/cpu/timing/timing.hpp
@@ -22,3 +22,4 @@ alwaysinline bool irq_test();
//joypad.cpp
void step_auto_joypad_poll();
+void step_auto_joypad_poll_NEW(bool polarity);
diff --git a/snes/snes.hpp b/snes/snes.hpp
index 37ed1feb..4e3ba64c 100755
--- a/snes/snes.hpp
+++ b/snes/snes.hpp
@@ -1,6 +1,7 @@
#ifndef SNES_HPP
#define SNES_HPP
#define BSNES_SUPPORTS_ADV_BREAKPOINTS
+#define BSNES_SUPPORTS_ALT_TIMINGS
namespace SNES {
namespace Info {
--
2.15.0.rc1

View file

@ -1,103 +0,0 @@
From 863bde899b53ae31e854096ac5258208c848a293 Mon Sep 17 00:00:00 2001
From: Ilari Liusvaara <ilari.liusvaara@elisanet.fi>
Date: Thu, 6 Mar 2014 21:07:54 +0200
Subject: [PATCH 15/27] Fix mouse speed support
---
snes/config/config.cpp | 1 +
snes/config/config.hpp | 3 +++
snes/controller/mouse/mouse.cpp | 11 +++++++++--
snes/controller/mouse/mouse.hpp | 1 +
4 files changed, 14 insertions(+), 2 deletions(-)
diff --git a/snes/config/config.cpp b/snes/config/config.cpp
index 206daae0..19831370 100755
--- a/snes/config/config.cpp
+++ b/snes/config/config.cpp
@@ -8,6 +8,7 @@ Configuration::Configuration() {
expansion_port = System::ExpansionPortDevice::BSX;
region = System::Region::Autodetect;
random = true;
+ mouse_speed_fix = false;
cpu.version = 2;
cpu.ntsc_frequency = 21477272; //315 / 88 * 6000000
diff --git a/snes/config/config.hpp b/snes/config/config.hpp
index dabde597..68fe0bde 100755
--- a/snes/config/config.hpp
+++ b/snes/config/config.hpp
@@ -1,9 +1,12 @@
+#define BSNES_SUPPORTS_MOUSE_SPEED_FIX
+
struct Configuration {
Input::Device controller_port1;
Input::Device controller_port2;
System::ExpansionPortDevice expansion_port;
System::Region region;
bool random;
+ bool mouse_speed_fix;
struct CPU {
unsigned version;
diff --git a/snes/controller/mouse/mouse.cpp b/snes/controller/mouse/mouse.cpp
index 1a066b98..caa7a358 100755
--- a/snes/controller/mouse/mouse.cpp
+++ b/snes/controller/mouse/mouse.cpp
@@ -1,6 +1,10 @@
#ifdef CONTROLLER_CPP
uint2 Mouse::data() {
+ if(config.mouse_speed_fix && latched) {
+ speed = (speed + 1) % 3;
+ return 0;
+ }
if(counter >= 32) return 1;
if(counter == 0) {
@@ -31,8 +35,8 @@ uint2 Mouse::data() {
case 8: return interface->inputPoll(port, Input::Device::Mouse, 0, (unsigned)Input::MouseID::Right);
case 9: return interface->inputPoll(port, Input::Device::Mouse, 0, (unsigned)Input::MouseID::Left);
- case 10: return 0; //speed (0 = slow, 1 = normal, 2 = fast, 3 = unused)
- case 11: return 0; // ||
+ case 10: return speed >> 1; //speed (0 = slow, 1 = normal, 2 = fast, 3 = unused)
+ case 11: return speed & 1; // ||
case 12: return 0; //signature
case 13: return 0; // ||
@@ -75,10 +79,12 @@ void Mouse::serialize(serializer& s) {
block[3] = (unsigned short)_position_x;
block[4] = (unsigned short)_position_y >> 8;
block[5] = (unsigned short)_position_y;
+ block[6] = speed;
s.array(block, Controller::SaveSize);
if(s.mode() == nall::serializer::Load) {
latched = (block[0] != 0);
counter = block[1];
+ speed = block[6];
_position_x = (short)(((unsigned short)block[2] << 8) | (unsigned short)block[3]);
_position_y = (short)(((unsigned short)block[4] << 8) | (unsigned short)block[5]);
}
@@ -87,6 +93,7 @@ void Mouse::serialize(serializer& s) {
Mouse::Mouse(bool port) : Controller(port) {
latched = 0;
counter = 0;
+ speed = 0;
}
#endif
diff --git a/snes/controller/mouse/mouse.hpp b/snes/controller/mouse/mouse.hpp
index b07c8ab7..13a9313e 100755
--- a/snes/controller/mouse/mouse.hpp
+++ b/snes/controller/mouse/mouse.hpp
@@ -6,6 +6,7 @@ struct Mouse : Controller {
private:
bool latched;
unsigned counter;
+ unsigned speed;
int _position_x;
int _position_y;
};
--
2.15.0.rc1

View file

@ -1,25 +0,0 @@
From 60267d1f22fd2ff3197c6c829640f66304c89283 Mon Sep 17 00:00:00 2001
From: Ilari Liusvaara <ilari.liusvaara@elisanet.fi>
Date: Sun, 16 Mar 2014 16:40:55 +0200
Subject: [PATCH 16/27] Fix tracelog of controller registers
---
snes/cpu/core/disassembler/disassembler.cpp | 2 ++
1 file changed, 2 insertions(+)
diff --git a/snes/cpu/core/disassembler/disassembler.cpp b/snes/cpu/core/disassembler/disassembler.cpp
index ab8dde24..624a80ce 100755
--- a/snes/cpu/core/disassembler/disassembler.cpp
+++ b/snes/cpu/core/disassembler/disassembler.cpp
@@ -1,6 +1,8 @@
#ifdef CPUCORE_CPP
uint8 CPUcore::dreadb(uint32 addr) {
+ if((addr & 0x40fff8) == 0x4218)
+ return bus.read(addr, false); //Controller registers are safe to read.
if((addr & 0x40ffff) >= 0x2000 && (addr & 0x40ffff) <= 0x5fff) {
//$[00-3f|80-bf]:[2000-5fff]
//do not read MMIO registers within debugger
--
2.15.0.rc1

View file

@ -1,105 +0,0 @@
From de71f12eb59a41899a5c77d797e144e6f0919777 Mon Sep 17 00:00:00 2001
From: Ilari Liusvaara <ilari.liusvaara@elisanet.fi>
Date: Mon, 17 Mar 2014 14:22:58 +0200
Subject: [PATCH 17/27] Fix performance problem with non-bus breakpoints
---
snes/memory/memory.cpp | 35 ++++++++++++++++++++++++++---------
snes/memory/memory.hpp | 1 +
snes/snes.hpp | 1 +
3 files changed, 28 insertions(+), 9 deletions(-)
diff --git a/snes/memory/memory.cpp b/snes/memory/memory.cpp
index a9a484a0..d22e3137 100755
--- a/snes/memory/memory.cpp
+++ b/snes/memory/memory.cpp
@@ -43,6 +43,7 @@ void Bus::map(
unsigned offset = 0;
for(unsigned bank = bank_lo; bank <= bank_hi; bank++) {
+ region_start.insert((bank << 16) | addr_lo);
for(unsigned addr = addr_lo; addr <= addr_hi; addr++) {
unsigned destaddr = (bank << 16) | addr;
if(mode == MapMode::Linear) destaddr = mirror(base + offset++, length);
@@ -60,6 +61,7 @@ void Bus::map_reset() {
idcount = 0;
map(MapMode::Direct, 0x00, 0xff, 0x0000, 0xffff, 0xFF, reader, writer);
+ region_start.clear();
}
void Bus::map_xml() {
@@ -70,11 +72,21 @@ void Bus::map_xml() {
unsigned Bus::enumerateMirrors(uint8 clazz, uint32 offset, unsigned start)
{
- unsigned i;
- for(i = start; i < 0x1000000; i++)
- if((classmap[i] == clazz && target[i] == offset) || (i == offset && clazz == 255))
- return i;
- return i;
+ if(clazz == 255) {
+ if(start > offset)
+ return 0x1000000;
+ else
+ return start;
+ }
+ //Given region can not contain the same address twice.
+ for(std::set<uint32>::iterator i = region_start.lower_bound(start); i != region_start.end(); i++) {
+ if(classmap[*i] != clazz) continue;
+ if(target[*i] > offset) continue;
+ uint32 wouldbe = offset - target[*i] + *i;
+ if(wouldbe > 0xFFFFFF) continue;
+ if(classmap[wouldbe] == clazz && target[wouldbe] == offset) return wouldbe;
+ }
+ return 0x1000000;
}
void Bus::clearDebugFlags()
@@ -94,10 +106,15 @@ void Bus::debugFlags(uint8 setf, uint8 clrf, uint8 clazz, uint32 offset)
setf <<= 3;
clrf <<= 3;
debugflags[offset] = (debugflags[offset] | setf) & ~clrf;
- } else
- for(unsigned i = 0; i < 0x1000000; i++)
- if(classmap[i] == clazz && target[i] == offset)
- debugflags[i] = (debugflags[i] | setf) & ~clrf;
+ } else {
+ uint32 i = 0;
+ while(true) {
+ i = enumerateMirrors(clazz, offset, i);
+ if(i >= 0x1000000) break;
+ debugflags[i] = (debugflags[i] | setf) & ~clrf;
+ i++;
+ }
+ }
}
Bus::Bus() {
diff --git a/snes/memory/memory.hpp b/snes/memory/memory.hpp
index c20e14db..ee0c0a9e 100755
--- a/snes/memory/memory.hpp
+++ b/snes/memory/memory.hpp
@@ -52,6 +52,7 @@ struct Bus {
uint8 *debugflags;
uint8 u_debugflags;
uint32 *target;
+ std::set<uint32> region_start;
unsigned idcount;
function<uint8 (unsigned)> reader[256];
diff --git a/snes/snes.hpp b/snes/snes.hpp
index 4e3ba64c..9589db9b 100755
--- a/snes/snes.hpp
+++ b/snes/snes.hpp
@@ -38,6 +38,7 @@ namespace SNES {
#include <nall/varint.hpp>
#include <nall/vector.hpp>
#include <nall/gameboy/cartridge.hpp>
+#include <set>
using namespace nall;
#include <gameboy/gameboy.hpp>
--
2.15.0.rc1

View file

@ -1,537 +0,0 @@
From 6bd069191d29ad70d38c82d59dd72cd0996fc45c Mon Sep 17 00:00:00 2001
From: Ilari Liusvaara <ilari.liusvaara@elisanet.fi>
Date: Mon, 31 Mar 2014 20:17:46 +0300
Subject: [PATCH 18/27] Support VRAM, OAM, CGRAM and APURAM breakpoints
---
snes/alt/ppu-compatibility/memory/memory.cpp | 44 +++++++++++++++++++++--
snes/alt/ppu-compatibility/ppu.hpp | 6 ++++
snes/cartridge/cartridge.hpp | 4 +++
snes/smp/core/core.hpp | 2 +-
snes/smp/core/memory.hpp | 6 ++--
snes/smp/core/opcodes.cpp | 36 +++++++++----------
snes/smp/debugger/debugger.cpp | 4 +--
snes/smp/debugger/debugger.hpp | 2 +-
snes/smp/memory/memory.cpp | 54 +++++++++++++++++++---------
snes/smp/memory/memory.hpp | 4 +--
snes/smp/smp.hpp | 4 +++
snes/snes.hpp | 1 +
12 files changed, 122 insertions(+), 45 deletions(-)
diff --git a/snes/alt/ppu-compatibility/memory/memory.cpp b/snes/alt/ppu-compatibility/memory/memory.cpp
index 3f120d84..e47cf201 100755
--- a/snes/alt/ppu-compatibility/memory/memory.cpp
+++ b/snes/alt/ppu-compatibility/memory/memory.cpp
@@ -47,20 +47,31 @@ uint8 PPU::vram_mmio_read(uint16 addr) {
data = vram[addr];
}
}
-
+ if(__builtin_expect(vram_debugflags[addr] & 0x1, 0)) {
+ debug_read(13, addr, data);
+ }
return data;
}
void PPU::vram_mmio_write(uint16 addr, uint8 data) {
if(regs.display_disabled == true) {
+ if(__builtin_expect(vram_debugflags[addr] & 0x2, 0)) {
+ debug_write(13, addr, data);
+ }
vram[addr] = data;
} else {
uint16 v = cpu.vcounter();
uint16 h = cpu.hcounter();
if(v == 0) {
if(h <= 4) {
+ if(__builtin_expect(vram_debugflags[addr] & 0x2, 0)) {
+ debug_write(13, addr, data);
+ }
vram[addr] = data;
} else if(h == 6) {
+ if(__builtin_expect(vram_debugflags[addr] & 0x2, 0)) {
+ debug_write(13, addr, cpu.regs.mdr);
+ }
vram[addr] = cpu.regs.mdr;
} else {
//no write
@@ -71,9 +82,15 @@ void PPU::vram_mmio_write(uint16 addr, uint8 data) {
if(h <= 4) {
//no write
} else {
+ if(__builtin_expect(vram_debugflags[addr] & 0x2, 0)) {
+ debug_write(13, addr, data);
+ }
vram[addr] = data;
}
} else {
+ if(__builtin_expect(vram_debugflags[addr] & 0x2, 0)) {
+ debug_write(13, addr, data);
+ }
vram[addr] = data;
}
}
@@ -93,7 +110,9 @@ uint8 PPU::oam_mmio_read(uint16 addr) {
data = oam[addr];
}
}
-
+ if(__builtin_expect(oam_debugflags[addr] & 0x1, 0)) {
+ debug_read(14, addr, data);
+ }
return data;
}
@@ -104,13 +123,22 @@ void PPU::oam_mmio_write(uint16 addr, uint8 data) {
sprite_list_valid = false;
if(regs.display_disabled == true) {
+ if(__builtin_expect(oam_debugflags[addr] & 0x2, 0)) {
+ debug_write(14, addr, data);
+ }
oam[addr] = data;
update_sprite_list(addr, data);
} else {
if(cpu.vcounter() < (!overscan() ? 225 : 240)) {
+ if(__builtin_expect(oam_debugflags[regs.ioamaddr] & 0x2, 0)) {
+ debug_write(14, regs.ioamaddr, data);
+ }
oam[regs.ioamaddr] = data;
update_sprite_list(regs.ioamaddr, data);
} else {
+ if(__builtin_expect(oam_debugflags[addr] & 0x2, 0)) {
+ debug_write(14, addr, data);
+ }
oam[addr] = data;
update_sprite_list(addr, data);
}
@@ -134,6 +162,9 @@ uint8 PPU::cgram_mmio_read(uint16 addr) {
}
if(addr & 1) data &= 0x7f;
+ if(__builtin_expect(cgram_debugflags[addr] & 0x1, 0)) {
+ debug_read(15, addr, data);
+ }
return data;
}
@@ -142,13 +173,22 @@ void PPU::cgram_mmio_write(uint16 addr, uint8 data) {
if(addr & 1) data &= 0x7f;
if(1 || regs.display_disabled == true) {
+ if(__builtin_expect(cgram_debugflags[addr] & 0x2, 0)) {
+ debug_write(15, addr, data);
+ }
cgram[addr] = data;
} else {
uint16 v = cpu.vcounter();
uint16 h = cpu.hcounter();
if(v < (!overscan() ? 225 : 240) && h >= 128 && h < 1096) {
+ if(__builtin_expect(cgram_debugflags[regs.icgramaddr] & 0x2, 0)) {
+ debug_write(15, regs.icgramaddr, data & 0x7f);
+ }
cgram[regs.icgramaddr] = data & 0x7f;
} else {
+ if(__builtin_expect(cgram_debugflags[addr] & 0x2, 0)) {
+ debug_write(15, addr, data);
+ }
cgram[addr] = data;
}
}
diff --git a/snes/alt/ppu-compatibility/ppu.hpp b/snes/alt/ppu-compatibility/ppu.hpp
index cccaabba..4adac4c4 100755
--- a/snes/alt/ppu-compatibility/ppu.hpp
+++ b/snes/alt/ppu-compatibility/ppu.hpp
@@ -3,6 +3,12 @@ public:
uint8 vram[128 * 1024];
uint8 oam[544];
uint8 cgram[512];
+ //4 is read, 2 is write.
+ uint8 vram_debugflags[128 * 1024];
+ uint8 oam_debugflags[544];
+ uint8 cgram_debugflags[512];
+ function<void (uint8, unsigned, uint8)> debug_read;
+ function<void (uint8, unsigned, uint8)> debug_write;
enum : bool { Threaded = true };
alwaysinline void step(unsigned clocks);
diff --git a/snes/cartridge/cartridge.hpp b/snes/cartridge/cartridge.hpp
index 82e73c4c..2358c088 100755
--- a/snes/cartridge/cartridge.hpp
+++ b/snes/cartridge/cartridge.hpp
@@ -26,6 +26,10 @@ struct Cartridge : property<Cartridge> {
SUFAMITURBO_RAMA = 10,
SUFAMITURBO_RAMB = 11,
BSXFLASH = 12,
+ VRAM = 13,
+ OAM = 14,
+ CGRAM = 15,
+ APURAM = 16,
};
enum class Slot : unsigned {
diff --git a/snes/smp/core/core.hpp b/snes/smp/core/core.hpp
index 13d69364..03f9ac66 100755
--- a/snes/smp/core/core.hpp
+++ b/snes/smp/core/core.hpp
@@ -1,6 +1,6 @@
struct SMPcore {
virtual void op_io() = 0;
- virtual uint8 op_read(uint16 addr) = 0;
+ virtual uint8 op_read(uint16 addr, bool exec) = 0;
virtual void op_write(uint16 addr, uint8 data) = 0;
virtual void op_step();
diff --git a/snes/smp/core/memory.hpp b/snes/smp/core/memory.hpp
index c4b6d99f..c297962f 100755
--- a/snes/smp/core/memory.hpp
+++ b/snes/smp/core/memory.hpp
@@ -1,9 +1,9 @@
alwaysinline uint8 op_readpc() {
- return op_read(regs.pc++);
+ return op_read(regs.pc++, true);
}
alwaysinline uint8 op_readsp() {
- return op_read(0x0100 | ++regs.s);
+ return op_read(0x0100 | ++regs.s, false);
}
alwaysinline void op_writesp(uint8 data) {
@@ -11,7 +11,7 @@ alwaysinline void op_writesp(uint8 data) {
}
alwaysinline uint8 op_readdp(uint8 addr) {
- return op_read((regs.p.p << 8) + addr);
+ return op_read((regs.p.p << 8) + addr, false);
}
alwaysinline void op_writedp(uint8 addr, uint8 data) {
diff --git a/snes/smp/core/opcodes.cpp b/snes/smp/core/opcodes.cpp
index 95b9844f..43db081d 100755
--- a/snes/smp/core/opcodes.cpp
+++ b/snes/smp/core/opcodes.cpp
@@ -11,7 +11,7 @@ template<uint8 (SMPcore::*op)(uint8)>
void SMPcore::op_adjust_addr() {
dp.l = op_readpc();
dp.h = op_readpc();
- rd = op_read(dp);
+ rd = op_read(dp, false);
rd = call(rd);
op_write(dp, rd);
}
@@ -78,7 +78,7 @@ template<uint8 (SMPcore::*op)(uint8, uint8)>
void SMPcore::op_read_addr(uint8 &r) {
dp.l = op_readpc();
dp.h = op_readpc();
- rd = op_read(dp);
+ rd = op_read(dp, false);
r = call(r, rd);
}
@@ -87,7 +87,7 @@ void SMPcore::op_read_addri(uint8 &r) {
dp.l = op_readpc();
dp.h = op_readpc();
op_io();
- rd = op_read(dp + r);
+ rd = op_read(dp + r, false);
regs.a = call(regs.a, rd);
}
@@ -127,7 +127,7 @@ void SMPcore::op_read_idpx() {
op_io();
sp.l = op_readdp(dp++);
sp.h = op_readdp(dp++);
- rd = op_read(sp);
+ rd = op_read(sp, false);
regs.a = call(regs.a, rd);
}
@@ -137,7 +137,7 @@ void SMPcore::op_read_idpy() {
op_io();
sp.l = op_readdp(dp++);
sp.h = op_readdp(dp++);
- rd = op_read(sp + regs.y);
+ rd = op_read(sp + regs.y, false);
regs.a = call(regs.a, rd);
}
@@ -153,7 +153,7 @@ void SMPcore::op_set_addr_bit() {
dp.h = op_readpc();
bit = dp >> 13;
dp &= 0x1fff;
- rd = op_read(dp);
+ rd = op_read(dp, false);
switch(opcode >> 5) {
case 0: //orc addr:bit
case 1: //orc !addr:bit
@@ -198,10 +198,10 @@ void SMPcore::op_set_flag(bool &flag, bool data) {
void SMPcore::op_test_addr(bool set) {
dp.l = op_readpc();
dp.h = op_readpc();
- rd = op_read(dp);
+ rd = op_read(dp, false);
regs.p.n = (regs.a - rd) & 0x80;
regs.p.z = (regs.a - rd) == 0;
- op_read(dp);
+ op_read(dp, false);
op_write(dp, set ? rd | regs.a : rd & ~regs.a);
}
@@ -216,7 +216,7 @@ void SMPcore::op_transfer(uint8 &from, uint8 &to) {
void SMPcore::op_write_addr(uint8 &r) {
dp.l = op_readpc();
dp.h = op_readpc();
- op_read(dp);
+ op_read(dp, false);
op_write(dp, r);
}
@@ -225,7 +225,7 @@ void SMPcore::op_write_addri(uint8 &i) {
dp.h = op_readpc();
op_io();
dp += i;
- op_read(dp);
+ op_read(dp, false);
op_write(dp, regs.a);
}
@@ -317,8 +317,8 @@ void SMPcore::op_bne_ydec() {
}
void SMPcore::op_brk() {
- rd.l = op_read(0xffde);
- rd.h = op_read(0xffdf);
+ rd.l = op_read(0xffde, false);
+ rd.h = op_read(0xffdf, false);
op_io();
op_io();
op_writesp(regs.pc.h);
@@ -411,8 +411,8 @@ void SMPcore::op_jmp_iaddrx() {
dp.h = op_readpc();
op_io();
dp += regs.x;
- rd.l = op_read(dp++);
- rd.h = op_read(dp++);
+ rd.l = op_read(dp++, false);
+ rd.h = op_read(dp++, false);
regs.pc = rd;
}
@@ -438,8 +438,8 @@ void SMPcore::op_jsr_addr() {
void SMPcore::op_jst() {
dp = 0xffde - ((opcode >> 4) << 1);
- rd.l = op_read(dp++);
- rd.h = op_read(dp++);
+ rd.l = op_read(dp++, false);
+ rd.h = op_read(dp++, false);
op_io();
op_io();
op_io();
@@ -505,7 +505,7 @@ void SMPcore::op_sta_idpx() {
op_io();
dp.l = op_readdp(sp++);
dp.h = op_readdp(sp++);
- op_read(dp);
+ op_read(dp, false);
op_write(dp, regs.a);
}
@@ -515,7 +515,7 @@ void SMPcore::op_sta_idpy() {
dp.h = op_readdp(sp++);
op_io();
dp += regs.y;
- op_read(dp);
+ op_read(dp, false);
op_write(dp, regs.a);
}
diff --git a/snes/smp/debugger/debugger.cpp b/snes/smp/debugger/debugger.cpp
index 9546c118..894fdac9 100755
--- a/snes/smp/debugger/debugger.cpp
+++ b/snes/smp/debugger/debugger.cpp
@@ -18,8 +18,8 @@ void SMPDebugger::op_step() {
synchronize_cpu();
}
-uint8 SMPDebugger::op_read(uint16 addr) {
- uint8 data = SMP::op_read(addr);
+uint8 SMPDebugger::op_read(uint16 addr, bool exec) {
+ uint8 data = SMP::op_read(addr, exec);
usage[addr] |= UsageRead;
debugger.breakpoint_test(Debugger::Breakpoint::Source::APURAM, Debugger::Breakpoint::Mode::Read, addr, data);
return data;
diff --git a/snes/smp/debugger/debugger.hpp b/snes/smp/debugger/debugger.hpp
index d5d28e53..26bc7af9 100755
--- a/snes/smp/debugger/debugger.hpp
+++ b/snes/smp/debugger/debugger.hpp
@@ -14,7 +14,7 @@ public:
bool opcode_edge;
void op_step();
- uint8 op_read(uint16 addr);
+ uint8 op_read(uint16 addr, bool exec);
void op_write(uint16 addr, uint8 data);
SMPDebugger();
diff --git a/snes/smp/memory/memory.cpp b/snes/smp/memory/memory.cpp
index 391324c4..58c11915 100755
--- a/snes/smp/memory/memory.cpp
+++ b/snes/smp/memory/memory.cpp
@@ -19,61 +19,83 @@ void SMP::port_write(uint2 port, uint8 data) {
apuram[0xf4 + port] = data;
}
-alwaysinline uint8 SMP::op_busread(uint16 addr) {
+alwaysinline uint8 SMP::op_busread(uint16 addr, bool exec) {
unsigned result;
+ uint8 data;
switch(addr) {
case 0xf0: //TEST -- write-only register
- return 0x00;
+ data = 0x00;
+ break;
case 0xf1: //CONTROL -- write-only register
- return 0x00;
+ data = 0x00;
+ break;
case 0xf2: //DSPADDR
- return status.dsp_addr;
+ data = status.dsp_addr;
+ break;
case 0xf3: //DSPDATA
//0x80-0xff are read-only mirrors of 0x00-0x7f
- return dsp.read(status.dsp_addr & 0x7f);
+ data = dsp.read(status.dsp_addr & 0x7f);
+ break;
case 0xf4: //CPUIO0
case 0xf5: //CPUIO1
case 0xf6: //CPUIO2
case 0xf7: //CPUIO3
synchronize_cpu();
- return cpu.port_read(addr);
+ data = cpu.port_read(addr);
+ break;
case 0xf8: //RAM0
- return status.ram00f8;
+ data = status.ram00f8;
+ break;
case 0xf9: //RAM1
- return status.ram00f9;
+ data = status.ram00f9;
+ break;
case 0xfa: //T0TARGET
case 0xfb: //T1TARGET
case 0xfc: //T2TARGET -- write-only registers
- return 0x00;
+ data = 0x00;
+ break;
case 0xfd: //T0OUT -- 4-bit counter value
result = timer0.stage3_ticks;
timer0.stage3_ticks = 0;
- return result;
+ data = result;
+ break;
case 0xfe: //T1OUT -- 4-bit counter value
result = timer1.stage3_ticks;
timer1.stage3_ticks = 0;
- return result;
+ data = result;
+ break;
case 0xff: //T2OUT -- 4-bit counter value
result = timer2.stage3_ticks;
timer2.stage3_ticks = 0;
- return result;
+ data = result;
+ break;
+ default:
+ data = ram_read(addr);
+ break;
}
-
- return ram_read(addr);
+ uint8 flag = exec ? 0x04 : 0x01;
+ if(__builtin_expect(debugflags[addr] & flag, 0)) {
+ debug_read(16, addr, data, exec);
+ }
+ return data;
}
alwaysinline void SMP::op_buswrite(uint16 addr, uint8 data) {
+ if(__builtin_expect(debugflags[addr] & 0x2, 0)) {
+ debug_write(16, addr, data);
+ }
+
switch(addr) {
case 0xf0: //TEST
if(regs.p.p) break; //writes only valid when P flag is clear
@@ -180,9 +202,9 @@ void SMP::op_io() {
cycle_edge();
}
-uint8 SMP::op_read(uint16 addr) {
+uint8 SMP::op_read(uint16 addr, bool exec) {
add_clocks(12);
- uint8 r = op_busread(addr);
+ uint8 r = op_busread(addr, exec);
add_clocks(12);
cycle_edge();
return r;
diff --git a/snes/smp/memory/memory.hpp b/snes/smp/memory/memory.hpp
index 1a07445d..faa28daa 100755
--- a/snes/smp/memory/memory.hpp
+++ b/snes/smp/memory/memory.hpp
@@ -1,9 +1,9 @@
uint8 ram_read(uint16 addr);
void ram_write(uint16 addr, uint8 data);
-uint8 op_busread(uint16 addr);
+uint8 op_busread(uint16 addr, bool exec);
void op_buswrite(uint16 addr, uint8 data);
void op_io();
-debugvirtual uint8 op_read(uint16 addr);
+debugvirtual uint8 op_read(uint16 addr, bool exec);
debugvirtual void op_write(uint16 addr, uint8 data);
diff --git a/snes/smp/smp.hpp b/snes/smp/smp.hpp
index 6b387cba..6b6ae837 100755
--- a/snes/smp/smp.hpp
+++ b/snes/smp/smp.hpp
@@ -1,6 +1,10 @@
struct SMP : public Processor, public SMPcore {
static const uint8 iplrom[64];
uint8 apuram[64 * 1024];
+ uint8 debugflags[64 * 1024];
+
+ function<void (uint8, unsigned, uint8, bool)> debug_read;
+ function<void (uint8, unsigned, uint8)> debug_write;
enum : bool { Threaded = true };
alwaysinline void step(unsigned clocks);
diff --git a/snes/snes.hpp b/snes/snes.hpp
index 9589db9b..27632bff 100755
--- a/snes/snes.hpp
+++ b/snes/snes.hpp
@@ -1,6 +1,7 @@
#ifndef SNES_HPP
#define SNES_HPP
#define BSNES_SUPPORTS_ADV_BREAKPOINTS
+#define BSNES_SUPPORTS_ADV_BREAKPOINTS_PPU
#define BSNES_SUPPORTS_ALT_TIMINGS
namespace SNES {
--
2.15.0.rc1

View file

@ -1,53 +0,0 @@
From f1106d3dffd27dab526a703aa434512495fbacea Mon Sep 17 00:00:00 2001
From: Ilari Liusvaara <ilari.liusvaara@elisanet.fi>
Date: Mon, 14 Apr 2014 21:21:36 +0300
Subject: [PATCH 19/27] SA1 trace hook support
---
snes/chip/sa1/sa1.cpp | 2 ++
snes/chip/sa1/sa1.hpp | 3 +++
snes/snes.hpp | 1 +
3 files changed, 6 insertions(+)
diff --git a/snes/chip/sa1/sa1.cpp b/snes/chip/sa1/sa1.cpp
index 30e00809..fdec362c 100755
--- a/snes/chip/sa1/sa1.cpp
+++ b/snes/chip/sa1/sa1.cpp
@@ -32,6 +32,8 @@ void SA1::enter() {
continue;
}
+ if(__builtin_expect(trace_enabled ? 1 : 0, 0))
+ step_event();
(this->*opcode_table[op_readpc()])();
}
}
diff --git a/snes/chip/sa1/sa1.hpp b/snes/chip/sa1/sa1.hpp
index 732b2a85..efd36376 100755
--- a/snes/chip/sa1/sa1.hpp
+++ b/snes/chip/sa1/sa1.hpp
@@ -15,6 +15,9 @@ public:
uint16 hcounter;
} status;
+ bool trace_enabled;
+ nall::function<void()> step_event;
+
static void Enter();
void enter();
void tick();
diff --git a/snes/snes.hpp b/snes/snes.hpp
index 27632bff..3bdca7e5 100755
--- a/snes/snes.hpp
+++ b/snes/snes.hpp
@@ -3,6 +3,7 @@
#define BSNES_SUPPORTS_ADV_BREAKPOINTS
#define BSNES_SUPPORTS_ADV_BREAKPOINTS_PPU
#define BSNES_SUPPORTS_ALT_TIMINGS
+#define BSNES_SUPPORTS_TRACE_SA1
namespace SNES {
namespace Info {
--
2.15.0.rc1

View file

@ -1,78 +0,0 @@
From cf662a12578778cb50c25d5275ce58deabd7eabe Mon Sep 17 00:00:00 2001
From: Ilari Liusvaara <ilari.liusvaara@elisanet.fi>
Date: Wed, 30 Apr 2014 00:18:58 +0300
Subject: [PATCH 20/27] Fixes to SA1 open bus emulation
---
snes/chip/sa1/memory/memory.cpp | 19 +++++++++++--------
1 file changed, 11 insertions(+), 8 deletions(-)
diff --git a/snes/chip/sa1/memory/memory.cpp b/snes/chip/sa1/memory/memory.cpp
index 9bb4ff20..614dfb0c 100755
--- a/snes/chip/sa1/memory/memory.cpp
+++ b/snes/chip/sa1/memory/memory.cpp
@@ -36,6 +36,7 @@ uint8 SA1::bus_read(unsigned addr) {
synchronize_cpu();
return bitmap_read(addr & 0x0fffff);
}
+ return regs.mdr;
}
void SA1::bus_write(unsigned addr, uint8 data) {
@@ -73,29 +74,31 @@ void SA1::bus_write(unsigned addr, uint8 data) {
//to avoid syncing the S-CPU and SA-1*; as both chips are able to access
//these ports.
uint8 SA1::vbr_read(unsigned addr) {
+ //Let's share the bus state with main SA1 bus (is this correct?)
if((addr & 0x408000) == 0x008000) { //$00-3f|80-bf:8000-ffff
- return mmc_read(addr);
+ return regs.mdr = mmc_read(addr);
}
if((addr & 0xc00000) == 0xc00000) { //$c0-ff:0000-ffff
- return mmc_read(addr);
+ return regs.mdr = mmc_read(addr);
}
if((addr & 0x40e000) == 0x006000) { //$00-3f|80-bf:6000-7fff
- return cartridge.ram.read(addr & (cartridge.ram.size() - 1));
+ return regs.mdr = cartridge.ram.read(addr & (cartridge.ram.size() - 1));
}
if((addr & 0xf00000) == 0x400000) { //$40-4f:0000-ffff
- return cartridge.ram.read(addr & (cartridge.ram.size() - 1));
+ return regs.mdr = cartridge.ram.read(addr & (cartridge.ram.size() - 1));
}
if((addr & 0x40f800) == 0x000000) { //$00-3f|80-bf:0000-07ff
- return iram.read(addr & 2047);
+ return regs.mdr = iram.read(addr & 2047);
}
if((addr & 0x40f800) == 0x003000) { //$00-3f|80-bf:3000-37ff
- return iram.read(addr & 0x2047);
+ return regs.mdr = iram.read(addr & 0x2047);
}
+ return regs.mdr;
}
//ROM, I-RAM and MMIO registers are accessed at ~10.74MHz (2 clock ticks)
@@ -110,13 +113,13 @@ void SA1::op_io() {
uint8 SA1::op_read(unsigned addr, bool exec) {
tick();
if(((addr & 0x40e000) == 0x006000) || ((addr & 0xd00000) == 0x400000)) tick();
- return bus_read(addr);
+ return regs.mdr = bus_read(addr);
}
void SA1::op_write(unsigned addr, uint8 data) {
tick();
if(((addr & 0x40e000) == 0x006000) || ((addr & 0xd00000) == 0x400000)) tick();
- bus_write(addr, data);
+ bus_write(addr, regs.mdr = data);
}
uint8 SA1::mmc_read(unsigned addr) {
--
2.15.0.rc1

View file

@ -1,25 +0,0 @@
From 63fc77b07d517c2f9a0fd6ca3fa94f30fb0f5ec2 Mon Sep 17 00:00:00 2001
From: Ilari Liusvaara <ilari.liusvaara@elisanet.fi>
Date: Sun, 15 Jun 2014 22:01:26 +0300
Subject: [PATCH 21/27] Call notify latch function on alternate timings mode
too
---
snes/cpu/timing/joypad.cpp | 1 +
1 file changed, 1 insertion(+)
diff --git a/snes/cpu/timing/joypad.cpp b/snes/cpu/timing/joypad.cpp
index ae8e94f8..3fd4d23e 100755
--- a/snes/cpu/timing/joypad.cpp
+++ b/snes/cpu/timing/joypad.cpp
@@ -41,6 +41,7 @@ void CPU::step_auto_joypad_poll_NEW(bool polarity) {
} else {
if(status.auto_joypad_counter == 1) {
status.auto_joypad_active = true;
+ interface->notifyLatched();
input.port1->latch(1);
input.port2->latch(1);
}
--
2.15.0.rc1

View file

@ -1,288 +0,0 @@
From 5bc96b8aeea26729ef4399c2d8d5e562894616e1 Mon Sep 17 00:00:00 2001
From: Ilari Liusvaara <ilari.liusvaara@elisanet.fi>
Date: Tue, 20 Jan 2015 10:04:58 +0200
Subject: [PATCH 22/27] Support DMA tracing
---
snes/alt/ppu-compatibility/mmio/mmio.cpp | 18 +++++++
snes/alt/ppu-compatibility/ppu.cpp | 1 +
snes/alt/ppu-compatibility/ppu.hpp | 4 ++
snes/cpu/cpu.cpp | 1 +
snes/cpu/cpu.hpp | 1 +
snes/cpu/dma/dma.cpp | 84 ++++++++++++++++++++++++++++++++
snes/cpu/dma/dma.hpp | 5 ++
snes/ppu/mmio/mmio.cpp | 18 +++++++
snes/ppu/ppu.cpp | 1 +
snes/ppu/ppu.hpp | 3 ++
snes/snes.hpp | 1 +
11 files changed, 137 insertions(+)
diff --git a/snes/alt/ppu-compatibility/mmio/mmio.cpp b/snes/alt/ppu-compatibility/mmio/mmio.cpp
index aedb67c1..0a269cc0 100755
--- a/snes/alt/ppu-compatibility/mmio/mmio.cpp
+++ b/snes/alt/ppu-compatibility/mmio/mmio.cpp
@@ -1,5 +1,23 @@
#ifdef PPU_CPP
+size_t PPU::get_dma_oam_subaddr(char* buf)
+{
+ return sprintf(buf, "[%03x]", regs.oam_addr);
+}
+
+size_t PPU::get_dma_cgram_subaddr(char* buf)
+{
+ return sprintf(buf, "[%02x%c]", regs.cgram_addr >> 1, (regs.cgram_addr & 1) ?
+ 'H' : 'L');
+}
+
+size_t PPU::get_dma_vram_subaddr(char* buf)
+{
+ return sprintf(buf, "[%04x map%d inc %d on %s]", regs.vram_addr << 1,
+ regs.vram_mapping, 2 * regs.vram_incsize, regs.vram_incmode ? "high" :
+ "low");
+}
+
//INIDISP
void PPU::mmio_w2100(uint8 value) {
if(regs.display_disabled == true && cpu.vcounter() == (!overscan() ? 225 : 240)) {
diff --git a/snes/alt/ppu-compatibility/ppu.cpp b/snes/alt/ppu-compatibility/ppu.cpp
index 122b1430..ac886edc 100755
--- a/snes/alt/ppu-compatibility/ppu.cpp
+++ b/snes/alt/ppu-compatibility/ppu.cpp
@@ -1,4 +1,5 @@
#include <snes/snes.hpp>
+#include <cstdio>
#define PPU_CPP
namespace SNES {
diff --git a/snes/alt/ppu-compatibility/ppu.hpp b/snes/alt/ppu-compatibility/ppu.hpp
index 4adac4c4..b0eabf7c 100755
--- a/snes/alt/ppu-compatibility/ppu.hpp
+++ b/snes/alt/ppu-compatibility/ppu.hpp
@@ -14,6 +14,10 @@ public:
alwaysinline void step(unsigned clocks);
alwaysinline void synchronize_cpu();
+ size_t get_dma_oam_subaddr(char* buf);
+ size_t get_dma_cgram_subaddr(char* buf);
+ size_t get_dma_vram_subaddr(char* buf);
+
#include "memory/memory.hpp"
#include "mmio/mmio.hpp"
#include "render/render.hpp"
diff --git a/snes/cpu/cpu.cpp b/snes/cpu/cpu.cpp
index 39da6b16..ce112afa 100755
--- a/snes/cpu/cpu.cpp
+++ b/snes/cpu/cpu.cpp
@@ -1,4 +1,5 @@
#include <snes/snes.hpp>
+#include <cstdio>
#define CPU_CPP
namespace SNES {
diff --git a/snes/cpu/cpu.hpp b/snes/cpu/cpu.hpp
index 49445773..fd665b1f 100755
--- a/snes/cpu/cpu.hpp
+++ b/snes/cpu/cpu.hpp
@@ -26,6 +26,7 @@ struct CPU : public Processor, public CPUcore, public PPUcounter {
~CPU();
bool controller_flag;
+ function<void(const char*)> dma_trace_fn;
private:
#include "dma/dma.hpp"
#include "memory/memory.hpp"
diff --git a/snes/cpu/dma/dma.cpp b/snes/cpu/dma/dma.cpp
index 0a00bfea..8f7be263 100755
--- a/snes/cpu/dma/dma.cpp
+++ b/snes/cpu/dma/dma.cpp
@@ -144,6 +144,7 @@ void CPU::dma_run() {
for(unsigned i = 0; i < 8; i++) {
if(channel[i].dma_enabled == false) continue;
+ dma_trace_start(i);
unsigned index = 0;
do {
@@ -155,6 +156,7 @@ void CPU::dma_run() {
dma_write(false);
dma_edge();
+ dma_trace_end(i);
channel[i].dma_enabled = false;
}
@@ -202,6 +204,7 @@ void CPU::hdma_run() {
channel[i].dma_enabled = false; //HDMA run during DMA will stop DMA mid-transfer
if(channel[i].hdma_do_transfer) {
+ dma_trace_hdma(i);
static const unsigned transfer_length[8] = { 1, 2, 2, 4, 4, 4, 2, 4 };
unsigned length = transfer_length[channel[i].transfer_mode];
for(unsigned index = 0; index < length; index++) {
@@ -286,4 +289,85 @@ void CPU::dma_reset() {
pipe.data = 0;
}
+size_t CPU::dma_trace_subaddr(char* buf, uint8 b_addr)
+{
+ if(b_addr == 0x04 || b_addr == 0x38) {
+ return ppu.get_dma_oam_subaddr(buf);
+ }
+ if(b_addr == 0x22 || b_addr == 0x3B) {
+ return ppu.get_dma_cgram_subaddr(buf);
+ }
+ if(b_addr == 0x18 || b_addr == 0x19 || b_addr == 0x39 || b_addr == 0x3A) {
+ return ppu.get_dma_vram_subaddr(buf);
+ }
+ if(b_addr == 0x80) {
+ return sprintf(buf, "[%06x]", 0x7e0000 | status.wram_addr);
+ }
+ return 0;
+}
+
+void CPU::dma_trace_start(unsigned i)
+{
+ if(!dma_trace_fn) return;
+ char buf[512];
+ size_t ptr = 0;
+ unsigned bytes = channel[i].transfer_size;
+ if(!bytes) bytes = 0x10000;
+ ptr += sprintf(buf + ptr, "-- DMA%i %d(%x) bytes ", i, bytes, bytes);
+ if(channel[i].direction) {
+ //B->A
+ ptr += sprintf(buf + ptr, "%02x", channel[i].dest_addr);
+ ptr += dma_trace_subaddr(buf + ptr, channel[i].dest_addr);
+ ptr += sprintf(buf + ptr, "-> %02x%04x", channel[i].source_bank,
+ channel[i].source_addr);
+ } else {
+ //A->B
+ ptr += sprintf(buf + ptr, "%02x%04x -> %02x", channel[i].source_bank,
+ channel[i].source_addr, channel[i].dest_addr);
+ ptr += dma_trace_subaddr(buf + ptr, channel[i].dest_addr);
+ }
+ if(channel[i].fixed_transfer)
+ ptr += sprintf(buf + ptr, " fixed");
+ else if(channel[i].reverse_transfer)
+ ptr += sprintf(buf + ptr, " decrement");
+ else
+ ptr += sprintf(buf + ptr, " incrment");
+ ptr += sprintf(buf + ptr, " mode%d --", channel[i].transfer_mode);
+ dma_trace_fn(buf);
+}
+
+void CPU::dma_trace_end(unsigned i)
+{
+ if(!dma_trace_fn) return;
+ if(!channel[i].transfer_size) return; //No message for complete DMA.
+ char buf[512];
+ size_t ptr = 0;
+ sprintf(buf, "-- DMA%i aborted with %d(0x%x) bytes remaining --", i,
+ (int)channel[i].transfer_size, (unsigned)channel[i].transfer_size);
+ dma_trace_fn(buf);
+}
+
+void CPU::dma_trace_hdma(unsigned i)
+{
+ if(!dma_trace_fn) return;
+ char buf[512];
+ size_t ptr = 0;
+ unsigned addr = channel[i].indirect ?
+ (channel[i].indirect_bank << 16) | (channel[i].indirect_addr) :
+ (channel[i].source_bank << 16) | (channel[i].hdma_addr);
+ ptr += sprintf(buf + ptr, "-- HDMA%i %06x -> %02x", i, addr,
+ channel[i].dest_addr);
+ ptr += dma_trace_subaddr(buf + ptr, channel[i].dest_addr);
+ if(channel[i].indirect)
+ ptr += sprintf(buf + ptr, " indirect");
+ if(channel[i].fixed_transfer)
+ ptr += sprintf(buf + ptr, " fixed");
+ else if(channel[i].reverse_transfer)
+ ptr += sprintf(buf + ptr, " decrement");
+ else
+ ptr += sprintf(buf + ptr, " incrment");
+ ptr += sprintf(buf + ptr, " mode%d --", channel[i].transfer_mode);
+ dma_trace_fn(buf);
+}
+
#endif
diff --git a/snes/cpu/dma/dma.hpp b/snes/cpu/dma/dma.hpp
index 33755bde..8740bb3a 100755
--- a/snes/cpu/dma/dma.hpp
+++ b/snes/cpu/dma/dma.hpp
@@ -77,3 +77,8 @@ void hdma_init();
void dma_power();
void dma_reset();
+
+size_t dma_trace_subaddr(char* buf, uint8 b_addr);
+void dma_trace_start(unsigned i);
+void dma_trace_end(unsigned i);
+void dma_trace_hdma(unsigned i);
diff --git a/snes/ppu/mmio/mmio.cpp b/snes/ppu/mmio/mmio.cpp
index 302f74f8..4a4fb9ce 100755
--- a/snes/ppu/mmio/mmio.cpp
+++ b/snes/ppu/mmio/mmio.cpp
@@ -1,5 +1,23 @@
#ifdef PPU_CPP
+size_t PPU::get_dma_oam_subaddr(char* buf)
+{
+ return sprintf(buf, "[%03x]", regs.oam_addr);
+}
+
+size_t PPU::get_dma_cgram_subaddr(char* buf)
+{
+ return sprintf(buf, "[%02x%c]", regs.cgram_addr >> 1, (regs.cgram_addr & 1) ?
+ 'H' : 'L');
+}
+
+size_t PPU::get_dma_vram_subaddr(char* buf)
+{
+ return sprintf(buf, "[%04x map%d inc %d on %s]", regs.vram_addr << 1,
+ regs.vram_mapping, 2 * regs.vram_incsize, regs.vram_incmode ? "high" :
+ "low");
+}
+
bool PPU::interlace() const {
return display.interlace;
}
diff --git a/snes/ppu/ppu.cpp b/snes/ppu/ppu.cpp
index 13e231cf..58742098 100755
--- a/snes/ppu/ppu.cpp
+++ b/snes/ppu/ppu.cpp
@@ -1,4 +1,5 @@
#include <snes/snes.hpp>
+#include <cstdio>
#define PPU_CPP
namespace SNES {
diff --git a/snes/ppu/ppu.hpp b/snes/ppu/ppu.hpp
index fdba113c..0addb775 100755
--- a/snes/ppu/ppu.hpp
+++ b/snes/ppu/ppu.hpp
@@ -21,6 +21,9 @@ struct PPU : public Processor, public PPUcounter {
PPU();
~PPU();
+ size_t get_dma_oam_subaddr(char* buf);
+ size_t get_dma_cgram_subaddr(char* buf);
+ size_t get_dma_vram_subaddr(char* buf);
private:
uint32 *surface;
uint32 *output;
diff --git a/snes/snes.hpp b/snes/snes.hpp
index 3bdca7e5..7c48ebb3 100755
--- a/snes/snes.hpp
+++ b/snes/snes.hpp
@@ -4,6 +4,7 @@
#define BSNES_SUPPORTS_ADV_BREAKPOINTS_PPU
#define BSNES_SUPPORTS_ALT_TIMINGS
#define BSNES_SUPPORTS_TRACE_SA1
+#define BSNES_SUPPORTS_DMA_TRACE
namespace SNES {
namespace Info {
--
2.15.0.rc1

View file

@ -1,86 +0,0 @@
From 9682df9e33c366dfe047a99c8bcefc2c8ab29620 Mon Sep 17 00:00:00 2001
From: Ilari Liusvaara <ilari.liusvaara@elisanet.fi>
Date: Sat, 24 Jan 2015 16:46:18 +0200
Subject: [PATCH 23/27] Add autopoller and IRQ/NMI tracing
---
snes/cpu/cpu.cpp | 3 +++
snes/cpu/timing/joypad.cpp | 16 ++++++++++++++--
2 files changed, 17 insertions(+), 2 deletions(-)
diff --git a/snes/cpu/cpu.cpp b/snes/cpu/cpu.cpp
index ce112afa..e11fc882 100755
--- a/snes/cpu/cpu.cpp
+++ b/snes/cpu/cpu.cpp
@@ -69,14 +69,17 @@ void CPU::enter() {
if(status.interrupt_pending) {
status.interrupt_pending = false;
if(status.nmi_pending) {
+ if(dma_trace_fn) dma_trace_fn("-- NMI occured --");
status.nmi_pending = false;
regs.vector = (regs.e == false ? 0xffea : 0xfffa);
op_irq();
} else if(status.irq_pending) {
+ if(dma_trace_fn) dma_trace_fn("-- IRQ occured --");
status.irq_pending = false;
regs.vector = (regs.e == false ? 0xffee : 0xfffe);
op_irq();
} else if(status.reset_pending) {
+ if(dma_trace_fn) dma_trace_fn("-- RESET occured --");
status.reset_pending = false;
add_clocks(186);
regs.pc.l = bus.read(0xfffc, false);
diff --git a/snes/cpu/timing/joypad.cpp b/snes/cpu/timing/joypad.cpp
index 3fd4d23e..afca7504 100755
--- a/snes/cpu/timing/joypad.cpp
+++ b/snes/cpu/timing/joypad.cpp
@@ -6,9 +6,9 @@ void CPU::step_auto_joypad_poll() {
//cache enable state at first iteration
if(status.auto_joypad_counter == 0) status.auto_joypad_latch = status.auto_joypad_poll;
status.auto_joypad_active = status.auto_joypad_counter <= 15;
-
if(status.auto_joypad_active && status.auto_joypad_latch) {
if(status.auto_joypad_counter == 0) {
+ if(dma_trace_fn) dma_trace_fn("-- Start automatic polling --");
interface->notifyLatched();
input.port1->latch(1);
input.port2->latch(1);
@@ -23,6 +23,12 @@ void CPU::step_auto_joypad_poll() {
status.joy2 = (status.joy2 << 1) | (bool)(port1 & 1);
status.joy3 = (status.joy3 << 1) | (bool)(port0 & 2);
status.joy4 = (status.joy4 << 1) | (bool)(port1 & 2);
+ if(status.auto_joypad_counter == 15) {
+ char buf[512];
+ sprintf(buf, "-- End automatic polling [%04x %04x %04x %04x] --",
+ status.joy1, status.joy2, status.joy3, status.joy4);
+ if(dma_trace_fn) dma_trace_fn(buf);
+ }
}
status.auto_joypad_counter++;
@@ -40,6 +46,7 @@ void CPU::step_auto_joypad_poll_NEW(bool polarity) {
status.auto_joypad_active = false;
} else {
if(status.auto_joypad_counter == 1) {
+ if(dma_trace_fn) dma_trace_fn("-- Start automatic polling --");
status.auto_joypad_active = true;
interface->notifyLatched();
input.port1->latch(1);
@@ -58,8 +65,13 @@ void CPU::step_auto_joypad_poll_NEW(bool polarity) {
status.joy3 = (status.joy3 << 1) | (bool)(port0 & 2);
status.joy4 = (status.joy4 << 1) | (bool)(port1 & 2);
}
- if(status.auto_joypad_counter == 34)
+ if(status.auto_joypad_counter == 34) {
status.auto_joypad_active = false;
+ char buf[512];
+ sprintf(buf, "-- End automatic polling [%04x %04x %04x %04x] --",
+ status.joy1, status.joy2, status.joy3, status.joy4);
+ if(dma_trace_fn) dma_trace_fn(buf);
+ }
}
status.auto_joypad_counter++;
}
--
2.15.0.rc1

View file

@ -1,50 +0,0 @@
From f2bbef8a4e12e05190a68dfe410cff3e4b1eb13f Mon Sep 17 00:00:00 2001
From: Ilari Liusvaara <ilari.liusvaara@elisanet.fi>
Date: Sat, 8 Aug 2015 11:09:41 +0300
Subject: [PATCH 24/27] Build fixes for GCC 5.X
---
nall/bit.hpp | 21 +++++++++++++++------
1 file changed, 15 insertions(+), 6 deletions(-)
diff --git a/nall/bit.hpp b/nall/bit.hpp
index 67a35ad6..11d9d8de 100755
--- a/nall/bit.hpp
+++ b/nall/bit.hpp
@@ -8,18 +8,27 @@ namespace nall {
}
template<int bits> constexpr inline unsigned uclip(const unsigned x) {
- enum { m = (1U << (bits - 1)) + ((1U << (bits - 1)) - 1) };
- return (x & m);
+ return x & ((1U << (bits - 1)) + ((1U << (bits - 1)) - 1));
+ }
+
+ template<int bits> constexpr inline signed sclamp_b() {
+ return 1U << (bits - 1);
+ }
+
+ template<int bits> constexpr inline signed sclamp_m() {
+ return (1U << (bits - 1)) - 1;
}
template<int bits> constexpr inline signed sclamp(const signed x) {
- enum { b = 1U << (bits - 1), m = (1U << (bits - 1)) - 1 };
- return (x > m) ? m : (x < -b) ? -b : x;
+ return (x > sclamp_m<bits>()) ? sclamp_m<bits>() : (x < -sclamp_b<bits>()) ? -sclamp_b<bits>() : x;
+ }
+
+ template<int bits> constexpr inline signed sclip_m() {
+ return (1U << (bits)) - 1;
}
template<int bits> constexpr inline signed sclip(const signed x) {
- enum { b = 1U << (bits - 1), m = (1U << bits) - 1 };
- return ((x & m) ^ b) - b;
+ return ((x & sclip_m<bits>()) ^ sclamp_b<bits>()) - sclamp_b<bits>();
}
namespace bit {
--
2.15.0.rc1

View file

@ -1,26 +0,0 @@
From d39571de650d49636778a73c66414aff372c08af Mon Sep 17 00:00:00 2001
From: Ilari Liusvaara <ilari.liusvaara@elisanet.fi>
Date: Mon, 7 Sep 2015 20:48:14 +0300
Subject: [PATCH 25/27] Fix MSU-1 bug where write to MSU1BASE+4 is mirred to
MSUBASE+5
---
snes/chip/msu1/msu1.cpp | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/snes/chip/msu1/msu1.cpp b/snes/chip/msu1/msu1.cpp
index 71700e60..ec1cf46a 100755
--- a/snes/chip/msu1/msu1.cpp
+++ b/snes/chip/msu1/msu1.cpp
@@ -107,7 +107,7 @@ void MSU1::mmio_write(unsigned addr, uint8 data) {
if(datafile.open()) datafile.seek(mmio.data_offset);
mmio.data_busy = false;
break;
- case 4: mmio.audio_track = (mmio.audio_track & 0xff00) | (data << 0);
+ case 4: mmio.audio_track = (mmio.audio_track & 0xff00) | (data << 0); break;
case 5: mmio.audio_track = (mmio.audio_track & 0x00ff) | (data << 8);
if(audiofile.open()) audiofile.close();
if(audiofile.open(interface->path(Cartridge::Slot::Base, { "-", (unsigned)mmio.audio_track, ".pcm" }), file::mode::read)) {
--
2.15.0.rc1

View file

@ -1,25 +0,0 @@
From c0a2270cfd5f56e8a311b36011e1f15fac6c54ca Mon Sep 17 00:00:00 2001
From: Ilari Liusvaara <ilariliusvaara@welho.com>
Date: Tue, 9 Aug 2016 18:54:57 +0300
Subject: [PATCH 26/27] Add <vector> to avoid compile error due to missing
std::vector
---
snes/snes.hpp | 1 +
1 file changed, 1 insertion(+)
diff --git a/snes/snes.hpp b/snes/snes.hpp
index 7c48ebb3..3a65e360 100755
--- a/snes/snes.hpp
+++ b/snes/snes.hpp
@@ -22,6 +22,7 @@ namespace SNES {
#include <libco/libco.h>
+#include <vector>
#include <nall/platform.hpp>
#include <nall/algorithm.hpp>
#include <nall/any.hpp>
--
2.15.0.rc1

View file

@ -1,377 +0,0 @@
From 4cfbbeadc3abe3e3911f7f59ce57b715edc76563 Mon Sep 17 00:00:00 2001
From: Ilari Liusvaara <ilariliusvaara@welho.com>
Date: Wed, 25 Oct 2017 14:18:34 +0300
Subject: [PATCH 27/27] Bus fixes: Do not update MDR on read from CPU MMIO
space
Also, updates the controller read timings to be more accurate.
---
snes/config/config.cpp | 1 +
snes/config/config.hpp | 1 +
snes/cpu/cpu.cpp | 2 +
snes/cpu/memory/memory.cpp | 26 ++++++++-
snes/cpu/mmio/mmio.cpp | 14 +++--
snes/cpu/timing/joypad.cpp | 132 +++++++++++++++++++++++++++++++++++++++------
snes/cpu/timing/timing.cpp | 11 ++--
snes/cpu/timing/timing.hpp | 3 +-
snes/snes.hpp | 1 +
9 files changed, 166 insertions(+), 25 deletions(-)
diff --git a/snes/config/config.cpp b/snes/config/config.cpp
index 19831370..8dcfd7e8 100755
--- a/snes/config/config.cpp
+++ b/snes/config/config.cpp
@@ -15,6 +15,7 @@ Configuration::Configuration() {
cpu.pal_frequency = 21281370;
cpu.wram_init_value = 0x55;
cpu.alt_poll_timings = false;
+ cpu.bus_fixes = false;
smp.ntsc_frequency = 24607104; //32040.5 * 768
smp.pal_frequency = 24607104;
diff --git a/snes/config/config.hpp b/snes/config/config.hpp
index 68fe0bde..d8577e39 100755
--- a/snes/config/config.hpp
+++ b/snes/config/config.hpp
@@ -14,6 +14,7 @@ struct Configuration {
unsigned pal_frequency;
unsigned wram_init_value;
bool alt_poll_timings;
+ bool bus_fixes;
} cpu;
struct SMP {
diff --git a/snes/cpu/cpu.cpp b/snes/cpu/cpu.cpp
index e11fc882..5e8e3137 100755
--- a/snes/cpu/cpu.cpp
+++ b/snes/cpu/cpu.cpp
@@ -1,5 +1,7 @@
#include <snes/snes.hpp>
#include <cstdio>
+#include <iostream>
+#include <cassert>
#define CPU_CPP
namespace SNES {
diff --git a/snes/cpu/memory/memory.cpp b/snes/cpu/memory/memory.cpp
index 31f82c31..df439c22 100755
--- a/snes/cpu/memory/memory.cpp
+++ b/snes/cpu/memory/memory.cpp
@@ -14,10 +14,32 @@ uint8 CPU::op_read(uint32 addr, bool exec) {
status.clock_count = speed(addr);
dma_edge();
add_clocks(status.clock_count - 4);
- regs.mdr = bus.read(addr, exec);
+ //MDR presents the state held by parasitic capacitance of the external bus.
+ //This bus is not affected by reads from CPU-internal registers, only if
+ //some external device responds. SDD1 does hook some of these addresses, but
+ //passes read straight through, as expected (as the CPU probably won't
+ //monitor if external device responds, even if it broadcasts a read).
+ //
+ //We use 4000-43FF as CPU register range, and not 4000-437F it likely is
+ //for quickness of checking. This will only affect things if some device
+ //tries to map the 4380-43FF range (that device will still work correctly,
+ //but openbus in that range won't).
+ //
+ //This was discovered while investigating why one Super Metroid glitch
+ //worked on emulator but crashed on real console.
+ //
+ //a word fetch from 2f4017 AND 0xfffc results in 2f3c and a word fetch from
+ //2f4210 AND 0x7f7f results in 2f22. This also extends to long fetches
+ //by arguments. E.g. long argument fetch from 94420F with 2F already on
+ //the bus AND 0x7f7fff results in 2f222f.
+ //
+ //The reason for masking some bits in above explanation was to ignore some
+ //known bits in those registers (bits 7 of 4210 and 4211, bits 0&1 of 4017).
+ uint8_t tmp = bus.read(addr, exec);
+ if(!config.cpu.bus_fixes || (addr & 0x40FC00) != 0x004000) regs.mdr = tmp;
add_clocks(4);
alu_edge();
- return regs.mdr;
+ return tmp;
}
void CPU::op_write(uint32 addr, uint8 data) {
diff --git a/snes/cpu/mmio/mmio.cpp b/snes/cpu/mmio/mmio.cpp
index 30048c19..be2990a3 100755
--- a/snes/cpu/mmio/mmio.cpp
+++ b/snes/cpu/mmio/mmio.cpp
@@ -33,9 +33,17 @@ void CPU::mmio_w2183(uint8 data) {
//strobing $4016.d0 affects both controller port latches.
//$4017 bit 0 writes are ignored.
void CPU::mmio_w4016(uint8 data) {
- if(data&1) interface->notifyLatched();
- input.port1->latch(data & 1);
- input.port2->latch(data & 1);
+ //Only consider autoassert if both busfix and auto flags are set.
+ auto auto_asserted = (status.auto_joypad_counter & 384) == 384;
+ //Bit 6 of status.auto_joypad_counter follows "manual" latch.
+ auto oldstatus = auto_asserted || (status.auto_joypad_counter & 64) != 0;
+ status.auto_joypad_counter &= ~64;
+ status.auto_joypad_counter |= (data & 1) << 6;
+ auto newstatus = auto_asserted || (status.auto_joypad_counter & 64) != 0;
+ //If !oldstatus and newstatus, signal latch.
+ if(!oldstatus && newstatus) interface->notifyLatched();
+ input.port1->latch(newstatus);
+ input.port2->latch(newstatus);
}
//JOYSER0
diff --git a/snes/cpu/timing/joypad.cpp b/snes/cpu/timing/joypad.cpp
index afca7504..b60be020 100755
--- a/snes/cpu/timing/joypad.cpp
+++ b/snes/cpu/timing/joypad.cpp
@@ -3,11 +3,14 @@
//called every 256 clocks; see CPU::add_clocks()
void CPU::step_auto_joypad_poll() {
if(vcounter() >= (ppu.overscan() == false ? 225 : 240)) {
+ auto cycle = status.auto_joypad_counter & 63;
//cache enable state at first iteration
- if(status.auto_joypad_counter == 0) status.auto_joypad_latch = status.auto_joypad_poll;
- status.auto_joypad_active = status.auto_joypad_counter <= 15;
+ if(cycle == 0) status.auto_joypad_latch = status.auto_joypad_poll;
+ status.auto_joypad_active = cycle <= 15;
if(status.auto_joypad_active && status.auto_joypad_latch) {
- if(status.auto_joypad_counter == 0) {
+ if(cycle == 0) {
+ if(status.auto_joypad_counter & 128)
+ std::cerr << "step_auto_joypad_poll(): bus fixes set (counter=" << status.auto_joypad_counter << ")???" << std::endl;
if(dma_trace_fn) dma_trace_fn("-- Start automatic polling --");
interface->notifyLatched();
input.port1->latch(1);
@@ -23,7 +26,7 @@ void CPU::step_auto_joypad_poll() {
status.joy2 = (status.joy2 << 1) | (bool)(port1 & 1);
status.joy3 = (status.joy3 << 1) | (bool)(port0 & 2);
status.joy4 = (status.joy4 << 1) | (bool)(port1 & 2);
- if(status.auto_joypad_counter == 15) {
+ if(cycle == 15) {
char buf[512];
sprintf(buf, "-- End automatic polling [%04x %04x %04x %04x] --",
status.joy1, status.joy2, status.joy3, status.joy4);
@@ -31,32 +34,129 @@ void CPU::step_auto_joypad_poll() {
}
}
- status.auto_joypad_counter++;
+ //Only bits 0-5 are supposed to increment.
+ if(cycle < 60)
+ status.auto_joypad_counter++;
}
}
//called every 128 clocks; see CPU::add_clocks()
-void CPU::step_auto_joypad_poll_NEW(bool polarity) {
- if(status.auto_joypad_counter > 0 && status.auto_joypad_counter <= 34) {
+void CPU::step_auto_joypad_poll_NEW2(bool polarity) {
+ //Poll starts on multiple of 128 mod 256 clocks (polarity=false) on first
+ //vblank scanline. If autopoller is off, mark as done for the frame.
+ if(vcounter() >= (ppu.overscan() == false ? 225 : 240) && !polarity &&
+ (status.auto_joypad_counter & 63) == 0) {
+ if(!(status.auto_joypad_counter & 128))
+ std::cerr << "step_auto_joypad_poll_NEW2(): bus fixes clear???" << std::endl;
+ //Preserve high bits of autopoll counter.
+ auto x = status.auto_joypad_counter & ~63;
+ status.auto_joypad_counter = x | (status.auto_joypad_poll ? 1 : 36);
+ status.auto_joypad_latch = status.auto_joypad_poll;
+ }
+ //Abuse bit 6 of counter for "manual" poll flag. Bit 7 is supposed to be
+ //always set.
+ auto cycle = status.auto_joypad_counter & 63;
+ auto old_latchstate = (status.auto_joypad_counter & 320) != 0;
+ //If not enabled... This is not latched, as autopoll can be aborted.
+ if(!status.auto_joypad_poll && cycle > 0 && cycle < 36) {
+ if(dma_trace_fn) dma_trace_fn("-- Automatic polling ABORTED --");
+ status.auto_joypad_counter += (36 - cycle);
+ status.auto_joypad_active = false;
+ status.auto_joypad_latch = false;
+ //Release autopoll latch.
+ status.auto_joypad_counter &= ~256; //Autopoll clears latch.
+ auto new_latchstate = (status.auto_joypad_counter & 320) != 0;
+ if(old_latchstate && !new_latchstate) {
+ input.port1->latch(0);
+ input.port2->latch(0);
+ }
+ return;
+ }
+ //On cycle #1, latch is asserted (unless latch is already high, in this
+ //case the autopoller is supposed to force latch high too).
+ if(cycle == 1) {
+ if(dma_trace_fn) dma_trace_fn("-- Start automatic polling --");
+ //Assert autopoll latch.
+ status.auto_joypad_counter |= 256;
+ auto new_latchstate = (status.auto_joypad_counter & 320) != 0;
+ if(!old_latchstate && new_latchstate) {
+ interface->notifyLatched();
+ input.port1->latch(1);
+ input.port2->latch(1);
+ }
+ }
+ //On cycle #2, busy is asserted and controllers are cleared.
+ if(cycle == 2) {
+ status.joy1 = 0;
+ status.joy2 = 0;
+ status.joy3 = 0;
+ status.joy4 = 0;
+ status.auto_joypad_active = true;
+ }
+ //Then, on cycle #3, latch is deasserted, unless "manual" latch forces
+ //real latch high.
+ if(cycle == 3) {
+ //Release autopoll latch.
+ status.auto_joypad_counter &= ~256;
+ auto new_latchstate = (status.auto_joypad_counter & 320) != 0;
+ if(old_latchstate && !new_latchstate) {
+ input.port1->latch(0);
+ input.port2->latch(0);
+ }
+ }
+ //Then on cycles #4, #6, #8, ..., #34, a bit is shifted. Also, clock would
+ //go low, but we can not emulate that.
+ if(cycle >= 4 && cycle <= 34 && cycle % 2 == 0) {
+ uint2 port0 = input.port1->data();
+ uint2 port1 = input.port2->data();
+ status.joy1 = (status.joy1 << 1) | (bool)(port0 & 1);
+ status.joy2 = (status.joy2 << 1) | (bool)(port1 & 1);
+ status.joy3 = (status.joy3 << 1) | (bool)(port0 & 2);
+ status.joy4 = (status.joy4 << 1) | (bool)(port1 & 2);
+ }
+ //Then on cycles #5, #7, #9, ..., #35, clock drops high, But we can not
+ //emulate that.
+ //Then on cycle #35, busy flag is deasserted and poll is complete.
+ if(cycle == 35) {
+ status.auto_joypad_active = false;
+ char buf[512];
+ sprintf(buf, "-- End automatic polling [%04x %04x %04x %04x] --",
+ status.joy1, status.joy2, status.joy3, status.joy4);
+ if(dma_trace_fn) dma_trace_fn(buf);
+ }
+ //The entiere train is 35 cycles.
+ if(cycle > 0 && cycle < 36) {
+ status.auto_joypad_counter++;
+ }
+}
+
+
+//called every 128 clocks; see CPU::add_clocks()
+void CPU::step_auto_joypad_poll_NEW(bool polarity, bool new2) {
+ if(new2) return step_auto_joypad_poll_NEW2(polarity);
+ auto cycle = status.auto_joypad_counter & 63;
+ if(cycle > 0 && cycle <= 34) {
if(!status.auto_joypad_latch) {
//FIXME: Is this right, busy flag goes on even if not enabled???
- if(status.auto_joypad_counter == 1)
+ if(cycle == 1)
status.auto_joypad_active = true;
- if(status.auto_joypad_counter == 34)
+ if(cycle == 34)
status.auto_joypad_active = false;
} else {
- if(status.auto_joypad_counter == 1) {
+ if(cycle == 1) {
+ if(status.auto_joypad_counter & 128)
+ std::cerr << "step_auto_joypad_poll_NEW(): bus fixes set???" << std::endl;
if(dma_trace_fn) dma_trace_fn("-- Start automatic polling --");
status.auto_joypad_active = true;
interface->notifyLatched();
input.port1->latch(1);
input.port2->latch(1);
}
- if(status.auto_joypad_counter == 3) {
+ if(cycle == 3) {
input.port1->latch(0);
input.port2->latch(0);
}
- if((status.auto_joypad_counter & 1) != 0 && status.auto_joypad_counter != 1) {
+ if((cycle & 1) != 0 && cycle != 1) {
uint2 port0 = input.port1->data();
uint2 port1 = input.port2->data();
@@ -65,7 +165,7 @@ void CPU::step_auto_joypad_poll_NEW(bool polarity) {
status.joy3 = (status.joy3 << 1) | (bool)(port0 & 2);
status.joy4 = (status.joy4 << 1) | (bool)(port1 & 2);
}
- if(status.auto_joypad_counter == 34) {
+ if(cycle == 34) {
status.auto_joypad_active = false;
char buf[512];
sprintf(buf, "-- End automatic polling [%04x %04x %04x %04x] --",
@@ -75,9 +175,11 @@ void CPU::step_auto_joypad_poll_NEW(bool polarity) {
}
status.auto_joypad_counter++;
}
- if(vcounter() >= (ppu.overscan() == false ? 225 : 240) && status.auto_joypad_counter == 0 && !polarity) {
+ if(vcounter() >= (ppu.overscan() == false ? 225 : 240) && cycle == 0 && !polarity) {
+ //Preserve high bits of autopoller counter.
+ auto x = status.auto_joypad_counter & ~63;
status.auto_joypad_latch = status.auto_joypad_poll;
- status.auto_joypad_counter = 1;
+ status.auto_joypad_counter = x | 1;
}
}
diff --git a/snes/cpu/timing/timing.cpp b/snes/cpu/timing/timing.cpp
index d7cf24f3..ef81d891 100755
--- a/snes/cpu/timing/timing.cpp
+++ b/snes/cpu/timing/timing.cpp
@@ -17,12 +17,12 @@ void CPU::add_clocks(unsigned clocks) {
step(clocks);
- if(config.cpu.alt_poll_timings) {
+ if(config.cpu.alt_poll_timings || config.cpu.bus_fixes) {
bool opolarity = (status.auto_joypad_clock & 128);
status.auto_joypad_clock = (status.auto_joypad_clock + clocks) & 0xFF;
bool npolarity = (status.auto_joypad_clock & 128);
if(opolarity != npolarity)
- step_auto_joypad_poll_NEW(opolarity);
+ step_auto_joypad_poll_NEW(opolarity, config.cpu.bus_fixes);
} else {
status.auto_joypad_clock += clocks;
if(status.auto_joypad_clock >= 256) {
@@ -53,7 +53,8 @@ void CPU::scanline() {
status.hdma_init_position = (cpu_version == 1 ? 12 + 8 - dma_counter() : 12 + dma_counter());
status.hdma_init_triggered = false;
- status.auto_joypad_counter = 0;
+ //Only clear the low 6 bits (counter).
+ status.auto_joypad_counter &= ~63;
}
//DRAM refresh occurs once every scanline
@@ -200,7 +201,9 @@ void CPU::timing_reset() {
status.auto_joypad_active = false;
status.auto_joypad_latch = false;
- status.auto_joypad_counter = 0;
+ //Set bit 7 of joypad counter if bus fixes are active (for combined
+ //latch behavior).
+ status.auto_joypad_counter = config.cpu.bus_fixes ? 128 : 0;
status.auto_joypad_clock = 0;
}
diff --git a/snes/cpu/timing/timing.hpp b/snes/cpu/timing/timing.hpp
index bf15a727..8be2b830 100755
--- a/snes/cpu/timing/timing.hpp
+++ b/snes/cpu/timing/timing.hpp
@@ -22,4 +22,5 @@ alwaysinline bool irq_test();
//joypad.cpp
void step_auto_joypad_poll();
-void step_auto_joypad_poll_NEW(bool polarity);
+void step_auto_joypad_poll_NEW(bool polarity, bool new2);
+void step_auto_joypad_poll_NEW2(bool polarity);
diff --git a/snes/snes.hpp b/snes/snes.hpp
index 3a65e360..961842b3 100755
--- a/snes/snes.hpp
+++ b/snes/snes.hpp
@@ -3,6 +3,7 @@
#define BSNES_SUPPORTS_ADV_BREAKPOINTS
#define BSNES_SUPPORTS_ADV_BREAKPOINTS_PPU
#define BSNES_SUPPORTS_ALT_TIMINGS
+#define BSNES_SUPPORTS_BUS_FIXES
#define BSNES_SUPPORTS_TRACE_SA1
#define BSNES_SUPPORTS_DMA_TRACE
--
2.15.0.rc1

View file

@ -1,7 +1,7 @@
From 6c3da8eb6516d25e97b46d97fb0d3d24ca9ecfd0 Mon Sep 17 00:00:00 2001
From: Ilari Liusvaara <ilari.liusvaara@elisanet.fi>
Date: Wed, 9 Nov 2011 00:37:44 +0200
Subject: [PATCH 1/8] Don't use time() in emulating chips
Subject: [PATCH 1/7] Don't use time() in emulating chips
Instead of using time() in chip emulation, create new interface method
currentTime(), defaulting to time(0). This way frontend can cleanly
@ -80,5 +80,5 @@ index f1a48c0..df975e8 100755
extern Interface *interface;
--
1.8.4.4
1.8.4.rc3

View file

@ -1,7 +1,7 @@
From c87e7d9288a91db3b32b5ba4b2b74e52c0d3c11d Mon Sep 17 00:00:00 2001
From: Ilari Liusvaara <ilari.liusvaara@elisanet.fi>
Date: Wed, 9 Nov 2011 01:52:08 +0200
Subject: [PATCH 2/8] Save controller state when savestating
Subject: [PATCH 2/7] Save controller state when savestating
When savestating, save the controller state and restore it upon loadstate.
Prevents libsnes from mixing up buttons.
@ -342,5 +342,5 @@ index 9f5273d..005e731 100755
if(cartridge.mode() == Cartridge::Mode::SufamiTurbo) sufamiturbo.serialize(s);
#if defined(GAMEBOY)
--
1.8.4.4
1.8.4.rc3

View file

@ -1,7 +1,7 @@
From a62794b0bfa1d2bfc8907a1e4d4e5aa6fe3ee426 Mon Sep 17 00:00:00 2001
From: Ilari Liusvaara <ilari.liusvaara@elisanet.fi>
Date: Fri, 11 Nov 2011 19:49:46 +0200
Subject: [PATCH 3/8] Allow frontend to control random number seed
Subject: [PATCH 3/7] Allow frontend to control random number seed
---
snes/interface/interface.cpp | 5 +++++
@ -49,5 +49,5 @@ index 284e389..99901ff 100755
region = config.region;
expansion = config.expansion_port;
--
1.8.4.4
1.8.4.rc3

View file

@ -1,7 +1,7 @@
From 33ecd422954b7e15d9e83b7035b07ffb52f4e1e8 Mon Sep 17 00:00:00 2001
From: Ilari Liusvaara <ilari.liusvaara@elisanet.fi>
Date: Wed, 7 Mar 2012 16:57:18 +0200
Subject: [PATCH 4/8] Fix mouse polling
Subject: [PATCH 4/7] Fix mouse polling
Don't poll for mouse motion excessive number of times (no need to poll it for
each bit!)
@ -59,5 +59,5 @@ index b66ea51..b07c8ab 100755
+ int _position_y;
};
--
1.8.4.4
1.8.4.rc3

View file

@ -1,7 +1,7 @@
From 52a1a595f4473b4de0cdedcb018aef68108a2c73 Mon Sep 17 00:00:00 2001
From: Ilari Liusvaara <ilari.liusvaara@elisanet.fi>
Date: Mon, 24 Sep 2012 21:46:09 +0300
Subject: [PATCH 5/8] Add needed support for detecting true polls as opposed to
Subject: [PATCH 5/7] Add needed support for detecting true polls as opposed to
just autopolling
---
@ -65,5 +65,5 @@ index 8b6aaa6..c5ee930 100755
//DMAPx
uint8 CPU::mmio_r43x0(uint8 i) {
--
1.8.4.4
1.8.4.rc3

View file

@ -1,7 +1,7 @@
From 74b67f36961839fcbc1caa23930151bd9b3e9d7e Mon Sep 17 00:00:00 2001
From: Ilari Liusvaara <ilari.liusvaara@elisanet.fi>
Date: Sun, 14 Oct 2012 23:29:40 +0300
Subject: [PATCH 6/8] Fix compiling on GCC 4.7
Subject: [PATCH 6/7] Fix compiling on GCC 4.7
---
nall/string.hpp | 2 +-
@ -34,5 +34,5 @@ index 3b2be7a..ca90762 100755
#include <nall/snes/cartridge.hpp>
#include <nall/gameboy/cartridge.hpp>
--
1.8.4.4
1.8.4.rc3

View file

@ -1,7 +1,7 @@
From 5dc532e67245f1e83504be4a21fef1ab15b08af2 Mon Sep 17 00:00:00 2001
From: Ilari Liusvaara <ilari.liusvaara@elisanet.fi>
Date: Sun, 27 Oct 2013 10:52:45 +0200
Subject: [PATCH 7/8] Support notifying latches
Subject: [PATCH 7/7] Support notifying latches
---
snes/cpu/mmio/mmio.cpp | 1 +
@ -61,5 +61,5 @@ index 30ee7fd..203f7b0 100755
extern Interface *interface;
--
1.8.4.4
1.8.4.rc3

View file

@ -1,22 +0,0 @@
From ce0634fe5a8dea973ca9c357ec788740fbcfcf09 Mon Sep 17 00:00:00 2001
From: Ilari Liusvaara <ilari.liusvaara@elisanet.fi>
Date: Sat, 30 Nov 2013 10:28:05 +0200
Subject: [PATCH 8/8] Support auto-detecting bsnes version
---
bsnes.mk | 3 +++
1 file changed, 3 insertions(+)
create mode 100644 bsnes.mk
diff --git a/bsnes.mk b/bsnes.mk
new file mode 100644
index 0000000..2248b71
--- /dev/null
+++ b/bsnes.mk
@@ -0,0 +1,3 @@
+BSNES_SUPPORTS_DEBUGGER=
+LIBSNES_DIR=ui-libsnes
+BSNES_VERSION=086
--
1.8.4.4

View file

@ -1,7 +1,7 @@
From a8018b3c90314bd0c112842fe81b27e978b891eb Mon Sep 17 00:00:00 2001
From: Ilari Liusvaara <ilari.liusvaara@elisanet.fi>
Date: Wed, 9 Nov 2011 00:37:44 +0200
Subject: [PATCH 1/8] Don't use time() in emulating chips
Subject: [PATCH 1/7] Don't use time() in emulating chips
Instead of using time() in chip emulation, create new interface method
currentTime(), defaulting to time(0). This way frontend can cleanly
@ -80,5 +80,5 @@ index f1a48c0..df975e8 100755
extern Interface *interface;
--
1.8.4.4
1.8.4.rc3

View file

@ -1,7 +1,7 @@
From de423d6ec33a20f33652c6b9c8ce703b867b51bd Mon Sep 17 00:00:00 2001
From: Ilari Liusvaara <ilari.liusvaara@elisanet.fi>
Date: Wed, 9 Nov 2011 01:52:08 +0200
Subject: [PATCH 2/8] Save controller state when savestating
Subject: [PATCH 2/7] Save controller state when savestating
When savestating, save the controller state and restore it upon loadstate.
Prevents libsnes from mixing up buttons.
@ -342,5 +342,5 @@ index f746c3a..67e08a2 100755
if(cartridge.mode() == Cartridge::Mode::SufamiTurbo) sufamiturbo.serialize(s);
#if defined(GAMEBOY)
--
1.8.4.4
1.8.4.rc3

View file

@ -1,7 +1,7 @@
From e1fce124df0a1ea43324df65b9d0ee7262eda988 Mon Sep 17 00:00:00 2001
From: Ilari Liusvaara <ilari.liusvaara@elisanet.fi>
Date: Fri, 11 Nov 2011 19:49:46 +0200
Subject: [PATCH 3/8] Allow frontend to control random number seed
Subject: [PATCH 3/7] Allow frontend to control random number seed
---
snes/interface/interface.cpp | 5 +++++
@ -49,5 +49,5 @@ index 9b70bbf..cbd096c 100755
region = config.region;
expansion = config.expansion_port;
--
1.8.4.4
1.8.4.rc3

View file

@ -1,7 +1,7 @@
From 21e21c3b953f499bb3e309ff6a04b38763e7910a Mon Sep 17 00:00:00 2001
From: Ilari Liusvaara <ilari.liusvaara@elisanet.fi>
Date: Wed, 7 Mar 2012 16:57:18 +0200
Subject: [PATCH 4/8] Fix mouse polling
Subject: [PATCH 4/7] Fix mouse polling
Don't poll for mouse motion excessive number of times (no need to poll it for
each bit!)
@ -59,5 +59,5 @@ index b66ea51..b07c8ab 100755
+ int _position_y;
};
--
1.8.4.4
1.8.4.rc3

View file

@ -1,7 +1,7 @@
From 9b14075f51587694015f8507f1c7cb565fee8225 Mon Sep 17 00:00:00 2001
From: Ilari Liusvaara <ilari.liusvaara@elisanet.fi>
Date: Mon, 24 Sep 2012 21:46:09 +0300
Subject: [PATCH 5/8] Add needed support for detecting true polls as opposed to
Subject: [PATCH 5/7] Add needed support for detecting true polls as opposed to
just autopolling
---
@ -65,5 +65,5 @@ index 8b6aaa6..c5ee930 100755
//DMAPx
uint8 CPU::mmio_r43x0(uint8 i) {
--
1.8.4.4
1.8.4.rc3

View file

@ -1,7 +1,7 @@
From 8c41bf9b792c08ecbf22a87d4e85f3e4801e62d2 Mon Sep 17 00:00:00 2001
From: Ilari Liusvaara <ilari.liusvaara@elisanet.fi>
Date: Sun, 14 Oct 2012 23:25:33 +0300
Subject: [PATCH 6/8] Add missing include to libsnes.cpp
Subject: [PATCH 6/7] Add missing include to libsnes.cpp
---
target-libsnes/libsnes.cpp | 1 +
@ -19,5 +19,5 @@ index 3b2be7a..ca90762 100755
#include <nall/snes/cartridge.hpp>
#include <nall/gameboy/cartridge.hpp>
--
1.8.4.4
1.8.4.rc3

View file

@ -1,7 +1,7 @@
From 13643c86bfff3871968cf6e8b4f991465d4e81e7 Mon Sep 17 00:00:00 2001
From: Ilari Liusvaara <ilari.liusvaara@elisanet.fi>
Date: Sun, 27 Oct 2013 10:52:45 +0200
Subject: [PATCH 7/8] Support notifying latches
Subject: [PATCH 7/7] Support notifying latches
---
snes/cpu/mmio/mmio.cpp | 1 +
@ -61,5 +61,5 @@ index 30ee7fd..203f7b0 100755
extern Interface *interface;
--
1.8.4.4
1.8.4.rc3

View file

@ -1,22 +0,0 @@
From e74f6d6ce7b369d82abf1eed6d7c3e99af0d8f64 Mon Sep 17 00:00:00 2001
From: Ilari Liusvaara <ilari.liusvaara@elisanet.fi>
Date: Sat, 30 Nov 2013 10:28:40 +0200
Subject: [PATCH 8/8] Support auto-dectecting bsnes version
---
bsnes.mk | 3 +++
1 file changed, 3 insertions(+)
create mode 100644 bsnes.mk
diff --git a/bsnes.mk b/bsnes.mk
new file mode 100644
index 0000000..c31911f
--- /dev/null
+++ b/bsnes.mk
@@ -0,0 +1,3 @@
+BSNES_SUPPORTS_DEBUGGER=
+LIBSNES_DIR=target-libsnes
+BSNES_VERSION=087
--
1.8.4.4

View file

@ -1,124 +0,0 @@
#include <boost/filesystem.hpp>
#include <sys/time.h>
#include <fstream>
#include <cctype>
#include <set>
#include <map>
#include <iostream>
#include <string>
namespace boost_fs = boost::filesystem;
bool is_cmdhelp_file(const std::string& filename)
{
std::string _filename = filename;
return (_filename.length() > 8 && _filename.substr(0, 8) == "cmdhelp/");
}
std::string search_include(const std::list<std::string>& searchpath, const std::string& _filename,
const std::string& ref_by)
{
std::string filename = _filename;
//Hack: process cmdhelp includes internally as the date were for the JSON include.
if(is_cmdhelp_file(filename)) {
if(filename != "cmdhelp/inverselist.hpp") {
filename = "../src/" + filename;
//Replace the extension with .json.
size_t split = filename.find_last_of("./\\");
if(split < filename.length() && filename[split] == '.') {
filename = filename.substr(0, split) + ".json";
}
}
}
size_t p = ref_by.find_last_of("/");
if(p < ref_by.length()) {
std::string i = ref_by;
i = i.substr(0, p);
std::string real_fn = i + "/" + filename;
boost_fs::path p(real_fn);
if(boost_fs::exists(p) && boost_fs::is_regular_file(p))
return real_fn;
}
for(auto& i : searchpath) {
std::string real_fn = i + "/" + filename;
boost_fs::path p(real_fn);
if(boost_fs::exists(p) && boost_fs::is_regular_file(p))
return real_fn;
}
std::cerr << "WARNING: Include file '" << filename << "' not found." << std::endl;
return "";
}
time_t get_timestamp(const std::string& path)
{
boost_fs::path p(path);
if(!boost_fs::exists(p)) return 0;
return boost_fs::last_write_time(p);
}
time_t recursive_scan(const std::list<std::string>& searchpath, const std::string& filename,
std::map<std::string, time_t>& scanned)
{
if(filename == "")
return 0;
if(scanned.count(filename))
return 0;
std::ifstream fp(filename);
if(!fp) {
std::cerr << "WARNING: File '" << filename << "' can't be opened." << std::endl;
return 0;
}
time_t newest = get_timestamp(filename);
scanned[filename] = newest;
std::string tmp;
while(std::getline(fp, tmp)) {
if(tmp.length() > 0 && tmp[0] == '#') {
//Possibly include.
std::string included;
if(strncmp(tmp.c_str(), "#include", 8))
continue;
size_t ptr = 8;
while(ptr < tmp.length() && isspace((unsigned char)tmp[ptr]))
ptr++;
if(ptr == tmp.length())
continue;
if(tmp[ptr] != '\"')
continue;
size_t iptr = ++ptr;
while(ptr < tmp.length() && tmp[ptr] != '\"')
ptr++;
if(ptr == tmp.length())
continue;
included = tmp.substr(iptr, ptr - iptr);
newest = std::max(newest, recursive_scan(searchpath, search_include(searchpath, included,
filename), scanned));
}
}
return newest;
}
int main(int argc, char** argv)
{
std::list<std::string> searchpath;
std::list<std::string> files;
bool step = false;
for(int i = 1; i < argc; i++) {
if(!step && !strcmp(argv[i], "--"))
step = true;
else if(!step)
searchpath.push_back(argv[i]);
else
files.push_back(argv[i]);
}
searchpath.push_back(".");
for(auto& i : files) {
std::map<std::string, time_t> x;
time_t t = recursive_scan(searchpath, i, x);
if(get_timestamp(i + ".dep") < t) {
std::ofstream y(i + ".dep");
for(auto& j : x)
y << j.second << " " << j.first << std::endl;
}
}
return 0;
}

View file

@ -1,91 +0,0 @@
#include <iostream>
#include <fstream>
#include <sstream>
#include <cstring>
const char* hexes = "0123456789ABCDEF";
struct encoder
{
encoder(std::ostream& _output) : output(_output)
{
have_quote = false;
}
size_t operator()(unsigned char* buf, size_t bufuse, bool eof)
{
if(!bufuse) return 0;
std::ostringstream out;
size_t i = 0;
while(i < bufuse) {
if(!have_quote) {
out << "\"";
have_quote = true;
}
unsigned char ch = buf[i];
if(ch == 9) {
out << "\\t";
} else if(ch == 10) {
out << "\\n\"" << std::endl;
have_quote = false;
} else if(ch == 13) {
out << "\\r";
} else if(ch < 32) {
out << "\\x" << hexes[(ch >> 4)] << hexes[ch & 15];
} else if(ch == '\"') {
out << "\\\"";
} else if(ch == '\\') {
out << "\\\\";
} else if(ch < 127) {
out << ch;
} else {
out << "\\x" << hexes[(ch >> 4)] << hexes[ch & 15];
}
i++;
}
output << out.str();
return i;
}
size_t operator()()
{
if(have_quote) {
output << "\"";
have_quote = false;
}
}
private:
std::ostream& output;
bool have_quote;
};
void do_encode(std::istream& input, std::ostream& output)
{
char buf[4096];
size_t bufuse = 0;
bool eof = false;
encoder e(output);
while(true) {
if(!eof) {
input.read(buf + bufuse, 4096 - bufuse);
bufuse += input.gcount();
}
if(!input)
eof = true;
size_t bytes = e(reinterpret_cast<unsigned char*>(buf), bufuse, eof);
memmove(buf, buf + bytes, bufuse - bytes);
bufuse -= bytes;
if(eof && !bufuse) break;
}
e();
}
int main(int argc, char** argv)
{
if(argc != 3) {
std::cerr << "Usage: txt2cstr <symbol> <file>" << std::endl;
return 1;
}
std::ifstream in(argv[2], std::ios::binary);
std::cout << "const char* " << argv[1] << " =" << std::endl;
do_encode(in, std::cout);
std::cout << ";" << std::endl;
}

@ -1 +0,0 @@
Subproject commit a77b5548ae91cf66d1d18d4fbe2aa76eb39c7ea3

View file

@ -1,2 +0,0 @@
#pragma once
namespace STUBS { extern const char* inverse_cmd_list[]; }

View file

@ -4,48 +4,30 @@
#include <string>
#include <set>
#include <stdexcept>
#include <iostream>
#include <functional>
#include "library/framebuffer.hpp"
#include "library/dispatch.hpp"
#include "library/threads.hpp"
class master_dumper;
class dumper_factory_base;
class dumper_base;
class lua_state;
class dumper_factory_base
class adv_dumper
{
public:
/**
* Notifier base.
*/
class notifier
{
public:
virtual ~notifier() throw();
virtual void dumpers_updated() throw() = 0;
};
/**
* Detail flags.
*/
static const unsigned target_type_mask;
static const unsigned target_type_file;
static const unsigned target_type_prefix;
static const unsigned target_type_special;
static unsigned target_type_mask;
static unsigned target_type_file;
static unsigned target_type_prefix;
static unsigned target_type_special;
/**
* Register a dumper.
*
* Parameter id: The ID of dumper.
* Throws std::bad_alloc: Not enough memory.
*/
dumper_factory_base(const std::string& id);
adv_dumper(const std::string& id) throw(std::bad_alloc);
/**
* Unregister a dumper.
*/
~dumper_factory_base();
~adv_dumper();
/**
* Get ID of dumper.
*
@ -58,14 +40,14 @@ public:
* Returns: The set.
* Throws std::bad_alloc: Not enough memory.
*/
static std::set<dumper_factory_base*> get_dumper_set();
static std::set<adv_dumper*> get_dumper_set() throw(std::bad_alloc);
/**
* List all valid submodes.
*
* Returns: List of all valid submodes. Empty list means this dumper has no submodes.
* Throws std::bad_alloc: Not enough memory.
*/
virtual std::set<std::string> list_submodes() = 0;
virtual std::set<std::string> list_submodes() throw(std::bad_alloc) = 0;
/**
* Get mode details
*
@ -86,7 +68,7 @@ public:
* Returns: The name.
* Throws std::bad_alloc: Not enough memory.
*/
virtual std::string name() = 0;
virtual std::string name() throw(std::bad_alloc) = 0;
/**
* Get human-readable name for submode.
*
@ -94,193 +76,31 @@ public:
* Returns: The name.
* Throws std::bad_alloc: Not enough memory.
*/
virtual std::string modename(const std::string& mode) = 0;
virtual std::string modename(const std::string& mode) throw(std::bad_alloc) = 0;
/**
* Is this dumper busy dumping?
*
* Return: True if busy, false if not.
*/
virtual bool busy() = 0;
/**
* Start dump.
*
* parameter mode: The mode to dump using.
* parameter targetname: The target filename or prefix.
* returns: The dumper object.
* Throws std::bad_alloc: Not enough memory.
* Throws std::runtime_error: Can't start dump.
*/
virtual dumper_base* start(master_dumper& _mdumper, const std::string& mode, const std::string& targetname)
= 0;
virtual void start(const std::string& mode, const std::string& targetname) throw(std::bad_alloc,
std::runtime_error) = 0;
/**
* Is hidden?
* End current dump.
*/
virtual bool hidden() const { return false; }
/**
* Add dumper update notifier object.
*/
static void add_notifier(notifier& n);
/**
* Remove dumper update notifier object.
*/
static void drop_notifier(notifier& n);
/**
* Notify ctor finished.
*/
void ctor_notify();
/**
* Notify dumper change.
*/
static void run_notify();
virtual void end() throw() = 0;
private:
std::string d_id;
};
class master_dumper
{
public:
/**
* Information about run.
*/
struct gameinfo
{
public:
/**
* Construct game info.
*/
gameinfo();
/**
* Game name.
*/
std::string gamename;
/**
* Run length in seconds.
*/
double length;
/**
* Rerecord count (base 10 ASCII)
*/
std::string rerecords;
/**
* Authors. The first components are real names, the second components are nicknames. Either (but not both) may be
* blank.
*/
std::vector<std::pair<std::string, std::string>> authors;
/**
* Format human-redable representation of the length.
*
* Parameter digits: Number of sub-second digits to use.
* Returns: The time formated.
* Throws std::bad_alloc: Not enough memory.
*/
std::string get_readable_time(unsigned digits) const;
/**
* Get number of authors.
*
* Returns: Number of authors.
*/
size_t get_author_count() const throw();
/**
* Get short name of author (nickname if present, otherwise full name).
*
* Parameter idx: Index of author (0-based).
* Returns: The short name.
* Throws std::bad_alloc: Not enough memory.
*/
std::string get_author_short(size_t idx) const;
/**
* Get long name of author (full name and nickname if present).
*
* Parameter idx: Index of author (0-based).
* Returns: The long name.
* Throws std::bad_alloc: Not enough memory.
*/
std::string get_author_long(size_t idx) const;
/**
* Get rerecord count as a number. If rerecord count is too high, returns the maximum representatible count.
*
* Returns: The rerecord count.
*/
uint64_t get_rerecords() const throw();
};
/**
* Notifier.
*/
class notifier
{
public:
virtual ~notifier() throw();
virtual void dump_status_change() = 0;
};
/**
* Ctor.
*/
master_dumper(lua_state& _lua2);
/**
* Get instance for specified dumper.
*/
dumper_base* get_instance(dumper_factory_base* dumper) throw();
/**
* Is dumper busy in this instance?
*/
bool busy(dumper_factory_base* dumper) throw()
{
return get_instance(dumper) != NULL;
}
/**
* Call start on dumper.
*/
dumper_base* start(dumper_factory_base& factory, const std::string& mode, const std::string& targetname);
/**
* Add dumper update notifier object.
*/
void add_notifier(notifier& n);
/**
* Remove dumper update notifier object.
*/
void drop_notifier(notifier& n);
/**
* Add dumper update notifier object.
*/
void add_dumper(dumper_base& n);
/**
* Remove dumper update notifier object.
*/
void drop_dumper(dumper_base& n);
/**
* Get number of active dumpers.
*/
unsigned get_dumper_count() throw();
/**
* Call all notifiers (on_frame).
*/
void on_frame(struct framebuffer::raw& _frame, uint32_t fps_n, uint32_t fps_d);
/**
* Call all notifiers (on_sample).
*/
void on_sample(short l, short r);
/**
* Call all notifiers (on_rate_change)
*
* Also changes builtin rate variables.
*/
void on_rate_change(uint32_t n, uint32_t d);
/**
* Call all notifiers (on_gameinfo_change)
*
* Also changes builtin gameinfo structure.
*/
void on_gameinfo_change(const gameinfo& gi);
/**
* Get current sound rate in effect.
*/
std::pair<uint32_t, uint32_t> get_rate();
/**
* Get current gameinfo in effect.
*/
const gameinfo& get_gameinfo();
/**
* End all dumps.
*/
void end_dumps();
/**
* Set output stream.
*/
void set_output(std::ostream* _output);
/**
* Render Lua HUD on video.
*
@ -288,6 +108,9 @@ public:
* Parameter source: The source screen to read.
* Parameter hscl: The horizontal scale factor.
* Parameter vscl: The vertical scale factor.
* Parameter roffset: Red offset.
* Parameter goffset: Green offset.
* Parameter boffset: Blue offset.
* Parameter lgap: Left gap.
* Parameter tgap: Top gap.
* Parameter rgap: Right gap
@ -295,84 +118,13 @@ public:
* Parameter fn: Function to call between running lua hooks and actually rendering.
* Returns: True if frame should be dumped, false if not.
*/
template<bool X> bool render_video_hud(struct framebuffer::fb<X>& target, struct framebuffer::raw& source,
uint32_t hscl, uint32_t vscl, uint32_t lgap, uint32_t tgap, uint32_t rgap, uint32_t bgap,
std::function<void()> fn);
template<bool X> bool render_video_hud(struct framebuffer<X>& target, struct framebuffer_raw& source, uint32_t hscl,
uint32_t vscl, uint32_t roffset, uint32_t goffset, uint32_t boffset, uint32_t lgap, uint32_t tgap,
uint32_t rgap, uint32_t bgap, void(*fn)());
/**
* Calculate number of sound samples to drop due to dropped frame.
*/
uint64_t killed_audio_length(uint32_t fps_n, uint32_t fps_d, double& fraction);
private:
void statuschange();
friend class dumper_base;
std::map<dumper_factory_base*, dumper_base*> dumpers;
std::set<notifier*> notifications;
std::set<dumper_base*> sdumpers;
uint32_t current_rate_n;
uint32_t current_rate_d;
gameinfo current_gi;
std::ostream* output;
threads::rlock lock;
lua_state& lua2;
};
class dumper_base
{
public:
dumper_base();
dumper_base(master_dumper& _mdumper, dumper_factory_base& _fbase);
virtual ~dumper_base() throw();
/**
* New frame available.
*/
virtual void on_frame(struct framebuffer::raw& _frame, uint32_t fps_n, uint32_t fps_d) = 0;
/**
* New sample available.
*/
virtual void on_sample(short l, short r) = 0;
/**
* Sample rate is changing.
*/
virtual void on_rate_change(uint32_t n, uint32_t d) = 0;
/**
* Gameinfo is changing.
*/
virtual void on_gameinfo_change(const master_dumper::gameinfo& gi) = 0;
/**
* Dump is being forcibly ended.
*/
virtual void on_end() = 0;
/**
* Render Lua HUD on video. samples_killed is incremented if needed.
*
* Parameter target: The target screen to render on.
* Parameter source: The source screen to read.
* Parameter fps_n: Fps numerator.
* Parameter fps_d: Fps denominator.
* Parameter hscl: The horizontal scale factor.
* Parameter vscl: The vertical scale factor.
* Parameter lgap: Left gap.
* Parameter tgap: Top gap.
* Parameter rgap: Right gap
* Parameter bgap: Bottom gap.
* Parameter fn: Function to call between running lua hooks and actually rendering.
* Returns: True if frame should be dumped, false if not.
*/
template<bool X> bool render_video_hud(struct framebuffer::fb<X>& target, struct framebuffer::raw& source,
uint32_t fps_n, uint32_t fps_d, uint32_t hscl, uint32_t vscl, uint32_t lgap, uint32_t tgap,
uint32_t rgap, uint32_t bgap, std::function<void()> fn)
{
bool r = mdumper->render_video_hud(target, source, hscl, vscl, lgap, tgap, rgap, bgap, fn);
if(!r)
samples_killed += mdumper->killed_audio_length(fps_n, fps_d, akillfrac);
return r;
}
private:
friend class master_dumper;
uint64_t samples_killed;
master_dumper* mdumper;
dumper_factory_base* fbase;
double akillfrac;
};
uint64_t killed_audio_length(uint32_t fps_n, uint32_t fps_d, double& fraction);
#endif

View file

@ -1,108 +0,0 @@
#ifndef _audioapi_driver__hpp__included__
#define _audioapi_driver__hpp__included__
#include <stdexcept>
#include <string>
#include <map>
class audioapi_instance;
//All the following need to be implemented by the sound driver itself
struct _audioapi_driver
{
//These correspond to various audioapi_driver_* functions.
void (*init)() throw();
void (*quit)() throw();
void (*enable)(bool enable);
bool (*initialized)();
void (*set_device)(const std::string& pdev, const std::string& rdev);
std::string (*get_device)(bool rec);
std::map<std::string, std::string> (*get_devices)(bool rec);
const char* (*name)();
};
struct audioapi_driver
{
audioapi_driver(struct _audioapi_driver driver);
};
/**
* Initialize the driver.
*/
void audioapi_driver_init() throw();
/**
* Deinitialize the driver.
*/
void audioapi_driver_quit() throw();
/**
* Enable or disable sound.
*
* parameter enable: Enable sounds if true, otherwise disable sounds.
*/
void audioapi_driver_enable(bool enable) throw();
/**
* Has the sound system been successfully initialized?
*
* Returns: True if sound system has successfully initialized, false otherwise.
*/
bool audioapi_driver_initialized();
/**
* Set sound device (playback).
*
* - If new sound device is invalid, the sound device is not changed.
*
* Parameter pdev: The new sound device (playback).
* Parameter rdev: The new sound device (recording)
*/
void audioapi_driver_set_device(const std::string& pdev, const std::string& rdev);
/**
* Get current sound device (playback).
*
* Returns: The current sound device.
*/
std::string audioapi_driver_get_device(bool rec);
/**
* Get available sound devices (playback).
*
* Returns: The map of devices. Keyed by name of the device, values are human-readable names for devices.
*/
std::map<std::string, std::string> audioapi_driver_get_devices(bool rec);
/**
* Identification for sound plugin.
*/
const char* audioapi_driver_name() throw();
/**
* Add an instance to be mixed.
*/
void audioapi_connect_instance(audioapi_instance& instance);
/**
* Remove an instance from being mixed.
*/
void audioapi_disconnect_instance(audioapi_instance& instance);
/**
* Send a rate change.
*/
void audioapi_send_rate_change(unsigned rrate, unsigned prate);
/**
* Broadcast voice input to all instances.
*/
void audioapi_put_voice(float* samples, size_t count);
/**
* Get mixed music + voice out from all instances.
*/
void audioapi_get_mixed(int16_t* samples, size_t count, bool stereo);
#endif

View file

@ -1,55 +1,50 @@
#ifndef _audioapi__hpp__included__
#define _audioapi__hpp__included__
#include "library/threads.hpp"
#include <map>
#include <cstdint>
#include <cstdlib>
#include <string>
#include <stdexcept>
class audioapi_instance
{
public:
/**
* Audio API music buffer.
*/
struct buffer
{
struct audioapi_buffer
{
/**
* The samples.
*
* Note: May be NULL if no samples are available..
*/
int16_t* samples;
int16_t* samples;
/**
* Playback pointer in samples structure.
*/
size_t pointer;
size_t pointer;
/**
* Total number of samples in this buffer.
*/
size_t total;
size_t total;
/**
* True if buffer is stereo, false if mono.
*/
bool stereo;
bool stereo;
/**
* The rate in samples per second the buffer is supposed to be played at.
*/
double rate;
};
double rate;
};
/**
* Audio API VU calculator.
*/
struct vumeter
{
struct audioapi_vumeter
{
/**
* Initialize.
*/
vumeter();
audioapi_vumeter();
/**
* Submit samples.
*
@ -59,34 +54,38 @@ public:
* Parameter rate: Sound sampling rate.
* Parameter scale: Value to scale the samples by.
*/
void operator()(float* samples, size_t count, bool stereo, double rate, double scale);
void operator()(float* samples, size_t count, bool stereo, double rate, double scale);
/**
* Get VU value in dB.
*/
operator float() const throw() { return vu; }
private:
double accumulator;
size_t samples;
float vu;
void update_vu();
};
//Resampler.
class resampler
{
public:
resampler();
//After call, either insize or outsize is zero.
void resample(float*& in, size_t& insize, float*& out, size_t& outsize, double ratio, bool stereo);
private:
double position;
double vAl, vBl, vCl, vDl, vAr, vBr, vCr, vDr;
};
/**
* Ctor.
*/
audioapi_instance();
~audioapi_instance();
operator float() const throw() { return vu; }
private:
double accumulator;
size_t samples;
float vu;
void update_vu();
};
//VU values.
extern audioapi_vumeter audioapi_vu_mleft;
extern audioapi_vumeter audioapi_vu_mright;
extern audioapi_vumeter audioapi_vu_vout;
extern audioapi_vumeter audioapi_vu_vin;
//Resampler.
class audioapi_resampler
{
public:
audioapi_resampler();
//After call, either insize or outsize is zero.
void resample(float*& in, size_t& insize, float*& out, size_t& outsize, double ratio, bool stereo);
private:
double position;
double vAl, vBl, vCl, vDl, vAr, vBr, vCr, vDr;
};
//The following are intended to be used by the emulator core.
/**
* Submit a buffer for playback on music channel.
*
@ -95,97 +94,114 @@ public:
* Parameter stereo: If true, the signal is stereo. If false, mono.
* Parameter rate: Rate of buffer in samples per second.
*/
void submit_buffer(int16_t* samples, size_t count, bool stereo, double rate);
void audioapi_submit_buffer(int16_t* samples, size_t count, bool stereo, double rate);
/**
* Get the voice channel playback/record rate.
*
* Returns: The rate in samples per second (first for recording, then for playback).
*/
std::pair<unsigned,unsigned> voice_rate();
std::pair<unsigned,unsigned> audioapi_voice_rate();
/**
* Get the voice channel nominal playback/record rate.
*
* Returns: The rate in samples per second.
*/
unsigned orig_voice_rate();
unsigned audioapi_orig_voice_rate();
/**
* Get the voice channel playback status register.
*
* Returns: The number of samples free for playback.
*/
unsigned voice_p_status();
unsigned audioapi_voice_p_status();
/**
* Get the voice channel playback status register2.
*
* Returns: The number of samples in playback buffer.
*/
unsigned voice_p_status2();
unsigned audioapi_voice_p_status2();
/**
* Get the voice channel record status register.
*
* Returns: The number of samples in capture buffer.
*/
unsigned voice_r_status();
unsigned audioapi_voice_r_status();
/**
* Play sound on voice channel.
*
* Parameter samples: The samples to play.
* Parameter count: Number of samples to play. Must be less than number of samples free for playback.
*/
void play_voice(float* samples, size_t count);
void audioapi_play_voice(float* samples, size_t count);
/**
* Capture sound on voice channel.
*
* Parameter samples: The buffer to store captured samples to.
* Parameter count: Number of samples to capture. Must be less than number of samples used for capture.
*/
void record_voice(float* samples, size_t count);
void audioapi_record_voice(float* samples, size_t count);
/**
* Init the audio. Call on emulator startup.
*/
void init();
void audioapi_init();
/**
* Quit the audio. Call on emulator shutdown.
*/
void quit();
void audioapi_quit();
/**
* Set music volume.
*
* Parameter volume: The volume (0-1).
*/
void music_volume(float volume);
void audioapi_music_volume(float volume);
/**
* Get music volume.
*
* Returns: The music volume.
*/
float music_volume();
float audioapi_music_volume();
/**
* Set voice playback volume.
*
* Parameter volume: The volume (0-1).
*/
void voicep_volume(float volume);
void audioapi_voicep_volume(float volume);
/**
* Get voice playback volume.
*
* Returns: The voice playback volume.
*/
float voicep_volume();
float audioapi_voicep_volume();
/**
* Set voice capture volume.
*
* Parameter volume: The volume (0-1).
*/
void voicer_volume(float volume);
void audioapi_voicer_volume(float volume);
/**
* Get voice capture volume.
*
* Returns: The voice capture volume.
*/
float voicer_volume();
float audioapi_voicer_volume();
//The following are intended to be used by the driver from the callback
/**
* Get mixed music + voice buffer to play (at voice rate).
*
@ -193,7 +209,8 @@ public:
* Parameter count: Number of samples to generate.
* Parameter stereo: If true, return stereo buffer, else mono.
*/
void get_mixed(int16_t* samples, size_t count, bool stereo);
void audioapi_get_mixed(int16_t* samples, size_t count, bool stereo);
/**
* Get music channel buffer to play.
*
@ -202,7 +219,8 @@ public:
*
* Note: This should only be called from the sound driver.
*/
struct buffer get_music(size_t played);
struct audioapi_buffer audioapi_get_music(size_t played);
/**
* Get voice channel buffer to play.
*
@ -211,7 +229,8 @@ public:
*
* Note: This should only be called from the sound driver.
*/
void get_voice(float* samples, size_t count);
void audioapi_get_voice(float* samples, size_t count);
/**
* Put recorded voice channel buffer.
*
@ -221,7 +240,8 @@ public:
* Note: Even if audio driver does not support capture, one should send in silence.
* Note: This should only be called from the sound driver.
*/
void put_voice(float* samples, size_t count);
void audioapi_put_voice(float* samples, size_t count);
/**
* Set the voice channel playback/record rate.
*
@ -231,56 +251,80 @@ public:
* Note: This should only be called from the sound driver.
* Note: Setting rate to 0 enables dummy callbacks.
*/
void voice_rate(unsigned rate_r, unsigned rate_p);
/**
* Suppress all future VU updates.
*/
static void disable_vu_updates();
//Vu values.
vumeter vu_mleft;
vumeter vu_mright;
vumeter vu_vout;
vumeter vu_vin;
private:
struct dummy_cb_proc
{
dummy_cb_proc(audioapi_instance& _parent);
int operator()();
audioapi_instance& parent;
};
dummy_cb_proc dummyproc;
threads::thread* dummythread;
//3 music buffers is not enough due to huge blocksizes used by SDL.
const static unsigned MUSIC_BUFFERS = 8;
const static unsigned voicep_bufsize = 65536;
const static unsigned voicer_bufsize = 65536;
const static unsigned music_bufsize = 8192;
float voicep_buffer[voicep_bufsize];
float voicer_buffer[voicer_bufsize];
int16_t music_buffer[MUSIC_BUFFERS * music_bufsize];
volatile bool music_stereo[MUSIC_BUFFERS];
volatile double music_rate[MUSIC_BUFFERS];
volatile size_t music_size[MUSIC_BUFFERS];
unsigned music_ptr;
unsigned last_complete_music_seen;
volatile unsigned last_complete_music;
volatile unsigned voicep_get;
volatile unsigned voicep_put;
volatile unsigned voicer_get;
volatile unsigned voicer_put;
volatile unsigned voice_rate_play;
volatile unsigned orig_voice_rate_play;
volatile unsigned voice_rate_rec;
volatile bool dummy_cb_active_record;
volatile bool dummy_cb_active_play;
volatile bool dummy_cb_quit;
volatile float _music_volume;
volatile float _voicep_volume;
volatile float _voicer_volume;
resampler music_resampler;
bool last_adjust; //Adjusting consequtively is too hard.
static bool vu_disabled;
void audioapi_voice_rate(unsigned rate_r, unsigned rate_p);
//All the following need to be implemented by the sound driver itself
struct _audioapi_driver
{
//These correspond to various audioapi_driver_* functions.
void (*init)() throw();
void (*quit)() throw();
void (*enable)(bool enable);
bool (*initialized)();
void (*set_device)(const std::string& pdev, const std::string& rdev);
std::string (*get_device)(bool rec);
std::map<std::string, std::string> (*get_devices)(bool rec);
const char* (*name)();
};
struct audioapi_driver
{
audioapi_driver(struct _audioapi_driver driver);
};
/**
* Initialize the driver.
*/
void audioapi_driver_init() throw();
/**
* Deinitialize the driver.
*/
void audioapi_driver_quit() throw();
/**
* Enable or disable sound.
*
* parameter enable: Enable sounds if true, otherwise disable sounds.
*/
void audioapi_driver_enable(bool enable) throw();
/**
* Has the sound system been successfully initialized?
*
* Returns: True if sound system has successfully initialized, false otherwise.
*/
bool audioapi_driver_initialized();
/**
* Set sound device (playback).
*
* - If new sound device is invalid, the sound device is not changed.
*
* Parameter pdev: The new sound device (playback).
* Parameter rdev: The new sound device (recording)
*/
void audioapi_driver_set_device(const std::string& pdev, const std::string& rdev) throw(std::bad_alloc,
std::runtime_error);
/**
* Get current sound device (playback).
*
* Returns: The current sound device.
*/
std::string audioapi_driver_get_device(bool rec) throw(std::bad_alloc);
/**
* Get available sound devices (playback).
*
* Returns: The map of devices. Keyed by name of the device, values are human-readable names for devices.
*/
std::map<std::string, std::string> audioapi_driver_get_devices(bool rec) throw(std::bad_alloc);
/**
* Identification for sound plugin.
*/
const char* audioapi_driver_name() throw();
#endif

View file

@ -1,31 +1,13 @@
#ifndef _command__hpp__included__
#define _command__hpp__included__
#include "library/command.hpp"
#include "library/threads.hpp"
#include <stdexcept>
#include <string>
#include <set>
#include "library/commands.hpp"
extern command::set lsnes_cmds;
extern command_group lsnes_cmd;
namespace keyboard
{
class mapper;
class invbind;
}
class alias_binds_manager
{
public:
alias_binds_manager(keyboard::mapper& _mapper, command::group& _command);
~alias_binds_manager();
void operator()();
private:
keyboard::mapper& mapper;
command::group& command;
threads::lock mut;
std::map<std::string, keyboard::invbind*> alias_binds;
};
void refresh_alias_binds();
#endif

View file

@ -1,154 +1,20 @@
#ifndef _controller__hpp__included__
#define _controller__hpp__included__
#include <string>
#include <map>
#include "library/dispatch.hpp"
#include "library/command.hpp"
#include "controllerframe.hpp"
#include "project.hpp"
struct project_info;
struct controller_state;
struct emu_framebuffer;
struct emulator_dispatch;
struct lua_state;
struct core_core;
namespace keyboard { class invbind; }
namespace keyboard { class ctrlrkey; }
namespace keyboard { class mapper; }
namespace keyboard { class keyboard; }
namespace portctrl { struct type; }
namespace portctrl { struct controller; }
class button_mapping
{
public:
struct controller_bind
{
std::string cclass;
unsigned number;
std::string name;
int mode; //0 => Button, 1 => Axis pair, 2 => Single axis.
bool xrel;
bool yrel;
unsigned control1;
unsigned control2; //Axis only, UINT_MAX if not valid.
int16_t rmin;
int16_t rmax;
bool centered;
};
struct active_bind
{
unsigned port;
unsigned controller;
struct controller_bind bind;
};
struct controller_triple
{
std::string cclass;
unsigned port;
unsigned controller;
bool operator<(const struct controller_triple& t) const throw()
{
if(cclass < t.cclass) return true;
if(cclass > t.cclass) return false;
if(port < t.port) return true;
if(port > t.port) return false;
if(controller < t.controller) return true;
if(controller > t.controller) return false;
return false;
}
bool operator==(const struct controller_triple& t) const throw()
{
return (cclass == t.cclass && port == t.port && controller == t.controller);
}
};
/**
* Ctor.
*/
button_mapping(controller_state& _controls, keyboard::mapper& mapper, keyboard::keyboard& keyboard,
emu_framebuffer& fbuf, emulator_dispatch& _dispatch, lua_state& _lua2, command::group& _cmd);
/**
* Dtor.
*/
~button_mapping();
/**
* Reread active buttons.
*/
void reread();
/**
* Reinitialize buttons.
*/
void reinit();
/**
* Load macros.
*/
void load(controller_state& ctrlstate);
/**
* Load macros (from project).
*/
void load(controller_state& ctrlstate, project_info& pinfo);
/**
* Cleanup memory used.
*/
void cleanup();
/**
* Lookup button by name.
*/
std::pair<int, int> byname(const std::string& name);
/**
* Map of button keys.
*/
std::map<std::string, std::string> button_keys;
private:
void do_analog_action(const std::string& a);
void do_autofire_action(const std::string& a, int mode);
void do_action(const std::string& name, short state, int mode);
void promote_key(keyboard::ctrlrkey& k);
void add_button(const std::string& name, const controller_bind& binding);
void process_controller(portctrl::controller& controller, unsigned number);
void process_controller(std::map<std::string, unsigned>& allocated,
std::map<controller_triple, unsigned>& assigned, portctrl::controller& controller, unsigned port,
unsigned number_in_port);
void process_port(std::map<std::string, unsigned>& allocated,
std::map<controller_triple, unsigned>& assigned, unsigned port, portctrl::type& ptype);
void init();
bool check_button_active(const std::string& name);
void do_button_action(const std::string& name, short newstate, int mode);
void send_analog(const std::string& name, int32_t x, int32_t y);
std::map<std::string, keyboard::invbind*> macro_binds;
std::map<std::string, keyboard::invbind*> macro_binds2;
std::map<std::string, controller_bind> all_buttons;
std::map<std::string, active_bind> active_buttons;
std::map<std::string, keyboard::ctrlrkey*> added_keys;
std::set<core_core*> cores_done;
bool promote_autohold;
bool promote_autofire;
bool promote_typed;
controller_state& controls;
keyboard::mapper& mapper;
keyboard::keyboard& keyboard;
emu_framebuffer& fbuf;
emulator_dispatch& edispatch;
lua_state& lua2;
command::group& cmd;
struct dispatch::target<> ncore;
command::_fnptr<const std::string&> button_p;
command::_fnptr<const std::string&> button_r;
command::_fnptr<const std::string&> button_h;
command::_fnptr<const std::string&> button_t;
command::_fnptr<const std::string&> button_d;
command::_fnptr<const std::string&> button_ap;
command::_fnptr<const std::string&> button_ar;
command::_fnptr<const std::string&> button_at;
command::_fnptr<const std::string&> button_a;
command::_fnptr<> afire_p;
command::_fnptr<> afire_n;
command::_fnptr<> ahold_p;
command::_fnptr<> ahold_n;
command::_fnptr<> typed_p;
command::_fnptr<> typed_n;
};
void reread_active_buttons();
void reinitialize_buttonmap();
void load_macros(controller_state& ctrlstate);
void load_project_macros(controller_state& ctrlstate, project_info& pinfo);
void cleanup_all_keys();
std::pair<int, int> controller_by_name(const std::string& name);
extern controller_state controls;
extern std::map<std::string, std::string> button_keys;
#endif

View file

@ -15,15 +15,8 @@
#include <vector>
#include <map>
#include <list>
#include "library/portctrl-data.hpp"
#include "library/command.hpp"
#include "library/threads.hpp"
class project_state;
class movie_logic;
class button_mapping;
class emulator_dispatch;
class status_updater;
#include "library/controller-data.hpp"
#include "library/threadtypes.hpp"
/**
* Controllers state.
@ -34,8 +27,7 @@ public:
/**
* Constructor.
*/
controller_state(project_state& _project, movie_logic& _mlogic, button_mapping& _buttons,
emulator_dispatch& _dispatch, status_updater& _supdater, command::group& _cmd) throw();
controller_state() throw();
/**
* Convert lcid (Logical Controller ID) into pcid (Physical Controler ID).
*
@ -65,29 +57,29 @@ public:
* Parameter ptype: The new types for ports.
* Throws std::runtime_error: Illegal port type.
*/
void set_ports(const portctrl::type_set& ptype);
void set_ports(const port_type_set& ptype) throw(std::runtime_error);
/**
* Get status of current controls (with autohold/autofire factored in).
*
* Parameter framenum: Number of current frame (for evaluating autofire).
* Returns: The current controls.
*/
portctrl::frame get(uint64_t framenum) throw();
controller_frame get(uint64_t framenum) throw();
/**
* Commit given controls (autohold/autofire is ignored).
*
* Parameter controls: The controls to commit
*/
void commit(portctrl::frame controls) throw();
void commit(controller_frame controls) throw();
/**
* Get status of committed controls.
* Returns: The committed controls.
*/
portctrl::frame get_committed() throw();
controller_frame get_committed() throw();
/**
* Get blank frame.
*/
portctrl::frame get_blank() throw();
controller_frame get_blank() throw();
/**
* Send analog input to given controller.
*
@ -202,16 +194,16 @@ public:
bool is_present(unsigned port, unsigned controller) throw();
void erase_macro(const std::string& macro);
std::set<std::string> enumerate_macro();
portctrl::macro& get_macro(const std::string& macro);
void set_macro(const std::string& macro, const portctrl::macro& m);
void apply_macro(portctrl::frame& f);
controller_macro& get_macro(const std::string& macro);
void set_macro(const std::string& macro, const controller_macro& m);
void apply_macro(controller_frame& f);
void rename_macro(const std::string& old, const std::string& newn);
void do_macro(const std::string& a, int mode);
std::set<std::string> active_macro_set();
void advance_macros();
std::map<std::string, uint64_t> get_macro_frames();
void set_macro_frames(const std::map<std::string, uint64_t>& f);
private:
void do_macro(const std::string& a, int mode);
struct autofire_info
{
uint64_t first_frame;
@ -224,27 +216,29 @@ private:
int mode;
int16_t state;
};
void reread_tasinput_mode(const portctrl::type_set& ptype);
const portctrl::type_set* types;
portctrl::frame _input;
portctrl::frame _autohold;
portctrl::frame _framehold;
void reread_tasinput_mode(const port_type_set& ptype);
const port_type_set* types;
controller_frame _input;
controller_frame _autohold;
controller_frame _framehold;
std::map<unsigned, autofire_info> _autofire;
std::map<unsigned, tasinput_info> _tasinput;
bool tasinput_enaged;
portctrl::frame _committed;
std::map<std::string, portctrl::macro> all_macros;
std::list<std::pair<uint64_t, portctrl::macro*>> active_macros;
threads::lock macro_lock;
project_state& project;
movie_logic& mlogic;
button_mapping& buttons;
emulator_dispatch& edispatch;
status_updater& supdater;
command::group& cmd;
command::_fnptr<const std::string&> macro_p;
command::_fnptr<const std::string&> macro_r;
command::_fnptr<const std::string&> macro_t;
controller_frame _committed;
std::map<std::string, controller_macro> all_macros;
std::list<std::pair<uint64_t, controller_macro*>> active_macros;
mutex_class macro_lock;
};
/**
* Generic port controller name function.
*/
template<unsigned controllers, const char** name>
inline const char* generic_controller_name(unsigned controller)
{
if(controller >= controllers)
return NULL;
return *name;
}
#endif

View file

@ -1,203 +0,0 @@
#ifndef _debug__hpp__included__
#define _debug__hpp__included__
#include <functional>
#include <fstream>
#include <cstdint>
#include "library/command.hpp"
#include "library/dispatch.hpp"
class emulator_dispatch;
class loaded_rom;
class memory_space;
/**
* Debugging context.
*/
class debug_context
{
public:
debug_context(emulator_dispatch& _dispatch, loaded_rom& _rom, memory_space& _mspace, command::group& _cmd);
/**
* Type of event.
*/
enum etype
{
DEBUG_READ,
DEBUG_WRITE,
DEBUG_EXEC,
DEBUG_TRACE,
DEBUG_FRAME,
};
/**
* Parameters for read/write/execute event.
*/
struct params_rwx
{
uint64_t addr; //Address.
uint64_t value; //Value/CPU.
};
/**
* Parameters for trace event.
*/
struct params_trace
{
uint64_t cpu; //CPU number.
const char* decoded_insn; //Decoded instruction
bool true_insn; //True instruction flag.
};
/**
* Parameters for frame event.
*/
struct params_frame
{
uint64_t frame; //Frame number.
bool loadstated; //Loadstate flag.
};
/**
* Parameters for debug callback.
*/
struct params
{
etype type;
union {
params_rwx rwx; //READ/WRITE/EXECUTE
params_trace trace; //TRACE.
params_frame frame; //FRAME.
};
};
/**
* Base class of debugging callbacks.
*/
struct callback_base
{
/**
* Destructor.
*/
virtual ~callback_base();
/**
* Do a callback.
*/
virtual void callback(const params& p) = 0;
/**
* Notify about killed callback.
*/
virtual void killed(uint64_t addr, etype type) = 0;
};
/**
* Placeholder for all addresses.
*/
static const uint64_t all_addresses;
/**
* Add a callback.
*/
void add_callback(uint64_t addr, etype type, callback_base& cb);
/**
* Remove a callback.
*/
void remove_callback(uint64_t addr, etype type, callback_base& cb);
/**
* Fire a read callback.
*/
void do_callback_read(uint64_t addr, uint64_t value);
/**
* Fire a write callback.
*/
void do_callback_write(uint64_t addr, uint64_t value);
/**
* Fire a exec callback.
*/
void do_callback_exec(uint64_t addr, uint64_t value);
/**
* Fire a trace callback.
*/
void do_callback_trace(uint64_t cpu, const char* str, bool true_insn = true);
/**
* Fire a frame callback.
*/
void do_callback_frame(uint64_t frame, bool loadstate);
/**
* Set a cheat.
*/
void set_cheat(uint64_t addr, uint64_t value);
/**
* Clear a cheat.
*/
void clear_cheat(uint64_t addr);
/**
* Set execute callback mask.
*/
void setxmask(uint64_t mask);
/**
* Set tracelog file.
*/
void tracelog(uint64_t cpu, const std::string& filename);
/**
* Tracelogging on?
*/
bool is_tracelogging(uint64_t cpu);
/**
* Change tracelog change callback.
*/
void set_tracelog_change_cb(std::function<void()> cb);
/**
* Notify a core change.
*/
void core_change();
/**
* Request a break.
*/
void request_break();
//These are public only for some debugging stuff.
typedef std::list<callback_base*> cb_list;
std::map<uint64_t, cb_list> read_cb;
std::map<uint64_t, cb_list> write_cb;
std::map<uint64_t, cb_list> exec_cb;
std::map<uint64_t, cb_list> trace_cb;
std::map<uint64_t, cb_list> frame_cb;
private:
void do_showhooks();
void do_genevent(const std::string& a);
void do_tracecmd(const std::string& a);
cb_list dummy_cb; //Always empty.
uint64_t xmask = 1;
std::function<void()> tracelog_change_cb;
emulator_dispatch& edispatch;
loaded_rom& rom;
memory_space& mspace;
command::group& cmd;
struct dispatch::target<> corechange;
bool corechange_r = false;
bool requesting_break = false;
command::_fnptr<> showhooks;
command::_fnptr<const std::string&> genevent;
command::_fnptr<const std::string&> tracecmd;
struct tracelog_file : public callback_base
{
std::ofstream stream;
std::string full_filename;
unsigned refcnt;
tracelog_file(debug_context& parent);
~tracelog_file();
void callback(const params& p);
void killed(uint64_t addr, etype type);
private:
debug_context& parent;
};
std::map<uint64_t, tracelog_file*> trace_outputs;
std::map<uint64_t, cb_list>& get_lists(etype type)
{
switch(type) {
case DEBUG_READ: return read_cb;
case DEBUG_WRITE: return write_cb;
case DEBUG_EXEC: return exec_cb;
case DEBUG_TRACE: return trace_cb;
case DEBUG_FRAME: return frame_cb;
default: throw std::runtime_error("Invalid debug callback type");
}
}
};
#endif

View file

@ -1,6 +1,7 @@
#ifndef _dispatch__hpp__included__
#define _dispatch__hpp__included__
#include "core/keymapper.hpp"
#include "library/framebuffer.hpp"
#include "library/dispatch.hpp"
@ -10,32 +11,266 @@
#include <set>
#include <map>
struct emulator_dispatch
/**
* Video data region is NTSC.
*/
#define VIDEO_REGION_NTSC 0
/**
* Video data region is PAL.
*/
#define VIDEO_REGION_PAL 1
/**
* Information about run.
*/
struct gameinfo_struct
{
emulator_dispatch();
void set_error_streams(std::ostream* stream);
dispatch::source<> autohold_reconfigure;
dispatch::source<unsigned, unsigned, unsigned, bool> autohold_update;
dispatch::source<unsigned, unsigned, unsigned, unsigned, unsigned> autofire_update;
dispatch::source<> close;
dispatch::source<std::pair<std::string, std::string>> sound_change;
dispatch::source<> screen_update;
dispatch::source<> status_update;
dispatch::source<bool> sound_unmute;
dispatch::source<bool> mode_change;
dispatch::source<> core_change;
dispatch::source<> title_change;
dispatch::source<> branch_change;
dispatch::source<> mbranch_change;
dispatch::source<bool> core_changed;
dispatch::source<> voice_stream_change;
dispatch::source<> vu_change;
dispatch::source<> subtitle_change;
dispatch::source<unsigned, unsigned, int> multitrack_change;
dispatch::source<> action_update;
public:
/**
* Construct game info.
*/
gameinfo_struct() throw(std::bad_alloc);
/**
* Game name.
*/
std::string gamename;
/**
* Run length in seconds.
*/
double length;
/**
* Rerecord count (base 10 ASCII)
*/
std::string rerecords;
/**
* Authors. The first components are real names, the second components are nicknames. Either (but not both) may be
* blank.
*/
std::vector<std::pair<std::string, std::string>> authors;
/**
* Format human-redable representation of the length.
*
* Parameter digits: Number of sub-second digits to use.
* Returns: The time formated.
* Throws std::bad_alloc: Not enough memory.
*/
std::string get_readable_time(unsigned digits) const throw(std::bad_alloc);
/**
* Get number of authors.
*
* Returns: Number of authors.
*/
size_t get_author_count() const throw();
/**
* Get short name of author (nickname if present, otherwise full name).
*
* Parameter idx: Index of author (0-based).
* Returns: The short name.
* Throws std::bad_alloc: Not enough memory.
*/
std::string get_author_short(size_t idx) const throw(std::bad_alloc);
/**
* Get rerecord count as a number. If rerecord count is too high, returns the maximum representatible count.
*
* Returns: The rerecord count.
*/
uint64_t get_rerecords() const throw();
};
extern dispatch::source<> notify_new_core;
/**
* Information dispatch.
*
* This class handles dispatching information between the components of the emulator.
*
* Each kind of information has virtual method on_foo() which can be overridden to handle events of that type, and
* static method do_foo(), which calls on_foo on all known objects.
*
* The information is delivered to each instance of this class.
*/
class information_dispatch
{
public:
/**
* Create new object to receive information dispatch events.
*
* Parameter name: The name for the object.
* Throws std::bad_alloc: Not enough memory.
*/
information_dispatch(const std::string& name) throw(std::bad_alloc);
/**
* Destroy object.
*/
virtual ~information_dispatch() throw();
/**
* A frame has been received.
*
* The default handler does nothing.
*
* Parameter _frame: The frame object.
* Parameter fps_n: Numerator of current video fps.
* Parameter fps_d: Denominator of current video fps.
*/
virtual void on_frame(struct framebuffer_raw& _frame, uint32_t fps_n, uint32_t fps_d);
/**
* Call all on_frame() handlers.
*
* Calls on_new_dumper() on dumpers that had that not yet called.
*/
static void do_frame(struct framebuffer_raw& _frame, uint32_t fps_n, uint32_t fps_d) throw();
/**
* A sample has been received.
*
* The default handler does nothing.
*
* Parameter l: The left channel sample (16 bit signed).
* Parameter r: The right channel sample (16 bit signed).
*/
virtual void on_sample(short l, short r);
/**
* Call all on_sample() handlers.
*
* Calls on_new_dumper() on dumpers that had that not yet called.
*/
static void do_sample(short l, short r) throw();
/**
* Dump is ending.
*
* Calls on_new_dumper() on dumpers that had that not yet called.
*
* The default handler does nothing.
*/
virtual void on_dump_end();
/**
* Call all on_dump_end() handlers.
*/
static void do_dump_end() throw();
/**
* Sound sampling rate is changing
*
* The default handler prints warning if dumper flag is set.
*
* Parameter rate_n: Numerator of the new sampling rate in Hz.
* Parameter rate_d: Denominator of the new sampling rate in Hz.
*/
virtual void on_sound_rate(uint32_t rate_n, uint32_t rate_d);
/**
* Call all on_sound_rate() methods and save the parameters.
*
* Calls on_new_dumper() on dumpers that had that not yet called.
*/
static void do_sound_rate(uint32_t rate_n, uint32_t rate_d) throw();
/**
* Get the sound rate most recently set by on_sound_rate().
*
* Returns: The first component is the numerator, the second is the denominator.
*/
static std::pair<uint32_t, uint32_t> get_sound_rate() throw();
/**
* Game information is changing.
*
* The default handler does nothing.
*
* Parameter gi: The new game info.
*/
virtual void on_gameinfo(const struct gameinfo_struct& gi);
/**
* Call all on_gameinfo() handlers and save the gameinfo.
*/
static void do_gameinfo(const struct gameinfo_struct& gi) throw();
/**
* Get the gameinfo most recently set by do_gameinfo().
*
* Returns: The gameinfo.
*/
static const struct gameinfo_struct& get_gameinfo() throw();
/**
* Return the dumper flag for this dispatch target.
*
* The default implementation returns false.
*
* If dumper flag is set:
* - on_sound_rate() default handler prints a warning.
* - All dumping related do_* functions triggers calls to to on_new_dumper() on all handlers the next time they
* are called.
* - Destroying the handler triggers calls to on_destroy_dumper() on all handlers (if on_new_dumper() has been
* called).
*/
virtual bool get_dumper_flag() throw();
/**
* Notify that a new dumper is joining.
*
* Parameter dumper: The name of the dumper object.
*/
virtual void on_new_dumper(const std::string& dumper);
/**
* Notify that a dumper is leaving.
*
* Parameter dumper: The name of the dumper object.
*/
virtual void on_destroy_dumper(const std::string& dumper);
/**
* Get number of active dumpers.
*
* Calls on_new_dumper() on dumpers that had that not yet called.
*
* Returns: The dumper count.
*/
static unsigned get_dumper_count() throw();
/**
* Get set of active dumpers.
*
* Calls on_new_dumper() on dumpers that had that not yet called.
*
* Returns: The set of dumper names.
* Throws std::bad_alloc: Not enough memory.
*/
static std::set<std::string> get_dumpers() throw(std::bad_alloc);
/**
* Get name of target.
*/
const std::string& get_name() throw();
/**
* Notify that some dumper has attached, deattached, popped into existence or disappeared.
*
* Default implementation does nothing.
*/
virtual void on_dumper_update();
/**
* Call on_dumper_update on on all objects.
*/
static void do_dumper_update() throw();
protected:
/**
* Call to indicate this target is interested in sound sample data.
*/
void enable_send_sound() throw(std::bad_alloc);
private:
static void update_dumpers(bool nocalls = false) throw();
bool known_if_dumper;
bool marked_as_dumper;
std::string target_name;
bool notified_as_dumper;
};
void dispatch_set_error_streams(std::ostream* stream);
extern struct dispatcher<> notify_autohold_reconfigure;
extern struct dispatcher<unsigned, unsigned, unsigned, bool> notify_autohold_update;
extern struct dispatcher<unsigned, unsigned, unsigned, unsigned, unsigned> notify_autofire_update;
extern struct dispatcher<> notify_close;
extern struct dispatcher<framebuffer<false>&> notify_set_screen;
extern struct dispatcher<std::pair<std::string, std::string>> notify_sound_change;
extern struct dispatcher<> notify_screen_update;
extern struct dispatcher<> notify_status_update;
extern struct dispatcher<bool> notify_sound_unmute;
extern struct dispatcher<bool> notify_mode_change;
extern struct dispatcher<> notify_core_change;
extern struct dispatcher<bool> notify_core_changed;
extern struct dispatcher<> notify_new_core;
extern struct dispatcher<> notify_voice_stream_change;
extern struct dispatcher<> notify_vu_change;
extern struct dispatcher<> notify_subtitle_change;
extern struct dispatcher<unsigned, unsigned, int> notify_multitrack_change;
#endif

View file

@ -1,99 +0,0 @@
#ifndef _emustatus__hpp__included__
#define _emustatus__hpp__included__
#include <stdexcept>
#include <string>
#include <set>
#include <map>
#include "library/command.hpp"
#include "library/triplebuffer.hpp"
class movie_logic;
class project_state;
class voice_commentary;
class emulator_runmode;
class master_dumper;
class save_jukebox;
class slotinfo_cache;
class framerate_regulator;
class controller_state;
class multitrack_edit;
class lua_state;
class loaded_rom;
class memwatch_set;
class emulator_dispatch;
struct _lsnes_status
{
const static int pause_none; //pause: No pause.
const static int pause_normal; //pause: Normal pause.
const static int pause_break; //pause: Break pause.
const static uint64_t subframe_savepoint; //subframe: Point of save.
const static uint64_t subframe_video; //subframe: Point of video output.
bool valid;
bool movie_valid; //The movie state variables are valid?
uint64_t curframe; //Current frame number.
uint64_t length; //Movie length.
uint64_t lag; //Lag counter.
uint64_t subframe; //Subframe number.
bool dumping; //Video dump active.
unsigned speed; //Speed%
bool saveslot_valid; //Save slot number/info valid.
uint64_t saveslot; //Save slot number.
std::u32string slotinfo; //Save slot info.
bool branch_valid; //Branch info valid?
std::u32string branch; //Current branch.
bool mbranch_valid; //Movie branch info valid?
std::u32string mbranch; //Current movie branch.
std::u32string macros; //Currently active macros.
int pause; //Pause mode.
char mode; //Movie mode: C:Corrupt, R:Readwrite, P:Readonly, F:Finished.
bool rtc_valid; //RTC time valid?
std::u32string rtc; //RTC time.
std::vector<std::u32string> inputs; //Input display.
std::map<std::string, std::u32string> mvars; //Memory watches.
std::map<std::string, std::u32string> lvars; //Lua variables.
};
struct slotinfo_cache
{
slotinfo_cache(movie_logic& _mlogic, command::group& _cmd);
std::string get(const std::string& _filename);
void flush(const std::string& _filename);
void flush();
private:
std::map<std::string, std::string> cache;
movie_logic& mlogic;
command::group& cmd;
command::_fnptr<> flushcmd;
};
struct status_updater
{
public:
status_updater(project_state& _project, movie_logic& _mlogic, voice_commentary& _commentary,
triplebuffer::triplebuffer<_lsnes_status>& _status, emulator_runmode& _runmode, master_dumper& _mdumper,
save_jukebox& _jukebox, slotinfo_cache& _slotcache, framerate_regulator& _framerate,
controller_state& _controls, multitrack_edit& _mteditor, lua_state& _lua2, loaded_rom& _rom,
memwatch_set& _mwatch, emulator_dispatch& _dispatch);
void update();
private:
project_state& project;
movie_logic& mlogic;
voice_commentary& commentary;
triplebuffer::triplebuffer<_lsnes_status>& status;
emulator_runmode& runmode;
master_dumper& mdumper;
save_jukebox& jukebox;
slotinfo_cache& slotcache;
framerate_regulator& framerate;
controller_state& controls;
multitrack_edit& mteditor;
lua_state& lua2;
loaded_rom& rom;
memwatch_set& mwatch;
emulator_dispatch& dispatch;
};
#endif

View file

@ -1,15 +1,12 @@
#ifndef _filedownload__hpp__included__
#define _filedownload__hpp__included__
#include "library/threads.hpp"
#include "library/threadtypes.hpp"
#include "library/httpreq.hpp"
#include "library/urirewrite.hpp"
#include <string>
#include <list>
#include <vector>
class loaded_rom;
struct file_download
{
//Variables.
@ -19,21 +16,20 @@ struct file_download
file_download();
~file_download();
//Lauch.
void do_async(loaded_rom& rom);
void do_async();
void cancel();
//Status.
volatile bool finished; //This signals download finishing, call finish().
std::string errormsg;
http_async_request req;
std::string statusmsg();
threads::cv cond;
threads::lock m;
cv_class cond;
mutex_class m;
//Internal.
void _do_async(loaded_rom& rom);
void _do_async();
std::string tempname;
std::string tempname2;
};
extern urirewrite::rewriter lsnes_uri_rewrite;
#endif

View file

@ -1,7 +1,7 @@
#ifndef _fileupload__hpp__included__
#define _fileupload__hpp__included__
#include "library/threads.hpp"
#include "library/threadtypes.hpp"
#include "library/httpreq.hpp"
#include "library/httpauth.hpp"
#include <string>
@ -35,7 +35,7 @@ struct file_upload
dh25519_http_auth* dh25519;
http_async_request* req;
std::list<std::string> msgs;
threads::lock m;
mutex_class m;
void add_msg(const std::string& msg);
};

View file

@ -2,117 +2,105 @@
#define _framebuffer__hpp__included__
#include "core/window.hpp"
#include "core/queue.hpp"
#include "library/command.hpp"
#include "library/framebuffer.hpp"
#include "library/triplebuffer.hpp"
#include <stdexcept>
class subtitle_commentary;
class memwatch_set;
class emulator_dispatch;
class lua_state;
class loaded_rom;
class status_updater;
namespace settingvar
{
class group;
}
namespace keyboard
{
class keyboard;
}
/**
* Emulator frame buffer.
* Triple buffering logic.
*/
class emu_framebuffer
class triplebuffer_logic
{
public:
emu_framebuffer(subtitle_commentary& _subtitles, settingvar::group& _settings, memwatch_set& _mwatch,
keyboard::keyboard& _keyboard, emulator_dispatch& _dispatch, lua_state& _lua2, loaded_rom& _rom,
status_updater& _supdater, command::group& _cmd, input_queue& _iqueue);
/**
* Create new triple buffer logic.
*/
triplebuffer_logic() throw(std::bad_alloc);
/**
* Destructor.
*/
~triplebuffer_logic() throw();
/**
* Get index for write buffer.Also starts write cycle.
*
* Returns: Write buffer index (0-2).
*/
unsigned start_write() throw();
/**
* Notify that write cycle has ended.
*/
void end_write() throw();
/**
* Get index for read buffer. Also starts read cycle.
*
* Returns: Read buffer index (0-2).
*/
unsigned start_read() throw();
/**
* Notify that read cycle has ended.
*/
void end_read() throw();
private:
triplebuffer_logic(triplebuffer_logic&);
triplebuffer_logic& operator=(triplebuffer_logic&);
mutex_class mut;
unsigned read_active;
unsigned write_active;
unsigned read_active_slot;
unsigned write_active_slot;
unsigned last_complete_slot;
};
/**
* The main framebuffer.
*/
framebuffer::raw main_framebuffer;
extern framebuffer_raw main_framebuffer;
/**
* Special screen: "SYSTEM STATE CORRUPT".
*/
static framebuffer::raw screen_corrupt;
extern framebuffer_raw screen_corrupt;
/**
* The main screen to draw on.
*/
framebuffer::fb<false> main_screen;
extern framebuffer<false> main_screen;
/**
* Initialize special screens.
*
* throws std::bad_alloc: Not enough memory.
*/
static void init_special_screens();
void init_special_screens() throw(std::bad_alloc);
/**
* Copy framebuffer to backing store, running Lua hooks if any.
*/
void redraw_framebuffer(framebuffer::raw& torender, bool no_lua = false, bool spontaneous = false);
void redraw_framebuffer(framebuffer_raw& torender, bool no_lua = false, bool spontaneous = false);
/**
* Redraw the framebuffer, reusing contents from last redraw. Runs lua hooks if last redraw ran them.
*/
void redraw_framebuffer();
void redraw_framebuffer();
/**
* Return last complete framebuffer.
*/
framebuffer::raw get_framebuffer();
framebuffer_raw get_framebuffer() throw(std::bad_alloc);
/**
* Render framebuffer to main screen.
*/
void render_framebuffer();
void render_framebuffer();
/**
* Get the size of current framebuffer.
*/
std::pair<uint32_t, uint32_t> get_framebuffer_size();
std::pair<uint32_t, uint32_t> get_framebuffer_size();
/**
* Take a screenshot to specified file.
*/
void take_screenshot(const std::string& file);
void take_screenshot(const std::string& file) throw(std::bad_alloc, std::runtime_error);
/**
* Kill pending requests associated with object.
*/
void render_kill_request(void* obj);
void render_kill_request(void* obj);
/**
* Get latest screen received from core.
*/
framebuffer::raw& render_get_latest_screen();
void render_get_latest_screen_end();
private:
void do_screenshot(command::arg_filename a);
struct render_info
{
framebuffer::raw fbuf;
framebuffer::queue rq;
uint32_t hscl;
uint32_t vscl;
uint32_t lgap;
uint32_t rgap;
uint32_t tgap;
uint32_t bgap;
};
render_info buffer1;
render_info buffer2;
render_info buffer3;
triplebuffer::triplebuffer<render_info> buffering;
bool last_redraw_no_lua;
subtitle_commentary& subtitles;
settingvar::group& settings;
memwatch_set& mwatch;
keyboard::keyboard& keyboard;
emulator_dispatch& edispatch;
lua_state& lua2;
loaded_rom& rom;
status_updater& supdater;
command::group& cmd;
input_queue& iqueue;
command::_fnptr<command::arg_filename> screenshot;
};
framebuffer_raw& render_get_latest_screen();
void render_get_latest_screen_end();
#endif

View file

@ -2,75 +2,54 @@
#define _framerate__hpp__included__
#include <cstdint>
#include "library/threads.hpp"
#include "library/command.hpp"
#define FRAMERATE_HISTORY_FRAMES 10
/**
* Framerate regulator.
*/
class framerate_regulator
{
public:
framerate_regulator(command::group& _cmd);
/**
* Set the target speed multiplier.
*
* Parameter multiplier: The multiplier target. May be INFINITE.
*/
void set_speed_multiplier(double multiplier) throw();
/**
* Increase the speed to next step.
*/
void increase_speed() throw();
/**
* Decrease the speed to next step.
*/
void decrease_speed() throw();
void set_speed_multiplier(double multiplier) throw();
/**
* Get the target speed multiplier.
*
* Returns: The multiplier. May be INFINITE.
*/
double get_speed_multiplier() throw();
double get_speed_multiplier() throw();
/**
* Sets the nominal frame rate. Framerate limiting tries to maintain the nominal framerate when there is no other
* explict framerate to maintain.
*/
void set_nominal_framerate(double fps) throw();
void set_nominal_framerate(double fps) throw();
/**
* Returns the current realized framerate multiplier.
*
* returns: The framerate multiplier the system is currently archiving.
*/
double get_realized_multiplier() throw();
double get_realized_multiplier() throw();
/**
* Freeze time.
*
* Parameter usec: Current time in microseconds.
*/
void freeze_time(uint64_t usec);
void freeze_time(uint64_t usec);
/**
* Unfreeze time.
*
* Parameter usec: Current time in microseconds.
*/
void unfreeze_time(uint64_t usec);
void unfreeze_time(uint64_t usec);
/**
* Acknowledge frame start for timing purposes. If time is frozen, it is automatically unfrozen.
*
* parameter usec: Current time (relative to some unknown epoch) in microseconds.
*/
void ack_frame_tick(uint64_t usec) throw();
void ack_frame_tick(uint64_t usec) throw();
/**
* Computes the number of microseconds to wait for next frame.
@ -78,48 +57,16 @@ public:
* parameter usec: Current time (relative to some unknown epoch) in microseconds.
* returns: Number of more microseconds to wait.
*/
uint64_t to_wait_frame(uint64_t usec) throw();
uint64_t to_wait_frame(uint64_t usec) throw();
/**
* Return microsecond-resolution time since unix epoch.
*/
static uint64_t get_utime();
uint64_t get_utime();
/**
* Wait specified number of microseconds.
*/
void wait_usec(uint64_t usec);
/**
* Turbo flag.
*/
bool turboed;
private:
void set_speed_cmd(const std::string& args);
uint64_t get_time(uint64_t curtime, bool update);
double get_realized_fps();
void add_frame(uint64_t linear_time);
std::pair<bool, double> read_fps();
//Step should be ODD.
void set_speedstep(unsigned step);
//Step can be EVEN if between steps.
unsigned get_speedstep();
uint64_t last_time_update;
uint64_t time_at_last_update;
bool time_frozen;
uint64_t frame_number;
uint64_t frame_start_times[FRAMERATE_HISTORY_FRAMES];
//Framerate.
double nominal_framerate;
double multiplier_framerate;
bool framerate_realtime_locked;
threads::lock framerate_lock;
command::group& cmd;
command::_fnptr<> turbo_p;
command::_fnptr<> turbo_r;
command::_fnptr<> turbo_t;
command::_fnptr<const std::string&> setspeed_t;
command::_fnptr<> spd_inc;
command::_fnptr<> spd_dec;
};
void wait_usec(uint64_t usec);
#endif

View file

@ -1,74 +0,0 @@
#ifndef _instance_map__hpp__included__
#define _instance_map__hpp__included__
#include <map>
class emulator_instance;
template<typename T> class instance_map
{
public:
/**
* Destroy a instance map.
*/
~instance_map()
{
for(auto i : instances)
delete i.second;
instances.clear();
}
/**
* Does this instance exist?
*/
bool exists(emulator_instance& inst)
{
return instances.count(&inst);
}
/**
* Lookup a instance. Returns NULL if none.
*/
T* lookup(emulator_instance& inst)
{
if(!instances.count(&inst))
return NULL;
return instances[&inst];
}
/**
* Create a new instance.
*/
template<typename... U> T* create(emulator_instance& inst, U... args)
{
T* out = NULL;
try {
out = new T(inst, args...);
instances[&inst] = out;
return out;
} catch(...) {
if(out) delete out;
throw;
}
}
/**
* Erase a instance.
*/
void destroy(emulator_instance& inst)
{
if(instances.count(&inst)) {
delete instances[&inst];
instances.erase(&inst);
}
}
/**
* Remove a instance.
*/
void remove(emulator_instance& inst)
{
if(instances.count(&inst)) {
instances.erase(&inst);
}
}
private:
std::map<emulator_instance*, T*> instances;
};
#endif

View file

@ -1,143 +0,0 @@
#ifndef _instance__hpp__included__
#define _instance__hpp__included__
#include "library/threads.hpp"
#include <cstring>
class movie_logic;
class memory_space;
class memwatch_set;
class voice_commentary;
class subtitle_commentary;
class movie_branches;
class multitrack_edit;
class _lsnes_status;
class alias_binds_manager;
class rrdata;
class cart_mappings_refresher;
class controller_state;
class project_state;
class debug_context;
class framerate_regulator;
class emu_framebuffer;
class input_queue;
class master_dumper;
class button_mapping;
class emulator_dispatch;
class slotinfo_cache;
class lua_state;
class audioapi_instance;
class loaded_rom;
class save_jukebox;
class emulator_runmode;
class status_updater;
namespace command { class group; }
namespace lua { class state; }
namespace settingvar { class group; }
namespace settingvar { class cache; }
namespace keyboard { class keyboard; }
namespace keyboard { class mapper; }
namespace triplebuffer { template<typename T> class triplebuffer; }
class dtor_list
{
struct entry
{
void* ptr;
void (*free1)(void* ptr);
void (*free2)(void* ptr);
entry* prev;
};
public:
dtor_list();
~dtor_list();
void destroy();
template<typename T> void prealloc(T*& ptr)
{
entry e;
e.ptr = ptr = reinterpret_cast<T*>(new char[sizeof(T) + 32]);
memset((char*)ptr, 0, sizeof(T) + 32);
e.free1 = null;
e.free2 = free2;
e.prev = list;
list = new entry(e);
}
template<typename T, typename... U> void init(T*& ptr, U&... args)
{
if(ptr) {
//Find the entry.
entry* e = list;
while(e->ptr != ptr)
e = e->prev;
new(ptr) T(args...);
e->free1 = free1_p<T>;
} else {
entry e;
e.ptr = ptr = new T(args...);
e.free1 = free1<T>;
e.free2 = null;
e.prev = list;
list = new entry(e);
}
}
private:
entry* list;
static void null(void* ptr) {}
static void free2(void* ptr) { delete[] reinterpret_cast<char*>(ptr); }
template<typename T> static void free1(void* ptr) { delete reinterpret_cast<T*>(ptr); }
template<typename T> static void free1_p(void* ptr) { reinterpret_cast<T*>(ptr)->~T(); }
};
struct emulator_instance
{
emulator_instance();
~emulator_instance();
emulator_dispatch* dispatch;
movie_logic* mlogic;
memory_space* memory;
lua::state* lua;
lua_state* lua2;
memwatch_set* mwatch;
settingvar::group* settings;
settingvar::cache* setcache;
voice_commentary* commentary;
subtitle_commentary* subtitles;
movie_branches* mbranch;
controller_state* controls;
button_mapping* buttons;
multitrack_edit* mteditor;
_lsnes_status* status_A;
_lsnes_status* status_B;
_lsnes_status* status_C;
triplebuffer::triplebuffer<_lsnes_status>* status;
keyboard::keyboard* keyboard;
command::group* command;
keyboard::mapper* mapper;
alias_binds_manager* abindmanager;
rrdata* nrrdata;
cart_mappings_refresher* cmapper;
project_state* project;
debug_context* dbg;
framerate_regulator* framerate;
emu_framebuffer* fbuf;
input_queue* iqueue;
master_dumper* mdumper;
slotinfo_cache* slotcache;
audioapi_instance* audio;
loaded_rom* rom;
save_jukebox* jukebox;
emulator_runmode* runmode;
status_updater* supdater;
threads::id emu_thread;
time_t random_seed_value;
dtor_list D;
private:
emulator_instance(const emulator_instance&);
emulator_instance& operator=(const emulator_instance&);
};
extern emulator_instance lsnes_instance;
emulator_instance& CORE();
#endif

View file

@ -4,60 +4,37 @@
#include <list>
#include <cstdint>
#include <string>
#include "library/command.hpp"
class emulator_dispatch;
void voicethread_task();
void voicethread_kill();
void voice_frame_number(uint64_t newframe, double rate);
namespace settingvar
enum external_stream_format
{
class group;
}
class voice_commentary
{
public:
enum external_stream_format
{
EXTFMT_SOX,
EXTFMT_OGGOPUS
};
struct playback_stream_info
{
uint64_t id;
uint64_t base;
uint64_t length;
};
voice_commentary(settingvar::group& _settings, emulator_dispatch& _dispatch, audioapi_instance& _audio,
command::group& _cmd);
~voice_commentary();
void init();
void kill();
void frame_number(uint64_t newframe, double rate);
bool collection_loaded();
std::list<playback_stream_info> get_stream_info();
void play_stream(uint64_t id);
void export_stream(uint64_t id, const std::string& filename, external_stream_format fmt);
uint64_t import_stream(uint64_t ts, const std::string& filename, external_stream_format fmt);
void delete_stream(uint64_t id);
void export_superstream(const std::string& filename);
void load_collection(const std::string& filename);
void unload_collection();
void alter_timebase(uint64_t id, uint64_t ts);
uint64_t parse_timebase(const std::string& n);
double ts_seconds(uint64_t ts);
float get_gain(uint64_t id);
void set_gain(uint64_t id, float gain);
void set_active_flag(bool flag);
private:
void* internal;
settingvar::group& settings;
emulator_dispatch& edispatch;
audioapi_instance& audio;
command::group& cmd;
command::_fnptr<> tangentp;
command::_fnptr<> tangentr;
EXTFMT_SOX,
EXTFMT_OGGOPUS
};
struct playback_stream_info
{
uint64_t id;
uint64_t base;
uint64_t length;
};
bool voicesub_collection_loaded();
std::list<playback_stream_info> voicesub_get_stream_info();
void voicesub_play_stream(uint64_t id);
void voicesub_export_stream(uint64_t id, const std::string& filename, external_stream_format fmt);
uint64_t voicesub_import_stream(uint64_t ts, const std::string& filename, external_stream_format fmt);
void voicesub_delete_stream(uint64_t id);
void voicesub_export_superstream(const std::string& filename);
void voicesub_load_collection(const std::string& filename);
void voicesub_unload_collection();
void voicesub_alter_timebase(uint64_t id, uint64_t ts);
uint64_t voicesub_parse_timebase(const std::string& n);
double voicesub_ts_seconds(uint64_t ts);
float voicesub_get_gain(uint64_t id);
void voicesub_set_gain(uint64_t id, float gain);
#endif

View file

@ -23,7 +23,7 @@ struct joystick_driver
* - The call occurs in the main thread.
* - Implemented by the joystick plugin.
*/
void joystick_driver_init(bool soft = false) throw();
void joystick_driver_init() throw();
/**
* Joystick quit function.
*
@ -31,7 +31,13 @@ void joystick_driver_init(bool soft = false) throw();
* - The call occurs in the main thread.
* - Implemented by the joystick plugin.
*/
void joystick_driver_quit(bool soft = false) throw();
void joystick_driver_quit() throw();
/**
* This thread becomes the joystick polling thread.
*
* - Called in joystick polling thread.
*/
void joystick_driver_thread_fn() throw();
/**
* Signal the joystick thread to quit.
*/

View file

@ -1,88 +0,0 @@
#ifndef _jukebox__hpp__included__
#define _jukebox__hpp__included__
#include <functional>
#include <cstdlib>
#include <string>
namespace settingvar { class group; }
class save_jukebox_listener;
/**
* Save jukebox.
*/
class save_jukebox
{
public:
/**
* Ctor.
*/
save_jukebox(settingvar::group& _settings, command::group& _cmd);
/**
* Dtor.
*/
~save_jukebox();
/**
* Get current slot.
*
* Throws std::runtime_exception: No slot selected.
*/
size_t get_slot();
/**
* Set current slot.
*
* Parameter slot: The slot to select.
* Throws std::runtime_exception: Slot out of range.
*/
void set_slot(size_t slot);
/**
* Cycle next slot.
*
* Throws std::runtime_exception: No slot selected.
*/
void cycle_next();
/**
* Cycle previous slot.
*
* Throws std::runtime_exception: No slot selected.
*/
void cycle_prev();
/**
* Get save as binary flag.
*/
bool save_binary();
/**
* Get name of current jukebox slot.
*
* Throws std::runtime_exception: No slot selected.
*/
std::string get_slot_name();
/**
* Set size of jukebox.
*
* Parameter size: The new size.
*/
void set_size(size_t size);
/**
* Set update function.
*/
void set_update(std::function<void()> _update);
/**
* Unset update function.
*/
void unset_update();
private:
void do_slotsel(const std::string& arg);
settingvar::group& settings;
size_t current_slot;
size_t current_size;
std::function<void()> update;
save_jukebox_listener* listener;
command::group& cmd;
command::_fnptr<const std::string&> slotsel;
command::_fnptr<> cycleprev;
command::_fnptr<> cyclenext;
};
#endif

View file

@ -10,17 +10,22 @@
#include <iostream>
#include "misc.hpp"
#include "library/keyboard.hpp"
#include "library/keyboard-mapper.hpp"
#include "library/gamepad.hpp"
#include "library/keymapper.hpp"
#include "library/joystick2.hpp"
/**
* Inverse bindings set.
* Our keyboard
*/
extern keyboard::invbind_set lsnes_invbinds;
extern keyboard lsnes_kbd;
/**
* Our key mapper.
*/
extern keyboard_mapper lsnes_mapper;
/**
* Gamepad HW.
*/
extern gamepad::set lsnes_gamepads;
extern hw_gamepad_set lsnes_gamepads;
/**
* Initialize gamepads (need to be called before initializing joysticks).
*/

View file

@ -4,11 +4,7 @@
#include "library/loadlib.hpp"
void handle_post_loadlibrary();
void autoload_libraries(void(*on_error)(const std::string& libname, const std::string& err, bool system) = NULL);
void with_loaded_library(const loadlib::module& l);
bool with_unloaded_library(loadlib::module& l);
std::string loadlib_debug_get_user_library_dir();
std::string loadlib_debug_get_system_library_dir();
void autoload_libraries();
void with_loaded_library(loaded_library* l);
#endif

View file

@ -3,16 +3,18 @@
#include "settings.hpp"
#include "rom.hpp"
#include "romloader.hpp"
#include "moviefile.hpp"
#include "movie.hpp"
/**
* \brief Emulator main loop.
*/
void main_loop(struct loaded_rom& rom, struct moviefile& settings, bool load_has_to_succeed = false);
void main_loop(struct loaded_rom& rom, struct moviefile& settings, bool load_has_to_succeed = false)
throw(std::bad_alloc, std::runtime_error);
std::vector<std::string> get_jukebox_names();
void set_jukebox_names(const std::vector<std::string>& newj);
void init_main_callbacks();
void update_movie_state();
extern std::string msu1_base_path;
/**
@ -28,10 +30,9 @@ void switch_projects(const std::string& newproj);
void close_rom();
void load_new_rom(const romload_request& req);
void reload_current_rom();
void do_break_pause();
void convert_break_to_pause();
extern settingvar::supervariable<settingvar::model_bool<settingvar::yes_no>> movie_dflt_binary;
extern settingvar::supervariable<settingvar::model_bool<settingvar::yes_no>> save_dflt_binary;
extern setting_var<setting_var_model_bool<setting_yes_no>> jukebox_dflt_binary;
extern setting_var<setting_var_model_bool<setting_yes_no>> movie_dflt_binary;
extern setting_var<setting_var_model_bool<setting_yes_no>> save_dflt_binary;
#endif

View file

@ -1,32 +0,0 @@
#ifndef _mbranch__hpp__included__
#define _mbranch__hpp__included__
#define MBRANCH_IMPORT_TEXT 0
#define MBRANCH_IMPORT_BINARY 1
#define MBRANCH_IMPORT_MOVIE 2
class emulator_dispatch;
class status_updater;
class movie_logic;
struct movie_branches
{
movie_branches(movie_logic& _mlogic, emulator_dispatch& _dispatch, status_updater& _supdater);
std::string name(const std::string& internal);
std::set<std::string> enumerate();
std::string get();
void set(const std::string& branch);
void _new(const std::string& branch, const std::string& from);
void rename(const std::string& oldn, const std::string& newn);
void _delete(const std::string& branch);
std::set<std::string> _movie_branches(const std::string& filename);
void import_branch(const std::string& filename, const std::string& ibranch, const std::string& branchname,
int mode);
void export_branch(const std::string& filename, const std::string& branchname, bool binary);
private:
movie_logic& mlogic;
emulator_dispatch& edispatch;
status_updater& supdater;
};
#endif

View file

@ -6,20 +6,10 @@
#include <vector>
#include <cstdint>
#include <stdexcept>
#include "library/memoryspace.hpp"
class memory_space;
class movie_logic;
class loaded_rom;
extern memory_space lsnes_memory;
class cart_mappings_refresher
{
public:
cart_mappings_refresher(memory_space& _mspace, movie_logic& _mlogic, loaded_rom& _rom);
void operator()();
private:
memory_space& mspace;
movie_logic& mlogic;
loaded_rom& rom;
};
void refresh_cart_mappings() throw(std::bad_alloc);
#endif

View file

@ -4,189 +4,11 @@
#include <string>
#include <stdexcept>
#include <set>
#include <functional>
#include "library/memorywatch.hpp"
#include "library/json.hpp"
class memory_space;
class project_state;
class loaded_rom;
class emu_framebuffer;
namespace framebuffer { class queue; }
std::string evaluate_watch(const std::string& expr) throw(std::bad_alloc);
std::set<std::string> get_watches() throw(std::bad_alloc);
std::string get_watchexpr_for(const std::string& w) throw(std::bad_alloc);
void set_watchexpr_for(const std::string& w, const std::string& expr) throw(std::bad_alloc);
void do_watch_memory();
/**
* lsnes memory watch printer variables.
*/
struct memwatch_printer
{
/**
* Ctor.
*/
memwatch_printer();
/**
* Serialize the printer to JSON value.
*/
JSON::node serialize();
/**
* Unserialize the printer from JSON value.
*/
void unserialize(const JSON::node& node);
/**
* Get a printer object corresponding to this object.
*/
GC::pointer<memorywatch::item_printer> get_printer_obj(
std::function<GC::pointer<mathexpr::mathexpr>(const std::string& n)> vars);
//Fields.
enum position_category {
PC_DISABLED,
PC_MEMORYWATCH,
PC_ONSCREEN
} position;
bool cond_enable; //Ignored for disabled.
std::string enabled; //Ignored for disabled.
std::string onscreen_xpos;
std::string onscreen_ypos;
bool onscreen_alt_origin_x;
bool onscreen_alt_origin_y;
bool onscreen_cliprange_x;
bool onscreen_cliprange_y;
std::string onscreen_font; //"" is system default.
int64_t onscreen_fg_color;
int64_t onscreen_bg_color;
int64_t onscreen_halo_color;
};
/**
* lsnes memory watch item.
*/
struct memwatch_item
{
/**
* Ctor.
*/
memwatch_item();
/**
* Serialize the item to JSON value.
*/
JSON::node serialize();
/**
* Unserialize the item from JSON value.
*/
void unserialize(const JSON::node& node);
/**
* Get memory read operator.
*
* If bytes == 0, returns NULL.
*/
mathexpr::operinfo* get_memread_oper(memory_space& memory, loaded_rom& rom);
/**
* Translate compatiblity item.
*/
void compatiblity_unserialize(memory_space& memory, const std::string& item);
//Fields
memwatch_printer printer; //The printer.
std::string expr; //The main expression.
std::string format; //Format.
unsigned bytes; //Number of bytes to read (0 => Not memory read operator).
bool signed_flag; //Is signed?
bool float_flag; //Is float?
int endianess; //Endianess (-1 => little, 0 => host, 1 => Big).
uint64_t scale_div; //Scale divisor.
uint64_t addr_base; //Address base.
uint64_t addr_size; //Address size (0 => All).
};
struct memwatch_set
{
memwatch_set(memory_space& _memory, project_state& _project, emu_framebuffer& _fbuf,
loaded_rom& rom);
/**
* Get the specified memory watch item.
*/
memwatch_item& get(const std::string& name);
/**
* Get the specified memory watch item as JSON serialization.
*
* Parameter name: The item name.
* Parameter printer: JSON pretty-printer to use.
*/
std::string get_string(const std::string& name, JSON::printer* printer = NULL);
/**
* Set the specified memory watch item. Fills the runtime variables.
*
* Parameter name: The name of the new item.
* Parameter item: The item to insert. Fields are shallow-copied.
*/
void set(const std::string& name, memwatch_item& item);
/**
* Set the specified memory watch item from JSON serialization. Fills the runtime variables.
*
* Parameter name: The name of the new item.
* Parameter item: The serialization of item to insert.
*/
void set(const std::string& name, const std::string& item);
/**
* Set multiple items at once.
*
* Parameter list: The list of items.
*/
void set_multi(std::list<std::pair<std::string, memwatch_item>>& list);
/**
* Set multiple items at once from JSON descriptions.
*
* Parameter list: The list of items.
*/
void set_multi(std::list<std::pair<std::string, std::string>>& list);
/**
* Rename a memory watch item.
*
* Parameter oname: The old name.
* Parameter newname: The new name.
* Returns: True on success, false if failed (new item already exists).
*/
bool rename(const std::string& oname, const std::string& newname);
/**
* Delete an item.
*
* Parameter name: The name of the item to delete.
*/
void clear(const std::string& name);
/**
* Delete multiple items.
*
* Parameter names: The names of the items to delete.
*/
void clear_multi(const std::set<std::string>& name);
/**
* Enumerate item names.
*/
std::set<std::string> enumerate();
/**
* Get value of specified memory watch as a string.
*/
std::string get_value(const std::string& name);
/**
* Watch all the items.
*
* Parameter rq: The render queue to use.
*/
void watch(struct framebuffer::queue& rq);
/**
* Get memory watch vars that go to window.
*/
const std::map<std::string, std::u32string>& get_window_vars() { return window_vars; }
private:
void rebuild(std::map<std::string, memwatch_item>& nitems);
std::map<std::string, memwatch_item> items;
std::map<std::string, std::u32string> window_vars;
std::map<std::string, bool> used_memorywatches;
void erase_unused_watches();
void watch_output(const std::string& name, const std::string& value);
memorywatch::set watch_set;
memory_space& memory;
project_state& project;
emu_framebuffer& fbuf;
loaded_rom& rom;
};
#endif
#endif

View file

@ -1,25 +0,0 @@
#ifndef _messages__hpp__included__
#define _messages__hpp__included__
#include <iostream>
/**
* messages -> window::out().
*/
class messages_relay_class
{
public:
operator std::ostream&() { return getstream(); }
static std::ostream& getstream();
};
template<typename T> inline std::ostream& operator<<(messages_relay_class& x, T value)
{
return messages_relay_class::getstream() << value;
};
inline std::ostream& operator<<(messages_relay_class& x, std::ostream& (*fn)(std::ostream& o))
{
return fn(messages_relay_class::getstream());
};
extern messages_relay_class messages;
#endif

View file

@ -5,7 +5,57 @@
#include <vector>
#include <stdexcept>
#include "library/string.hpp"
#include "library/memtracker.hpp"
/**
* \brief Get random hexes
*
* Get string of random hex characters of specified length.
*
* \param length The number of hex characters to return.
* \return The random hexadecimal string.
* \throws std::bad_alloc Not enough memory.
*/
std::string get_random_hexstring(size_t length) throw(std::bad_alloc);
/**
* \brief Set random seed
*
* This function sets the random seed to use.
*
* \param seed The value to use as seed.
* \throw std::bad_alloc Not enough memory.
*/
void set_random_seed(const std::string& seed) throw(std::bad_alloc);
/**
* \brief Set random seed to (hopefully) unique value
*
* This function sets the random seed to value that should only be used once. Note, the value is not necressarily
* crypto-secure, even if it is unique.
*
* \throw std::bad_alloc Not enough memory.
*/
void set_random_seed() throw(std::bad_alloc);
/**
* \brief Load a ROM.
*
* Given commandline arguments, load a ROM.
*
* \param cmdline The command line.
* \return The loaded ROM set.
* \throws std::bad_alloc Not enough memory.
* \throws std::runtime_error Can't load the ROMset.
*/
struct loaded_rom load_rom_from_commandline(std::vector<std::string> cmdline) throw(std::bad_alloc,
std::runtime_error);
/**
* \brief Dump listing of regions to graphics system messages.
*
* \throws std::bad_alloc Not enough memory.
*/
void dump_region_map() throw(std::bad_alloc);
/**
* \brief Fatal error.
@ -20,13 +70,31 @@ void fatal_error() throw();
* \return The config directory path.
* \throw std::bad_alloc Not enough memory.
*/
std::string get_config_path();
std::string get_config_path() throw(std::bad_alloc);
/**
* \brief Panic on OOM.
*/
void OOM_panic();
/**
* messages -> window::out().
*/
class messages_relay_class
{
public:
operator std::ostream&() { return getstream(); }
static std::ostream& getstream();
};
template<typename T> inline std::ostream& operator<<(messages_relay_class& x, T value)
{
return messages_relay_class::getstream() << value;
};
inline std::ostream& operator<<(messages_relay_class& x, std::ostream& (*fn)(std::ostream& o))
{
return fn(messages_relay_class::getstream());
};
extern messages_relay_class messages;
uint32_t gcd(uint32_t a, uint32_t b) throw();
@ -59,4 +127,14 @@ std::string mangle_name(const std::string& orig);
*/
std::string get_temp_file();
/**
* Mix some entropy.
*/
void random_mix_timing_entropy();
/**
* 256 bits of as high quality entropy as possible.
*/
void highrandom_256(uint8_t* buf);
#endif

View file

@ -5,12 +5,10 @@
#include <cstdint>
#include <stdexcept>
#include "core/controllerframe.hpp"
#include "core/moviefile.hpp"
#include "library/rrdata.hpp"
#include "library/movie.hpp"
/**
* Class encapsulating bridge logic between core interface and movie code.
* Class encapsulating bridge logic between bsnes interface and movie code.
*/
class movie_logic
{
@ -19,46 +17,18 @@ public:
* Create new bridge.
*/
movie_logic() throw();
/**
* Has movie?
*/
operator bool() throw() { return mov; }
bool operator!() throw() { return !mov; }
/**
* Get the movie instance associated.
*
* returns: The movie instance.
*/
movie& get_movie();
/**
* Set the movie instance associated.
*/
void set_movie(movie& _mov, bool free_old = false) throw();
/**
* Get the current movie file.
*/
moviefile& get_mfile();
/**
* Set the current movie file.
*/
void set_mfile(moviefile& _mf, bool free_old = false) throw();
/**
* Get current rrdata.
*/
rrdata_set& get_rrdata();
/**
* Set current rrdata.
*/
void set_rrdata(rrdata_set& _rrd, bool free_old = false) throw();
movie& get_movie() throw();
/**
* Notify about new frame starting.
*/
void new_frame_starting(bool dont_poll);
void new_frame_starting(bool dont_poll) throw(std::bad_alloc, std::runtime_error);
/**
* Poll for input.
@ -70,36 +40,16 @@ public:
* throws std::bad_alloc: Not enough memory.
* throws std::runtime_error: Error polling for input.
*/
short input_poll(unsigned port, unsigned dev, unsigned id);
short input_poll(unsigned port, unsigned dev, unsigned id) throw(std::bad_alloc, std::runtime_error);
/**
* Called when movie code needs new controls snapshot.
*
* parameter subframe: True if this is for subframe update, false if for frame update.
*/
portctrl::frame update_controls(bool subframe, bool forced = false);
/**
* Notify user poll (exit poll advance).
*
* returns: If true, update_controls is forced.
*/
bool notify_user_poll();
/**
* Release memory for mov, mf and rrd.
*/
void release_memory();
/**
* Set frob with data routine.
*/
void set_frob_with_value(std::function<void(unsigned,unsigned,unsigned,short&)> func);
controller_frame update_controls(bool subframe) throw(std::bad_alloc, std::runtime_error);
private:
std::function<void(unsigned,unsigned,unsigned,short&)> frob_with_value;
movie_logic(const movie_logic&);
movie_logic& operator=(const movie_logic&);
movie* mov;
moviefile* mf;
rrdata_set* rrd;
movie mov;
};
#endif

View file

@ -1,47 +1,40 @@
#ifndef _moviedata__hpp__included__
#define _moviedata__hpp__included__
#include "core/emustatus.hpp"
#include "core/moviefile.hpp"
#include "core/movie.hpp"
#include "library/rrdata.hpp"
#include "moviefile.hpp"
#include "movie.hpp"
//Load state, always switch to Readwrite.
#define LOAD_STATE_RW 0
//Load state, never switch to Readwrite.
#define LOAD_STATE_RO 1
//Load state, don't muck with movie data.
#define LOAD_STATE_PRESERVE 2
//Load state, ignoring the actual state.
#define LOAD_STATE_MOVIE 3
//Load state, switch to readwrite if previously there and loaded state is at the end.
#define LOAD_STATE_DEFAULT 4
//Load state, switch to readwrite if previously there.
#define LOAD_STATE_CURRENT 5
//No load state, rewind movie to start.
#define LOAD_STATE_BEGINNING 6
//No load state, reload ROM.
#define LOAD_STATE_ROMRELOAD 7
//Load state, loading everything, switch to readwrite if loaded state is at the end.
#define LOAD_STATE_INITIAL 8
//Load state, along with all branches, switch to readwrite if loaded state is at the end.
#define LOAD_STATE_ALLBRANCH 9
#define SAVE_STATE 0
#define SAVE_MOVIE 1
std::string resolve_relative_path(const std::string& path);
std::pair<std::string, std::string> split_author(const std::string& author);
extern struct moviefile our_movie;
extern struct loaded_rom our_rom;
extern bool system_corrupt;
std::vector<char>& get_host_memory();
movie& get_movie();
void do_save_state(const std::string& filename, int binary);
void do_save_movie(const std::string& filename, int binary);
void do_load_rom();
void do_load_rewind();
void do_load_state(struct moviefile& _movie, int lmode, bool& used);
std::string resolve_relative_path(const std::string& path);
std::pair<std::string, std::string> split_author(const std::string& author) throw(std::bad_alloc,
std::runtime_error);
void do_save_state(const std::string& filename, int binary) throw(std::bad_alloc, std::runtime_error);
void do_save_movie(const std::string& filename, int binary) throw(std::bad_alloc, std::runtime_error);
void do_load_beginning(bool reloading = false) throw(std::bad_alloc, std::runtime_error);
void do_load_state(struct moviefile& _movie, int lmode);
bool do_load_state(const std::string& filename, int lmode);
std::string translate_name_mprefix(std::string original, int& binary, int save);
std::string translate_name_mprefix(std::string original, int& binary, bool save);
extern std::string last_save;
extern movie_logic movb;
/**
* Restore the actual core state from quicksave. Only call in rewind callback.
@ -50,21 +43,11 @@ extern std::string last_save;
* Parameter secs: The seconds counter.
* Parameter ssecs: The subsecond counter.
*/
void mainloop_restore_state(const dynamic_state& state);
void mainloop_restore_state(const std::vector<char>& state, uint64_t secs, uint64_t ssecs);
std::string get_mprefix_for_project();
void set_mprefix_for_project(const std::string& pfx);
void set_mprefix_for_project(const std::string& prjid, const std::string& pfx);
class rrdata
{
public:
rrdata();
rrdata_set::instance operator()();
static std::string filename(const std::string& projectid);
private:
bool init;
rrdata_set::instance next;
};
#endif

View file

@ -1,31 +0,0 @@
#ifndef _moviefile_binary__hpp__included__
#define _moviefile_binary__hpp__included__
/**
* The binary movie extension tags.
*/
enum lsnes_movie_tags
{
TAG_ANCHOR_SAVE = 0xf5e0fad7,
TAG_AUTHOR = 0xafff97b4,
TAG_CORE_VERSION = 0xe4344c7e,
TAG_GAMENAME = 0xe80d6970,
TAG_HOSTMEMORY = 0x3bf9d187,
TAG_MACRO = 0xd261338f,
TAG_MOVIE = 0xf3dca44b,
TAG_MOVIE_SRAM = 0xbbc824b7,
TAG_MOVIE_TIME = 0x18c3a975,
TAG_PROJECT_ID = 0x359bfbab,
TAG_ROMHASH = 0x0428acfc,
TAG_RRDATA = 0xa3a07f71,
TAG_SAVE_SRAM = 0xae9bfb2f,
TAG_SAVESTATE = 0x2e5bc2ac,
TAG_SCREENSHOT = 0xc6760d0e,
TAG_SUBTITLE = 0x6a7054d3,
TAG_RAMCONTENT = 0xd3ec3770,
TAG_ROMHINT = 0x6f715830,
TAG_BRANCH = 0xf2e60707,
TAG_BRANCH_NAME = 0x6dcb2155
};
#endif

View file

@ -1,64 +0,0 @@
#ifndef _moviefile_common__hpp__included__
#define _moviefile_common__hpp__included__
#include <functional>
#include "core/moviefile.hpp"
#define DEFAULT_RTC_SECOND 1000000000ULL
#define DEFAULT_RTC_SUBSECOND 0ULL
template<typename target>
static void moviefile_write_settings(target& w, const std::map<std::string, std::string>& settings,
core_setting_group& sgroup, std::function<void(target& w, const std::string& name,
const std::string& value)> writefn)
{
for(auto i : settings) {
if(!sgroup.settings.count(i.first))
continue;
if(sgroup.settings.find(i.first)->second.dflt == i.second)
continue;
writefn(w, i.first, i.second);
}
}
struct moviefile_branch_extractor_text : public moviefile::branch_extractor
{
moviefile_branch_extractor_text(const std::string& filename);
~moviefile_branch_extractor_text();
std::set<std::string> enumerate();
void read(const std::string& name, portctrl::frame_vector& v);
private:
zip::reader z;
};
struct moviefile_branch_extractor_binary : public moviefile::branch_extractor
{
moviefile_branch_extractor_binary(const std::string& filename);
~moviefile_branch_extractor_binary();
std::set<std::string> enumerate();
void read(const std::string& name, portctrl::frame_vector& v);
private:
int s;
};
struct moviefile_sram_extractor_text : public moviefile::sram_extractor
{
moviefile_sram_extractor_text(const std::string& filename);
~moviefile_sram_extractor_text();
std::set<std::string> enumerate();
void read(const std::string& name, std::vector<char>& v);
private:
zip::reader z;
};
struct moviefile_sram_extractor_binary : public moviefile::sram_extractor
{
moviefile_sram_extractor_binary(const std::string& filename);
~moviefile_sram_extractor_binary();
std::set<std::string> enumerate();
void read(const std::string& name, std::vector<char>& v);
private:
int s;
};
#endif

View file

@ -6,77 +6,10 @@
#include <stdexcept>
#include <map>
#include "core/controllerframe.hpp"
#include "core/rom-small.hpp"
#include "core/rom.hpp"
#include "core/subtitles.hpp"
#include "interface/romtype.hpp"
#include "library/rrdata.hpp"
#include "library/zip.hpp"
class loaded_rom;
/**
* Dynamic state parts of movie file.
*/
struct dynamic_state
{
/**
* Ctor.
*/
dynamic_state();
/**
* Contents of SRAM on time of savestate (if is_savestate is true).
*/
std::map<std::string, std::vector<char>> sram;
/**
* Core savestate (if is_savestate is true).
*/
std::vector<char> savestate; //Savestate to load (if is_savestate is true).
/**
* Host memory (if is_savestate is true).
*/
std::vector<char> host_memory;
/**
* Screenshot (if is_savestate is true).
*/
std::vector<char> screenshot;
/**
* Current frame (if is_savestate is true).
*/
uint64_t save_frame;
/**
* Number of lagged frames (if is_savestate is true).
*/
uint64_t lagged_frames;
/**
* Poll counters (if is_savestate is true).
*/
std::vector<uint32_t> pollcounters;
/**
* Poll flag.
*/
unsigned poll_flag;
/**
* Current RTC second.
*/
int64_t rtc_second;
/**
* Current RTC subsecond.
*/
int64_t rtc_subsecond;
/**
* Active macros at savestate.
*/
std::map<std::string, uint64_t> active_macros;
/**
* Clear the state to power-on defaults.
*/
void clear(int64_t sec, int64_t ssec, const std::map<std::string, std::vector<char>>& initsram);
/**
* Swap the dynamic state with another.
*/
void swap(dynamic_state& s) throw();
};
/**
* This structure gives parsed representationg of movie file, as result of decoding or for encoding.
*/
@ -98,47 +31,14 @@ struct moviefile
uint64_t current_frame;
uint64_t rerecords;
private:
void load(zip::reader& r);
void binary_io(int s);
void binary_io(std::istream& s);
};
/**
* Extract branches.
*/
struct branch_extractor
{
branch_extractor(const std::string& filename);
virtual ~branch_extractor();
virtual std::set<std::string> enumerate() { return real->enumerate(); }
virtual void read(const std::string& name, portctrl::frame_vector& v) { real->read(name, v); }
protected:
branch_extractor() { real = NULL; }
private:
branch_extractor* real;
};
/**
* Extract SRAMs.
*/
struct sram_extractor
{
sram_extractor(const std::string& filename);
virtual ~sram_extractor();
virtual std::set<std::string> enumerate() { return real->enumerate(); }
virtual void read(const std::string& name, std::vector<char>& v) { real->read(name, v); }
protected:
sram_extractor() { real = NULL; }
private:
sram_extractor* real;
};
/**
* Identify if file is movie/savestate file or not.
*/
static bool is_movie_or_savestate(const std::string& filename);
/**
* This constructor construct movie structure with default settings.
*
* throws std::bad_alloc: Not enough memory.
*/
moviefile();
moviefile() throw(std::bad_alloc);
/**
* This constructor loads a movie/savestate file and fills structure accordingly.
@ -148,18 +48,7 @@ struct moviefile
* throws std::bad_alloc: Not enough memory.
* throws std::runtime_error: Can't load the movie file
*/
moviefile(const std::string& filename, core_type& romtype);
/**
* Fill a stub movie with specified loaded ROM.
*
* Parameter rom: The rom.
* Parameter settings: The settings.
* Parameter rtc_sec: The RTC seconds value.
* Parameter rtc_subsec: The RTC subseconds value.
*/
moviefile(loaded_rom& rom, std::map<std::string, std::string>& c_settings, uint64_t rtc_sec,
uint64_t rtc_subsec);
moviefile(const std::string& filename, core_type& romtype) throw(std::bad_alloc, std::runtime_error);
/**
* Reads this movie structure and saves it into file.
@ -167,15 +56,15 @@ struct moviefile
* parameter filename: The file to save to.
* parameter compression: The compression level 0-9. 0 is uncompressed.
* parameter binary: Save in binary form if true.
* parameter rrd: The rerecords data.
* throws std::bad_alloc: Not enough memory.
* throws std::runtime_error: Can't save the movie file.
*/
void save(const std::string& filename, unsigned compression, bool binary, rrdata_set& rrd, bool as_state);
void save(const std::string& filename, unsigned compression, bool binary) throw(std::bad_alloc,
std::runtime_error);
/**
* Reads this movie structure and saves it to stream (uncompressed ZIP).
*/
void save(std::ostream& outstream, rrdata_set& rrd, bool as_state);
void save(std::ostream& outstream) throw(std::bad_alloc, std::runtime_error);
/**
* Force loading as corrupt.
*/
@ -232,22 +121,62 @@ struct moviefile
* Contents of RAM on time of initial powerup.
*/
std::map<std::string, std::vector<char>> ramcontent;
/**
* True if savestate, false if movie.
*/
bool is_savestate;
/**
* Contents of SRAM on time of savestate (if is_savestate is true).
*/
std::map<std::string, std::vector<char>> sram;
/**
* Core savestate (if is_savestate is true).
*/
std::vector<char> savestate; //Savestate to load (if is_savestate is true).
/**
* Anchoring core savestate (if not empty).
*/
std::vector<char> anchor_savestate;
/**
* Host memory (if is_savestate is true).
*/
std::vector<char> host_memory;
/**
* Screenshot (if is_savestate is true).
*/
std::vector<char> screenshot;
/**
* Current frame (if is_savestate is true).
*/
uint64_t save_frame;
/**
* Number of lagged frames (if is_savestate is true).
*/
uint64_t lagged_frames;
/**
* Poll counters (if is_savestate is true).
*/
std::vector<uint32_t> pollcounters;
/**
* Poll flag.
*/
unsigned poll_flag;
/**
* Compressed rrdata.
*/
std::vector<char> c_rrdata;
/**
* Input for each (sub)frame (points to active branch).
* Input for each (sub)frame.
*/
portctrl::frame_vector* input;
controller_frame_vector input; //Input for each frame.
/**
* Branches.
* Current RTC second.
*/
std::map<std::string, portctrl::frame_vector> branches;
int64_t rtc_second;
/**
* Current RTC subsecond.
*/
int64_t rtc_subsecond;
/**
* Movie starting RTC second.
*/
@ -269,9 +198,9 @@ struct moviefile
*/
std::map<moviefile_subtiming, std::string> subtitles;
/**
* Dynamic state.
* Active macros at savestate.
*/
dynamic_state dyn;
std::map<std::string, uint64_t> active_macros;
/**
* Get number of frames in movie.
*
@ -281,54 +210,17 @@ struct moviefile
/**
* Get length of the movie
*
* returns: Length of the movie in milliseconds.
* returns: Length of the movie in nanoseconds.
*/
uint64_t get_movie_length() throw();
/**
* Return reference to memory slot.
*/
static moviefile*& memref(const std::string& slot);
/**
* Copy data.
*/
void copy_fields(const moviefile& mv);
/**
* Create a default branch.
*/
void create_default_branch(portctrl::type_set& ports);
/**
* Get name of current branch.
*/
const std::string& current_branch();
/**
* Fork a branch.
*/
void fork_branch(const std::string& oldname, const std::string& newname);
/**
* Fixup input pointer post-copy.
*/
void fixup_current_branch(const moviefile& mv);
/**
* Clear the dynamic state to power-on defaults.
*/
void clear_dynstate();
/**
* Get the filename of the movie.
*/
std::string get_filename() { return filename; }
static moviefile& memref(const std::string& slot);
private:
moviefile(const moviefile&);
moviefile& operator=(const moviefile&);
void binary_io(int stream, rrdata_set& rrd, bool as_state);
void binary_io(int stream, struct core_type& romtype);
void save(zip::writer& w, rrdata_set& rrd, bool as_state);
void load(zip::reader& r, core_type& romtype);
memtracker::autorelease tracker;
std::string filename;
void binary_io(std::ostream& stream) throw(std::bad_alloc, std::runtime_error);
void binary_io(std::istream& stream, struct core_type& romtype) throw(std::bad_alloc, std::runtime_error);
void save(zip_writer& w) throw(std::bad_alloc, std::runtime_error);
};
void emerg_save_movie(const moviefile& mv, rrdata_set& rrd);
#endif

View file

@ -2,11 +2,8 @@
#define _multitrack__hpp__included__
#include <map>
#include "library/threads.hpp"
class controller_state;
class movie_logic;
class emulator_dispatch;
#include "library/threadtypes.hpp"
#include "library/controller-data.hpp"
class multitrack_edit
{
@ -18,8 +15,6 @@ public:
MT_OR,
MT_XOR
};
multitrack_edit(movie_logic& _mlogic, controller_state& _controls, emulator_dispatch& _dispatch,
status_updater& _supdater, button_mapping& _buttons, command::group& _cmd);
void enable(bool state);
void set(unsigned port, unsigned controller, state s);
void set_and_notify(unsigned port, unsigned controller, state s);
@ -27,24 +22,14 @@ public:
state get(unsigned port, unsigned controller);
bool is_enabled();
void config_altered();
void process_frame(portctrl::frame& input);
void process_frame(controller_frame& input);
bool any_records();
private:
void do_mt_fwd();
void do_mt_bw();
void do_mt_set(const std::string& args);
threads::lock mlock;
mutex_class mutex;
bool enabled;
std::map<std::pair<unsigned, unsigned>, state> controllerstate;
movie_logic& mlogic;
controller_state& controls;
emulator_dispatch& edispatch;
status_updater& supdater;
button_mapping& buttons;
command::group& cmd;
command::_fnptr<> mt_f;
command::_fnptr<> mt_b;
command::_fnptr<const std::string&> mt_s;
};
extern multitrack_edit multitrack_editor;
#endif

View file

@ -1,12 +0,0 @@
#ifndef _nullcore__hpp__included__
#define _nullcore__hpp__included__
class core_core;
class core_type;
class core_region;
core_core& get_null_core();
core_type& get_null_type();
core_region& get_null_region();
#endif

View file

@ -5,27 +5,9 @@
#include <map>
#include <list>
#include <vector>
#include "core/rom-small.hpp"
#include "library/command.hpp"
#include "library/json.hpp"
class voice_commentary;
class memwatch_set;
class controller_state;
class button_mapping;
class emulator_dispatch;
class input_queue;
class status_updater;
namespace settingvar { class cache; }
//A branch.
struct project_branch_info
{
//Parent branch ID.
uint64_t pbid;
//Name.
std::string name;
};
#include "core/controller.hpp"
#include "core/rom.hpp"
//Information about project.
struct project_info
@ -50,12 +32,6 @@ struct project_info
std::map<std::string, std::string> watches;
//Macros.
std::map<std::string, JSON::node> macros;
//Branches.
std::map<uint64_t, project_branch_info> branches;
uint64_t active_branch;
uint64_t next_branch;
//Filename this was loaded from.
std::string filename;
//Stub movie data.
std::string gametype;
std::map<std::string, std::string> settings;
@ -70,180 +46,65 @@ struct project_info
std::vector<char> anchor_savestate;
int64_t movie_rtc_second;
int64_t movie_rtc_subsecond;
/**
* Make empty project info.
*/
project_info(emulator_dispatch& _dispatch);
/**
* Obtain parent of branch.
*
* Parameter bid: The branch ID.
* Returns: The parent branch ID.
* Throws std::runtime_error: Invalid branch ID.
*
* Note: bid 0 is root. Calling this on root always gives 0.
*/
uint64_t get_parent_branch(uint64_t bid);
/**
* Get current branch id.
*
* Returns: The branch id.
*/
uint64_t get_current_branch() { return active_branch; }
/**
* Set current branch.
*
* Parameter bid: The branch id.
* Throws std::runtime_error: Invalid branch ID.
*/
void set_current_branch(uint64_t bid);
/**
* Get name of branch.
*
* Parameter bid: The branch id.
* Throws std::runtime_error: Invalid branch ID.
* Note: The name of ROOT branch is always empty string.
*/
const std::string& get_branch_name(uint64_t bid);
/**
* Set name of branch.
*
* Parameter bid: The branch id.
* Parameter name: The new name
* Throws std::runtime_error: Invalid branch ID.
* Note: The name of ROOT branch can't be changed.
*/
void set_branch_name(uint64_t bid, const std::string& name);
/**
* Set parent branch of branch.
*
* Parameter bid: The branch id.
* Parameter pbid: The new parent branch id.
* Throws std::runtime_error: Invalid branch ID, or cyclic dependency.
* Note: The parent of ROOT branch can't be set.
*/
void set_parent_branch(uint64_t bid, uint64_t pbid);
/**
* Enumerate child branches of specified branch.
*
* Parameter bid: The branch id.
* Returns: The set of chilid branch IDs.
* Throws std::runtime_error: Invalid branch ID.
*/
std::set<uint64_t> branch_children(uint64_t bid);
/**
* Create a new branch.
*
* Parameter pbid: Parent of the new branch.
* Parameter name: Name of new branch.
* Returns: Id of new branch.
* Throws std::runtime_error: Invalid branch ID.
*/
uint64_t create_branch(uint64_t pbid, const std::string& name);
/**
* Delete a branch.
*
* Parameter bid: The branch id.
* Throws std::runtime_error: Invalid branch ID or branch has children.
*/
void delete_branch(uint64_t bid);
/**
* Get name of current branch as string.
*/
std::string get_branch_string();
/**
* Flush the project to disk.
*/
void flush();
private:
void write(std::ostream& s);
emulator_dispatch& edispatch;
};
class project_state
{
public:
project_state(voice_commentary& _commentary, memwatch_set& _mwatch, command::group& _command,
controller_state& _controls, settingvar::group& _setgroup, button_mapping& _buttons,
emulator_dispatch& _edispatch, input_queue& _iqueue, loaded_rom& _rom, status_updater& _supdater);
~project_state();
/**
* Get currently active project.
*
* Returns: The currently active project or NULL if none.
*/
project_info* get();
project_info* project_get();
/**
* Change currently active project. This reloads Lua VM, ROM and savestate.
*
* Parameter p: The new currently active project, or NULL to switch out of any project.
* Parameter current: If true, do not reload ROM, movie nor state.
*/
bool set(project_info* p, bool current = false);
bool project_set(project_info* p, bool current = false);
/**
* Enumerate all known projects.
*
* Returns: Map from IDs of projects to project names.
*/
std::map<std::string, std::string> enumerate();
std::map<std::string, std::string> project_enumerate();
/**
* Load a given project.
*
* Parameter id: The ID of project to load.
* Returns: The project information.
*/
project_info& load(const std::string& id);
project_info& project_load(const std::string& id);
/**
* Flush any changes to project to disk.
*
* Parameter: The project to flush (NULL is no-op).
*/
void project_flush(project_info* p);
/**
* Get project movie path.
*
* Returns: The movie path.
*/
std::string moviepath();
std::string project_moviepath();
/**
* Get project other path.
*
* Returns: The other path.
*/
std::string otherpath();
std::string project_otherpath();
/**
* Get project savestate extension.
*
* Returns: The savestate extension.
*/
std::string savestate_ext();
std::string project_savestate_ext();
/**
* Copy watches to project
*/
void copy_watches(project_info& p);
void project_copy_watches(project_info& p);
/**
* Copy macros to project.
*/
void copy_macros(project_info& p, controller_state& s);
private:
void recursive_list_branch(uint64_t bid, std::set<unsigned>& dset, unsigned depth, bool last_of);
void do_branch_ls();
void do_branch_mk(const std::string& a);
void do_branch_rm(const std::string& a);
void do_branch_set(const std::string& a);
void do_branch_rp(const std::string& a);
void do_branch_mv(const std::string& a);
project_info* active_project;
voice_commentary& commentary;
memwatch_set& mwatch;
command::group& command;
controller_state& controls;
settingvar::group& setgroup;
button_mapping& buttons;
emulator_dispatch& edispatch;
input_queue& iqueue;
loaded_rom& rom;
status_updater& supdater;
command::_fnptr<> branch_ls;
command::_fnptr<const std::string&> branch_mk;
command::_fnptr<const std::string&> branch_rm;
command::_fnptr<const std::string&> branch_set;
command::_fnptr<const std::string&> branch_rp;
command::_fnptr<const std::string&> branch_mv;
};
void project_copy_macros(project_info& p, controller_state& s);
#endif

View file

@ -1,144 +0,0 @@
#ifndef _queue__hpp__included__
#define _queue__hpp__included__
#include "library/exrethrow.hpp"
#include "library/keyboard.hpp"
#include "library/threads.hpp"
#include <functional>
#include <deque>
namespace command
{
class group;
}
/**
* Information about keypress.
*/
struct keypress_info
{
/**
* Create null keypress (no modifiers, NULL key and released).
*/
keypress_info();
/**
* Create new keypress.
*/
keypress_info(keyboard::modifier_set mod, keyboard::key& _key, short _value);
/**
* Create new keypress (two keys).
*/
keypress_info(keyboard::modifier_set mod, keyboard::key& _key, keyboard::key& _key2, short _value);
/**
* Modifier set.
*/
keyboard::modifier_set modifiers;
/**
* The actual key (first)
*/
keyboard::key* key1;
/**
* The actual key (second)
*/
keyboard::key* key2;
/**
* Value for the press
*/
short value;
};
template<typename T>
void functor_call_helper2(void* args)
{
(*reinterpret_cast<T*>(args))();
delete reinterpret_cast<T*>(args);
}
struct input_queue
{
struct function_queue_entry
{
std::function<void()> fn;
std::function<void(std::exception& e)> onerror;
};
//Queue stuff.
threads::lock queue_lock;
threads::cv queue_condition;
std::deque<keypress_info> keypresses;
std::deque<std::pair<const char*, std::string>> commands;
std::deque<function_queue_entry> functions;
volatile uint64_t functions_executed;
volatile uint64_t next_function;
volatile bool system_thread_available;
bool queue_function_run;
/**
* Ctor.
*/
input_queue(command::group& _command);
/**
* Queue keypress.
*
* - Can be called from any thread.
*
* Parameter k: The keypress to queue.
*/
void queue(const keypress_info& k);
/**
* Queue command.
*
* - Can be called from any thread.
*
* Parameter c: The command to queue.
*/
void queue(const std::string& c);
/**
* Queue command and arguments.
*
* - Can be called from any thread.
*
* Parameter c: The command to queue.
* Parameter a: The arguments for function.
*/
void queue(const char* c, const std::string& a);
/**
* Queue function to be called in emulation thread.
*
* - Can be called from any thread (exception: Synchronous mode can not be used from emulation nor main threads).
*
* Parameter f: The function to execute.
* Parameter onerror: Function to call on error.
* Parameter arg: Argument to pass to the function.
* Parameter sync: If true, execute function call synchronously, else asynchronously.
*/
void queue(std::function<void()> f, std::function<void(std::exception& e)> onerror, bool sync);
/**
* Run all queues.
*/
void run_queues() throw();
/**
* Call function synchronously in emulation thread.
*/
void run(std::function<void()> fn)
{
exrethrow::storage ex;
queue(fn, [&ex](std::exception& e) { ex = exrethrow::storage(e); }, true);
if(ex) ex.rethrow();
}
/**
* Queue asynchrous function in emulation thread.
*/
void run_async(std::function<void()> fn,
std::function<void(std::exception& e)> onerror)
{
queue(fn, onerror, false);
}
/**
* Run internal queues.
*/
void run_queue(bool unlocked) throw();
private:
command::group& command;
};
#endif

View file

@ -1,55 +0,0 @@
#ifndef _random__hpp__included__
#define _random__hpp__included__
#include <string>
#include <vector>
#include <stdexcept>
#include "library/string.hpp"
/**
* \brief Get random hexes
*
* Get string of random hex characters of specified length.
*
* \param length The number of hex characters to return.
* \return The random hexadecimal string.
* \throws std::bad_alloc Not enough memory.
*/
std::string get_random_hexstring(size_t length);
/**
* \brief Set random seed
*
* This function sets the random seed to use.
*
* \param seed The value to use as seed.
* \throw std::bad_alloc Not enough memory.
*/
void set_random_seed(const std::string& seed);
/**
* \brief Set random seed to (hopefully) unique value
*
* This function sets the random seed to value that should only be used once. Note, the value is not necressarily
* crypto-secure, even if it is unique.
*
* \throw std::bad_alloc Not enough memory.
*/
void set_random_seed();
/**
* Mix some entropy.
*/
void random_mix_timing_entropy();
/**
* 256 bits of as high quality entropy as possible.
*/
void highrandom_256(uint8_t* buf);
/**
* Contribute buffer of entropy.
*/
void contribute_random_entropy(void* buf, size_t bytes);
#endif

Some files were not shown because too many files have changed in this diff Show more