2010-08-11 00:40:59 +00:00
|
|
|
#ifdef CPU_CPP
|
|
|
|
|
|
|
|
void CPU::queue_event(unsigned id) {
|
|
|
|
switch(id) {
|
|
|
|
case QueueEvent::DramRefresh: return add_clocks(40);
|
|
|
|
case QueueEvent::HdmaRun: return hdma_run();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void CPU::last_cycle() {
|
2010-08-12 00:39:41 +00:00
|
|
|
if(status.irq_lock) {
|
|
|
|
status.irq_lock = false;
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2010-08-11 00:40:59 +00:00
|
|
|
if(status.nmi_transition) {
|
|
|
|
regs.wai = false;
|
|
|
|
status.nmi_transition = false;
|
|
|
|
status.nmi_pending = true;
|
|
|
|
}
|
|
|
|
|
2010-08-12 00:39:41 +00:00
|
|
|
if(status.irq_transition || regs.irq) {
|
2010-08-11 00:40:59 +00:00
|
|
|
regs.wai = false;
|
|
|
|
status.irq_transition = false;
|
|
|
|
status.irq_pending = !regs.p.i;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void CPU::add_clocks(unsigned clocks) {
|
2010-08-12 00:39:41 +00:00
|
|
|
if(status.hirq_enabled) {
|
|
|
|
if(status.virq_enabled) {
|
|
|
|
unsigned cpu_time = vcounter() * 1364 + hcounter();
|
|
|
|
unsigned irq_time = status.vtime * 1364 + status.htime * 4;
|
Updated to v067r23 release.
byuu says:
Added missing $4200 IRQ lock, which fixes Chou Aniki on the fast CPU
core, so slower PCs can get their brotherly love on.
Added range-based controller IOBit latching to the fast CPU core, which
enables Super Scope and Justifier support. Uses the priority queue as
well, so there is zero speed-hit. Given the way range-testing works, the
trigger point may vary by 1-2 pixels when firing at the same spot. Not
really a big deal when it avoids a massive speed penalty.
Fixed PAL and interlace-mode HVIRQs at V=0,H<2 on the fast CPU core.
Added the dot-renderer's sprite list update-on-OAM-write functionality
to the scanline-based PPU renderer. Unfortunately it looks like all the
speed gain was already taken from the global dirty flag I was using
before, but this certainly won't hurt speed any, so whatever.
Added #ifdef to stop CoInitialize(0) on non-Windows ports.
Added #ifdefs to stop gradient fade on Windows port. Not going to fuck
over the Linux port aesthetic because of Qt bug #47,326,927. If there's
a way to tell what Qt theme is being used, I can leave it enabled for
XP/Vista themes.
Moved HDMA trigger from 1104 to 1112, and reduced channel overhead from
24 to 16, to better simulate one-cycle DMA->CPU sync.
Code clarity: I've re-added my varint.hpp classes, and am actively using
them in the accuracy cores. So far, I haven't done anything that would
detriment speed, but it is certainly cool. The APU ports exposed by the
CPU and SMP now take uint2 address arguments, the CPU WRAM address
register is a uint17, and the IRQ H/VTIME values are uint10. This
basically allows the source to clearly convey the data sizes, and
eliminates the need to manually mask values when writing to registers or
reading from memory. I'm going to be doing this everywhere, and it will
have a speed impact eventually, because the automation means we can't
skip masks when we know the data is already masked off.
Source: archive contains the launcher code, so that I can look into why
it's crashing on XP tomorrow.
It doesn't look like Circuit USA's flags are going to work too well with
this new CPU core. Still not sure what the hell Robocop vs The
Terminator is doing, I'll read through the mega SNES thread for clues
tomorrow. Speedy Gonzales is definitely broken, as modifying the MDR was
breaking things with my current core. Probably because the new CPU core
doesn't wait for a cycle edge to trigger.
I was thinking that perhaps we could keep some form of cheat codes list
to work as game-specific hacks for the performance core. Keeps the hacks
out of the emulator, but could allow the remaining bugs to be worked
around for people who have no choice but to use the performance core.
2010-08-16 09:42:20 +00:00
|
|
|
unsigned framelines = (system.region() == System::Region::NTSC ? 262 : 312) + field();
|
|
|
|
if(cpu_time > irq_time) irq_time += framelines * 1364;
|
2010-08-12 00:39:41 +00:00
|
|
|
bool irq_valid = status.irq_valid;
|
|
|
|
status.irq_valid = cpu_time <= irq_time && cpu_time + clocks > irq_time;
|
|
|
|
if(!irq_valid && status.irq_valid) status.irq_line = true;
|
|
|
|
} else {
|
|
|
|
unsigned irq_time = status.htime * 4;
|
|
|
|
if(hcounter() > irq_time) irq_time += 1364;
|
|
|
|
bool irq_valid = status.irq_valid;
|
|
|
|
status.irq_valid = hcounter() <= irq_time && hcounter() + clocks > irq_time;
|
|
|
|
if(!irq_valid && status.irq_valid) status.irq_line = true;
|
2010-08-11 00:40:59 +00:00
|
|
|
}
|
2010-08-12 00:39:41 +00:00
|
|
|
if(status.irq_line) status.irq_transition = true;
|
|
|
|
} else if(status.virq_enabled) {
|
2010-08-11 00:40:59 +00:00
|
|
|
bool irq_valid = status.irq_valid;
|
2010-08-12 00:39:41 +00:00
|
|
|
status.irq_valid = vcounter() == status.vtime;
|
|
|
|
if(!irq_valid && status.irq_valid) status.irq_line = true;
|
|
|
|
if(status.irq_line) status.irq_transition = true;
|
Updated to v067r23 release.
byuu says:
Fixed bsnes launcher on Windows XP
Fixed Windows bsnes launcher internationalization support (emulator can
be in a folder with spaces and Japanese characters, and you can drag
a Japanese file name onto the launcher, and it will load it properly)
Moved fast CPU to use a switch table for MMIO, unfortunately for no
speed gain
Bus::read/write take uint24 parameters for address, luckily no speed
penalty
MMIOAccess gained a handle() function, and hid the mmio[] table. Makes
hooking it cleaner
Added malloc.h header to nall/function.hpp to fix a ridiculous GCC 4.5.0
error
Fixed a fairly large bug in the fast CPU IRQ handler, which fixes
Robocop et al
Forgot to bump revision to .24 in the compiled binaries, too lazy to
recompile or hex edit to change them
Unfortunately, in order to add nice battery usage, I have to add the
sleep calls to the video and audio wait loops. But they don't know
anything about the GUI and its settings, nor do I really want to make
them know about this setting. I do not want to force allow it. Even with
the media timer trick, Sleep(0) makes Vsync+Async fail a lot more
frequently than never sleeping at all. I would rather laptop users
suffer 100% utilization of a single core than for all users to not be
able to get good audio+video sync. Not sure what to do about that, so
I'll probably just remove the battery usage comment from performance
mode for now.
2010-08-18 05:33:29 +00:00
|
|
|
} else {
|
|
|
|
status.irq_valid = false;
|
2010-08-11 00:40:59 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
tick(clocks);
|
2010-08-12 00:39:41 +00:00
|
|
|
queue.tick(clocks);
|
|
|
|
step(clocks);
|
2010-08-11 00:40:59 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
void CPU::scanline() {
|
|
|
|
synchronize_smp();
|
|
|
|
synchronize_ppu();
|
2011-06-26 12:51:37 +00:00
|
|
|
synchronize_coprocessors();
|
2010-08-11 00:40:59 +00:00
|
|
|
system.scanline();
|
|
|
|
|
|
|
|
if(vcounter() == 0) hdma_init();
|
|
|
|
|
|
|
|
queue.enqueue(534, QueueEvent::DramRefresh);
|
|
|
|
|
|
|
|
if(vcounter() <= (ppu.overscan() == false ? 224 : 239)) {
|
Updated to v067r23 release.
byuu says:
Added missing $4200 IRQ lock, which fixes Chou Aniki on the fast CPU
core, so slower PCs can get their brotherly love on.
Added range-based controller IOBit latching to the fast CPU core, which
enables Super Scope and Justifier support. Uses the priority queue as
well, so there is zero speed-hit. Given the way range-testing works, the
trigger point may vary by 1-2 pixels when firing at the same spot. Not
really a big deal when it avoids a massive speed penalty.
Fixed PAL and interlace-mode HVIRQs at V=0,H<2 on the fast CPU core.
Added the dot-renderer's sprite list update-on-OAM-write functionality
to the scanline-based PPU renderer. Unfortunately it looks like all the
speed gain was already taken from the global dirty flag I was using
before, but this certainly won't hurt speed any, so whatever.
Added #ifdef to stop CoInitialize(0) on non-Windows ports.
Added #ifdefs to stop gradient fade on Windows port. Not going to fuck
over the Linux port aesthetic because of Qt bug #47,326,927. If there's
a way to tell what Qt theme is being used, I can leave it enabled for
XP/Vista themes.
Moved HDMA trigger from 1104 to 1112, and reduced channel overhead from
24 to 16, to better simulate one-cycle DMA->CPU sync.
Code clarity: I've re-added my varint.hpp classes, and am actively using
them in the accuracy cores. So far, I haven't done anything that would
detriment speed, but it is certainly cool. The APU ports exposed by the
CPU and SMP now take uint2 address arguments, the CPU WRAM address
register is a uint17, and the IRQ H/VTIME values are uint10. This
basically allows the source to clearly convey the data sizes, and
eliminates the need to manually mask values when writing to registers or
reading from memory. I'm going to be doing this everywhere, and it will
have a speed impact eventually, because the automation means we can't
skip masks when we know the data is already masked off.
Source: archive contains the launcher code, so that I can look into why
it's crashing on XP tomorrow.
It doesn't look like Circuit USA's flags are going to work too well with
this new CPU core. Still not sure what the hell Robocop vs The
Terminator is doing, I'll read through the mega SNES thread for clues
tomorrow. Speedy Gonzales is definitely broken, as modifying the MDR was
breaking things with my current core. Probably because the new CPU core
doesn't wait for a cycle edge to trigger.
I was thinking that perhaps we could keep some form of cheat codes list
to work as game-specific hacks for the performance core. Keeps the hacks
out of the emulator, but could allow the remaining bugs to be worked
around for people who have no choice but to use the performance core.
2010-08-16 09:42:20 +00:00
|
|
|
queue.enqueue(1104 + 8, QueueEvent::HdmaRun);
|
|
|
|
}
|
|
|
|
|
2010-08-11 00:40:59 +00:00
|
|
|
bool nmi_valid = status.nmi_valid;
|
|
|
|
status.nmi_valid = vcounter() >= (ppu.overscan() == false ? 225 : 240);
|
|
|
|
if(!nmi_valid && status.nmi_valid) {
|
|
|
|
status.nmi_line = true;
|
|
|
|
if(status.nmi_enabled) status.nmi_transition = true;
|
|
|
|
} else if(nmi_valid && !status.nmi_valid) {
|
|
|
|
status.nmi_line = false;
|
|
|
|
}
|
|
|
|
|
|
|
|
if(status.auto_joypad_poll_enabled && vcounter() == (ppu.overscan() == false ? 227 : 242)) {
|
|
|
|
run_auto_joypad_poll();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void CPU::run_auto_joypad_poll() {
|
2011-06-26 12:51:37 +00:00
|
|
|
input.port1->latch(1);
|
|
|
|
input.port2->latch(1);
|
|
|
|
input.port1->latch(0);
|
|
|
|
input.port2->latch(0);
|
|
|
|
|
2010-08-11 00:40:59 +00:00
|
|
|
uint16 joy1 = 0, joy2 = 0, joy3 = 0, joy4 = 0;
|
|
|
|
for(unsigned i = 0; i < 16; i++) {
|
2011-06-26 12:51:37 +00:00
|
|
|
uint8 port0 = input.port1->data();
|
|
|
|
uint8 port1 = input.port2->data();
|
2010-08-11 00:40:59 +00:00
|
|
|
|
|
|
|
joy1 |= (port0 & 1) ? (0x8000 >> i) : 0;
|
|
|
|
joy2 |= (port1 & 1) ? (0x8000 >> i) : 0;
|
|
|
|
joy3 |= (port0 & 2) ? (0x8000 >> i) : 0;
|
|
|
|
joy4 |= (port1 & 2) ? (0x8000 >> i) : 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
status.joy1l = joy1;
|
|
|
|
status.joy1h = joy1 >> 8;
|
|
|
|
|
|
|
|
status.joy2l = joy2;
|
|
|
|
status.joy2h = joy2 >> 8;
|
|
|
|
|
|
|
|
status.joy3l = joy3;
|
|
|
|
status.joy3h = joy3 >> 8;
|
|
|
|
|
|
|
|
status.joy4l = joy4;
|
|
|
|
status.joy4h = joy4 >> 8;
|
|
|
|
}
|
|
|
|
|
|
|
|
#endif
|