Path: blob/master/libsnes/bsnes/snes/chip/sa1/mmio/mmio.cpp
2 views
#ifdef SA1_CPP12//(CCNT) SA-1 control3void SA1::mmio_w2200(uint8 data) {4if(mmio.sa1_resb && !(data & 0x80)) {5//reset SA-1 CPU6regs.pc.w = mmio.crv;7regs.pc.b = 0x00;8}910mmio.sa1_irq = (data & 0x80);11mmio.sa1_rdyb = (data & 0x40);12mmio.sa1_resb = (data & 0x20);13mmio.sa1_nmi = (data & 0x10);14mmio.smeg = (data & 0x0f);1516if(mmio.sa1_irq) {17mmio.sa1_irqfl = true;18if(mmio.sa1_irqen) mmio.sa1_irqcl = 0;19}2021if(mmio.sa1_nmi) {22mmio.sa1_nmifl = true;23if(mmio.sa1_nmien) mmio.sa1_nmicl = 0;24}25}2627//(SIE) S-CPU interrupt enable28void SA1::mmio_w2201(uint8 data) {29if(!mmio.cpu_irqen && (data & 0x80)) {30if(mmio.cpu_irqfl) {31mmio.cpu_irqcl = 0;32cpu.regs.irq = 1;33}34}3536if(!mmio.chdma_irqen && (data & 0x20)) {37if(mmio.chdma_irqfl) {38mmio.chdma_irqcl = 0;39cpu.regs.irq = 1;40}41}4243mmio.cpu_irqen = (data & 0x80);44mmio.chdma_irqen = (data & 0x20);45}4647//(SIC) S-CPU interrupt clear48void SA1::mmio_w2202(uint8 data) {49mmio.cpu_irqcl = (data & 0x80);50mmio.chdma_irqcl = (data & 0x20);5152if(mmio.cpu_irqcl ) mmio.cpu_irqfl = false;53if(mmio.chdma_irqcl) mmio.chdma_irqfl = false;5455if(!mmio.cpu_irqfl && !mmio.chdma_irqfl) cpu.regs.irq = 0;56}5758//(CRV) SA-1 reset vector59void SA1::mmio_w2203(uint8 data) { mmio.crv = (mmio.crv & 0xff00) | data; }60void SA1::mmio_w2204(uint8 data) { mmio.crv = (data << 8) | (mmio.crv & 0xff); }6162//(CNV) SA-1 NMI vector63void SA1::mmio_w2205(uint8 data) { mmio.cnv = (mmio.cnv & 0xff00) | data; }64void SA1::mmio_w2206(uint8 data) { mmio.cnv = (data << 8) | (mmio.cnv & 0xff); }6566//(CIV) SA-1 IRQ vector67void SA1::mmio_w2207(uint8 data) { mmio.civ = (mmio.civ & 0xff00) | data; }68void SA1::mmio_w2208(uint8 data) { mmio.civ = (data << 8) | (mmio.civ & 0xff); }6970//(SCNT) S-CPU control71void SA1::mmio_w2209(uint8 data) {72mmio.cpu_irq = (data & 0x80);73mmio.cpu_ivsw = (data & 0x40);74mmio.cpu_nvsw = (data & 0x10);75mmio.cmeg = (data & 0x0f);7677if(mmio.cpu_irq) {78mmio.cpu_irqfl = true;79if(mmio.cpu_irqen) {80mmio.cpu_irqcl = 0;81cpu.regs.irq = 1;82}83}84}8586//(CIE) SA-1 interrupt enable87void SA1::mmio_w220a(uint8 data) {88if(!mmio.sa1_irqen && (data & 0x80) && mmio.sa1_irqfl ) mmio.sa1_irqcl = 0;89if(!mmio.timer_irqen && (data & 0x40) && mmio.timer_irqfl) mmio.timer_irqcl = 0;90if(!mmio.dma_irqen && (data & 0x20) && mmio.dma_irqfl ) mmio.dma_irqcl = 0;91if(!mmio.sa1_nmien && (data & 0x10) && mmio.sa1_nmifl ) mmio.sa1_nmicl = 0;9293mmio.sa1_irqen = (data & 0x80);94mmio.timer_irqen = (data & 0x40);95mmio.dma_irqen = (data & 0x20);96mmio.sa1_nmien = (data & 0x10);97}9899//(CIC) SA-1 interrupt clear100void SA1::mmio_w220b(uint8 data) {101mmio.sa1_irqcl = (data & 0x80);102mmio.timer_irqcl = (data & 0x40);103mmio.dma_irqcl = (data & 0x20);104mmio.sa1_nmicl = (data & 0x10);105106if(mmio.sa1_irqcl) mmio.sa1_irqfl = false;107if(mmio.timer_irqcl) mmio.timer_irqfl = false;108if(mmio.dma_irqcl) mmio.dma_irqfl = false;109if(mmio.sa1_nmicl) mmio.sa1_nmifl = false;110}111112//(SNV) S-CPU NMI vector113void SA1::mmio_w220c(uint8 data) { mmio.snv = (mmio.snv & 0xff00) | data; }114void SA1::mmio_w220d(uint8 data) { mmio.snv = (data << 8) | (mmio.snv & 0xff); }115116//(SIV) S-CPU IRQ vector117void SA1::mmio_w220e(uint8 data) { mmio.siv = (mmio.siv & 0xff00) | data; }118void SA1::mmio_w220f(uint8 data) { mmio.siv = (data << 8) | (mmio.siv & 0xff); }119120//(TMC) H/V timer control121void SA1::mmio_w2210(uint8 data) {122mmio.hvselb = (data & 0x80);123mmio.ven = (data & 0x02);124mmio.hen = (data & 0x01);125}126127//(CTR) SA-1 timer restart128void SA1::mmio_w2211(uint8 data) {129status.vcounter = 0;130status.hcounter = 0;131}132133//(HCNT) H-count134void SA1::mmio_w2212(uint8 data) { mmio.hcnt = (mmio.hcnt & 0xff00) | (data << 0); }135void SA1::mmio_w2213(uint8 data) { mmio.hcnt = (mmio.hcnt & 0x00ff) | (data << 8); }136137//(VCNT) V-count138void SA1::mmio_w2214(uint8 data) { mmio.vcnt = (mmio.vcnt & 0xff00) | (data << 0); }139void SA1::mmio_w2215(uint8 data) { mmio.vcnt = (mmio.vcnt & 0x00ff) | (data << 8); }140141//(CXB) Super MMC bank C142void SA1::mmio_w2220(uint8 data) {143mmio.cbmode = (data & 0x80);144mmio.cb = (data & 0x07);145}146147//(DXB) Super MMC bank D148void SA1::mmio_w2221(uint8 data) {149mmio.dbmode = (data & 0x80);150mmio.db = (data & 0x07);151}152153//(EXB) Super MMC bank E154void SA1::mmio_w2222(uint8 data) {155mmio.ebmode = (data & 0x80);156mmio.eb = (data & 0x07);157}158159//(FXB) Super MMC bank F160void SA1::mmio_w2223(uint8 data) {161mmio.fbmode = (data & 0x80);162mmio.fb = (data & 0x07);163}164165//(BMAPS) S-CPU BW-RAM address mapping166void SA1::mmio_w2224(uint8 data) {167mmio.sbm = (data & 0x1f);168}169170//(BMAP) SA-1 BW-RAM address mapping171void SA1::mmio_w2225(uint8 data) {172mmio.sw46 = (data & 0x80);173mmio.cbm = (data & 0x7f);174}175176//(SWBE) S-CPU BW-RAM write enable177void SA1::mmio_w2226(uint8 data) {178mmio.swen = (data & 0x80);179}180181//(CWBE) SA-1 BW-RAM write enable182void SA1::mmio_w2227(uint8 data) {183mmio.cwen = (data & 0x80);184}185186//(BWPA) BW-RAM write-protected area187void SA1::mmio_w2228(uint8 data) {188mmio.bwp = (data & 0x0f);189}190191//(SIWP) S-CPU I-RAM write protection192void SA1::mmio_w2229(uint8 data) {193mmio.siwp = data;194}195196//(CIWP) SA-1 I-RAM write protection197void SA1::mmio_w222a(uint8 data) {198mmio.ciwp = data;199}200201//(DCNT) DMA control202void SA1::mmio_w2230(uint8 data) {203mmio.dmaen = (data & 0x80);204mmio.dprio = (data & 0x40);205mmio.cden = (data & 0x20);206mmio.cdsel = (data & 0x10);207mmio.dd = (data & 0x04);208mmio.sd = (data & 0x03);209210if(mmio.dmaen == 0) dma.line = 0;211}212213//(CDMA) character conversion DMA parameters214void SA1::mmio_w2231(uint8 data) {215mmio.chdend = (data & 0x80);216mmio.dmasize = (data >> 2) & 7;217mmio.dmacb = (data & 0x03);218219if(mmio.chdend) cpubwram.dma = false;220if(mmio.dmasize > 5) mmio.dmasize = 5;221if(mmio.dmacb > 2) mmio.dmacb = 2;222}223224//(SDA) DMA source device start address225void SA1::mmio_w2232(uint8 data) { mmio.dsa = (mmio.dsa & 0xffff00) | (data << 0); }226void SA1::mmio_w2233(uint8 data) { mmio.dsa = (mmio.dsa & 0xff00ff) | (data << 8); }227void SA1::mmio_w2234(uint8 data) { mmio.dsa = (mmio.dsa & 0x00ffff) | (data << 16); }228229//(DDA) DMA destination start address230void SA1::mmio_w2235(uint8 data) {231mmio.dda = (mmio.dda & 0xffff00) | (data << 0);232}233234void SA1::mmio_w2236(uint8 data) {235mmio.dda = (mmio.dda & 0xff00ff) | (data << 8);236237if(mmio.dmaen == true) {238if(mmio.cden == 0 && mmio.dd == DMA::DestIRAM) {239dma_normal();240} else if(mmio.cden == 1 && mmio.cdsel == 1) {241dma_cc1();242}243}244}245246void SA1::mmio_w2237(uint8 data) {247mmio.dda = (mmio.dda & 0x00ffff) | (data << 16);248249if(mmio.dmaen == true) {250if(mmio.cden == 0 && mmio.dd == DMA::DestBWRAM) {251dma_normal();252}253}254}255256//(DTC) DMA terminal counter257void SA1::mmio_w2238(uint8 data) { mmio.dtc = (mmio.dtc & 0xff00) | (data << 0); }258void SA1::mmio_w2239(uint8 data) { mmio.dtc = (mmio.dtc & 0x00ff) | (data << 8); }259260//(BBF) BW-RAM bitmap format261void SA1::mmio_w223f(uint8 data) {262mmio.bbf = (data & 0x80);263}264265//(BRF) bitmap register files266void SA1::mmio_w2240(uint8 data) { mmio.brf[ 0] = data; }267void SA1::mmio_w2241(uint8 data) { mmio.brf[ 1] = data; }268void SA1::mmio_w2242(uint8 data) { mmio.brf[ 2] = data; }269void SA1::mmio_w2243(uint8 data) { mmio.brf[ 3] = data; }270void SA1::mmio_w2244(uint8 data) { mmio.brf[ 4] = data; }271void SA1::mmio_w2245(uint8 data) { mmio.brf[ 5] = data; }272void SA1::mmio_w2246(uint8 data) { mmio.brf[ 6] = data; }273void SA1::mmio_w2247(uint8 data) { mmio.brf[ 7] = data;274if(mmio.dmaen == true) {275if(mmio.cden == 1 && mmio.cdsel == 0) {276dma_cc2();277}278}279}280281void SA1::mmio_w2248(uint8 data) { mmio.brf[ 8] = data; }282void SA1::mmio_w2249(uint8 data) { mmio.brf[ 9] = data; }283void SA1::mmio_w224a(uint8 data) { mmio.brf[10] = data; }284void SA1::mmio_w224b(uint8 data) { mmio.brf[11] = data; }285void SA1::mmio_w224c(uint8 data) { mmio.brf[12] = data; }286void SA1::mmio_w224d(uint8 data) { mmio.brf[13] = data; }287void SA1::mmio_w224e(uint8 data) { mmio.brf[14] = data; }288void SA1::mmio_w224f(uint8 data) { mmio.brf[15] = data;289if(mmio.dmaen == true) {290if(mmio.cden == 1 && mmio.cdsel == 0) {291dma_cc2();292}293}294}295296//(MCNT) arithmetic control297void SA1::mmio_w2250(uint8 data) {298mmio.acm = (data & 0x02);299mmio.md = (data & 0x01);300301if(mmio.acm) mmio.mr = 0;302}303304//(MAL) multiplicand / dividend low305void SA1::mmio_w2251(uint8 data) {306mmio.ma = (mmio.ma & 0xff00) | data;307}308309//(MAH) multiplicand / dividend high310void SA1::mmio_w2252(uint8 data) {311mmio.ma = (data << 8) | (mmio.ma & 0x00ff);312}313314//(MBL) multiplier / divisor low315void SA1::mmio_w2253(uint8 data) {316mmio.mb = (mmio.mb & 0xff00) | data;317}318319//(MBH) multiplier / divisor high320//multiplication / cumulative sum only resets MB321//division resets both MA and MB322void SA1::mmio_w2254(uint8 data) {323mmio.mb = (data << 8) | (mmio.mb & 0x00ff);324325if(mmio.acm == 0) {326if(mmio.md == 0) {327//signed multiplication328mmio.mr = (int16)mmio.ma * (int16)mmio.mb;329mmio.mb = 0;330} else {331//unsigned division332if(mmio.mb == 0) {333mmio.mr = 0;334} else {335int16 quotient = (int16)mmio.ma / (uint16)mmio.mb;336uint16 remainder = (int16)mmio.ma % (uint16)mmio.mb;337mmio.mr = (remainder << 16) | quotient;338}339mmio.ma = 0;340mmio.mb = 0;341}342} else {343//sigma (accumulative multiplication)344mmio.mr += (int16)mmio.ma * (int16)mmio.mb;345mmio.overflow = (mmio.mr >= (1ULL << 40));346mmio.mr &= (1ULL << 40) - 1;347mmio.mb = 0;348}349}350351//(VBD) variable-length bit processing352void SA1::mmio_w2258(uint8 data) {353mmio.hl = (data & 0x80);354mmio.vb = (data & 0x0f);355if(mmio.vb == 0) mmio.vb = 16;356357if(mmio.hl == 0) {358//fixed mode359mmio.vbit += mmio.vb;360mmio.va += (mmio.vbit >> 3);361mmio.vbit &= 7;362}363}364365//(VDA) variable-length bit game pak ROM start address366void SA1::mmio_w2259(uint8 data) { mmio.va = (mmio.va & 0xffff00) | (data << 0); }367void SA1::mmio_w225a(uint8 data) { mmio.va = (mmio.va & 0xff00ff) | (data << 8); }368void SA1::mmio_w225b(uint8 data) { mmio.va = (mmio.va & 0x00ffff) | (data << 16); mmio.vbit = 0; }369370//(SFR) S-CPU flag read371uint8 SA1::mmio_r2300() {372uint8 data;373data = mmio.cpu_irqfl << 7;374data |= mmio.cpu_ivsw << 6;375data |= mmio.chdma_irqfl << 5;376data |= mmio.cpu_nvsw << 4;377data |= mmio.cmeg;378return data;379}380381//(CFR) SA-1 flag read382uint8 SA1::mmio_r2301() {383uint8 data;384data = mmio.sa1_irqfl << 7;385data |= mmio.timer_irqfl << 6;386data |= mmio.dma_irqfl << 5;387data |= mmio.sa1_nmifl << 4;388data |= mmio.smeg;389return data;390}391392//(HCR) hcounter read393uint8 SA1::mmio_r2302() {394//latch counters395mmio.hcr = status.hcounter >> 2;396mmio.vcr = status.vcounter;397return mmio.hcr >> 0; }398uint8 SA1::mmio_r2303() { return mmio.hcr >> 8; }399400//(VCR) vcounter read401uint8 SA1::mmio_r2304() { return mmio.vcr >> 0; }402uint8 SA1::mmio_r2305() { return mmio.vcr >> 8; }403404//(MR) arithmetic result405uint8 SA1::mmio_r2306() { return mmio.mr >> 0; }406uint8 SA1::mmio_r2307() { return mmio.mr >> 8; }407uint8 SA1::mmio_r2308() { return mmio.mr >> 16; }408uint8 SA1::mmio_r2309() { return mmio.mr >> 24; }409uint8 SA1::mmio_r230a() { return mmio.mr >> 32; }410411//(OF) arithmetic overflow flag412uint8 SA1::mmio_r230b() { return mmio.overflow << 7; }413414//(VDPL) variable-length data read port low415uint8 SA1::mmio_r230c() {416uint32 data = (vbr_read(mmio.va + 0) << 0)417| (vbr_read(mmio.va + 1) << 8)418| (vbr_read(mmio.va + 2) << 16);419data >>= mmio.vbit;420return data >> 0;421}422423//(VDPH) variable-length data read port high424uint8 SA1::mmio_r230d() {425uint32 data = (vbr_read(mmio.va + 0) << 0)426| (vbr_read(mmio.va + 1) << 8)427| (vbr_read(mmio.va + 2) << 16);428data >>= mmio.vbit;429430if(mmio.hl == 1) {431//auto-increment mode432mmio.vbit += mmio.vb;433mmio.va += (mmio.vbit >> 3);434mmio.vbit &= 7;435}436437return data >> 8;438}439440//(VC) version code register441uint8 SA1::mmio_r230e() {442return 0x01; //true value unknown443}444445uint8 SA1::mmio_read(unsigned addr) {446(co_active() == cpu.thread ? cpu.synchronize_coprocessors() : synchronize_cpu());447addr &= 0xffff;448449switch(addr) {450case 0x2300: return mmio_r2300();451case 0x2301: return mmio_r2301();452case 0x2302: return mmio_r2302();453case 0x2303: return mmio_r2303();454case 0x2304: return mmio_r2304();455case 0x2305: return mmio_r2305();456case 0x2306: return mmio_r2306();457case 0x2307: return mmio_r2307();458case 0x2308: return mmio_r2308();459case 0x2309: return mmio_r2309();460case 0x230a: return mmio_r230a();461case 0x230b: return mmio_r230b();462case 0x230c: return mmio_r230c();463case 0x230d: return mmio_r230d();464case 0x230e: return mmio_r230e();465}466467return 0x00;468}469470void SA1::mmio_write(unsigned addr, uint8 data) {471(co_active() == cpu.thread ? cpu.synchronize_coprocessors() : synchronize_cpu());472addr &= 0xffff;473474switch(addr) {475case 0x2200: return mmio_w2200(data);476case 0x2201: return mmio_w2201(data);477case 0x2202: return mmio_w2202(data);478case 0x2203: return mmio_w2203(data);479case 0x2204: return mmio_w2204(data);480case 0x2205: return mmio_w2205(data);481case 0x2206: return mmio_w2206(data);482case 0x2207: return mmio_w2207(data);483case 0x2208: return mmio_w2208(data);484case 0x2209: return mmio_w2209(data);485case 0x220a: return mmio_w220a(data);486case 0x220b: return mmio_w220b(data);487case 0x220c: return mmio_w220c(data);488case 0x220d: return mmio_w220d(data);489case 0x220e: return mmio_w220e(data);490case 0x220f: return mmio_w220f(data);491492case 0x2210: return mmio_w2210(data);493case 0x2211: return mmio_w2211(data);494case 0x2212: return mmio_w2212(data);495case 0x2213: return mmio_w2213(data);496case 0x2214: return mmio_w2214(data);497case 0x2215: return mmio_w2215(data);498499case 0x2220: return mmio_w2220(data);500case 0x2221: return mmio_w2221(data);501case 0x2222: return mmio_w2222(data);502case 0x2223: return mmio_w2223(data);503case 0x2224: return mmio_w2224(data);504case 0x2225: return mmio_w2225(data);505case 0x2226: return mmio_w2226(data);506case 0x2227: return mmio_w2227(data);507case 0x2228: return mmio_w2228(data);508case 0x2229: return mmio_w2229(data);509case 0x222a: return mmio_w222a(data);510511case 0x2230: return mmio_w2230(data);512case 0x2231: return mmio_w2231(data);513case 0x2232: return mmio_w2232(data);514case 0x2233: return mmio_w2233(data);515case 0x2234: return mmio_w2234(data);516case 0x2235: return mmio_w2235(data);517case 0x2236: return mmio_w2236(data);518case 0x2237: return mmio_w2237(data);519case 0x2238: return mmio_w2238(data);520case 0x2239: return mmio_w2239(data);521522case 0x223f: return mmio_w223f(data);523case 0x2240: return mmio_w2240(data);524case 0x2241: return mmio_w2241(data);525case 0x2242: return mmio_w2242(data);526case 0x2243: return mmio_w2243(data);527case 0x2244: return mmio_w2244(data);528case 0x2245: return mmio_w2245(data);529case 0x2246: return mmio_w2246(data);530case 0x2247: return mmio_w2247(data);531case 0x2248: return mmio_w2248(data);532case 0x2249: return mmio_w2249(data);533case 0x224a: return mmio_w224a(data);534case 0x224b: return mmio_w224b(data);535case 0x224c: return mmio_w224c(data);536case 0x224d: return mmio_w224d(data);537case 0x224e: return mmio_w224e(data);538case 0x224f: return mmio_w224f(data);539540case 0x2250: return mmio_w2250(data);541case 0x2251: return mmio_w2251(data);542case 0x2252: return mmio_w2252(data);543case 0x2253: return mmio_w2253(data);544case 0x2254: return mmio_w2254(data);545546case 0x2258: return mmio_w2258(data);547case 0x2259: return mmio_w2259(data);548case 0x225a: return mmio_w225a(data);549case 0x225b: return mmio_w225b(data);550}551}552553#endif554555556