mirror of https://github.com/bsnes-emu/bsnes.git
22 Commits
Author | SHA1 | Message | Date |
---|---|---|---|
Tim Allen | c50723ef61 |
Update to v100r15 release.
byuu wrote: Aforementioned scheduler changes added. Longer explanation of why here: http://hastebin.com/raw/toxedenece Again, we really need to test this as thoroughly as possible for regressions :/ This is a really major change that affects absolutely everything: all emulation cores, all coprocessors, etc. Also added ADDX and SUB to the 68K core, which brings us just barely above 50% of the instruction encoding space completed. [Editor's note: The "aformentioned scheduler changes" were described in a previous forum post: Unfortunately, 64-bits just wasn't enough precision (we were getting misalignments ~230 times a second on 21/24MHz clocks), so I had to move to 128-bit counters. This of course doesn't exist on 32-bit architectures (and probably not on all 64-bit ones either), so for now ... higan's only going to compile on 64-bit machines until we figure something out. Maybe we offer a "lower precision" fallback for machines that lack uint128_t or something. Using the booth algorithm would be way too slow. Anyway, the precision is now 2^-96, which is roughly 10^-29. That puts us far beyond the yoctosecond. Suck it, MAME :P I'm jokingly referring to it as the byuusecond. The other 32-bits of precision allows a 1Hz clock to run up to one full second before all clocks need to be normalized to prevent overflow. I fixed a serious wobbling issue where I was using clock > other.clock for synchronization instead of clock >= other.clock; and also another aliasing issue when two threads share a common frequency, but don't run in lock-step. The latter I don't even fully understand, but I did observe it in testing. nall/serialization.hpp has been extended to support 128-bit integers, but without explicitly naming them (yay generic code), so nall will still compile on 32-bit platforms for all other applications. Speed is basically a wash now. FC's a bit slower, SFC's a bit faster. The "longer explanation" in the linked hastebin is: Okay, so the idea is that we can have an arbitrary number of oscillators. Take the SNES: - CPU/PPU clock = 21477272.727272hz - SMP/DSP clock = 24576000hz - Cartridge DSP1 clock = 8000000hz - Cartridge MSU1 clock = 44100hz - Controller Port 1 modem controller clock = 57600hz - Controller Port 2 barcode battler clock = 115200hz - Expansion Port exercise bike clock = 192000hz Is this a pathological case? Of course it is, but it's possible. The first four do exist in the wild already: see Rockman X2 MSU1 patch. Manifest files with higan let you specify any frequency you want for any component. The old trick higan used was to hold an int64 counter for each thread:thread synchronization, and adjust it like so: - if thread A steps X clocks; then clock += X * threadB.frequency - if clock >= 0; switch to threadB - if thread B steps X clocks; then clock -= X * threadA.frequency - if clock < 0; switch to threadA But there are also system configurations where one processor has to synchronize with more than one other processor. Take the Genesis: - the 68K has to sync with the Z80 and PSG and YM2612 and VDP - the Z80 has to sync with the 68K and PSG and YM2612 - the PSG has to sync with the 68K and Z80 and YM2612 Now I could do this by having an int64 clock value for every association. But these clock values would have to be outside the individual Thread class objects, and we would have to update every relationship's clock value. So the 68K would have to update the Z80, PSG, YM2612 and VDP clocks. That's four expensive 64-bit multiply-adds per clock step event instead of one. As such, we have to account for both possibilities. The only way to do this is with a single time base. We do this like so: - setup: scalar = timeBase / frequency - step: clock += scalar * clocks Once per second, we look at every thread, find the smallest clock value. Then subtract that value from all threads. This prevents the clock counters from overflowing. Unfortunately, these oscillator values are psychotic, unpredictable, and often times repeating fractions. Even with a timeBase of 1,000,000,000,000,000,000 (one attosecond); we get rounding errors every ~16,300 synchronizations. Specifically, this happens with a CPU running at 21477273hz (rounded) and SMP running at 24576000hz. That may be good enough for most emulators, but ... you know how I am. Plus, even at the attosecond level, we're really pushing against the limits of 64-bit integers. Given the reciprocal inverse, a frequency of 1Hz (which does exist in higan!) would have a scalar that consumes 1/18th of the entire range of a uint64 on every single step. Yes, I could raise the frequency, and then step by that amount, I know. But I don't want to have weird gotchas like that in the scheduler core. Until I increase the accuracy to about 100 times greater than a yoctosecond, the rounding errors are too great. And since the only choice above 64-bit values is 128-bit values; we might as well use all the extra headroom. 2^-96 as a timebase gives me the ability to have both a 1Hz and 4GHz clock; and run them both for a full second; before an overflow event would occur. Another hastebin includes demonstration code: #include <libco/libco.h> #include <nall/nall.hpp> using namespace nall; // cothread_t mainThread = nullptr; const uint iterations = 100'000'000; const uint cpuFreq = 21477272.727272 + 0.5; const uint smpFreq = 24576000.000000 + 0.5; const uint cpuStep = 4; const uint smpStep = 5; // struct ThreadA { cothread_t handle = nullptr; uint64 frequency = 0; int64 clock = 0; auto create(auto (*entrypoint)() -> void, uint frequency) { this->handle = co_create(65536, entrypoint); this->frequency = frequency; this->clock = 0; } }; struct CPUA : ThreadA { static auto Enter() -> void; auto main() -> void; CPUA() { create(&CPUA::Enter, cpuFreq); } } cpuA; struct SMPA : ThreadA { static auto Enter() -> void; auto main() -> void; SMPA() { create(&SMPA::Enter, smpFreq); } } smpA; uint8 queueA[iterations]; uint offsetA; cothread_t resumeA = cpuA.handle; auto EnterA() -> void { offsetA = 0; co_switch(resumeA); } auto QueueA(uint value) -> void { queueA[offsetA++] = value; if(offsetA >= iterations) { resumeA = co_active(); co_switch(mainThread); } } auto CPUA::Enter() -> void { while(true) cpuA.main(); } auto CPUA::main() -> void { QueueA(1); smpA.clock -= cpuStep * smpA.frequency; if(smpA.clock < 0) co_switch(smpA.handle); } auto SMPA::Enter() -> void { while(true) smpA.main(); } auto SMPA::main() -> void { QueueA(2); smpA.clock += smpStep * cpuA.frequency; if(smpA.clock >= 0) co_switch(cpuA.handle); } // struct ThreadB { cothread_t handle = nullptr; uint128_t scalar = 0; uint128_t clock = 0; auto print128(uint128_t value) { string s; while(value) { s.append((char)('0' + value % 10)); value /= 10; } s.reverse(); print(s, "\n"); } //femtosecond (10^15) = 16306 //attosecond (10^18) = 688838 //zeptosecond (10^21) = 13712691 //yoctosecond (10^24) = 13712691 (hitting a dead-end on a rounding error causing a wobble) //byuusecond? ( 2^96) = (perfect? 79,228 times more precise than a yoctosecond) auto create(auto (*entrypoint)() -> void, uint128_t frequency) { this->handle = co_create(65536, entrypoint); uint128_t unitOfTime = 1; //for(uint n : range(29)) unitOfTime *= 10; unitOfTime <<= 96; //2^96 time units ... this->scalar = unitOfTime / frequency; print128(this->scalar); this->clock = 0; } auto step(uint128_t clocks) -> void { clock += clocks * scalar; } auto synchronize(ThreadB& thread) -> void { if(clock >= thread.clock) co_switch(thread.handle); } }; struct CPUB : ThreadB { static auto Enter() -> void; auto main() -> void; CPUB() { create(&CPUB::Enter, cpuFreq); } } cpuB; struct SMPB : ThreadB { static auto Enter() -> void; auto main() -> void; SMPB() { create(&SMPB::Enter, smpFreq); clock = 1; } } smpB; auto correct() -> void { auto minimum = min(cpuB.clock, smpB.clock); cpuB.clock -= minimum; smpB.clock -= minimum; } uint8 queueB[iterations]; uint offsetB; cothread_t resumeB = cpuB.handle; auto EnterB() -> void { correct(); offsetB = 0; co_switch(resumeB); } auto QueueB(uint value) -> void { queueB[offsetB++] = value; if(offsetB >= iterations) { resumeB = co_active(); co_switch(mainThread); } } auto CPUB::Enter() -> void { while(true) cpuB.main(); } auto CPUB::main() -> void { QueueB(1); step(cpuStep); synchronize(smpB); } auto SMPB::Enter() -> void { while(true) smpB.main(); } auto SMPB::main() -> void { QueueB(2); step(smpStep); synchronize(cpuB); } // #include <nall/main.hpp> auto nall::main(string_vector) -> void { mainThread = co_active(); uint masterCounter = 0; while(true) { print(masterCounter++, " ...\n"); auto A = clock(); EnterA(); auto B = clock(); print((double)(B - A) / CLOCKS_PER_SEC, "s\n"); auto C = clock(); EnterB(); auto D = clock(); print((double)(D - C) / CLOCKS_PER_SEC, "s\n"); for(uint n : range(iterations)) { if(queueA[n] != queueB[n]) return print("fail at ", n, "\n"); } } } ...and that's everything.] |
|
Tim Allen | ca277cd5e8 |
Update to v100r14 release.
byuu says: (Windows: compile with -fpermissive to silence an annoying error. I'll fix it in the next WIP.) I completely replaced the time management system in higan and overhauled the scheduler. Before, processor threads would have "int64 clock"; and there would be a 1:1 relationship between two threads. When thread A ran for X cycles, it'd subtract X * B.Frequency from clock; and when thread B ran for Y cycles, it'd add Y * A.Frequency from clock. This worked well and allowed perfect precision; but it doesn't work when you have more complicated relationships: eg the 68K can sync to the Z80 and PSG; the Z80 to the 68K and PSG; so the PSG needs two counters. The new system instead uses a "uint64 clock" variable that represents time in attoseconds. Every time the scheduler exits, it subtracts the smallest clock count from all threads, to prevent an overflow scenario. The only real downside is that rounding errors mean that roughly every 20 minutes, we have a rounding error of one clock cycle (one 20,000,000th of a second.) However, this only applies to systems with multiple oscillators, like the SNES. And when you're in that situation ... there's no such thing as a perfect oscillator anyway. A real SNES will be thousands of times less out of spec than 1hz per 20 minutes. The advantages are pretty immense. First, we obviously can now support more complex relationships between threads. Second, we can build a much more abstracted scheduler. All of libco is now abstracted away completely, which may permit a state-machine / coroutine version of Thread in the future. We've basically gone from this: auto SMP::step(uint clocks) -> void { clock += clocks * (uint64)cpu.frequency; dsp.clock -= clocks; if(dsp.clock < 0 && !scheduler.synchronizing()) co_switch(dsp.thread); if(clock >= 0 && !scheduler.synchronizing()) co_switch(cpu.thread); } To this: auto SMP::step(uint clocks) -> void { Thread::step(clocks); synchronize(dsp); synchronize(cpu); } As you can see, we don't have to do multiple clock adjustments anymore. This is a huge win for the SNES CPU that had to update the SMP, DSP, all peripherals and all coprocessors. Likewise, we don't have to synchronize all coprocessors when one runs, now we can just synchronize the active one to the CPU. Third, when changing the frequencies of threads (think SGB speed setting modes, GBC double-speed mode, etc), it no longer causes the "int64 clock" value to be erroneous. Fourth, this results in a fairly decent speedup, mostly across the board. Aside from the GBA being mostly a wash (for unknown reasons), it's about an 8% - 12% speedup in every other emulation core. Now, all of this said ... this was an unbelievably massive change, so ... you know what that means >_> If anyone can help test all types of SNES coprocessors, and some other system games, it'd be appreciated. ---- Lastly, we have a bitchin' new about screen. It unfortunately adds ~200KiB onto the binary size, because the PNG->C++ header file transformation doesn't compress very well, and I want to keep the original resource files in with the higan archive. I might try some things to work around this file size increase in the future, but for now ... yeah, slightly larger archive sizes, sorry. The logo's a bit busted on Windows (the Label control's background transparency and alignment settings aren't working), but works well on GTK. I'll have to fix Windows before the next official release. For now, look on my Twitter feed if you want to see what it's supposed to look like. ---- EDIT: forgot about ICD2::Enter. It's doing some weird inverse run-to-save thing that I need to implement support for somehow. So, save states on the SGB core probably won't work with this WIP. |
|
Tim Allen | 76a8ecd32a |
Update to v100r03 release.
byuu says: Changelog: - moved Thread, Scheduler, Cheat functionality into emulator/ for all cores - start of actual Mega Drive emulation (two 68K instructions) I'm going to be rather terse on MD emulation, as it's too early for any meaningful dialogue here. |
|
Tim Allen | f48b332c83 |
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 |
|
Tim Allen | ccd8878d75 |
Update to v099r07 release.
byuu says: Changelog: - (hopefully) fixed BS Memory and Sufami Turbo slot loading - ported GB, GBA, WS cores to use nall/vfs - completely removed loadRequest, saveRequest functionality from Emulator::Interface and ui-tomoko - loadRequest(folder) is now load(folder) - save states now use a shared Emulator::SerializerVersion string - whenever this is bumped, all older states will break; but this makes bumping state versions way easier - also, the version string makes it a lot easier to identify compatibility windows for save states - SNES PPU now uses uint16 vram[32768] for memory accesses [hex_usr] NOTE: Super Game Boy loading is currently broken, and I'm not entirely sure how to fix it :/ The file loading handoff was -really- complicated, and so I'm kind of at a loss ... so for now, don't try it. Everything else should theoretically work, so please report any bugs you find. So, this is pretty much it. I'd be very curious to hear feedback from people who objected to the old nall/stream design, whether they are happy with the new file loading system or think it could use further improvements. The 16-bit VRAM turned out to be a wash on performance (roughly the same as before. 1fps slower on Zelda 3, 1fps faster on Yoshi's Island.) The main reason for this was because Yoshi's Island was breaking horribly until I changed the vramRead, vramWrite functions to take uint15 instead of uint16. I suspect the issue is we're using uint16s in some areas now that need to be uint15, and this game is setting the VRAM address to 0x8000+, causing us to go out of bounds on memory accesses. But ... I want to go ahead and do something cute for fun, and just because we can ... and this new interface is so incredibly perfect for it!! I want to support an SNES unit with 128KiB of VRAM. Not out of the box, but as a fun little tweakable thing. The SNES was clearly designed to support that, they just didn't use big enough VRAM chips, and left one of the lines disconnected. So ... let's connect it anyway! In the end, if we design it right, the only code difference should be one area where we mask by 15-bits instead of by 16-bits. |
|
Tim Allen | 875f031182 |
Update to v099r06 release.
byuu says: Changelog: - Super Famicom core converted to use nall/vfs - excludes Super Game Boy; since that's invoked from inside the GB core This was definitely the major obstacle to test nall/vfs' applicability. Things worked out pretty great in the end. We went from 22.0KiB (cartridge) + 18.6KiB (interface) to 24.5KiB (cartridge) + 11.4KiB (interface). Or 40.7KiB to 36.0KiB. This removes a very large source of indirection. Before it was: "coprocessor <=> cartridge <=> interface" for loading and saving data, and now it's just "coprocessor <=> cartridge". And it may make sense to eventually turn this into just "cartridge -> coprocessor" by making each coprocessor class handle its own markup parsing. It's nice to have all the manifest parsing in one location (well, sans MSU1); but it's also nice for loading/unloading to be handled by each coprocessor itself. So I'll have to think longer about that one. I've also started handling Interface::save() differently. Instead of keeping track of memory IDs and filenames, and iterating through that vector of objects ... instead I now have a system that mirrors the markup parsing on loading, but handles saving instead. This was actually the reason the code size savings weren't more significant, but I like this style more. As before, it removes an extra level of indirection. So ... next up, I need to port over the GB, then GBA, then WS cores. These shouldn't take too long since they're all very simple with just ROM+RAM(+RTC) right now. Then get the SGB callbacks using vfs. Then after that, gut all the old stream stuff from nall and higan. Kill the (load,save)Request stuff, rename the load(Gamepak)Request to something simpler, and then we should be good. Anyway ... these are some huge changes. |
|
Tim Allen | e2ee6689a0 |
Update to v098r06 release.
byuu says: Changelog: - emulation cores now refresh video from host thread instead of cothreads (fix AMD crash) - SFC: fixed another bug with leap year months in SharpRTC emulation - SFC: cleaned up camelCase on function names for armdsp,epsonrtc,hitachidsp,mcc,nss,sharprtc classes - GB: added MBC1M emulation (requires manually setting mapper=MBC1M in manifest.bml for now, sorry) - audio: implemented Emulator::Audio mixer and effects processor - audio: implemented Emulator::Stream interface - it is now possible to have more than two audio streams: eg SNES + SGB + MSU1 + Voicer-Kun (eventually) - audio: added reverb delay + reverb level settings; exposed balance configuration in UI - video: reworked palette generation to re-enable saturation, gamma, luminance adjustments - higan/emulator.cpp is gone since there was nothing left in it I know you guys are going to say the color adjust/balance/reverb stuff is pointless. And indeed it mostly is. But I like the idea of allowing some fun special effects and configurability that isn't system-wide. Note: there seems to be some kind of added audio lag in the SGB emulation now, and I don't really understand why. The code should be effectively identical to what I had before. The only main thing is that I'm sampling things to 48000hz instead of 32040hz before mixing. There's no point where I'm intentionally introducing added latency though. I'm kind of stumped, so if anyone wouldn't mind taking a look at it, it'd be much appreciated :/ I don't have an MSU1 test ROM, but the latency issue may affect MSU1 as well, and that would be very bad. |
|
Tim Allen | 55e507d5df |
Update to v098r05 release.
byuu says: Changelog: - WS/WSC: re-added support for screen rotation (code is inside WS core) - ruby: changed sample(uint16_t left, uint16_t right) to sample(int16_t left, int16_t right); - requires casting to uint prior to shifting in each driver, but I felt it was misleading to use uint16_t just to avoid that - ruby: WASAPI is now built in by default; has wareya's improvements, and now supports latency adjust - tomoko: audio settings panel has new "Exclusive Mode" checkbox for WASAPI driver only - note: although the setting *does* take effect in real-time, I'd suggest restarting the emulator after changing it - tomoko: audio latency can now be set to 0ms (which in reality means "the minimum supported by the driver") - all: increased cothread size from 512KiB to 2MiB to see if it fixes bullshit AMD driver crashes - this appears to cause a slight speed penalty due to cache locality going down between threads, though |
|
Tim Allen | 1929ad47d2 |
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.] |
|
Tim Allen | 7403e69307 |
Update to v098r02 release.
byuu says: Changelog: - SFC: fixed a regression on auto joypad polling due to missing parentheses - SFC: exported new PPU::vdisp() const -> uint; function [1] - SFC: merged PPU MMIO functions into the read/write handles (as I previously did for the CPU) - higan: removed individual emulator core names (bnes, bsnes, bgb, bgba, bws) [2] Forgot: - to remove /tomoko from the about dialog [1] note that technically I was relying on the cached, per-frame overscan setting when the CPU and light guns were polling the number of active display scanlines per frame. This was technically incorrect as you can change this value mid-frame and it'll kick in. I've never seen any game toggle overscan every frame, we only know about this because anomie tested this a long time ago. So, nothing should break, but ... you know how the SNES is. You can't even look at the code without something breaking, so I figured I'd mention it >_> [2] I'll probably keep referring to the SNES core as bsnes anyway. I don't mind if you guys use the b<system> names as shorthand. The simplification is mostly to make the branding easier. |
|
Tim Allen | 19e1d89f00 |
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. |
|
Tim Allen | 3d3ac8c1db |
Update to v097r22 release.
byuu says: Changelog: - WS: fixed lods, scas instructions - WS: implemented missing GRP4 instructions - WS: fixed transparency for screen one - WSC: added color-mode PPU rendering - WS+WSC: added packed pixel mode support - WS+WSC: added dummy sound register reads/writes - SFC: added threading to SuperDisc (it's hanging for right now; need to clear IRQ on $21e2 writes) SuperDisc Timer and Sound Check were failing before due to not turning off IRQs on $21e4 clear, so I'm happy that's fixed now. Riviera starts now, and displays the first intro screen before crashing. Huge, huge amounts of corrupted graphics, though. This game's really making me work for it :( No color games seem fully playable yet, but a lot of monochrome and color games are now at least showing more intro screen graphics before dying. This build defaults to horizontal orientation, but I left the inputs bound to vertical orientation. Whoops. I still need to implement a screen flip key binding. |
|
Tim Allen | fc7d5991ce |
Update to v097r18 release.
byuu says: Changelog: - fixed SNES sprite priority regression from r17 - added nall/windows/guard.hpp to guard against global namespace pollution (similar to nall/xorg/guard.hpp) - almost fixed Windows compilation (still accuracy profile only, sorry) - finished porting all of gba/ppu's registers over to the new .bit,.bits format ... all GBA registers.cpp files gone now - the "processors :=" line in the target-$(ui)/GNUmakefile is no longer required - processors += added to each emulator core - duplicates are removed using the new nall/GNUmakefile's $(unique) function - SFC core can be compiled without the GB core now - "-DSFC_SUPERGAMEBOY" is required to build in SGB support now (it's set in target-tomoko/GNUmakefile) - started once again on loki (higan/target-loki/) [as before, loki is Linux/BSD only on account of needing hiro::Console] loki shouldn't be too horrendous ... I hope. I just have the base skeleton ready for now. But the code from v094r08 should be mostly copyable over to it. It's just that it's about 50KiB of incredibly tricky code that has to be just perfect, so it's not going to be quick. But at least with the skeleton, it'll be a lot easier to pick away at it as I want. Windows compilation fix: move hiro/windows/header.hpp line 18 (header guard) to line 16 instead. |
|
Tim Allen | 6c83329cae |
Update to v097r13 release.
byuu says: I refactored my schedulers. Added about ten lines to each scheduler, and removed about 100 lines of calling into internal state in the scheduler for the FC,SFC cores and about 30-40 lines for the other cores. All of its state is now private. Also reworked all of the entry points to static auto Enter() and auto main(). Where Enter() handles all the synchronization stuff, and main() doesn't need the while(true); loop forcing another layer of indentation everywhere. Took a few hours to do, but totally worth it. I'm surprised I didn't do this sooner. Also updated icarus gmake install rule to copy over the database. |
|
Tim Allen | 72b6a8b32e |
Update to v096r04 release.
byuu says: Changelog: - fixed S-DD1 RAM writes (Star Ocean audio fixed) - applied all of the DMG test ROM fixes discussed earlier; passes many more test ROMs now - at least until the GBVideoPlayer is working: for debugging purposes, CPU/PPU single-step now instead of sync just-in-time (~30% slower) - fixed OS X crash on NSTextView (hopefully, would be very odd if not) Unfortunately passing these test ROMs caused my favorite GB/GBC game to break all of its graphics =( Shin Megami Tensei - Devichil - Kuro no Sho (Japan) is all garbled now. I'm really quite bummed by this ... but I guess I'll go through and revert r04's fixes one at a time until I find what's causing it. On the plus side, Astro Rabby is playable now. Still acts weird when pressing B/A on the first screen, but the start button will start the game. EDIT: got it. Shin Megami Tensei - Devichil requires FF4F (VBK) to be readable. Before, it was always returning 0x00. With my return 0xFF patch, that broke. But it should be returning the VBK value, which also fixes it. Also need to handle FF68/FF6A reads. Was really hoping that'd help GBVideoPlayer too, but nope. It doesn't read any of those three registers. |
|
Tim Allen | 47d4bd4d81 |
Update to v096r01 release.
byuu says: Changelog: - restructured the project and removed a whole bunch of old/dead directives from higan/GNUmakefile - huge amounts of work on hiro/cocoa (compiles but ~70% of the functionality is commented out) - fixed a masking error in my ARM CPU disassembler [Lioncash] - SFC: decided to change board cic=(411,413) back to board region=(ntsc,pal) ... the former was too obtuse If you rename Boolean (it's a problem with an include from ruby, not from hiro) and disable all the ruby drivers, you can compile an OS X binary, but obviously it's not going to do anything. It's a boring WIP, I just wanted to push out the project structure change now at the start of this WIP cycle. |
|
Tim Allen | 4e2eb23835 |
Update to v093 release.
byuu says: Changelog: - added Cocoa target: higan can now be compiled for OS X Lion [Cydrak, byuu] - SNES/accuracy profile hires color blending improvements - fixes Marvelous text [AWJ] - fixed a slight bug in SNES/SA-1 VBR support caused by a typo - added support for multi-pass shaders that can load external textures (requires OpenGL 3.2+) - added game library path (used by ananke->Import Game) to Settings->Advanced - system profiles, shaders and cheats database can be stored in "all users" shared folders now (eg /usr/share on Linux) - all configuration files are in BML format now, instead of XML (much easier to read and edit this way) - main window supports drag-and-drop of game folders (but not game files / ZIP archives) - audio buffer clears when entering a modal loop on Windows (prevents audio repetition with DirectSound driver) - a substantial amount of code clean-up (probably the biggest refactoring to date) One highly desired target for this release was to default to the optimal drivers instead of the safest drivers, but because AMD drivers don't seem to like my OpenGL 3.2 driver, I've decided to postpone that. AMD has too big a market share. Hopefully with v093 officially released, we can get some public input on what AMD doesn't like. |
|
Tim Allen | 29ea5bd599 |
Update to v092r09 release.
byuu says: This will be another massive diff from the previous version. All of higan was updated to use the new foo& bar syntax, and I also updated switch statements to be consistent as well (but not in the disassemblers, was starting to get an RSI just from what I already did.) phoenix/{windows, cocoa, qt} need to be updated to use "string foo" instead of "const string& foo", and after that, the major diffs should be finished. This archive is the first time I'm posting my copy-on-write, size+capacity nall::string class, so any feedback on that is welcome as well. |
|
Tim Allen | d9400084c2 |
Update to v092r02 release.
byuu says: Changelog: - merged AWJ's hires color blending improvements (most notably: fixes Marvelous' text) - created sfc/base/ to store base unit (expansion port device) emulation - synchronized the markup of Satellaview and Sufami Turbo cartridge slots in the board markup - fixed "Initializing ..." typo in timing settings If at all possible, I'd really like to have heavy testing of games that use hires graphics to check for any regressions. I trust AWJ's code, and all of the test ROMs I have thrown at it all appear to work great. But better safe than sorry. Same deal for any core changes, it's a lot better to catch it now than after v093 is released. |
|
Tim Allen | bbc33fe05f |
Update to higan v092r01, ananke v02r01 and purify v03r01 releases.
byuu says: higan changelog: - compiler is set to g++-4.7, subst(cc,++) rule is gone, C files compile with $(compiler) -x c - make throws an error when you specify an invalid profile or compile on an unsupported platform (instead of hanging forever) - added unverified.png to resources (causes too big of a speed hit to actually check for folder/unverified file ... so disabled for now) - fixed default browser paths for Game Boy, Sufami Turbo and BS-X Satellaview (have to delete paths.cfg to see this) - browser home button seeks to configpath()/higan/library.cfg - settings->driver is now settings->advanced, and it adds game library path setting and profile information - emulation cores now load manifest files internally, manifest.bml is not required for a game folder to be recognized by higan as such - BS-X Satellaview and Sufami Turbo slot cartridge handling moved out of sfc/chip and into sfc/slot - Video::StartFullScreen only sets fullscreen when a game is specified on the command-line purify and ananke changelog: - library output path shown in purify window - added button to change library path - squelch firmware warning windows to prevent multi-threading crash, but only via purify (they show up in higan still) |
|
Tim Allen | 032e924495 |
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) |
|
Tim Allen | 94b2538af5 |
Update to higan v091 release.
byuu says: Basically just a project rename, with s/bsnes/higan and the new icon from lowkee added in. It won't compile on Windows because I forgot to update the resource.rc file, and a path transform command isn't working on Windows. It was really just meant as a starting point, so that v091 WIPs can flow starting from .00 with the new name (it overshadows bsnes v091, so publicly speaking this "shouldn't exist" and will probably be deleted from Google Code when v092 is ready.) |