mirror of https://github.com/bsnes-emu/bsnes.git
325 lines
6.0 KiB
C++
325 lines
6.0 KiB
C++
#include <sfc/sfc.hpp>
|
|
|
|
namespace SuperFamicom {
|
|
|
|
SA1 sa1;
|
|
|
|
#include "serialization.cpp"
|
|
#include "bus/bus.cpp"
|
|
#include "dma/dma.cpp"
|
|
#include "memory/memory.cpp"
|
|
#include "mmio/mmio.cpp"
|
|
|
|
auto SA1::Enter() -> void {
|
|
while(true) scheduler.synchronize(), sa1.main();
|
|
}
|
|
|
|
auto SA1::main() -> void {
|
|
if(mmio.sa1_rdyb || mmio.sa1_resb) {
|
|
//SA-1 co-processor is asleep
|
|
tick();
|
|
synchronizeCPU();
|
|
return;
|
|
}
|
|
|
|
if(status.interrupt_pending) {
|
|
status.interrupt_pending = false;
|
|
op_irq();
|
|
return;
|
|
}
|
|
|
|
op_exec();
|
|
}
|
|
|
|
auto SA1::op_irq() -> void {
|
|
op_read(regs.pc.d);
|
|
op_io();
|
|
if(!regs.e) op_writestack(regs.pc.b);
|
|
op_writestack(regs.pc.h);
|
|
op_writestack(regs.pc.l);
|
|
op_writestack(regs.e ? (regs.p & ~0x10) : regs.p);
|
|
regs.pc.w = regs.vector;
|
|
regs.pc.b = 0x00;
|
|
regs.p.i = 1;
|
|
regs.p.d = 0;
|
|
}
|
|
|
|
auto SA1::last_cycle() -> void {
|
|
if(mmio.sa1_nmi && !mmio.sa1_nmicl) {
|
|
status.interrupt_pending = true;
|
|
regs.vector = mmio.cnv;
|
|
mmio.sa1_nmifl = true;
|
|
mmio.sa1_nmicl = 1;
|
|
regs.wai = false;
|
|
} else if(!regs.p.i) {
|
|
if(mmio.timer_irqen && !mmio.timer_irqcl) {
|
|
status.interrupt_pending = true;
|
|
regs.vector = mmio.civ;
|
|
mmio.timer_irqfl = true;
|
|
regs.wai = false;
|
|
} else if(mmio.dma_irqen && !mmio.dma_irqcl) {
|
|
status.interrupt_pending = true;
|
|
regs.vector = mmio.civ;
|
|
mmio.dma_irqfl = true;
|
|
regs.wai = false;
|
|
} else if(mmio.sa1_irq && !mmio.sa1_irqcl) {
|
|
status.interrupt_pending = true;
|
|
regs.vector = mmio.civ;
|
|
mmio.sa1_irqfl = true;
|
|
regs.wai = false;
|
|
}
|
|
}
|
|
}
|
|
|
|
auto SA1::interrupt_pending() -> bool {
|
|
return status.interrupt_pending;
|
|
}
|
|
|
|
auto SA1::tick() -> void {
|
|
step(2);
|
|
if(++status.tick_counter == 0) synchronizeCPU();
|
|
|
|
//adjust counters:
|
|
//note that internally, status counters are in clocks;
|
|
//whereas MMIO register counters are in dots (4 clocks = 1 dot)
|
|
if(mmio.hvselb == 0) {
|
|
//HV timer
|
|
status.hcounter += 2;
|
|
if(status.hcounter >= 1364) {
|
|
status.hcounter = 0;
|
|
if(++status.vcounter >= status.scanlines) status.vcounter = 0;
|
|
}
|
|
} else {
|
|
//linear timer
|
|
status.hcounter += 2;
|
|
status.vcounter += (status.hcounter >> 11);
|
|
status.hcounter &= 0x07ff;
|
|
status.vcounter &= 0x01ff;
|
|
}
|
|
|
|
//test counters for timer IRQ
|
|
switch((mmio.ven << 1) + (mmio.hen << 0)) {
|
|
case 0: break;
|
|
case 1: if(status.hcounter == (mmio.hcnt << 2)) trigger_irq(); break;
|
|
case 2: if(status.vcounter == mmio.vcnt && status.hcounter == 0) trigger_irq(); break;
|
|
case 3: if(status.vcounter == mmio.vcnt && status.hcounter == (mmio.hcnt << 2)) trigger_irq(); break;
|
|
}
|
|
}
|
|
|
|
auto SA1::trigger_irq() -> void {
|
|
mmio.timer_irqfl = true;
|
|
if(mmio.timer_irqen) mmio.timer_irqcl = 0;
|
|
}
|
|
|
|
auto SA1::init() -> void {
|
|
}
|
|
|
|
auto SA1::load() -> void {
|
|
}
|
|
|
|
auto SA1::unload() -> void {
|
|
rom.reset();
|
|
iram.reset();
|
|
bwram.reset();
|
|
}
|
|
|
|
auto SA1::power() -> void {
|
|
regs.a = regs.x = regs.y = 0x0000;
|
|
regs.s = 0x01ff;
|
|
}
|
|
|
|
auto SA1::reset() -> void {
|
|
create(SA1::Enter, system.cpuFrequency());
|
|
|
|
cpubwram.dma = false;
|
|
for(auto addr : range(iram.size())) {
|
|
iram.write(addr, 0x00);
|
|
}
|
|
|
|
regs.pc.d = 0x000000;
|
|
regs.x.h = 0x00;
|
|
regs.y.h = 0x00;
|
|
regs.s.h = 0x01;
|
|
regs.d = 0x0000;
|
|
regs.db = 0x00;
|
|
regs.p = 0x34;
|
|
regs.e = 1;
|
|
regs.mdr = 0x00;
|
|
regs.wai = false;
|
|
regs.vector = 0x0000;
|
|
|
|
status.tick_counter = 0;
|
|
|
|
status.interrupt_pending = false;
|
|
|
|
status.scanlines = (system.region() == System::Region::NTSC ? 262 : 312);
|
|
status.vcounter = 0;
|
|
status.hcounter = 0;
|
|
|
|
dma.line = 0;
|
|
|
|
//$2200 CCNT
|
|
mmio.sa1_irq = false;
|
|
mmio.sa1_rdyb = false;
|
|
mmio.sa1_resb = true;
|
|
mmio.sa1_nmi = false;
|
|
mmio.smeg = 0;
|
|
|
|
//$2201 SIE
|
|
mmio.cpu_irqen = false;
|
|
mmio.chdma_irqen = false;
|
|
|
|
//$2202 SIC
|
|
mmio.cpu_irqcl = false;
|
|
mmio.chdma_irqcl = false;
|
|
|
|
//$2203,$2204 CRV
|
|
mmio.crv = 0x0000;
|
|
|
|
//$2205,$2206 CNV
|
|
mmio.cnv = 0x0000;
|
|
|
|
//$2207,$2208 CIV
|
|
mmio.civ = 0x0000;
|
|
|
|
//$2209 SCNT
|
|
mmio.cpu_irq = false;
|
|
mmio.cpu_ivsw = false;
|
|
mmio.cpu_nvsw = false;
|
|
mmio.cmeg = 0;
|
|
|
|
//$220a CIE
|
|
mmio.sa1_irqen = false;
|
|
mmio.timer_irqen = false;
|
|
mmio.dma_irqen = false;
|
|
mmio.sa1_nmien = false;
|
|
|
|
//$220b CIC
|
|
mmio.sa1_irqcl = false;
|
|
mmio.timer_irqcl = false;
|
|
mmio.dma_irqcl = false;
|
|
mmio.sa1_nmicl = false;
|
|
|
|
//$220c,$220d SNV
|
|
mmio.snv = 0x0000;
|
|
|
|
//$220e,$220f SIV
|
|
mmio.siv = 0x0000;
|
|
|
|
//$2210
|
|
mmio.hvselb = false;
|
|
mmio.ven = false;
|
|
mmio.hen = false;
|
|
|
|
//$2212,$2213 HCNT
|
|
mmio.hcnt = 0x0000;
|
|
|
|
//$2214,$2215 VCNT
|
|
mmio.vcnt = 0x0000;
|
|
|
|
//$2220-2223 CXB, DXB, EXB, FXB
|
|
mmio.cbmode = 0;
|
|
mmio.dbmode = 0;
|
|
mmio.ebmode = 0;
|
|
mmio.fbmode = 0;
|
|
|
|
mmio.cb = 0x00;
|
|
mmio.db = 0x01;
|
|
mmio.eb = 0x02;
|
|
mmio.fb = 0x03;
|
|
|
|
//$2224 BMAPS
|
|
mmio.sbm = 0x00;
|
|
|
|
//$2225 BMAP
|
|
mmio.sw46 = false;
|
|
mmio.cbm = 0x00;
|
|
|
|
//$2226 SWBE
|
|
mmio.swen = false;
|
|
|
|
//$2227 CWBE
|
|
mmio.cwen = false;
|
|
|
|
//$2228 BWPA
|
|
mmio.bwp = 0x0f;
|
|
|
|
//$2229 SIWP
|
|
mmio.siwp = 0x00;
|
|
|
|
//$222a CIWP
|
|
mmio.ciwp = 0x00;
|
|
|
|
//$2230 DCNT
|
|
mmio.dmaen = false;
|
|
mmio.dprio = false;
|
|
mmio.cden = false;
|
|
mmio.cdsel = false;
|
|
mmio.dd = 0;
|
|
mmio.sd = 0;
|
|
|
|
//$2231 CDMA
|
|
mmio.chdend = false;
|
|
mmio.dmasize = 0;
|
|
mmio.dmacb = 0;
|
|
|
|
//$2232-$2234 SDA
|
|
mmio.dsa = 0x000000;
|
|
|
|
//$2235-$2237 DDA
|
|
mmio.dda = 0x000000;
|
|
|
|
//$2238,$2239 DTC
|
|
mmio.dtc = 0x0000;
|
|
|
|
//$223f BBF
|
|
mmio.bbf = 0;
|
|
|
|
//$2240-$224f BRF
|
|
for(unsigned i = 0; i < 16; i++) {
|
|
mmio.brf[i] = 0x00;
|
|
}
|
|
|
|
//$2250 MCNT
|
|
mmio.acm = 0;
|
|
mmio.md = 0;
|
|
|
|
//$2251,$2252 MA
|
|
mmio.ma = 0x0000;
|
|
|
|
//$2253,$2254 MB
|
|
mmio.mb = 0x0000;
|
|
|
|
//$2258 VBD
|
|
mmio.hl = false;
|
|
mmio.vb = 16;
|
|
|
|
//$2259-$225b
|
|
mmio.va = 0x000000;
|
|
mmio.vbit = 0;
|
|
|
|
//$2300 SFR
|
|
mmio.cpu_irqfl = false;
|
|
mmio.chdma_irqfl = false;
|
|
|
|
//$2301 CFR
|
|
mmio.sa1_irqfl = false;
|
|
mmio.timer_irqfl = false;
|
|
mmio.dma_irqfl = false;
|
|
mmio.sa1_nmifl = false;
|
|
|
|
//$2302,$2303 HCR
|
|
mmio.hcr = 0x0000;
|
|
|
|
//$2304,$2305 VCR
|
|
mmio.vcr = 0x0000;
|
|
|
|
//$2306-$230a MR
|
|
mmio.mr = 0;
|
|
|
|
//$230b
|
|
mmio.overflow = false;
|
|
}
|
|
|
|
}
|