bsnes/bsnes/emulator/emulator.hpp

136 lines
3.4 KiB
C++
Raw Normal View History

#ifndef EMULATOR_HPP
#define EMULATOR_HPP
Update to v088r10 release. byuu says: ethos is going to be absolutely amazing. You guys are in for a treat :D I'm impressing the hell out of myself with how well-structured this code is, it's allowing me to do amazing new things. Just a small sampling of what's in store (and already implemented): The file browser will display folders as "[ folder name ]", and cartridge folders as "Game Name" (no extension, no /) [icons would be nicer, but well ... phoenix.] Folders are sorted above cartridge folders. Cartridge folders for other systems do not show up in the list. Not only are unique paths stored for each image type, your position in the list is saved across runs. Some voodoo was added to GTK+ so that all targets even scroll directly to that item when you open the list. Load->System->Enter restarts your last game. That sounds really simple and obvious, but it makes an -incredible- difference. Didn't realize it until I tried an implementation of it, wow. The input mapping list now lets you bind as many hotkeys as you want to any given input. So SFC::Port1::Joypad::B = Keyboard::Z or Joypad::Button1 ... no need to remap everything to switch between keyboard and joypad. Either one activates the key. There is a separate Hotkeys tab now. This should hopefully end the confusion about how to remap hotkeys that users experience. Hotkeys are different, too. Instead of OR logic, they use AND logic. So Fullscreen = Keyboard::Alt and Keyboard::Enter. Both must be pressed to enter the key. This lets you easily implement "super" modifier keys. The actual codebase has new features the old UI never had, and has about ~50% of the old functionality (so far, of course), yet is only ~25% as much code. The entire GUI no longer needs to pull in all the headers for each emulated system. It just needs a small interface header file. Then bind the entire system with exactly **two** lines of code. Everything is dynamically generated for you after that.
2012-04-30 23:43:23 +00:00
namespace Emulator {
static const char Name[] = "bsnes";
Update to v088r14 release. byuu says: Changelog: - added NSS DIP switch settings window (when loading NSS carts with appropriate manifest.xml file) - added video shader selection (they go in ~/.config/bsnes/Video Shaders/ now) - added driver selection - added timing settings (not only allows video/audio settings, also has code to dynamically compute the values for you ... and it actually works pretty good!) - moved "None" controller device to bottom of list (it is the least likely to be used, after all) - added Interface::path() to support MSU1, USART, Link - input and hotkey mappings remember list position after assignment - and more! target-ethos now has all of the functionality of target-ui, and more. Final code size for the port is 101.2KB (ethos) vs 167.6KB (ui). A ~67% reduction in code size, yet it does even more! And you can add or remove an entire system with only three lines of code (Makefile include, header include, interface append.) The only problem left is that the BS-X BIOS won't load the BS Zelda no Densetsu file. I can't figure out why it's not working, would appreciate any assistance, but otherwise I'm probably just going to leave it broken for v089, sorry. So the show stoppers for a new release at this point are: - fix laevateinn to compile with the new interface changes (shouldn't be too hard, it'll still use the old, direct interface.) - clean up Emulator::Interface as much as possible (trim down Information, mediaRequest should use an alternate struct designed to load firmware / slots separately) - enhance purify to strip SNES ROM headers, and it really needs a GUI interface - it would be highly desirable to make a launcher that can create a cartridge folder from an existing ROM set (* ethos will need to accept command-line arguments for this.) - probably need to remember which controller was selected in each port for each system across runs - need to fix the cursor for Super Scope / Justifier games (move from 19-bit to 32-bit colors broke it) - have to refactor that cache.(hv)offset thing to fix ASP
2012-05-06 23:27:42 +00:00
static const char Version[] = "088.14";
Update to v088r10 release. byuu says: ethos is going to be absolutely amazing. You guys are in for a treat :D I'm impressing the hell out of myself with how well-structured this code is, it's allowing me to do amazing new things. Just a small sampling of what's in store (and already implemented): The file browser will display folders as "[ folder name ]", and cartridge folders as "Game Name" (no extension, no /) [icons would be nicer, but well ... phoenix.] Folders are sorted above cartridge folders. Cartridge folders for other systems do not show up in the list. Not only are unique paths stored for each image type, your position in the list is saved across runs. Some voodoo was added to GTK+ so that all targets even scroll directly to that item when you open the list. Load->System->Enter restarts your last game. That sounds really simple and obvious, but it makes an -incredible- difference. Didn't realize it until I tried an implementation of it, wow. The input mapping list now lets you bind as many hotkeys as you want to any given input. So SFC::Port1::Joypad::B = Keyboard::Z or Joypad::Button1 ... no need to remap everything to switch between keyboard and joypad. Either one activates the key. There is a separate Hotkeys tab now. This should hopefully end the confusion about how to remap hotkeys that users experience. Hotkeys are different, too. Instead of OR logic, they use AND logic. So Fullscreen = Keyboard::Alt and Keyboard::Enter. Both must be pressed to enter the key. This lets you easily implement "super" modifier keys. The actual codebase has new features the old UI never had, and has about ~50% of the old functionality (so far, of course), yet is only ~25% as much code. The entire GUI no longer needs to pull in all the headers for each emulated system. It just needs a small interface header file. Then bind the entire system with exactly **two** lines of code. Everything is dynamically generated for you after that.
2012-04-30 23:43:23 +00:00
static const char Author[] = "byuu";
static const char License[] = "GPLv3";
}
#include <nall/platform.hpp>
#include <nall/algorithm.hpp>
#include <nall/dl.hpp>
#include <nall/dsp.hpp>
#include <nall/endian.hpp>
#include <nall/file.hpp>
#include <nall/function.hpp>
#include <nall/priorityqueue.hpp>
#include <nall/property.hpp>
#include <nall/random.hpp>
#include <nall/serializer.hpp>
#include <nall/sha256.hpp>
#include <nall/stdint.hpp>
#include <nall/string.hpp>
#include <nall/utility.hpp>
#include <nall/varint.hpp>
#include <nall/vector.hpp>
Update to v088r03 release. byuu says: static vector<uint8_t> file::read(const string &filename); replaces: static bool file::read(const string &filename, uint8_t *&data, unsigned &size); This allows automatic deletion of the underlying data. Added vectorstream, which is obviously a vector<uint8_t> wrapper for a data stream. Plan is for all data accesses inside my emulation cores to take stream objects, especially MSU1. This lets you feed the core anything: memorystream, filestream, zipstream, gzipstream, httpstream, etc. There will still be exceptions for link and serial, those need actual library files on disk. But those aren't official hardware devices anyway. So to help with speed a bit, I'm rethinking the video rendering path. Previous system: - core outputs system-native samples (SNES = 19-bit LRGB, NES = 9-bit emphasis+palette, DMG = 2-bit grayscale, etc.) - interfaceSystem transforms samples to 30-bit via lookup table inside the emulation core - interfaceSystem masks off overscan areas, if enabled - interfaceUI runs filter to produce new target buffer, if enabled - interfaceUI transforms 30-bit video to native display depth (24-bit or 30-bit), and applies color-adjustments (gamma, etc) at the same time New system: - all cores now generate an internal palette, and call Interface::videoColor(uint32_t source, uint16_t red, uint16_t green, uint16_t blue) to get native display color post-adjusted (gamma, etc applied already.) - all cores output to uint32_t* buffer now (output video.palette[color] instead of just color) - interfaceUI runs filter to produce new target buffer, if enabled - interfaceUI memcpy()'s buffer to the video card videoColor() is pretty neat. source is the raw pixel (as per the old-format, 19-bit SNES, 9-bit NES, etc), and you can create a color from that if you really want to. Or return that value to get a buffer just like v088 and below. red, green, blue are 16-bits per channel, because why the hell not, right? Just lop off all the bits you don't want. If you have more bits on your display than that, fuck you :P The last step is extremely difficult to avoid. Video cards can and do have pitches that differ from the width of the texture. Trying to make the core account for this would be really awful. And even if we did that, the emulation routine would need to write directly to a video card RAM buffer. Some APIs require you to lock the video buffer while writing, so this would leave the video buffer locked for a long time. Probably not catastrophic, but still awful. And lastly, if the emulation core tried writing directly to the display texture, software filters would no longer be possible (unless you -really- jump through hooks and divert to a memory buffer when a filter is enabled, but ... fuck.) Anyway, the point of all that work was to eliminate an extra video copy, and the need for a really painful 30-bit to 24-bit conversion (three shifts, three masks, three array indexes.) So this basically reverts us, performance-wise, to where we were pre-30 bit support. [...] The downside to this is that we're going to need a filter for each output depth. Since the array type is uint32_t*, and I don't intend to support higher or lower depths, we really only need 24+30-bit versions of each filter. Kinda shitty, but oh well.
2012-04-27 12:12:53 +00:00
#include <nall/stream/memory.hpp>
using namespace nall;
#include "interface.hpp"
//debugging function hook:
//no overhead (and no debugger invocation) if not compiled with -DDEBUGGER
//wraps testing of function to allow invocation without a defined callback
template<typename T> struct hook;
template<typename R, typename... P> struct hook<R (P...)> {
function<R (P...)> callback;
R operator()(P... p) const {
#if defined(DEBUGGER)
if(callback) return callback(std::forward<P>(p)...);
#endif
return R();
}
hook() {}
hook(const hook &hook) { callback = hook.callback; }
hook(void *function) { callback = function; }
hook(R (*function)(P...)) { callback = function; }
Update to v088r03 release. byuu says: static vector<uint8_t> file::read(const string &filename); replaces: static bool file::read(const string &filename, uint8_t *&data, unsigned &size); This allows automatic deletion of the underlying data. Added vectorstream, which is obviously a vector<uint8_t> wrapper for a data stream. Plan is for all data accesses inside my emulation cores to take stream objects, especially MSU1. This lets you feed the core anything: memorystream, filestream, zipstream, gzipstream, httpstream, etc. There will still be exceptions for link and serial, those need actual library files on disk. But those aren't official hardware devices anyway. So to help with speed a bit, I'm rethinking the video rendering path. Previous system: - core outputs system-native samples (SNES = 19-bit LRGB, NES = 9-bit emphasis+palette, DMG = 2-bit grayscale, etc.) - interfaceSystem transforms samples to 30-bit via lookup table inside the emulation core - interfaceSystem masks off overscan areas, if enabled - interfaceUI runs filter to produce new target buffer, if enabled - interfaceUI transforms 30-bit video to native display depth (24-bit or 30-bit), and applies color-adjustments (gamma, etc) at the same time New system: - all cores now generate an internal palette, and call Interface::videoColor(uint32_t source, uint16_t red, uint16_t green, uint16_t blue) to get native display color post-adjusted (gamma, etc applied already.) - all cores output to uint32_t* buffer now (output video.palette[color] instead of just color) - interfaceUI runs filter to produce new target buffer, if enabled - interfaceUI memcpy()'s buffer to the video card videoColor() is pretty neat. source is the raw pixel (as per the old-format, 19-bit SNES, 9-bit NES, etc), and you can create a color from that if you really want to. Or return that value to get a buffer just like v088 and below. red, green, blue are 16-bits per channel, because why the hell not, right? Just lop off all the bits you don't want. If you have more bits on your display than that, fuck you :P The last step is extremely difficult to avoid. Video cards can and do have pitches that differ from the width of the texture. Trying to make the core account for this would be really awful. And even if we did that, the emulation routine would need to write directly to a video card RAM buffer. Some APIs require you to lock the video buffer while writing, so this would leave the video buffer locked for a long time. Probably not catastrophic, but still awful. And lastly, if the emulation core tried writing directly to the display texture, software filters would no longer be possible (unless you -really- jump through hooks and divert to a memory buffer when a filter is enabled, but ... fuck.) Anyway, the point of all that work was to eliminate an extra video copy, and the need for a really painful 30-bit to 24-bit conversion (three shifts, three masks, three array indexes.) So this basically reverts us, performance-wise, to where we were pre-30 bit support. [...] The downside to this is that we're going to need a filter for each output depth. Since the array type is uint32_t*, and I don't intend to support higher or lower depths, we really only need 24+30-bit versions of each filter. Kinda shitty, but oh well.
2012-04-27 12:12:53 +00:00
template<typename C> hook(R (C::*function)(P...), C *object) { callback = {function, object}; }
template<typename C> hook(R (C::*function)(P...) const, C *object) { callback = {function, object}; }
template<typename L> hook(const L& function) { callback = function; }
hook& operator=(const hook& hook) { callback = hook.callback; return *this; }
};
#if defined(DEBUGGER)
#define privileged public
#else
#define privileged private
#endif
Update to v087r30 release. byuu says: Changelog: - DMA channel masks added (some are 27-bit source/target and some are 14-bit length -- hooray, varuint_t class.) - No more state.pending flags. Instead, we set dma.pending flag when we want a transfer (fixes GBA Video - Pokemon audio) [Cydrak] - fixed OBJ Vmosaic [Cydrak, krom] - OBJ cannot read <=0x13fff in BG modes 3-5 (fixes the garbled tile at the top-left of some games) - DMA timing should be much closer to hardware now, but probably not perfect - PPU frame blending uses blargg's bit-perfect, rounded method (slower, but what can you do?) - GBA carts really unload now - added nall/gba/cartridge.hpp: used when there is no manifest. Scans ROMs for library tags, and selects the first valid one found - added EEPROM auto-detection when EEPROM size=0. Forces disk/save state size to 8192 (otherwise states could crash between pre and post detect.) - detects first read after a set read address command when the size is zero, and sets all subsequent bit-lengths to that value, prints detected size to terminal - added nall/nes/cartridge.hpp: moves iNES detection out of emulation core. Important to note: long-term goal is to remove all nall/(system)/cartridge.hpp detections from the core and replace with databases. All in good time. Anyway, the GBA workarounds should work for ~98.5% of the library, if my pre-scanning was correct (~40 games with odd tags. I reject ones without numeric versions now, too.) I think we're basically at a point where we can release a new version now. Compatibility should be relatively high (at least for a first release), and fixes are only going to affect one or two games at a time. I'd like to start doing some major cleaning house internally (rename NES->Famicom, SNES->SuperFamicom and such.) Would be much wiser to do that on a .01 WIP to minimize regressions. The main problems with a release now: - speed is pretty bad, haven't really optimized much yet (not sure how much we can improve it yet, this usually isn't easy) - sound isn't -great-, but the GBA audio sucks anyway :P - couple of known bugs (Sonic X video, etc.)
2012-04-22 10:49:19 +00:00
typedef int1_t int1;
typedef int2_t int2;
typedef int3_t int3;
typedef int4_t int4;
typedef int5_t int5;
typedef int6_t int6;
typedef int7_t int7;
typedef int8_t int8;
typedef int9_t int9;
Update to v085r08 release. byuu says: Changelog: - follow the Laevateinn topic to get most of it - also added NMI, IRQ step buttons to CPU debugger - also added trace masking + trace mask reset - also added memory export - cartridge loading is entirely folder-based now FitzRoy, I'll go ahead and make a second compromise with you for v086: I'll match the following: /path/to/SNES.sfc/*.sfc /path/to/NES.fc/*.prg, *.chr (split format) /path/to/NES.fc/*.fc (merged format) /path/to/GB.gb/*.gb /path/to/GBC.gbc/*.gbc Condition will be that there can only be one of each file. If there's more than one, it'll abort. That lets me name my ROMs as "Game.fc/Game.fc", and you can name yours as "Game.fc/cartridge.prg, cartridge.chr". Or whatever you want. We'll just go with that, see what fares out as the most popular, and then restrict it back to that method. The folder must have the .fc, etc extension though. That will be how we avoid false-positive folder matches. [Editor's note - the Laevateinn topic mentions these changes for v085r08: Added SMP/PPU breakpoints, SMP debugger, SMP stepping / tracing, memory editing on APU-bus / VRAM / OAM / CGRAM, save state menu, WRAM mirroring on breakpoints, protected MMIO memory regions (otherwise, viewing $002100 could crash your game.) Major missing components: - trace mask - trace mask clear / usage map clear - window geometry caching / sizing improvements - VRAM viewer - properties viewer - working memory export button The rest will most likely appear after v086 is released. ]
2012-02-12 05:35:40 +00:00
typedef int10_t int10;
typedef int11_t int11;
typedef int12_t int12;
typedef int13_t int13;
typedef int14_t int14;
typedef int15_t int15;
typedef int16_t int16;
typedef int17_t int17;
typedef int18_t int18;
typedef int19_t int19;
typedef int20_t int20;
typedef int21_t int21;
typedef int22_t int22;
typedef int23_t int23;
typedef int24_t int24;
typedef int25_t int25;
typedef int26_t int26;
typedef int27_t int27;
typedef int28_t int28;
typedef int29_t int29;
typedef int30_t int30;
typedef int31_t int31;
typedef int32_t int32;
typedef int64_t int64;
Update to v087r30 release. byuu says: Changelog: - DMA channel masks added (some are 27-bit source/target and some are 14-bit length -- hooray, varuint_t class.) - No more state.pending flags. Instead, we set dma.pending flag when we want a transfer (fixes GBA Video - Pokemon audio) [Cydrak] - fixed OBJ Vmosaic [Cydrak, krom] - OBJ cannot read <=0x13fff in BG modes 3-5 (fixes the garbled tile at the top-left of some games) - DMA timing should be much closer to hardware now, but probably not perfect - PPU frame blending uses blargg's bit-perfect, rounded method (slower, but what can you do?) - GBA carts really unload now - added nall/gba/cartridge.hpp: used when there is no manifest. Scans ROMs for library tags, and selects the first valid one found - added EEPROM auto-detection when EEPROM size=0. Forces disk/save state size to 8192 (otherwise states could crash between pre and post detect.) - detects first read after a set read address command when the size is zero, and sets all subsequent bit-lengths to that value, prints detected size to terminal - added nall/nes/cartridge.hpp: moves iNES detection out of emulation core. Important to note: long-term goal is to remove all nall/(system)/cartridge.hpp detections from the core and replace with databases. All in good time. Anyway, the GBA workarounds should work for ~98.5% of the library, if my pre-scanning was correct (~40 games with odd tags. I reject ones without numeric versions now, too.) I think we're basically at a point where we can release a new version now. Compatibility should be relatively high (at least for a first release), and fixes are only going to affect one or two games at a time. I'd like to start doing some major cleaning house internally (rename NES->Famicom, SNES->SuperFamicom and such.) Would be much wiser to do that on a .01 WIP to minimize regressions. The main problems with a release now: - speed is pretty bad, haven't really optimized much yet (not sure how much we can improve it yet, this usually isn't easy) - sound isn't -great-, but the GBA audio sucks anyway :P - couple of known bugs (Sonic X video, etc.)
2012-04-22 10:49:19 +00:00
typedef uint1_t uint1;
typedef uint2_t uint2;
typedef uint3_t uint3;
typedef uint4_t uint4;
typedef uint5_t uint5;
typedef uint6_t uint6;
typedef uint7_t uint7;
typedef uint8_t uint8;
typedef uint9_t uint9;
Update to v085r08 release. byuu says: Changelog: - follow the Laevateinn topic to get most of it - also added NMI, IRQ step buttons to CPU debugger - also added trace masking + trace mask reset - also added memory export - cartridge loading is entirely folder-based now FitzRoy, I'll go ahead and make a second compromise with you for v086: I'll match the following: /path/to/SNES.sfc/*.sfc /path/to/NES.fc/*.prg, *.chr (split format) /path/to/NES.fc/*.fc (merged format) /path/to/GB.gb/*.gb /path/to/GBC.gbc/*.gbc Condition will be that there can only be one of each file. If there's more than one, it'll abort. That lets me name my ROMs as "Game.fc/Game.fc", and you can name yours as "Game.fc/cartridge.prg, cartridge.chr". Or whatever you want. We'll just go with that, see what fares out as the most popular, and then restrict it back to that method. The folder must have the .fc, etc extension though. That will be how we avoid false-positive folder matches. [Editor's note - the Laevateinn topic mentions these changes for v085r08: Added SMP/PPU breakpoints, SMP debugger, SMP stepping / tracing, memory editing on APU-bus / VRAM / OAM / CGRAM, save state menu, WRAM mirroring on breakpoints, protected MMIO memory regions (otherwise, viewing $002100 could crash your game.) Major missing components: - trace mask - trace mask clear / usage map clear - window geometry caching / sizing improvements - VRAM viewer - properties viewer - working memory export button The rest will most likely appear after v086 is released. ]
2012-02-12 05:35:40 +00:00
typedef uint10_t uint10;
typedef uint11_t uint11;
typedef uint12_t uint12;
typedef uint13_t uint13;
typedef uint14_t uint14;
typedef uint15_t uint15;
typedef uint16_t uint16;
typedef uint17_t uint17;
typedef uint18_t uint18;
typedef uint19_t uint19;
typedef uint20_t uint20;
typedef uint21_t uint21;
typedef uint22_t uint22;
typedef uint23_t uint23;
typedef uint24_t uint24;
typedef uint25_t uint25;
typedef uint26_t uint26;
typedef uint27_t uint27;
typedef uint28_t uint28;
typedef uint29_t uint29;
typedef uint30_t uint30;
typedef uint31_t uint31;
typedef uint32_t uint32;
typedef uint_t<33> uint33;
Update to v085r08 release. byuu says: Changelog: - follow the Laevateinn topic to get most of it - also added NMI, IRQ step buttons to CPU debugger - also added trace masking + trace mask reset - also added memory export - cartridge loading is entirely folder-based now FitzRoy, I'll go ahead and make a second compromise with you for v086: I'll match the following: /path/to/SNES.sfc/*.sfc /path/to/NES.fc/*.prg, *.chr (split format) /path/to/NES.fc/*.fc (merged format) /path/to/GB.gb/*.gb /path/to/GBC.gbc/*.gbc Condition will be that there can only be one of each file. If there's more than one, it'll abort. That lets me name my ROMs as "Game.fc/Game.fc", and you can name yours as "Game.fc/cartridge.prg, cartridge.chr". Or whatever you want. We'll just go with that, see what fares out as the most popular, and then restrict it back to that method. The folder must have the .fc, etc extension though. That will be how we avoid false-positive folder matches. [Editor's note - the Laevateinn topic mentions these changes for v085r08: Added SMP/PPU breakpoints, SMP debugger, SMP stepping / tracing, memory editing on APU-bus / VRAM / OAM / CGRAM, save state menu, WRAM mirroring on breakpoints, protected MMIO memory regions (otherwise, viewing $002100 could crash your game.) Major missing components: - trace mask - trace mask clear / usage map clear - window geometry caching / sizing improvements - VRAM viewer - properties viewer - working memory export button The rest will most likely appear after v086 is released. ]
2012-02-12 05:35:40 +00:00
typedef uint64_t uint64;
Update to v087r30 release. byuu says: Changelog: - DMA channel masks added (some are 27-bit source/target and some are 14-bit length -- hooray, varuint_t class.) - No more state.pending flags. Instead, we set dma.pending flag when we want a transfer (fixes GBA Video - Pokemon audio) [Cydrak] - fixed OBJ Vmosaic [Cydrak, krom] - OBJ cannot read <=0x13fff in BG modes 3-5 (fixes the garbled tile at the top-left of some games) - DMA timing should be much closer to hardware now, but probably not perfect - PPU frame blending uses blargg's bit-perfect, rounded method (slower, but what can you do?) - GBA carts really unload now - added nall/gba/cartridge.hpp: used when there is no manifest. Scans ROMs for library tags, and selects the first valid one found - added EEPROM auto-detection when EEPROM size=0. Forces disk/save state size to 8192 (otherwise states could crash between pre and post detect.) - detects first read after a set read address command when the size is zero, and sets all subsequent bit-lengths to that value, prints detected size to terminal - added nall/nes/cartridge.hpp: moves iNES detection out of emulation core. Important to note: long-term goal is to remove all nall/(system)/cartridge.hpp detections from the core and replace with databases. All in good time. Anyway, the GBA workarounds should work for ~98.5% of the library, if my pre-scanning was correct (~40 games with odd tags. I reject ones without numeric versions now, too.) I think we're basically at a point where we can release a new version now. Compatibility should be relatively high (at least for a first release), and fixes are only going to affect one or two games at a time. I'd like to start doing some major cleaning house internally (rename NES->Famicom, SNES->SuperFamicom and such.) Would be much wiser to do that on a .01 WIP to minimize regressions. The main problems with a release now: - speed is pretty bad, haven't really optimized much yet (not sure how much we can improve it yet, this usually isn't easy) - sound isn't -great-, but the GBA audio sucks anyway :P - couple of known bugs (Sonic X video, etc.)
2012-04-22 10:49:19 +00:00
typedef varuint_t<unsigned> varuint;
#endif