2016-06-20 11:00:32 +00:00
|
|
|
auto Program::path(uint id) -> string {
|
|
|
|
return mediumPaths(id);
|
|
|
|
}
|
|
|
|
|
|
|
|
auto Program::open(uint id, string name, vfs::file::mode mode, bool required) -> vfs::shared::file {
|
2016-06-26 08:54:12 +00:00
|
|
|
if(name == "manifest.bml" && !path(id).endsWith(".sys/")) {
|
|
|
|
if(!file::exists({path(id), name}) || settings["Library/IgnoreManifests"].boolean()) {
|
|
|
|
if(auto manifest = execute("icarus", "--manifest", path(id))) {
|
|
|
|
return vfs::memory::file::open(manifest.output.data<uint8_t>(), manifest.output.size());
|
|
|
|
}
|
2016-06-20 11:00:32 +00:00
|
|
|
}
|
|
|
|
}
|
2016-06-26 08:54:12 +00:00
|
|
|
|
|
|
|
if(auto result = vfs::fs::file::open({path(id), name}, mode)) return result;
|
|
|
|
|
2016-06-25 08:53:11 +00:00
|
|
|
if(required) {
|
|
|
|
MessageDialog()
|
|
|
|
.setTitle({"Error"})
|
|
|
|
.setText({"Error: missing required file:\n\n", path(id), name})
|
|
|
|
.error();
|
|
|
|
}
|
2016-06-26 08:54:12 +00:00
|
|
|
|
2016-06-20 11:00:32 +00:00
|
|
|
return {};
|
|
|
|
}
|
|
|
|
|
2016-06-25 08:53:11 +00:00
|
|
|
auto Program::load(uint id, string name, string type) -> maybe<uint> {
|
2016-06-26 08:54:12 +00:00
|
|
|
string location;
|
|
|
|
if(mediumQueue) {
|
2016-07-01 11:58:12 +00:00
|
|
|
location = mediumQueue.takeLeft();
|
2016-06-26 08:54:12 +00:00
|
|
|
} else {
|
|
|
|
location = BrowserDialog()
|
|
|
|
.setTitle({"Load ", name})
|
|
|
|
.setPath({settings["Library/Location"].text(), name})
|
|
|
|
.setFilters({string{name, "|*.", type}, "All|*.*"})
|
|
|
|
.openFolder();
|
|
|
|
}
|
|
|
|
if(!directory::exists(location)) return mediumQueue.reset(), nothing;
|
Update to v094r22 release.
byuu says:
I fixed the hiro layout enable bug, so when you go to assign joypad
input, the window disables itself so your input doesn't mess with the
controls.
I added "reset" to the hotkeys, in case you feel like clearing all of
them at once.
I added device selection support and the ability to disable audio
synchronization (run > 60fps) to the ruby/OSS driver. This is exposed in
tomoko's configuration file.
I added checks to stringify so that assigning null char* strings to
nall::string won't cause crashes anymore (technically the crash was in
strlen(), which doesn't check for null strings, but whatever ... I'll do
the check myself.)
I hooked up BrowserDialog::folderSelect() to loading slotted media for
now. Tested it by loading a Game Boy game successfully through the Super
Game Boy. Definitely want to write a custom window for this though, that
looks more like the library dialog.
Remaining issues:
- finish slotted cart loader (SGB, BSX, ST)
- add DIP switch selection window (NSS) [I may end up punting this one
to v096]
- add more configuration panels (video, audio, timing)
2015-05-25 12:23:49 +00:00
|
|
|
|
Update to v099r08 release.
byuu says:
Changelog:
- nall/vfs work 100% completed; even SGB games load now
- emulation cores now call load() for the base cartridges as well
- updated port/device handling; portmask is gone; device ID bug should
be resolved now
- SNES controller port 1 multitap option was removed
- added support for 128KiB SNES PPU VRAM (for now, edit sfc/ppu/ppu.hpp
VRAM::size=0x10000; to enable)
Overall, nall/vfs was a huge success!! We've substantially reduced
the amount of boilerplate code everywhere, while still allowing (even
easier than before) support for RAM-based game loading/saving. All of
nall/stream is dead and buried.
I am considering removing Emulator::Interface::Medium::id and/or
bootable flag. Or at least, doing something different with it. The
values for the non-bootable GB/BS/ST entries duplicate the ID that is
supposed to be unique. They are for GB/GBC and WS/WSC. Maybe I'll use
this as the hardware revision selection ID, and then gut non-bootable
options. There's really no reason for that to be there. I think at one
point I was using it to generate library tabs for non-bootable systems,
but we don't do that anymore anyway.
Emulator::Interface::load() may not need the required flag anymore ... it
doesn't really do anything right now anyway.
I have a few reasons for having the cores load the base cartridge. Most
importantly, it is going to enable a special mode for the WonderSwan /
WonderSwan Color in the future. If we ever get the IPLROMs dumped ... it's
possible to boot these systems with no games inserted to set user profile
information and such. There are also other systems that may accept being
booted without a cartridge. To reach this state, you would load a game and
then cancel the load dialog. Right now, this results in games not loading.
The second reason is this prevents nasty crashes when loading fails. So
if you're missing a required manifest, the emulator won't die a violent
death anymore. It's able to back out at any point.
The third reason is consistency: loading the base cartridge works the
same as the slot cartridges.
The fourth reason is Emulator::Interface::open(uint pathID)
values. Before, the GB, SB, GBC modes were IDs 1,2,3 respectively. This
complicated things because you had to pass the correct ID. But now
instead, Emulator::Interface::load() returns maybe<uint> that is nothing
when no game is selected, and a pathID for a valid game. And now open()
can take this ID to access this game's folder contents.
The downside, which is temporary, is that command-line loading is
currently broken. But I do intend on restoring it. In fact, I want to do
better than before and allow multi-cart booting from the command-line by
specifying the base cartridge and then slot cartridges. The idea should
be pretty simple: keep a queue of pending filenames that we fill from
the command-line and/or drag-and-drop operations on the main window,
and then empty out the queue or prompt for load dialogs from the UI
when booting a system. This also might be a bit more unorthodox compared
to the traditional emulator design of "loadGame(filename)", but ... oh
well. It's easy enough still.
The port/device changes are fun. We simplified things quite a bit. The
portmask stuff is gone entirely. While ports and devices keep IDs,
this is really just sugar-coating so UIs can use for(auto& port :
emulator->ports) and access port.id; rather than having to use for(auto
n : range(emulator->ports)) { auto& port = emulator->ports[n]; ... };
but they should otherwise generally be identical to the order they appear
in their respective ranges. Still, don't rely on that.
Input::id is gone. There was no point since we also got rid of the nasty
Input::order vector. Since I was in here, I went ahead and caved on the
pedantics and renamed Input::guid to Input::userData.
I removed the SNES controller port 1 multitap option. Basically, the only
game that uses this is N-warp Daisakusen and, no offense to d4s, it's
not really a good game anyway. It's just a quick demo to show 8-players
on the SNES. But in the UI, all it does is confuse people into wasting
time mapping a controller they're never going to use, and they're going
to wonder which port to use. If more compelling use cases for 8-players
comes about, we can reconsider this. I left all the code to support this
in place, so all you have to do is uncomment one line to enable it again.
We now have dsnes emulation! :D
If you change PPU::VRAM::size to 0x10000 (words), then you should now
have 128KiB of VRAM. Even better, it serializes the used-VRAM size,
so your save states shouldn't crash on you if you swap between the two
(though if you try this, you're nuts.)
Note that this option does break commercial software. Yoshi's Island in
particular. This game is setting A15 on some PPU register writes, but
not on others. The end result of this is things break horribly in-game.
Also, this option is causing a very tiny speed hit for obvious reasons
with the variable masking value (I'm even using size-1 for now.) Given
how niche this is, I may just leave it a compile-time constant to avoid
the overhead cost. Otherwise, if we keep the option, then it'll go into
Super Famicom.sys/manifest.bml ... I'll flesh that out in the near-future.
----
Finally, some fun for my OCD ... my monitor suddenly cut out on me
in the middle of working on this WIP, about six hours in of non-stop
work. Had to hit a bunch of ctrl+alt+fN commands (among other things)
and trying to log in headless on another TTY to do issue commands,
trying to recover the display. Finally power cycled the monitor and it
came back up. So all my typing ended up going to who knows where.
Usually this sort of thing terrifies me enough that I scrap a WIP and
start over to ensure I didn't screw anything up during the crashed screen
when hitting keys randomly.
Obviously, everything compiles and appears to work fine. And I know
it's extremely paranoid, but OCD isn't logical, so ... I'm going
to go over every line of the 100KiB r07->r08 diff looking for any
corruption/errors/whatever.
----
Review finished.
r08 diff review notes:
- fc/controller/gamepad/gamepad.cpp:
use uint device = ID::Device::Gamepad; not id = ...;
- gb/cartridge/cartridge.hpp:
remove redundant uint _pathID; (in Information::pathID already)
- gb/cartridge/cartridge.hpp:
pull sha256 inside Information
- sfc/cartridge/load/cpp:
add " - Slot (A,B)" to interface->load("Sufami Turbo"); to be more
descriptive
- sfc/controller/gamepad/gamepad.cpp:
use uint device = ID::Device::Gamepad; not id = ...;
- sfc/interface/interface.cpp:
remove n variable from the Multitap device input generation loop
(now unused)
- sfc/interface/interface.hpp:
put struct Port above struct Device like the other classes
- ui-tomoko:
cheats.bml is reading from/writing to mediumPaths(0) [system folder
instead of game folder]
- ui-tomoko:
instead of mediumPaths(1) - call emulator->metadataPathID() or something
like that
2016-06-24 12:16:53 +00:00
|
|
|
uint pathID = mediumPaths.size();
|
|
|
|
mediumPaths.append(location);
|
|
|
|
return pathID;
|
2015-02-28 01:51:53 +00:00
|
|
|
}
|
|
|
|
|
Update to v096r07 release.
byuu says:
Changelog:
- configuration files are now stored in localpath() instead of configpath()
- Video gamma/saturation/luminance sliders are gone now, sorry
- added Video Filter->Blur Emulation [1]
- added Video Filter->Scanline Emulation [2]
- improvements to GBA audio emulation (fixes Minish Cap) [Jonas Quinn]
[1] For the Famicom, this does nothing. For the Super Famicom, this
performs horizontal blending for proper pseudo-hires translucency. For
the Game Boy, Game Boy Color, and Game Boy Advance, this performs
interframe blending (each frame is the average of the current and
previous frame), which is important for things like the GBVideoPlayer.
[2] Right now, this only applies to the Super Famicom, but it'll come to
the Famicom in the future. For the Super Famicom, this option doesn't
just add scanlines, it simulates the phosphor decay that's visible in
interlace mode. If you observe an interlaced game like RPM Racing on
a real SNES, you'll notice that even on perfectly still screens, the
image appears to shake. This option emulates that effect.
Note 1: the buffering right now is a little sub-optimal, so there will
be a slight speed hit with this new support. Since the core is now
generating native ARGB8888 colors, it might as well call out to the
interface to lock/unlock/refresh the video, that way it can render
directly to the screen. Although ... that might not be such a hot idea,
since the GBx interframe blending reads from the target buffer, and that
tends to be a catastrophic option for performance.
Note 2: the balanced and performance profiles for the SNES are
completely busted again. This WIP took 6 1/2 hours, and I'm exhausted.
Very much not looking forward to working on those, since those two have
all kinds of fucked up speedup tricks for non-interlaced and/or
non-hires video modes.
Note 3: if you're on Windows and you saved your system folders somewhere
else, now'd be a good time to move them to %localappdata%/higan
2016-01-15 10:06:51 +00:00
|
|
|
auto Program::videoRefresh(const uint32* data, uint pitch, uint width, uint height) -> void {
|
Update to v097r14 release.
byuu says:
This is a few days old, but oh well.
This WIP changes nall,hiro,ruby,icarus back to (u)int(8,16,32,64)_t.
I'm slowly pushing for (u)int(8,16,32,64) to use my custom
Integer<Size>/Natural<Size> classes instead. But it's going to be one
hell of a struggle to get that into higan.
2016-02-16 09:11:58 +00:00
|
|
|
uint32_t* output;
|
2015-12-21 09:16:47 +00:00
|
|
|
uint length;
|
2015-02-28 01:51:53 +00:00
|
|
|
|
2015-06-20 05:44:05 +00:00
|
|
|
if(video->lock(output, length, width, height)) {
|
2015-02-28 01:51:53 +00:00
|
|
|
pitch >>= 2, length >>= 2;
|
|
|
|
|
|
|
|
for(auto y : range(height)) {
|
2016-01-15 10:28:51 +00:00
|
|
|
memory::copy(output + y * length, data + y * pitch, width * sizeof(uint32));
|
2015-02-28 01:51:53 +00:00
|
|
|
}
|
|
|
|
|
2015-11-16 08:38:05 +00:00
|
|
|
if(emulator->information.overscan && settings["Video/Overscan/Mask"].boolean()) {
|
|
|
|
auto h = settings["Video/Overscan/Horizontal"].natural();
|
|
|
|
auto v = settings["Video/Overscan/Vertical"].natural();
|
2015-04-21 11:58:59 +00:00
|
|
|
|
|
|
|
if(h) for(auto y : range(height)) {
|
|
|
|
memory::fill(output + y * length, 4 * h);
|
|
|
|
memory::fill(output + y * length + (width - h), 4 * h);
|
|
|
|
}
|
|
|
|
|
|
|
|
if(v) for(auto y : range(v)) {
|
|
|
|
memory::fill(output + y * length, 4 * width);
|
|
|
|
memory::fill(output + (height - 1 - y) * length, 4 * width);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2015-06-20 05:44:05 +00:00
|
|
|
video->unlock();
|
|
|
|
video->refresh();
|
2015-02-28 01:51:53 +00:00
|
|
|
}
|
|
|
|
|
2015-12-21 09:16:47 +00:00
|
|
|
static uint frameCounter = 0;
|
2015-02-28 01:51:53 +00:00
|
|
|
static time_t previous, current;
|
|
|
|
frameCounter++;
|
|
|
|
|
|
|
|
time(¤t);
|
|
|
|
if(current != previous) {
|
|
|
|
previous = current;
|
2015-04-13 11:16:33 +00:00
|
|
|
statusText = {"FPS: ", frameCounter};
|
2015-02-28 01:51:53 +00:00
|
|
|
frameCounter = 0;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2016-06-01 11:23:22 +00:00
|
|
|
auto Program::audioSample(const double* samples, uint channels) -> void {
|
|
|
|
int16 left = sclamp<16>(samples[0] * 32768.0);
|
|
|
|
int16 right = sclamp<16>(samples[1] * 32768.0);
|
Update to v098r11 release.
byuu says:
Changelog:
- fixed nall/path.hpp compilation issue
- fixed ruby/audio/xaudio header declaration compilation issue (again)
- cleaned up xaudio2.hpp file to match my coding syntax (12.5% of the
file was whitespace overkill)
- added null terminator entry to nall/windows/utf8.hpp argc[] array
- nall/windows/guid.hpp uses the Windows API for generating the GUID
- this should stop all the bug reports where two nall users were
generating GUIDs at the exact same second
- fixed hiro/cocoa compilation issue with uint# types
- fixed major higan/sfc Super Game Boy audio latency issue
- fixed higan/sfc CPU core bug with pei, [dp], [dp]+y instructions
- major cleanups to higan/processor/r65816 core
- merged emulation/native-mode opcodes
- use camel-case naming on memory.hpp functions
- simplify address masking code for memory.hpp functions
- simplify a few opcodes themselves (avoid redundant copies, etc)
- rename regs.* to r.* to match modern convention of other CPU cores
- removed device.order<> concept from Emulator::Interface
- cores will now do the translation to make the job of the UI easier
- fixed plurality naming of arrays in Emulator::Interface
- example: emulator.ports[p].devices[d].inputs[i]
- example: vector<Medium> media
- probably more surprises
Major show-stoppers to the next official release:
- we need to work on GB core improvements: LY=153/0 case, multiple STAT
IRQs case, GBC audio output regs, etc.
- we need to re-add software cursors for light guns (Super Scope,
Justifier)
- after the above, we need to fix the turbo button for the Super Scope
I really have no idea how I want to implement the light guns. Ideally,
we'd want it in higan/video, so we can support the NES Zapper with the
same code. But this isn't going to be easy, because only the SNES knows
when its output is interlaced, and its resolutions can vary as
{256,512}x{224,240,448,480} which requires pixel doubling that was
hard-coded to the SNES-specific behavior, but isn't appropriate to be
exposed in higan/video.
2016-05-25 11:13:02 +00:00
|
|
|
audio->sample(left, right);
|
2015-02-28 01:51:53 +00:00
|
|
|
}
|
|
|
|
|
2015-12-21 09:16:47 +00:00
|
|
|
auto Program::inputPoll(uint port, uint device, uint input) -> int16 {
|
2016-01-15 10:28:51 +00:00
|
|
|
if(presentation->focused() || settings["Input/FocusLoss/AllowInput"].boolean()) {
|
2016-06-26 08:54:12 +00:00
|
|
|
auto& mapping = inputManager->emulator->ports[port].devices[device].mappings[input];
|
|
|
|
return mapping.poll();
|
2015-03-03 10:14:49 +00:00
|
|
|
}
|
2015-03-02 09:13:28 +00:00
|
|
|
return 0;
|
2015-02-28 01:51:53 +00:00
|
|
|
}
|
|
|
|
|
2015-12-21 09:16:47 +00:00
|
|
|
auto Program::inputRumble(uint port, uint device, uint input, bool enable) -> void {
|
2016-01-15 10:28:51 +00:00
|
|
|
if(presentation->focused() || settings["Input/FocusLoss/AllowInput"].boolean() || !enable) {
|
2016-06-26 08:54:12 +00:00
|
|
|
auto& mapping = inputManager->emulator->ports[port].devices[device].mappings[input];
|
|
|
|
return mapping.rumble(enable);
|
2015-08-24 09:42:11 +00:00
|
|
|
}
|
2015-02-28 01:51:53 +00:00
|
|
|
}
|
|
|
|
|
Update to v099r14 release.
byuu says:
Changelog:
- (u)int(max,ptr) abbreviations removed; use _t suffix now [didn't feel
like they were contributing enough to be worth it]
- cleaned up nall::integer,natural,real functionality
- toInteger, toNatural, toReal for parsing strings to numbers
- fromInteger, fromNatural, fromReal for creating strings from numbers
- (string,Markup::Node,SQL-based-classes)::(integer,natural,real)
left unchanged
- template<typename T> numeral(T value, long padding, char padchar)
-> string for print() formatting
- deduces integer,natural,real based on T ... cast the value if you
want to override
- there still exists binary,octal,hex,pointer for explicit print()
formatting
- lstring -> string_vector [but using lstring = string_vector; is
declared]
- would be nice to remove the using lstring eventually ... but that'd
probably require 10,000 lines of changes >_>
- format -> string_format [no using here; format was too ambiguous]
- using integer = Integer<sizeof(int)*8>; and using natural =
Natural<sizeof(uint)*8>; declared
- for consistency with boolean. These three are meant for creating
zero-initialized values implicitly (various uses)
- R65816::io() -> idle() and SPC700::io() -> idle() [more clear; frees
up struct IO {} io; naming]
- SFC CPU, PPU, SMP use struct IO {} io; over struct (Status,Registers) {}
(status,registers); now
- still some CPU::Status status values ... they didn't really fit into
IO functionality ... will have to think about this more
- SFC CPU, PPU, SMP now use step() exclusively instead of addClocks()
calling into step()
- SFC CPU joypad1_bits, joypad2_bits were unused; killed them
- SFC PPU CGRAM moved into PPU::Screen; since nothing else uses it
- SFC PPU OAM moved into PPU::Object; since nothing else uses it
- the raw uint8[544] array is gone. OAM::read() constructs values from
the OAM::Object[512] table now
- this avoids having to determine how we want to sub-divide the two
OAM memory sections
- this also eliminates the OAM::synchronize() functionality
- probably more I'm forgetting
The FPS fluctuations are driving me insane. This WIP went from 128fps to
137fps. Settled on 133.5fps for the final build. But nothing I changed
should have affected performance at all. This level of fluctuation makes
it damn near impossible to know whether I'm speeding things up or slowing
things down with changes.
2016-07-01 11:50:32 +00:00
|
|
|
auto Program::dipSettings(Markup::Node node) -> uint {
|
2016-02-28 11:42:52 +00:00
|
|
|
return 0;
|
2015-02-28 01:51:53 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
auto Program::notify(string text) -> void {
|
|
|
|
}
|