2012-04-29 06:16:44 +00:00
|
|
|
#include <sfc/sfc.hpp>
|
2010-08-09 13:28:56 +00:00
|
|
|
|
2012-04-26 10:51:13 +00:00
|
|
|
namespace SuperFamicom {
|
2010-08-09 13:28:56 +00:00
|
|
|
|
|
|
|
System system;
|
|
|
|
|
Update to v098r04 release.
byuu says:
Changelog:
- SFC: fixed behavior of 21fx $21fe register when no device is connected
(must return zero)
- SFC: reduced 21fx buffer size to 1024 bytes in both directions to
mirror the FT232H we are using
- SFC: eliminated dsp/modulo-array.hpp [1]
- higan: implemented higan/video interface and migrated all cores to it
[2]
[1] the echo history buffer was 8-bytes, so there was no need for it at
all here. Not sure what I was thinking. The BRR buffer was 12-bytes, and
has very weird behavior ... but there's only a single location in the
code where it actually writes to this buffer. It's much easier to just
write to the buffer three times there instead of implementing an entire
class just to abstract away two lines of code. This change actually
boosted the speed from ~124.5fps to around ~127.5fps, but that's within
the margin of error for GCC. I doubt it's actually faster this way.
The DSP core could really use a ton of work. It comes from a port of
blargg's spc_dsp to my coding style, but he was extremely fond of using
32-bit signed integers everywhere. There's a lot of opportunity to
remove red tape masking by resizing the variables to their actual state
sizes.
I really need to find where I put spc_dsp6.sfc from blargg. It's a great
test to verify if I've made any mistakes in my implementation that would
cause regressions. Don't suppose anyone has it?
[2] so again, the idea is that higan/audio and higan/video are going to
sit between the emulation cores and the user interfaces. The hope is to
output raw encoding data from the emulation cores without having to
worry about the video display format (generally 24-bit RGB) of the host
display. And also to avoid having to repeat myself with eg three
separate implementations of interframe blending, and so on.
Furthermore, the idea is that the user interface can configure its side
of the settings, and the emulation cores can configure their sides.
Thus, neither has to worry about the other end. And now we can spin off
new user interfaces much easier without having to mess with all of these
things.
Right now, I've implemented color emulation, interframe blending and
SNES horizontal color bleed. I did not implement scanlines (and
interlace effects for them) yet, but I probably will at some point.
Further, for right now, the WonderSwan/Color screen rotation is busted
and will only show games in the horizontal orientation. Obviously this
must be fixed before the next official release, but I'll want to think
about how to implement it.
Also, the SNES light gun pointers are missing for now.
Things are a bit messy right now as I've gone through several revisions
of how to handle these things, so a good house cleaning is in order once
everything is feature-complete again. I need to sit down and think
through how and where I want to handle things like light gun cursors,
LCD icons, and maybe even rasterized text messages.
And obviously ... higan/audio is still just nall::DSP's headers. I need
to revamp that whole interface. I want to make it quite powerful with
a true audio mixer so I can handle things like
SNES+SGB+MSU1+Voicer-Kun+SNES-CD (five separate audio streams at once.)
The video system has the concept of "effects" for things like color
bleed and interframe blending. I want to extend on this with useful
other effects, such as NTSC simulation, maybe bringing back my mini-HQ2x
filter, etc. I'd also like to restore the saturation/gamma/luma
adjustment sliders ... I always liked allowing people to compensate for
their displays without having to change settings system-wide. Lastly,
I've always wanted to see some audio effects. Although I doubt we'll
ever get my dream of CoreAudio-style profiles, I'd like to get some
basic equalizer settings and echo/reverb effects in there.
2016-04-11 21:29:56 +00:00
|
|
|
#include "video.cpp"
|
Update to v098r03 release.
byuu says:
It took several hours, but I've rebuilt much of the SNES' bus memory
mapping architecture.
The new design unifies the cartridge string-based mapping
("00-3f,80-bf:8000-ffff") and internal bus.map calls. The map() function
now has an accompanying unmap() function, and instead of a fixed 256
callbacks, it'll scan to find the first available slot. unmap() will
free slots up when zero addresses reference a given slot.
The controllers and expansion port are now both entirely dynamic.
Instead of load/unload/power/reset, they only have the constructor
(power/reset/load) and destructor (unload). What this means is you can
now dynamically change even expansion port devices after the system is
loaded.
Note that this is incredibly dangerous and stupid, but ... oh well. The
whole point of this was for 21fx. There's no way to change the expansion
port device prior to loading a game, but if the 21fx isn't active, then
the reset vector hijack won't work. Now you can load a 21fx game, change
the expansion port device, and simply reset the system to active the
device.
The unification of design between controller port devices and expansion
port devices is nice, and overall this results in a reduction of code
(all of the Mapping stuff in Cartridge is gone, replaced with direct bus
mapping.) And there's always the potential to expand this system more in
the future now.
The big missing feature right now is the ability to push/pop mappings.
So if you look at how the 21fx does the reset vector, you might vomit
a little bit. But ... it works.
Also changed exit(0) to _exit(0) in the POSIX version of nall::execute.
[The _exit(0) thing is an attempt to make higan not crash when it tries
to launch icarus and it's not on $PATH. The theory is that higan forks,
then the child tries to exec icarus and fails, so it exits, all the
unique_ptrs clean up their resources and tell the X server to free
things the parent process is still using. Calling _exit() prevents
destructors from running, and seems to prevent the problem. -Ed.]
2016-04-09 10:21:18 +00:00
|
|
|
#include "peripherals.cpp"
|
2016-01-23 07:29:34 +00:00
|
|
|
#include "random.cpp"
|
2010-08-09 13:28:56 +00:00
|
|
|
#include "serialization.cpp"
|
|
|
|
|
Update to v097r12 release.
byuu says:
Nothing WS-related this time.
First, I fixed expansion port device mapping. On first load, it was
mapping the expansion port device too late, so it ended up not taking
effect. I had to spin out the logic for that into
Program::connectDevices(). This was proving to be quite annoying while
testing eBoot (SNES-Hook simulation.)
Second, I fixed the audio->set(Frequency, Latency) functions to take
(uint) parameters from the configuration file, so the weird behavior
around changing settings in the audio panel should hopefully be gone
now.
Third, I rewrote the interface->load,unload functions to call into the
(Emulator)::System::load,unload functions. And I have those call out to
Cartridge::load,unload. Before, this was inverted, and Cartridge::load()
was invoking System::load(), which I felt was kind of backward.
The Super Game Boy really didn't like this change, however. And it took
me a few hours to power through it. Before, I had the Game Boy core
dummying out all the interface->(load,save)Request calls, and having the
SNES core make them for it. This is because the folder paths and IDs
will be different between the two cores.
I've redesigned things so that ICD2's Emulator::Interface overloads
loadRequest and saveRequest, and translates the requests into new
requests for the SuperFamicom core. This allows the Game Boy code to do
its own loading for everything without a bunch of Super Game Boy special
casing, and without any awkwardness around powering on with no cartridge
inserted.
This also lets the SNES side of things simply call into higher-level
GameBoy::interface->load,save(id, stream) functions instead of stabbing
at the raw underlying state inside of various Game Boy core emulation
classes. So things are a lot better abstracted now.
2016-02-08 03:17:59 +00:00
|
|
|
auto System::loaded() const -> bool { return _loaded; }
|
2016-01-23 07:29:34 +00:00
|
|
|
auto System::region() const -> Region { return _region; }
|
|
|
|
auto System::cpuFrequency() const -> uint { return _cpuFrequency; }
|
|
|
|
auto System::apuFrequency() const -> uint { return _apuFrequency; }
|
2015-11-10 11:02:29 +00:00
|
|
|
|
|
|
|
auto System::run() -> void {
|
2010-08-09 13:28:56 +00:00
|
|
|
scheduler.enter();
|
|
|
|
}
|
|
|
|
|
2015-11-10 11:02:29 +00:00
|
|
|
auto System::runToSave() -> void {
|
Update to v098r01 release.
byuu says:
Changelog:
- SFC: balanced profile removed
- SFC: performance profile removed
- SFC: code for handling non-threaded CPU, SMP, DSP, PPU removed
- SFC: Coprocessor, Controller (and expansion port) shared Thread code
merged to SFC::Cothread
- Cothread here just means "Thread with CPU affinity" (couldn't think
of a better name, sorry)
- SFC: CPU now has vector<Thread*> coprocessors, peripherals;
- this is the beginning of work to allow expansion port devices to be
dynamically changed at run-time
- ruby: all audio drivers default to 48000hz instead of 22050hz now if
no frequency is assigned
- note: the WASAPI driver can default to whatever the native frequency
is; doesn't have to be 48000hz
- tomoko: removed the ability to change the frequency from the UI (but
it will display the frequency used)
- tomoko: removed the timing settings panel
- the goal is to work toward smooth video via adaptive sync
- the model is broken by not being in control of the audio frequency
anyway
- it's further broken by PAL running at 50hz and WSC running at 75hz
- it was always broken anyway by SNES interlace timing varying from
progressive timing
- higan: audio/ stub created (for now, it's just nall/dsp/ moved here
and included as a header)
- higan: video/ stub created
- higan/GNUmakefile: now includes build rules for essential components
(libco, emulator, audio, video)
The audio changes are in preparation to merge wareya's awesome WASAPI
work without the need for the nall/dsp resampler.
2016-04-09 03:40:12 +00:00
|
|
|
scheduler.synchronize(cpu.thread);
|
|
|
|
scheduler.synchronize(smp.thread);
|
|
|
|
scheduler.synchronize(ppu.thread);
|
|
|
|
scheduler.synchronize(dsp.thread);
|
|
|
|
for(auto coprocessor : cpu.coprocessors) {
|
|
|
|
scheduler.synchronize(coprocessor->thread);
|
|
|
|
}
|
|
|
|
for(auto peripheral : cpu.peripherals) {
|
|
|
|
scheduler.synchronize(peripheral->thread);
|
2010-08-09 13:28:56 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2015-11-10 11:02:29 +00:00
|
|
|
auto System::init() -> void {
|
2012-05-26 08:18:42 +00:00
|
|
|
assert(interface != nullptr);
|
2010-08-09 13:28:56 +00:00
|
|
|
|
2011-01-08 09:58:41 +00:00
|
|
|
icd2.init();
|
2015-08-02 06:23:13 +00:00
|
|
|
mcc.init();
|
2011-05-06 14:16:46 +00:00
|
|
|
nss.init();
|
Update to v091r05 release.
[No prior releases were posted to the WIP thread. -Ed.]
byuu says:
Super Famicom mapping system has been reworked as discussed with the
mask= changes. offset becomes base, mode is gone. Also added support for
comma-separated fields in the address fields, to reduce the number of
map lines needed.
<?xml version="1.0" encoding="UTF-8"?>
<cartridge region="NTSC">
<superfx revision="2">
<rom name="program.rom" size="0x200000"/>
<ram name="save.rwm" size="0x8000"/>
<map id="io" address="00-3f,80-bf:3000-32ff"/>
<map id="rom" address="00-3f:8000-ffff" mask="0x8000"/>
<map id="rom" address="40-5f:0000-ffff"/>
<map id="ram" address="00-3f,80-bf:6000-7fff" size="0x2000"/>
<map id="ram" address="70-71:0000-ffff"/>
</superfx>
</cartridge>
Or in BML:
cartridge region=NTSC
superfx revision=2
rom name=program.rom size=0x200000
ram name=save.rwm size=0x8000
map id=io address=00-3f,80-bf:3000-32ff
map id=rom address=00-3f:8000-ffff mask=0x8000
map id=rom address=40-5f:0000-ffff
map id=ram address=00-3f,80-bf:6000-7fff size=0x2000
map id=ram address=70-71:0000-ffff
As a result of the changes, old mappings will no longer work. The above
XML example will run Super Mario World 2: Yoshi's Island. Otherwise,
you'll have to write your own.
All that's left now is to work some sort of database mapping system in,
so I can start dumping carts en masse.
The NES changes that FitzRoy asked for are mostly in as well.
Also, part of the reason I haven't released a WIP ... but fuck it, I'm
not going to wait forever to post a new WIP.
I've added a skeleton driver to emulate Campus Challenge '92 and
Powerfest '94. There's no actual emulation, except for the stuff I can
glean from looking at the pictures of the board. It has a DSP-1 (so
SR/DR registers), four ROMs that map in and out, RAM, etc.
I've also added preliminary mapping to upload high scores to a website,
but obviously I need the ROMs first.
2012-10-09 08:25:32 +00:00
|
|
|
event.init();
|
2010-08-09 13:28:56 +00:00
|
|
|
sa1.init();
|
2012-05-22 12:10:00 +00:00
|
|
|
superfx.init();
|
2012-02-26 07:59:44 +00:00
|
|
|
armdsp.init();
|
2012-05-22 12:10:00 +00:00
|
|
|
hitachidsp.init();
|
|
|
|
necdsp.init();
|
|
|
|
epsonrtc.init();
|
|
|
|
sharprtc.init();
|
2010-08-09 13:28:56 +00:00
|
|
|
spc7110.init();
|
2012-05-22 12:10:00 +00:00
|
|
|
sdd1.init();
|
2010-08-09 13:28:56 +00:00
|
|
|
obc1.init();
|
|
|
|
msu1.init();
|
2015-11-10 11:02:29 +00:00
|
|
|
|
2015-12-19 09:00:27 +00:00
|
|
|
bsmemory.init();
|
2010-08-09 13:28:56 +00:00
|
|
|
}
|
|
|
|
|
2015-11-10 11:02:29 +00:00
|
|
|
auto System::term() -> void {
|
2010-08-09 13:28:56 +00:00
|
|
|
}
|
|
|
|
|
2015-11-10 11:02:29 +00:00
|
|
|
auto System::load() -> void {
|
Update to v098r03 release.
byuu says:
It took several hours, but I've rebuilt much of the SNES' bus memory
mapping architecture.
The new design unifies the cartridge string-based mapping
("00-3f,80-bf:8000-ffff") and internal bus.map calls. The map() function
now has an accompanying unmap() function, and instead of a fixed 256
callbacks, it'll scan to find the first available slot. unmap() will
free slots up when zero addresses reference a given slot.
The controllers and expansion port are now both entirely dynamic.
Instead of load/unload/power/reset, they only have the constructor
(power/reset/load) and destructor (unload). What this means is you can
now dynamically change even expansion port devices after the system is
loaded.
Note that this is incredibly dangerous and stupid, but ... oh well. The
whole point of this was for 21fx. There's no way to change the expansion
port device prior to loading a game, but if the 21fx isn't active, then
the reset vector hijack won't work. Now you can load a 21fx game, change
the expansion port device, and simply reset the system to active the
device.
The unification of design between controller port devices and expansion
port devices is nice, and overall this results in a reduction of code
(all of the Mapping stuff in Cartridge is gone, replaced with direct bus
mapping.) And there's always the potential to expand this system more in
the future now.
The big missing feature right now is the ability to push/pop mappings.
So if you look at how the 21fx does the reset vector, you might vomit
a little bit. But ... it works.
Also changed exit(0) to _exit(0) in the POSIX version of nall::execute.
[The _exit(0) thing is an attempt to make higan not crash when it tries
to launch icarus and it's not on $PATH. The theory is that higan forks,
then the child tries to exec icarus and fails, so it exits, all the
unique_ptrs clean up their resources and tell the X server to free
things the parent process is still using. Calling _exit() prevents
destructors from running, and seems to prevent the problem. -Ed.]
2016-04-09 10:21:18 +00:00
|
|
|
bus.reset();
|
|
|
|
|
Update to v094r39 release.
byuu says:
Changelog:
- SNES mid-scanline BGMODE fixes finally merged (can run
atx2.zip{mode7.smc}+mtest(2).sfc properly now)
- Makefile now discards all built-in rules and variables
- switch on bool warning disabled for GCC now as well (was already
disabled for Clang)
- when loading a game, if any required files are missing, display
a warning message box (manifest.bml, program.rom, bios.rom, etc)
- when loading a game (or a game slot), if manifest.bml is missing, it
will invoke icarus to try and generate it
- if that fails (icarus is missing or the folder is bad), you will get
a warning telling you that the manifest can't be loaded
The warning prompt on missing files work for both games and the .sys
folders and their files. For some reason, failing to load the DMG/CGB
BIOS is causing a crash before I can display the modal dialog. I have no
idea why, and the stack frame backtrace is junk.
I also can't seem to abort the failed loading process. If I call
Program::unloadMedia(), I get a nasty segfault. Again with a really
nasty stack trace. So for now, it'll just end up sitting there emulating
an empty ROM (solid black screen.) In time, I'd like to fix that too.
Lastly, I need a better method than popen for Windows. popen is kind of
ugly and flashes a console window for a brief second even if the
application launched is linked with -mwindows. Not sure if there even is
one (I need to read the stdout result, so CreateProcess may not work
unless I do something nasty like "> %tmp%/temp") I'm also using the
regular popen instead of _wpopen, so for this WIP, it won't work if your
game folder has non-English letters in the path.
2015-08-04 09:00:55 +00:00
|
|
|
interface->loadRequest(ID::SystemManifest, "manifest.bml", true);
|
|
|
|
auto document = BML::unserialize(information.manifest);
|
Update to v092 release.
In the release thread, byuu says:
The first official release of higan has been posted. higan is the
new name for bsnes, and it continues with the latter's version
numbering.
Note that as of now, bsnes still exists. It's a module distributed
inside of higan. bsnes is now specific to my SNES emulator.
Due to last minute changes to the emulator interface, and missing
support in ananke, I wasn't able to include Cydrak's Nintendo DS
emulator dasShiny in this build, but I hope to do so in the next
release.
http://code.google.com/p/higan/downloads/list
For both new and experienced users, please read the higan user guide
first:
http://byuu.org/higan/user-guide
In the v091 WIP thread, byuu says:
r15->r16:
- BS-X MaskROM handling (partial ... need to split bsx/flash away
from sfc/chip, restructure code - it requires tagging the base
cart markup for now, but it needs to parse the slotted cart
markup)
- phoenixflags / phoenixlink += -m32
- nall/sort stability
- if(input.poll(scancode[activeScancode]) == false) return;
- MSU1 / USART need to use interface->path(1)
- MSU1 needs to use Markup::Document, not XML::Document
- case-insensitive folder listings
- remove nall/emulation/system.hpp files (move to ananke)
- remove rom/ram id= checks with indexing
X have cores ask for manifest.bml (skipped for v092's release, too
big a change)
- rename compatibility profile to balanced (so people don't assume
it has better compatibility than accuracy)
2013-01-14 12:10:20 +00:00
|
|
|
|
Update to v094r39 release.
byuu says:
Changelog:
- SNES mid-scanline BGMODE fixes finally merged (can run
atx2.zip{mode7.smc}+mtest(2).sfc properly now)
- Makefile now discards all built-in rules and variables
- switch on bool warning disabled for GCC now as well (was already
disabled for Clang)
- when loading a game, if any required files are missing, display
a warning message box (manifest.bml, program.rom, bios.rom, etc)
- when loading a game (or a game slot), if manifest.bml is missing, it
will invoke icarus to try and generate it
- if that fails (icarus is missing or the folder is bad), you will get
a warning telling you that the manifest can't be loaded
The warning prompt on missing files work for both games and the .sys
folders and their files. For some reason, failing to load the DMG/CGB
BIOS is causing a crash before I can display the modal dialog. I have no
idea why, and the stack frame backtrace is junk.
I also can't seem to abort the failed loading process. If I call
Program::unloadMedia(), I get a nasty segfault. Again with a really
nasty stack trace. So for now, it'll just end up sitting there emulating
an empty ROM (solid black screen.) In time, I'd like to fix that too.
Lastly, I need a better method than popen for Windows. popen is kind of
ugly and flashes a console window for a brief second even if the
application launched is linked with -mwindows. Not sure if there even is
one (I need to read the stdout result, so CreateProcess may not work
unless I do something nasty like "> %tmp%/temp") I'm also using the
regular popen instead of _wpopen, so for this WIP, it won't work if your
game folder has non-English letters in the path.
2015-08-04 09:00:55 +00:00
|
|
|
if(auto iplrom = document["system/smp/rom/name"].text()) {
|
|
|
|
interface->loadRequest(ID::IPLROM, iplrom, true);
|
2012-07-15 09:47:35 +00:00
|
|
|
}
|
|
|
|
|
Update to v097r12 release.
byuu says:
Nothing WS-related this time.
First, I fixed expansion port device mapping. On first load, it was
mapping the expansion port device too late, so it ended up not taking
effect. I had to spin out the logic for that into
Program::connectDevices(). This was proving to be quite annoying while
testing eBoot (SNES-Hook simulation.)
Second, I fixed the audio->set(Frequency, Latency) functions to take
(uint) parameters from the configuration file, so the weird behavior
around changing settings in the audio panel should hopefully be gone
now.
Third, I rewrote the interface->load,unload functions to call into the
(Emulator)::System::load,unload functions. And I have those call out to
Cartridge::load,unload. Before, this was inverted, and Cartridge::load()
was invoking System::load(), which I felt was kind of backward.
The Super Game Boy really didn't like this change, however. And it took
me a few hours to power through it. Before, I had the Game Boy core
dummying out all the interface->(load,save)Request calls, and having the
SNES core make them for it. This is because the folder paths and IDs
will be different between the two cores.
I've redesigned things so that ICD2's Emulator::Interface overloads
loadRequest and saveRequest, and translates the requests into new
requests for the SuperFamicom core. This allows the Game Boy code to do
its own loading for everything without a bunch of Super Game Boy special
casing, and without any awkwardness around powering on with no cartridge
inserted.
This also lets the SNES side of things simply call into higher-level
GameBoy::interface->load,save(id, stream) functions instead of stabbing
at the raw underlying state inside of various Game Boy core emulation
classes. So things are a lot better abstracted now.
2016-02-08 03:17:59 +00:00
|
|
|
cartridge.load();
|
2016-01-23 07:29:34 +00:00
|
|
|
_region = cartridge.region() == Cartridge::Region::NTSC ? Region::NTSC : Region::PAL;
|
2016-02-09 11:51:12 +00:00
|
|
|
_cpuFrequency = region() == Region::NTSC ? 21'477'272 : 21'281'370;
|
|
|
|
_apuFrequency = 24'606'720;
|
2010-08-09 13:28:56 +00:00
|
|
|
|
2015-08-02 06:23:13 +00:00
|
|
|
if(cartridge.hasICD2()) icd2.load();
|
|
|
|
if(cartridge.hasMCC()) mcc.load();
|
|
|
|
if(cartridge.hasNSSDIP()) nss.load();
|
|
|
|
if(cartridge.hasEvent()) event.load();
|
|
|
|
if(cartridge.hasSA1()) sa1.load();
|
|
|
|
if(cartridge.hasSuperFX()) superfx.load();
|
|
|
|
if(cartridge.hasARMDSP()) armdsp.load();
|
|
|
|
if(cartridge.hasHitachiDSP()) hitachidsp.load();
|
|
|
|
if(cartridge.hasNECDSP()) necdsp.load();
|
|
|
|
if(cartridge.hasEpsonRTC()) epsonrtc.load();
|
|
|
|
if(cartridge.hasSharpRTC()) sharprtc.load();
|
|
|
|
if(cartridge.hasSPC7110()) spc7110.load();
|
|
|
|
if(cartridge.hasSDD1()) sdd1.load();
|
|
|
|
if(cartridge.hasOBC1()) obc1.load();
|
|
|
|
if(cartridge.hasMSU1()) msu1.load();
|
|
|
|
|
2015-12-19 09:00:27 +00:00
|
|
|
if(cartridge.hasBSMemorySlot()) bsmemory.load();
|
2015-08-02 06:23:13 +00:00
|
|
|
if(cartridge.hasSufamiTurboSlots()) sufamiturboA.load(), sufamiturboB.load();
|
2011-01-29 09:48:44 +00:00
|
|
|
|
2015-11-10 11:02:29 +00:00
|
|
|
serializeInit();
|
Update to v098r04 release.
byuu says:
Changelog:
- SFC: fixed behavior of 21fx $21fe register when no device is connected
(must return zero)
- SFC: reduced 21fx buffer size to 1024 bytes in both directions to
mirror the FT232H we are using
- SFC: eliminated dsp/modulo-array.hpp [1]
- higan: implemented higan/video interface and migrated all cores to it
[2]
[1] the echo history buffer was 8-bytes, so there was no need for it at
all here. Not sure what I was thinking. The BRR buffer was 12-bytes, and
has very weird behavior ... but there's only a single location in the
code where it actually writes to this buffer. It's much easier to just
write to the buffer three times there instead of implementing an entire
class just to abstract away two lines of code. This change actually
boosted the speed from ~124.5fps to around ~127.5fps, but that's within
the margin of error for GCC. I doubt it's actually faster this way.
The DSP core could really use a ton of work. It comes from a port of
blargg's spc_dsp to my coding style, but he was extremely fond of using
32-bit signed integers everywhere. There's a lot of opportunity to
remove red tape masking by resizing the variables to their actual state
sizes.
I really need to find where I put spc_dsp6.sfc from blargg. It's a great
test to verify if I've made any mistakes in my implementation that would
cause regressions. Don't suppose anyone has it?
[2] so again, the idea is that higan/audio and higan/video are going to
sit between the emulation cores and the user interfaces. The hope is to
output raw encoding data from the emulation cores without having to
worry about the video display format (generally 24-bit RGB) of the host
display. And also to avoid having to repeat myself with eg three
separate implementations of interframe blending, and so on.
Furthermore, the idea is that the user interface can configure its side
of the settings, and the emulation cores can configure their sides.
Thus, neither has to worry about the other end. And now we can spin off
new user interfaces much easier without having to mess with all of these
things.
Right now, I've implemented color emulation, interframe blending and
SNES horizontal color bleed. I did not implement scanlines (and
interlace effects for them) yet, but I probably will at some point.
Further, for right now, the WonderSwan/Color screen rotation is busted
and will only show games in the horizontal orientation. Obviously this
must be fixed before the next official release, but I'll want to think
about how to implement it.
Also, the SNES light gun pointers are missing for now.
Things are a bit messy right now as I've gone through several revisions
of how to handle these things, so a good house cleaning is in order once
everything is feature-complete again. I need to sit down and think
through how and where I want to handle things like light gun cursors,
LCD icons, and maybe even rasterized text messages.
And obviously ... higan/audio is still just nall::DSP's headers. I need
to revamp that whole interface. I want to make it quite powerful with
a true audio mixer so I can handle things like
SNES+SGB+MSU1+Voicer-Kun+SNES-CD (five separate audio streams at once.)
The video system has the concept of "effects" for things like color
bleed and interframe blending. I want to extend on this with useful
other effects, such as NTSC simulation, maybe bringing back my mini-HQ2x
filter, etc. I'd also like to restore the saturation/gamma/luma
adjustment sliders ... I always liked allowing people to compensate for
their displays without having to change settings system-wide. Lastly,
I've always wanted to see some audio effects. Although I doubt we'll
ever get my dream of CoreAudio-style profiles, I'd like to get some
basic equalizer settings and echo/reverb effects in there.
2016-04-11 21:29:56 +00:00
|
|
|
configureVideo();
|
Update to v097r12 release.
byuu says:
Nothing WS-related this time.
First, I fixed expansion port device mapping. On first load, it was
mapping the expansion port device too late, so it ended up not taking
effect. I had to spin out the logic for that into
Program::connectDevices(). This was proving to be quite annoying while
testing eBoot (SNES-Hook simulation.)
Second, I fixed the audio->set(Frequency, Latency) functions to take
(uint) parameters from the configuration file, so the weird behavior
around changing settings in the audio panel should hopefully be gone
now.
Third, I rewrote the interface->load,unload functions to call into the
(Emulator)::System::load,unload functions. And I have those call out to
Cartridge::load,unload. Before, this was inverted, and Cartridge::load()
was invoking System::load(), which I felt was kind of backward.
The Super Game Boy really didn't like this change, however. And it took
me a few hours to power through it. Before, I had the Game Boy core
dummying out all the interface->(load,save)Request calls, and having the
SNES core make them for it. This is because the folder paths and IDs
will be different between the two cores.
I've redesigned things so that ICD2's Emulator::Interface overloads
loadRequest and saveRequest, and translates the requests into new
requests for the SuperFamicom core. This allows the Game Boy code to do
its own loading for everything without a bunch of Super Game Boy special
casing, and without any awkwardness around powering on with no cartridge
inserted.
This also lets the SNES side of things simply call into higher-level
GameBoy::interface->load,save(id, stream) functions instead of stabbing
at the raw underlying state inside of various Game Boy core emulation
classes. So things are a lot better abstracted now.
2016-02-08 03:17:59 +00:00
|
|
|
_loaded = true;
|
Update to v075 release.
byuu says:
This release brings improved Super Game Boy emulation, the final SHA256
hashes for the DSP-(1,1B,2,3,4) and ST-(0010,0011) coprocessors, user
interface improvements, and major internal code restructuring.
Changelog (since v074):
- completely rewrote memory sub-system to support 1-byte granularity in
XML mapping
- removed Memory inheritance and MMIO class completely, any address can
be mapped to any function now
- SuperFX: removed SuperFXBus : Bus, now implemented manually
- SA-1: removed SA1Bus : Bus, now implemented manually
- entire bus mapping is now static, happens once on cartridge load
- as a result, read/write handlers now handle MMC mapping; slower
average case, far faster worst case
- namespace memory is no more, RAM arrays are stored inside the chips
they are owned by now
- GameBoy: improved CPU HALT emulation, fixes Zelda: Link's Awakening
scrolling
- GameBoy: added serial emulation (cannot connect to another GB yet),
fixes Shin Megami Tensei - Devichil
- GameBoy: improved LCD STAT emulation, fixes Sagaia
- ui: added fullscreen support (F11 key), video settings allows for
three scale settings
- ui: fixed brightness, contrast, gamma, audio volume, input frequency
values on program startup
- ui: since Qt is dead, config file becomes bsnes.cfg once again
- Super Game Boy: you can now load the BIOS without a game inserted to
see a pretty white box
- ui-gameboy: can be built without SNES components now
- libsnes: now a UI target, compile with 'make ui=ui-libsnes'
- libsnes: added WRAM, APURAM, VRAM, OAM, CGRAM access (cheat search,
etc)
- source: removed launcher/, as the Qt port is now gone
- source: Makefile restructuring to better support new ui targets
- source: lots of other internal code cleanup work
2011-01-27 08:52:34 +00:00
|
|
|
}
|
|
|
|
|
2015-11-10 11:02:29 +00:00
|
|
|
auto System::unload() -> void {
|
Update to v097r12 release.
byuu says:
Nothing WS-related this time.
First, I fixed expansion port device mapping. On first load, it was
mapping the expansion port device too late, so it ended up not taking
effect. I had to spin out the logic for that into
Program::connectDevices(). This was proving to be quite annoying while
testing eBoot (SNES-Hook simulation.)
Second, I fixed the audio->set(Frequency, Latency) functions to take
(uint) parameters from the configuration file, so the weird behavior
around changing settings in the audio panel should hopefully be gone
now.
Third, I rewrote the interface->load,unload functions to call into the
(Emulator)::System::load,unload functions. And I have those call out to
Cartridge::load,unload. Before, this was inverted, and Cartridge::load()
was invoking System::load(), which I felt was kind of backward.
The Super Game Boy really didn't like this change, however. And it took
me a few hours to power through it. Before, I had the Game Boy core
dummying out all the interface->(load,save)Request calls, and having the
SNES core make them for it. This is because the folder paths and IDs
will be different between the two cores.
I've redesigned things so that ICD2's Emulator::Interface overloads
loadRequest and saveRequest, and translates the requests into new
requests for the SuperFamicom core. This allows the Game Boy code to do
its own loading for everything without a bunch of Super Game Boy special
casing, and without any awkwardness around powering on with no cartridge
inserted.
This also lets the SNES side of things simply call into higher-level
GameBoy::interface->load,save(id, stream) functions instead of stabbing
at the raw underlying state inside of various Game Boy core emulation
classes. So things are a lot better abstracted now.
2016-02-08 03:17:59 +00:00
|
|
|
if(!loaded()) return;
|
Update to v098r03 release.
byuu says:
It took several hours, but I've rebuilt much of the SNES' bus memory
mapping architecture.
The new design unifies the cartridge string-based mapping
("00-3f,80-bf:8000-ffff") and internal bus.map calls. The map() function
now has an accompanying unmap() function, and instead of a fixed 256
callbacks, it'll scan to find the first available slot. unmap() will
free slots up when zero addresses reference a given slot.
The controllers and expansion port are now both entirely dynamic.
Instead of load/unload/power/reset, they only have the constructor
(power/reset/load) and destructor (unload). What this means is you can
now dynamically change even expansion port devices after the system is
loaded.
Note that this is incredibly dangerous and stupid, but ... oh well. The
whole point of this was for 21fx. There's no way to change the expansion
port device prior to loading a game, but if the 21fx isn't active, then
the reset vector hijack won't work. Now you can load a 21fx game, change
the expansion port device, and simply reset the system to active the
device.
The unification of design between controller port devices and expansion
port devices is nice, and overall this results in a reduction of code
(all of the Mapping stuff in Cartridge is gone, replaced with direct bus
mapping.) And there's always the potential to expand this system more in
the future now.
The big missing feature right now is the ability to push/pop mappings.
So if you look at how the 21fx does the reset vector, you might vomit
a little bit. But ... it works.
Also changed exit(0) to _exit(0) in the POSIX version of nall::execute.
[The _exit(0) thing is an attempt to make higan not crash when it tries
to launch icarus and it's not on $PATH. The theory is that higan forks,
then the child tries to exec icarus and fails, so it exits, all the
unique_ptrs clean up their resources and tell the X server to free
things the parent process is still using. Calling _exit() prevents
destructors from running, and seems to prevent the problem. -Ed.]
2016-04-09 10:21:18 +00:00
|
|
|
peripherals.unload();
|
2015-11-10 11:02:29 +00:00
|
|
|
|
2015-08-02 06:23:13 +00:00
|
|
|
if(cartridge.hasICD2()) icd2.unload();
|
|
|
|
if(cartridge.hasMCC()) mcc.unload();
|
|
|
|
if(cartridge.hasNSSDIP()) nss.unload();
|
|
|
|
if(cartridge.hasEvent()) event.unload();
|
|
|
|
if(cartridge.hasSA1()) sa1.unload();
|
|
|
|
if(cartridge.hasSuperFX()) superfx.unload();
|
|
|
|
if(cartridge.hasARMDSP()) armdsp.unload();
|
|
|
|
if(cartridge.hasHitachiDSP()) hitachidsp.unload();
|
|
|
|
if(cartridge.hasNECDSP()) necdsp.unload();
|
|
|
|
if(cartridge.hasEpsonRTC()) epsonrtc.unload();
|
|
|
|
if(cartridge.hasSharpRTC()) sharprtc.unload();
|
|
|
|
if(cartridge.hasSPC7110()) spc7110.unload();
|
|
|
|
if(cartridge.hasSDD1()) sdd1.unload();
|
|
|
|
if(cartridge.hasOBC1()) obc1.unload();
|
|
|
|
if(cartridge.hasMSU1()) msu1.unload();
|
|
|
|
|
2015-12-19 09:00:27 +00:00
|
|
|
if(cartridge.hasBSMemorySlot()) bsmemory.unload();
|
2015-08-02 06:23:13 +00:00
|
|
|
if(cartridge.hasSufamiTurboSlots()) sufamiturboA.unload(), sufamiturboB.unload();
|
Update to v097r12 release.
byuu says:
Nothing WS-related this time.
First, I fixed expansion port device mapping. On first load, it was
mapping the expansion port device too late, so it ended up not taking
effect. I had to spin out the logic for that into
Program::connectDevices(). This was proving to be quite annoying while
testing eBoot (SNES-Hook simulation.)
Second, I fixed the audio->set(Frequency, Latency) functions to take
(uint) parameters from the configuration file, so the weird behavior
around changing settings in the audio panel should hopefully be gone
now.
Third, I rewrote the interface->load,unload functions to call into the
(Emulator)::System::load,unload functions. And I have those call out to
Cartridge::load,unload. Before, this was inverted, and Cartridge::load()
was invoking System::load(), which I felt was kind of backward.
The Super Game Boy really didn't like this change, however. And it took
me a few hours to power through it. Before, I had the Game Boy core
dummying out all the interface->(load,save)Request calls, and having the
SNES core make them for it. This is because the folder paths and IDs
will be different between the two cores.
I've redesigned things so that ICD2's Emulator::Interface overloads
loadRequest and saveRequest, and translates the requests into new
requests for the SuperFamicom core. This allows the Game Boy code to do
its own loading for everything without a bunch of Super Game Boy special
casing, and without any awkwardness around powering on with no cartridge
inserted.
This also lets the SNES side of things simply call into higher-level
GameBoy::interface->load,save(id, stream) functions instead of stabbing
at the raw underlying state inside of various Game Boy core emulation
classes. So things are a lot better abstracted now.
2016-02-08 03:17:59 +00:00
|
|
|
|
|
|
|
cartridge.unload();
|
|
|
|
_loaded = false;
|
Update to v074r10 release.
byuu says:
Major WIP, countless changes. I really went to town on cleaning up the
source today with all kinds of new ideas. I'll post the ones I remember,
use diff -ru to get the rest.
What I like the most is my new within template:
template<unsigned lo, unsigned hi>
alwaysinline bool within(unsigned addr) {
static const unsigned mask = ~(hi ^ lo);
return (addr & mask) == lo;
}
Before, you would see code like this:
if((addr & 0xe0e000) == 0x206000) { //$20-3f:6000-7fff
The comment is basically necessary, and you have to trust that the mask
is right, or do the math yourself.
Now, it looks like this:
if(within<0x20, 0x3f, 0x6000, 0x7fff>(addr)) {
That's the same as within<0x206000, 0x3f7fff>, I just made an
SNES-variant to more closely simulate my XML mapping style:
20-3f:6000-7fff.
Now obviously this has limitations, it only works in base-2 and it can't
manage some tricky edge cases like (addr & 0x408000) == 0x008000 for
00-3f|80-bf:8000-ffff. But for the most part, I'll be using this where
I can. The Game Boy is fully ported over to it (via the MBCs), but the
SNES only has the BS-X town cartridge moved over so far. SuperFX and
SA-1 at the very least could benefit.
Next up, since the memory map is now static, there's really no reason to
remap the entire thing at power-on and reset. So it is now set up at
cartridge load and that's it. I moved the CPU/PPU/WRAM mapping out of
memory.cpp and into their respective processors. A bit of duplication
only because there are multiple processor cores for the different
profiles, but I'm not worried about that. This is also going to be
necessary to fix the debugger.
Next, Coprocessor::enable() actually does what I initially intended it
to now: it is called once to turn a chip on after cartridge load. It's
not called on power cycle anymore. This should help fix power-cycle on
my serial simulation code, and was needed to map the bus exactly one
time. Although most stuff is mapped through XML, some chips still need
some manual hooks for monitoring and such (eg S-DD1.)
Next, I've started killing off memory::, it was initially an
over-reaction to the question of where to put APURAM (in the SMP or
DSP?). The idea was to have this namespace that contained all memory for
everything. But it was very annoying and tedious, and various chips
ignored the convention anyway like ST-0011 RAM, which couldn't work
anyway since it is natively uint16 and not uint8. Cx4 will need 24-bit
RAM eventually, too. There's 8->24-bit functions in there now, because
the HLE code is hideous.
So far, all the cartridge.cpp memory:: types have been destroyed.
memory::cartrom, memory::cartram become cartridge.rom and cartridge.ram.
memory::cartrtc was moved into the SRTC and SPC7110 classes directly.
memory::bsxflash was moved into BSXFlash. memory::bsxram and
memory::bsxpram were moved into BSXCartridge (the town cartridge).
memory::st[AB](rom|ram) were moved into a new area,
snes/chip/sufamiturbo. The snes/chip moniker really doesn't work so
well, since it also has base units, and the serial communications stuff
which is through the controller port, but oh well, now it also has the
base structure for the Sufami Turbo cartridge too. So now we have
sufamiturbo.slotA.rom, sufamiturbo.slotB.ram, etc.
Next, the ST-0010/ST-0011 actually save the data RAM to disk. This
wasn't at all compatible with my old system, and I didn't want to keep
adding memory types to check inside the main UI cartridge RAM loading
and saving routines.
So I built a NonVolatileRAM vector inside SNES::Cartridge, and any chip
that has memory it wants to save and load from disk can append onto it
: data, size, id ("srm", "rtc", "nec", etc) and slot (0 = cartridge,
1 = slot A, 2 = slot B)
To load and save memory, we just do a simple: foreach(memory,
SNES::cartridge.nvram) load/saveMemory(memory).
As a result, you can now keep your save games in F1 Race of Champions II
and Hayazashi Nidan Morita Shougi. Technically I think Metal Combat
should work this way as well, having the RAM being part of the chip
itself, but for now that chip just writes directly into cartridge.ram,
so it also technically saves to disk for now.
To avoid a potential conflict with a manipulated memory map, BS-X SRAM
and PSRAM are now .bss and .bsp, and not .srm and .psr. Honestly I don't
like .srm as an extension either, but it doesn't bother me enough to
break save RAM compatibility with other emulators, so don't worry about
that changing.
I finally killed off MappedRAM initializing size to ~0 (-1U). A size of
zero means there is no memory there just the same. This was an old
holdover for handling MMIO mapping, if I recall correctly. Something
about a size of zero on MMIO-Memory objects causing it to wrap the
address, so ~0 would let it map direct addresses ... or something.
Whatever, that's not needed at all anymore.
BSXBase becomes BSXSatellaview, and I've defaulted the device to being
attached since it won't affect non-BSX games anyway. Eventually the GUI
needs to make that an option. BSXCart becomes BSXCartridge. BSXFlash
remains unchanged.
I probably need to make Coprocessor::disable() functions now to free up
memory on unload, but it shouldn't hurt anything the way it is.
libsnes is most definitely broken to all hell and back now, and the
debugger is still shot. I suppose we'll need some tricky code to work
with the old ID system, and we'll need to add some more IDs for the new
memory types.
2011-01-24 08:59:45 +00:00
|
|
|
}
|
|
|
|
|
2015-11-10 11:02:29 +00:00
|
|
|
auto System::power() -> void {
|
|
|
|
random.seed((uint)time(0));
|
2011-03-20 13:57:55 +00:00
|
|
|
|
2010-08-09 13:28:56 +00:00
|
|
|
cpu.power();
|
|
|
|
smp.power();
|
|
|
|
dsp.power();
|
|
|
|
ppu.power();
|
|
|
|
|
2015-08-02 06:23:13 +00:00
|
|
|
if(cartridge.hasICD2()) icd2.power();
|
|
|
|
if(cartridge.hasMCC()) mcc.power();
|
|
|
|
if(cartridge.hasNSSDIP()) nss.power();
|
|
|
|
if(cartridge.hasEvent()) event.power();
|
|
|
|
if(cartridge.hasSA1()) sa1.power();
|
|
|
|
if(cartridge.hasSuperFX()) superfx.power();
|
|
|
|
if(cartridge.hasARMDSP()) armdsp.power();
|
|
|
|
if(cartridge.hasHitachiDSP()) hitachidsp.power();
|
|
|
|
if(cartridge.hasNECDSP()) necdsp.power();
|
|
|
|
if(cartridge.hasEpsonRTC()) epsonrtc.power();
|
|
|
|
if(cartridge.hasSharpRTC()) sharprtc.power();
|
|
|
|
if(cartridge.hasSPC7110()) spc7110.power();
|
|
|
|
if(cartridge.hasSDD1()) sdd1.power();
|
|
|
|
if(cartridge.hasOBC1()) obc1.power();
|
|
|
|
if(cartridge.hasMSU1()) msu1.power();
|
|
|
|
|
2015-12-19 09:00:27 +00:00
|
|
|
if(cartridge.hasBSMemorySlot()) bsmemory.power();
|
2010-08-09 13:28:56 +00:00
|
|
|
|
Update to v084r03 release.
(r02 was not posted to the WIP thread)
byuu says:
Internally, all color is processed with 30-bit precision. The filters
also operate at 30-bit depth.
There's a new config file setting, video.depth, which defaults to 24.
This causes the final output to downsample to 24-bit, as most will
require.
If you set it to 30-bit, the downsampling will not occur, and bsnes will
ask ruby for a 30-bit surface. If you don't have one available, you're
going to get bad colors. Or maybe even a crash with OpenGL.
I don't yet have detection code to make sure you have an appropriate
visual in place.
30-bit mode will really only work if you are running Linux, running Xorg
at Depth 30, use the OpenGL or XShm driver, have an nVidia Quadro or AMD
FireGL card with the official drivers, and have a 30-bit capable
monitor.
Lots of planning and work for very little gain here, but it's nice that
it's finally finished.
Oh, I had to change the contrast/brightness formulas a tiny bit, but
they still work and look nice.
2011-12-03 03:22:54 +00:00
|
|
|
reset();
|
2010-08-09 13:28:56 +00:00
|
|
|
}
|
|
|
|
|
2015-11-10 11:02:29 +00:00
|
|
|
auto System::reset() -> void {
|
2010-08-09 13:28:56 +00:00
|
|
|
cpu.reset();
|
|
|
|
smp.reset();
|
|
|
|
dsp.reset();
|
|
|
|
ppu.reset();
|
|
|
|
|
2015-08-02 06:23:13 +00:00
|
|
|
if(cartridge.hasICD2()) icd2.reset();
|
|
|
|
if(cartridge.hasMCC()) mcc.reset();
|
|
|
|
if(cartridge.hasNSSDIP()) nss.reset();
|
|
|
|
if(cartridge.hasEvent()) event.reset();
|
|
|
|
if(cartridge.hasSA1()) sa1.reset();
|
|
|
|
if(cartridge.hasSuperFX()) superfx.reset();
|
|
|
|
if(cartridge.hasARMDSP()) armdsp.reset();
|
|
|
|
if(cartridge.hasHitachiDSP()) hitachidsp.reset();
|
|
|
|
if(cartridge.hasNECDSP()) necdsp.reset();
|
|
|
|
if(cartridge.hasEpsonRTC()) epsonrtc.reset();
|
|
|
|
if(cartridge.hasSharpRTC()) sharprtc.reset();
|
|
|
|
if(cartridge.hasSPC7110()) spc7110.reset();
|
|
|
|
if(cartridge.hasSDD1()) sdd1.reset();
|
|
|
|
if(cartridge.hasOBC1()) obc1.reset();
|
|
|
|
if(cartridge.hasMSU1()) msu1.reset();
|
|
|
|
|
2015-12-19 09:00:27 +00:00
|
|
|
if(cartridge.hasBSMemorySlot()) bsmemory.reset();
|
2015-08-02 06:23:13 +00:00
|
|
|
|
|
|
|
if(cartridge.hasICD2()) cpu.coprocessors.append(&icd2);
|
|
|
|
if(cartridge.hasEvent()) cpu.coprocessors.append(&event);
|
|
|
|
if(cartridge.hasSA1()) cpu.coprocessors.append(&sa1);
|
|
|
|
if(cartridge.hasSuperFX()) cpu.coprocessors.append(&superfx);
|
|
|
|
if(cartridge.hasARMDSP()) cpu.coprocessors.append(&armdsp);
|
|
|
|
if(cartridge.hasHitachiDSP()) cpu.coprocessors.append(&hitachidsp);
|
|
|
|
if(cartridge.hasNECDSP()) cpu.coprocessors.append(&necdsp);
|
|
|
|
if(cartridge.hasEpsonRTC()) cpu.coprocessors.append(&epsonrtc);
|
|
|
|
if(cartridge.hasSharpRTC()) cpu.coprocessors.append(&sharprtc);
|
|
|
|
if(cartridge.hasSPC7110()) cpu.coprocessors.append(&spc7110);
|
|
|
|
if(cartridge.hasMSU1()) cpu.coprocessors.append(&msu1);
|
2010-08-09 13:28:56 +00:00
|
|
|
|
2016-02-09 11:51:12 +00:00
|
|
|
scheduler.reset();
|
Update to v098r03 release.
byuu says:
It took several hours, but I've rebuilt much of the SNES' bus memory
mapping architecture.
The new design unifies the cartridge string-based mapping
("00-3f,80-bf:8000-ffff") and internal bus.map calls. The map() function
now has an accompanying unmap() function, and instead of a fixed 256
callbacks, it'll scan to find the first available slot. unmap() will
free slots up when zero addresses reference a given slot.
The controllers and expansion port are now both entirely dynamic.
Instead of load/unload/power/reset, they only have the constructor
(power/reset/load) and destructor (unload). What this means is you can
now dynamically change even expansion port devices after the system is
loaded.
Note that this is incredibly dangerous and stupid, but ... oh well. The
whole point of this was for 21fx. There's no way to change the expansion
port device prior to loading a game, but if the 21fx isn't active, then
the reset vector hijack won't work. Now you can load a 21fx game, change
the expansion port device, and simply reset the system to active the
device.
The unification of design between controller port devices and expansion
port devices is nice, and overall this results in a reduction of code
(all of the Mapping stuff in Cartridge is gone, replaced with direct bus
mapping.) And there's always the potential to expand this system more in
the future now.
The big missing feature right now is the ability to push/pop mappings.
So if you look at how the 21fx does the reset vector, you might vomit
a little bit. But ... it works.
Also changed exit(0) to _exit(0) in the POSIX version of nall::execute.
[The _exit(0) thing is an attempt to make higan not crash when it tries
to launch icarus and it's not on $PATH. The theory is that higan forks,
then the child tries to exec icarus and fails, so it exits, all the
unique_ptrs clean up their resources and tell the X server to free
things the parent process is still using. Calling _exit() prevents
destructors from running, and seems to prevent the problem. -Ed.]
2016-04-09 10:21:18 +00:00
|
|
|
peripherals.reset();
|
2010-08-09 13:28:56 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
}
|