bsnes/higan/sfc/cpu/cpu.cpp

272 lines
6.2 KiB
C++
Raw Normal View History

#include <sfc/sfc.hpp>
namespace SuperFamicom {
CPU cpu;
#include "dma.cpp"
#include "memory.cpp"
#include "mmio.cpp"
#include "timing.cpp"
#include "irq.cpp"
#include "joypad.cpp"
#include "serialization.cpp"
auto CPU::interruptPending() const -> bool { return status.interruptPending; }
auto CPU::pio() const -> uint8 { return status.pio; }
auto CPU::joylatch() const -> bool { return status.joypadStrobeLatch; }
CPU::CPU() {
PPUcounter::scanline = {&CPU::scanline, this};
}
auto CPU::step(uint clocks) -> void {
smp.clock -= clocks * (uint64)smp.frequency;
ppu.clock -= clocks;
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
for(auto coprocessor : coprocessors) {
coprocessor->clock -= clocks * (uint64)coprocessor->frequency;
}
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
for(auto peripheral : peripherals) {
peripheral->clock -= clocks * (uint64)peripheral->frequency;
}
synchronizePeripherals();
}
auto CPU::synchronizeSMP() -> 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
if(smp.clock < 0) co_switch(smp.thread);
}
auto CPU::synchronizePPU() -> 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
if(ppu.clock < 0) co_switch(ppu.thread);
}
auto CPU::synchronizeCoprocessors() -> 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
for(auto coprocessor : coprocessors) {
if(coprocessor->clock < 0) co_switch(coprocessor->thread);
}
}
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
auto CPU::synchronizePeripherals() -> void {
for(auto peripheral : peripherals) {
if(peripheral->clock < 0) co_switch(peripheral->thread);
}
}
auto CPU::Enter() -> void {
while(true) scheduler.synchronize(), cpu.main();
}
auto CPU::main() -> void {
if(status.interruptPending) {
status.interruptPending = false;
if(status.nmiPending) {
status.nmiPending = false;
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
r.vector = r.e ? 0xfffa : 0xffea;
interrupt();
debugger.nmi();
} else if(status.irqPending) {
status.irqPending = false;
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
r.vector = r.e ? 0xfffe : 0xffee;
interrupt();
debugger.irq();
} else if(status.resetPending) {
status.resetPending = false;
Update to v097r32 release. byuu says: Changelog: - bsnes-accuracy emulates reset vector properly[1] - bsnes-balanced compiles once more - bsnes-performance compiles once more The balanced and performance profiles are fixed for the last time. They will be removed for v098r01. Please test this WIP as much as you can. I intend to release v098 soon. I know save states are a little unstable for the WS/WSC, but they work well enough for a release. If I can't figure it out soon, I'm going to post v098 anyway. [1] this one's been a really long time coming, but ... one of the bugs I found when I translated Tekkaman Blade was that my translation patch would crash every now and again when you hit the reset button on a real SNES, but it always worked upon power on. Turns out that while power-on initializes the stack register to $01ff, reset does things a little bit differently. Reset actually triggers the reset interrupt vector after putting the CPU into emulation mode, but it doesn't initialize the stack pointer. The net effect is that the stack high byte is set to $01, and the low byte is left as it was. And then the reset vector runs, which pushes the low 16-bits of the program counter, plus the processor flags, onto the stack frame. So you can actually tell where the game was at when the system was reset ... sort of. It's a really weird behavior to be sure. But here's the catch: say you're hacking a game, and so you hook the reset vector with jsl showMyTranslationCreditsSplashScreen, and inside this new subroutine, you then perform whatever bytes you hijacked, and then initialize the stack frame to go about your business drawing the screen, and when you're done, you return via rtl. Generally, this works fine. But if S={0100, 0101, or 0102}, then the stack will wrap due to being in emulation mode at reset. So it will write to {0100, 01ff, 01fe}. But now in your subroutine, you enable native mode. So when you return from your subroutine hijack, it reads the return address from {01ff, 0200, 0201} instead of the expected {01ff, 0100, 0101}. Thus, you get an invalid address back, and you "return" to the wrong location, and your program dies. The odds of this happening depend on how the game handles S, but generally speaking, it's a ~1:85 chance. By emulating this behavior, I'll likely expose this bug in many ROM hacks that do splash screen hooks like this, including my own Tekkaman Blade translation. And it's also very possible that there are commercial games that screw this up as well. But, it's what the real system does. So if any crashes start happening as of this WIP upon resetting the game, well ... it'd happen on real hardware, too.
2016-04-03 11:17:20 +00:00
addClocks(132);
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
r.vector = 0xfffc;
Update to v097r32 release. byuu says: Changelog: - bsnes-accuracy emulates reset vector properly[1] - bsnes-balanced compiles once more - bsnes-performance compiles once more The balanced and performance profiles are fixed for the last time. They will be removed for v098r01. Please test this WIP as much as you can. I intend to release v098 soon. I know save states are a little unstable for the WS/WSC, but they work well enough for a release. If I can't figure it out soon, I'm going to post v098 anyway. [1] this one's been a really long time coming, but ... one of the bugs I found when I translated Tekkaman Blade was that my translation patch would crash every now and again when you hit the reset button on a real SNES, but it always worked upon power on. Turns out that while power-on initializes the stack register to $01ff, reset does things a little bit differently. Reset actually triggers the reset interrupt vector after putting the CPU into emulation mode, but it doesn't initialize the stack pointer. The net effect is that the stack high byte is set to $01, and the low byte is left as it was. And then the reset vector runs, which pushes the low 16-bits of the program counter, plus the processor flags, onto the stack frame. So you can actually tell where the game was at when the system was reset ... sort of. It's a really weird behavior to be sure. But here's the catch: say you're hacking a game, and so you hook the reset vector with jsl showMyTranslationCreditsSplashScreen, and inside this new subroutine, you then perform whatever bytes you hijacked, and then initialize the stack frame to go about your business drawing the screen, and when you're done, you return via rtl. Generally, this works fine. But if S={0100, 0101, or 0102}, then the stack will wrap due to being in emulation mode at reset. So it will write to {0100, 01ff, 01fe}. But now in your subroutine, you enable native mode. So when you return from your subroutine hijack, it reads the return address from {01ff, 0200, 0201} instead of the expected {01ff, 0100, 0101}. Thus, you get an invalid address back, and you "return" to the wrong location, and your program dies. The odds of this happening depend on how the game handles S, but generally speaking, it's a ~1:85 chance. By emulating this behavior, I'll likely expose this bug in many ROM hacks that do splash screen hooks like this, including my own Tekkaman Blade translation. And it's also very possible that there are commercial games that screw this up as well. But, it's what the real system does. So if any crashes start happening as of this WIP upon resetting the game, well ... it'd happen on real hardware, too.
2016-04-03 11:17:20 +00:00
interrupt();
} else if(status.powerPending) {
status.powerPending = false;
addClocks(186);
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
r.pc.l = bus.read(0xfffc, r.mdr);
r.pc.h = bus.read(0xfffd, r.mdr);
}
}
debugger.execute(r.pc.d);
instruction();
}
auto CPU::load(Markup::Node node) -> bool {
version = max(1, min(2, node["cpu/version"].natural()));
return true;
}
auto CPU::power() -> void {
for(auto& byte : wram) byte = random(0x55);
//CPU
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
r.a = 0x0000;
r.x = 0x0000;
r.y = 0x0000;
r.s = 0x01ff;
//DMA
for(auto& channel : this->channel) {
channel.direction = 1;
channel.indirect = true;
channel.unused = true;
channel.reverseTransfer = true;
channel.fixedTransfer = true;
channel.transferMode = 7;
channel.targetAddress = 0xff;
channel.sourceAddress = 0xffff;
channel.sourceBank = 0xff;
channel.transferSize = 0xffff;
channel.indirectBank = 0xff;
channel.hdmaAddress = 0xffff;
channel.lineCounter = 0xff;
channel.unknown = 0xff;
}
Update to v097r32 release. byuu says: Changelog: - bsnes-accuracy emulates reset vector properly[1] - bsnes-balanced compiles once more - bsnes-performance compiles once more The balanced and performance profiles are fixed for the last time. They will be removed for v098r01. Please test this WIP as much as you can. I intend to release v098 soon. I know save states are a little unstable for the WS/WSC, but they work well enough for a release. If I can't figure it out soon, I'm going to post v098 anyway. [1] this one's been a really long time coming, but ... one of the bugs I found when I translated Tekkaman Blade was that my translation patch would crash every now and again when you hit the reset button on a real SNES, but it always worked upon power on. Turns out that while power-on initializes the stack register to $01ff, reset does things a little bit differently. Reset actually triggers the reset interrupt vector after putting the CPU into emulation mode, but it doesn't initialize the stack pointer. The net effect is that the stack high byte is set to $01, and the low byte is left as it was. And then the reset vector runs, which pushes the low 16-bits of the program counter, plus the processor flags, onto the stack frame. So you can actually tell where the game was at when the system was reset ... sort of. It's a really weird behavior to be sure. But here's the catch: say you're hacking a game, and so you hook the reset vector with jsl showMyTranslationCreditsSplashScreen, and inside this new subroutine, you then perform whatever bytes you hijacked, and then initialize the stack frame to go about your business drawing the screen, and when you're done, you return via rtl. Generally, this works fine. But if S={0100, 0101, or 0102}, then the stack will wrap due to being in emulation mode at reset. So it will write to {0100, 01ff, 01fe}. But now in your subroutine, you enable native mode. So when you return from your subroutine hijack, it reads the return address from {01ff, 0200, 0201} instead of the expected {01ff, 0100, 0101}. Thus, you get an invalid address back, and you "return" to the wrong location, and your program dies. The odds of this happening depend on how the game handles S, but generally speaking, it's a ~1:85 chance. By emulating this behavior, I'll likely expose this bug in many ROM hacks that do splash screen hooks like this, including my own Tekkaman Blade translation. And it's also very possible that there are commercial games that screw this up as well. But, it's what the real system does. So if any crashes start happening as of this WIP upon resetting the game, well ... it'd happen on real hardware, too.
2016-04-03 11:17:20 +00:00
status.powerPending = true;
status.interruptPending = true;
}
auto CPU::reset() -> void {
create(Enter, system.cpuFrequency());
coprocessors.reset();
PPUcounter::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
function<auto (uint24, uint8) -> uint8> reader;
function<auto (uint24, uint8) -> void> writer;
reader = {&CPU::readAPU, this};
writer = {&CPU::writeAPU, this};
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.map(reader, writer, "00-3f,80-bf:2140-217f");
reader = {&CPU::readCPU, this};
writer = {&CPU::writeCPU, this};
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.map(reader, writer, "00-3f,80-bf:2180-2183,4016-4017,4200-421f");
reader = {&CPU::readDMA, this};
writer = {&CPU::writeDMA, this};
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.map(reader, writer, "00-3f,80-bf:4300-437f");
reader = [](uint24 addr, uint8) -> uint8 { return cpu.wram[addr]; };
writer = [](uint24 addr, uint8 data) -> void { cpu.wram[addr] = data; };
bus.map(reader, writer, "00-3f,80-bf:0000-1fff", 0x2000);
bus.map(reader, writer, "7e-7f:0000-ffff", 0x20000);
//CPU
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
r.pc = 0x000000;
r.x.h = 0x00;
r.y.h = 0x00;
r.s.h = 0x01;
r.d = 0x0000;
r.db = 0x00;
r.p = 0x34;
r.e = 1;
r.mdr = 0x00;
r.wai = false;
r.vector = 0xfffc; //reset vector address
//$2140-217f
for(auto& port : status.port) port = 0x00;
//$2181-$2183
status.wramAddress = 0x000000;
//$4016-$4017
status.joypadStrobeLatch = 0;
status.joypad1_bits = ~0;
status.joypad2_bits = ~0;
//$4200
status.nmiEnabled = false;
status.hirqEnabled = false;
status.virqEnabled = false;
status.autoJoypadPoll = false;
//$4201
status.pio = 0xff;
//$4202-$4203
status.wrmpya = 0xff;
status.wrmpyb = 0xff;
//$4204-$4206
status.wrdiva = 0xffff;
status.wrdivb = 0xff;
//$4207-$420a
status.hirqPos = 0x01ff;
status.virqPos = 0x01ff;
//$420d
status.romSpeed = 8;
//$4214-$4217
status.rddiv = 0x0000;
status.rdmpy = 0x0000;
//$4218-$421f
status.joy1 = 0x0000;
status.joy2 = 0x0000;
status.joy3 = 0x0000;
status.joy4 = 0x0000;
//ALU
alu.mpyctr = 0;
alu.divctr = 0;
alu.shift = 0;
//DMA
for(auto& channel : this->channel) {
channel.dmaEnabled = false;
channel.hdmaEnabled = false;
channel.hdmaCompleted = false;
channel.hdmaDoTransfer = false;
}
pipe.valid = false;
pipe.addr = 0;
pipe.data = 0;
//Timing
status.clockCount = 0;
status.lineClocks = lineclocks();
status.irqLock = false;
status.dramRefreshPosition = (version == 1 ? 530 : 538);
status.dramRefreshed = false;
status.hdmaInitPosition = (version == 1 ? 12 + 8 - dmaCounter() : 12 + dmaCounter());
status.hdmaInitTriggered = false;
status.hdmaPosition = 1104;
status.hdmaTriggered = false;
status.nmiValid = false;
status.nmiLine = false;
status.nmiTransition = false;
status.nmiPending = false;
status.nmiHold = false;
status.irqValid = false;
status.irqLine = false;
status.irqTransition = false;
status.irqPending = false;
status.irqHold = false;
status.resetPending = !status.powerPending;
status.interruptPending = true;
status.dmaActive = false;
status.dmaCounter = 0;
status.dmaClocks = 0;
status.dmaPending = false;
status.hdmaPending = false;
status.hdmaMode = 0;
status.autoJoypadActive = false;
status.autoJoypadLatch = false;
status.autoJoypadCounter = 0;
status.autoJoypadClock = 0;
}
}