Update to v072r11 release.

A number of changes in this release were contributed by Cydrak in the
WIP thread, who described his changes from r09/r10 thusly:

- Call cpu.synchronize_coprocessor() on external R/W to avoid missing data
- Sign-extend K, L before multiplying
- Load IDB before ALU. Supports the MOV A, d; XOR A, A idiom which is
  all over the place
- Use 16-bit types in flag checks (notably Z)
- Flags mostly unified; hopefully at least OV0 and SGN work
- Carry-in comes from the *other* accumulator's flags, this is used for
  long arithmetic
- CMP is ~q (see the many CMP A; INC A where values get negated)
- SHR1 is arithmetic shift and retains the sign bit (Mario Kart sprites
  and physics are broken without it)
- SHL1 has carry-in per the datasheet, it doesn't seem to be used though
- XCHG probably byteswaps, but it's not used either
- Reversed DR external R/W order again, big-endian seems to break it

byuu described the remaining changes:

You do not need the XML files anymore, bsnes will automatically choose
the new uPD module, and look for dsp1b.bin.
If you make your own XML file, you can force the old HLE mode, or use
a differently-named PROM.
If and when we get the DSP-2,3,4 modules, bsnes v072.11 and above should
already be able to run them, assuming no more emulation core bugs.
This commit is contained in:
Tim Allen 2010-12-23 01:07:36 +11:00
parent 05526571e7
commit 9762a092d2
10 changed files with 188 additions and 293 deletions

View File

@ -408,7 +408,7 @@ SNESCartridge::SNESCartridge(const uint8_t *data, unsigned size) {
} }
if(has_dsp1) { if(has_dsp1) {
xml << " <necdsp program='DSP-1B'>\n"; xml << " <upd77c25 program='dsp1b.bin'>\n";
if(dsp1_mapper == DSP1LoROM1MB) { if(dsp1_mapper == DSP1LoROM1MB) {
xml << " <dr>\n"; xml << " <dr>\n";
xml << " <map address='20-3f:8000-bfff'/>\n"; xml << " <map address='20-3f:8000-bfff'/>\n";
@ -437,7 +437,7 @@ SNESCartridge::SNESCartridge(const uint8_t *data, unsigned size) {
xml << " <map address='80-9f:7000-7fff'/>\n"; xml << " <map address='80-9f:7000-7fff'/>\n";
xml << " </sr>\n"; xml << " </sr>\n";
} }
xml << " </necdsp>\n"; xml << " </upd77c25>\n";
} }
if(has_dsp2) { if(has_dsp2) {

View File

@ -232,9 +232,16 @@ void Cartridge::xml_parse_upd77c25(xml_element &root) {
foreach(attr, root.attribute) { foreach(attr, root.attribute) {
if(attr.name == "program") { if(attr.name == "program") {
upd77c25.program = attr.content; file fp;
} else if(attr.name == "data") { if(fp.open(string(dir(basename()), attr.content), file::mode::read)) {
upd77c25.data = attr.content; for(unsigned n = 0; n < 2048; n++) {
upd77c25.programROM[n] = fp.readm(3);
fp.read();
}
for(unsigned n = 0; n < 1024; n++) {
upd77c25.dataROM[n] = fp.readm(2);
}
}
} }
} }

View File

@ -0,0 +1,52 @@
#ifdef UPD77C25_CPP
void UPD77C25::serialize(serializer &s) {
s.array(dataRAM);
s.integer(regs.pc);
for(unsigned n = 0; n < 4; n++) s.integer(regs.stack[n]);
s.integer(regs.rp);
s.integer(regs.dp);
s.integer(regs.k);
s.integer(regs.l);
s.integer(regs.m);
s.integer(regs.n);
s.integer(regs.a);
s.integer(regs.b);
s.integer(regs.flaga.s1);
s.integer(regs.flaga.s0);
s.integer(regs.flaga.c);
s.integer(regs.flaga.z);
s.integer(regs.flaga.ov1);
s.integer(regs.flaga.ov0);
s.integer(regs.flagb.s1);
s.integer(regs.flagb.s0);
s.integer(regs.flagb.c);
s.integer(regs.flagb.z);
s.integer(regs.flagb.ov1);
s.integer(regs.flagb.ov0);
s.integer(regs.tr);
s.integer(regs.trb);
s.integer(regs.sr.rqm);
s.integer(regs.sr.usf1);
s.integer(regs.sr.usf0);
s.integer(regs.sr.drs);
s.integer(regs.sr.dma);
s.integer(regs.sr.drc);
s.integer(regs.sr.soc);
s.integer(regs.sr.sic);
s.integer(regs.sr.ei);
s.integer(regs.sr.p1);
s.integer(regs.sr.p0);
s.integer(regs.dr);
s.integer(regs.siack);
s.integer(regs.soack);
s.integer(regs.idb);
}
#endif

View File

@ -7,6 +7,7 @@
#define UPD77C25_CPP #define UPD77C25_CPP
namespace SNES { namespace SNES {
#include "serialization.cpp"
#include "disassembler.cpp" #include "disassembler.cpp"
UPD77C25 upd77c25; UPD77C25 upd77c25;
@ -17,7 +18,9 @@ void UPD77C25::Enter() { upd77c25.enter(); }
void UPD77C25::enter() { void UPD77C25::enter() {
while(true) { while(true) {
//print(disassemble(regs.pc), "\n"); if(scheduler.sync == Scheduler::SynchronizeMode::All) {
scheduler.exit(Scheduler::ExitReason::SynchronizeEvent);
}
uint24 opcode = programROM[regs.pc++]; uint24 opcode = programROM[regs.pc++];
switch(opcode >> 22) { switch(opcode >> 22) {
@ -27,7 +30,7 @@ void UPD77C25::enter() {
case 3: exec_ld(opcode); break; case 3: exec_ld(opcode); break;
} }
uint31 result = regs.k * regs.l; //sign + 30-bit result int32 result = (int32)regs.k * regs.l; //sign + 30-bit result
regs.m = result >> 15; //store sign + top 15-bits regs.m = result >> 15; //store sign + top 15-bits
regs.n = result << 1; //store low 15-bits + zero regs.n = result << 1; //store low 15-bits + zero
@ -46,195 +49,6 @@ void UPD77C25::exec_op(uint24 opcode) {
uint4 src = opcode >> 4; //move source uint4 src = opcode >> 4; //move source
uint4 dst = opcode >> 0; //move destination uint4 dst = opcode >> 0; //move destination
unsigned p, q, r;
Flag flag;
switch(pselect) {
case 0: p = dataRAM[regs.dp]; break;
case 1: p = regs.idb; break;
case 2: p = regs.m; break;
case 3: p = regs.n; break;
}
switch(asl) {
case 0: q = regs.a; flag = regs.flaga; break;
case 1: q = regs.b; flag = regs.flagb; break;
}
switch(alu) {
case 0: { //NOP
break;
}
case 1: { //OR
r = q | p;
flag.s0 = r & 0x8000;
flag.c = 0;
flag.z = !r;
flag.ov0 = 0;
flag.ov1 = 0;
break;
}
case 2: { //AND
r = q & p;
flag.s0 = r & 0x8000;
flag.c = 0;
flag.z = !r;
flag.ov0 = 0;
flag.ov1 = 0;
break;
}
case 3: { //XOR
r = q ^ p;
flag.s0 = r & 0x8000;
flag.c = 0;
flag.z = !r;
flag.ov0 = 0;
flag.ov1 = 0;
break;
}
case 4: { //SUB
r = q - p;
bool pov = (((p | q) & 0x8000) == 0x0000) && ((r & 0x8000) == 0x8000);
bool nov = (((p & q) & 0x8000) == 0x8000) && ((r & 0x8000) == 0x0000);
flag.s0 = r & 0x8000;
flag.s1 = pov;
flag.c = r > 0xffff;
flag.z = !r;
flag.ov0 = pov | nov;
flag.ov1 ^= flag.ov0;
break;
}
case 5: { //ADD
r = q + p;
bool pov = (((p | q) & 0x8000) == 0x0000) && ((r & 0x8000) == 0x8000);
bool nov = (((p & q) & 0x8000) == 0x8000) && ((r & 0x8000) == 0x0000);
flag.s0 = r & 0x8000;
flag.s1 = pov;
flag.c = r > 0xffff;
flag.z = !r;
flag.ov0 = pov | nov;
flag.ov1 ^= flag.ov0;
break;
}
case 6: { //SBB
r = q - p - flag.c;
bool pov = (((p | q) & 0x8000) == 0x0000) && ((r & 0x8000) == 0x8000);
bool nov = (((p & q) & 0x8000) == 0x8000) && ((r & 0x8000) == 0x0000);
flag.s0 = r & 0x8000;
flag.s1 = pov;
flag.c = r > 0xffff;
flag.z = !r;
flag.ov0 = pov | nov;
flag.ov1 ^= flag.ov0;
break;
}
case 7: { //ADC
r = q + p + flag.c;
bool pov = (((p | q) & 0x8000) == 0x0000) && ((r & 0x8000) == 0x8000);
bool nov = (((p & q) & 0x8000) == 0x8000) && ((r & 0x8000) == 0x0000);
flag.s0 = r & 0x8000;
flag.s1 = pov;
flag.c = r > 0xffff;
flag.z = !r;
flag.ov0 = pov | nov;
flag.ov1 ^= flag.ov0;
break;
}
case 8: { //DEC
r = q - 1;
bool pov = (((p | q) & 0x8000) == 0x0000) && ((r & 0x8000) == 0x8000);
bool nov = (((p & q) & 0x8000) == 0x8000) && ((r & 0x8000) == 0x0000);
flag.s0 = r & 0x8000;
flag.s1 = pov;
flag.c = r > 0xffff;
flag.z = !r;
flag.ov0 = pov | nov;
flag.ov1 ^= flag.ov0;
break;
}
case 9: { //INC
r = q + 1;
bool pov = (((p | q) & 0x8000) == 0x0000) && ((r & 0x8000) == 0x8000);
bool nov = (((p & q) & 0x8000) == 0x8000) && ((r & 0x8000) == 0x0000);
flag.s0 = r & 0x8000;
flag.s1 = pov;
flag.c = r > 0xffff;
flag.z = !r;
flag.ov0 = pov | nov;
flag.ov1 ^= flag.ov0;
break;
}
case 10: { //CMP (complement)
r = ~q;
flag.s0 = r & 0x8000;
flag.c = 0;
flag.z = !r;
flag.ov0 = 0;
flag.ov1 = 0;
break;
}
case 11: { //SHR1
r = q >> 1;
flag.s0 = r & 0x8000;
flag.c = q & 1;
flag.z = !r;
flag.ov0 = 0;
flag.ov1 = 0;
break;
}
case 12: { //SHL1
r = q << 1;
flag.s0 = r & 0x8000;
flag.c = r & 0x8000;
flag.z = !r;
flag.ov0 = 0;
flag.ov1 = 0;
break;
}
case 13: { //SHL2
r = q << 2;
flag.s0 = r & 0x8000;
flag.c = 0;
flag.z = !r;
flag.ov0 = 0;
flag.ov1 = 0;
break;
}
case 14: { //SHL4
r = q << 4;
flag.s0 = r & 0x8000;
flag.c = 0;
flag.z = !r;
flag.ov0 = 0;
flag.ov1 = 0;
break;
}
case 15: { //XCHG
r = (q << 8) | (q >> 8);
flag.s0 = r & 0x8000;
flag.c = 0;
flag.z = !r;
flag.ov0 = 0;
flag.ov1 = 0;
break;
}
}
switch(src) { switch(src) {
case 0: regs.idb = regs.trb; break; case 0: regs.idb = regs.trb; break;
case 1: regs.idb = regs.a; break; case 1: regs.idb = regs.a; break;
@ -243,7 +57,7 @@ void UPD77C25::exec_op(uint24 opcode) {
case 4: regs.idb = regs.dp; break; case 4: regs.idb = regs.dp; break;
case 5: regs.idb = regs.rp; break; case 5: regs.idb = regs.rp; break;
case 6: regs.idb = dataROM[regs.rp]; break; case 6: regs.idb = dataROM[regs.rp]; break;
case 7: regs.idb = regs.flaga.s1 ? 0x7fff : 0x8000; break; case 7: regs.idb = 0x8000 - regs.flaga.s1; break;
case 8: regs.idb = regs.dr; regs.sr.rqm = 1; break; case 8: regs.idb = regs.dr; regs.sr.rqm = 1; break;
case 9: regs.idb = regs.dr; break; case 9: regs.idb = regs.dr; break;
case 10: regs.idb = regs.sr; break; case 10: regs.idb = regs.sr; break;
@ -252,36 +66,92 @@ void UPD77C25::exec_op(uint24 opcode) {
case 13: regs.idb = regs.k; break; case 13: regs.idb = regs.k; break;
case 14: regs.idb = regs.l; break; case 14: regs.idb = regs.l; break;
case 15: regs.idb = dataRAM[regs.dp]; break; case 15: regs.idb = dataRAM[regs.dp]; break;
default: print("OP: unhandled src case ", strhex<2>(src), "\n"); break;
} }
switch(asl) { if(alu) {
case 0: regs.a = r; regs.flaga = flag; break; uint16 p, q, r;
case 1: regs.b = r; regs.flagb = flag; break; Flag flag;
bool c;
switch(pselect) {
case 0: p = dataRAM[regs.dp]; break;
case 1: p = regs.idb; break;
case 2: p = regs.m; break;
case 3: p = regs.n; break;
}
switch(asl) {
case 0: q = regs.a; flag = regs.flaga; c = regs.flagb.c; break;
case 1: q = regs.b; flag = regs.flagb; c = regs.flaga.c; break;
}
switch(alu) {
case 1: r = q | p; break; //OR
case 2: r = q & p; break; //AND
case 3: r = q ^ p; break; //XOR
case 4: r = q - p; break; //SUB
case 5: r = q + p; break; //ADD
case 6: r = q - p - c; break; //SBB
case 7: r = q + p + c; break; //ADC
case 8: r = q - 1; p = 1; break; //DEC
case 9: r = q + 1; p = 1; break; //INC
case 10: r = ~q; break; //CMP
case 11: r = (q >> 1) | (q & 0x8000); break; //SHR1 (ASR)
case 12: r = (q << 1) | c; break; //SHL1 (ROL)
case 13: r = (q << 2); break; //SHL2
case 14: r = (q << 4); break; //SHL4
case 15: r = (q << 8) | (q >> 8); break; //XCHG
}
flag.s0 = (r & 0x8000);
flag.z = (r == 0);
switch(alu) {
case 1: case 2: case 3: case 10: case 13: case 14: case 15: {
flag.c = 0;
flag.ov0 = 0;
flag.ov1 = 0;
break;
}
case 4: case 5: case 6: case 7: case 8: case 9: {
if(alu & 1) {
//addition
flag.ov0 = (q ^ r) & ~(q ^ p) & 0x8000;
flag.c = (r < q);
} else {
//subtraction
flag.ov0 = (q ^ r) & (q ^ p) & 0x8000;
flag.c = (r > q);
}
if(flag.ov0) {
flag.s1 = flag.ov1 ^ !(r & 0x8000);
flag.ov1 = !flag.ov1;
}
break;
}
case 11: {
flag.c = q & 1;
flag.ov0 = 0;
flag.ov1 = 0;
break;
}
case 12: {
flag.c = q >> 15;
flag.ov0 = 0;
flag.ov1 = 0;
break;
}
}
switch(asl) {
case 0: regs.a = r; regs.flaga = flag; break;
case 1: regs.b = r; regs.flagb = flag; break;
}
} }
switch(dst) { exec_ld((regs.idb << 6) + dst);
case 0: break;
case 1: regs.a = regs.idb; break;
case 2: regs.b = regs.idb; break;
case 3: regs.tr = regs.idb; break;
case 4: regs.dp = regs.idb; break;
case 5: regs.rp = regs.idb; break;
case 6: regs.dr = regs.idb; regs.sr.rqm = 1; break;
case 7: regs.sr = (regs.sr & 0x9000) | (regs.idb & ~0x9000); break;
//case 8: regs.sol = regs.idb; break;
//case 9: regs.som = regs.idb; break;
case 10: regs.k = regs.idb; break;
case 11: regs.k = regs.idb; regs.l = dataROM[regs.rp]; break;
case 12: regs.k = dataRAM[regs.dp | 0x40]; regs.l = regs.idb; break;
case 13: regs.l = regs.idb; break;
case 14: regs.trb = regs.idb; break;
case 15: dataRAM[regs.dp] = regs.idb; break;
default: print("OP: unhandled dst case ", strhex<2>(dst), "\n"); break;
}
switch(dpl) { switch(dpl) {
case 0: break; //DPNOP
case 1: regs.dp = (regs.dp & 0xf0) + ((regs.dp + 1) & 0x0f); break; //DPINC case 1: regs.dp = (regs.dp & 0xf0) + ((regs.dp + 1) & 0x0f); break; //DPINC
case 2: regs.dp = (regs.dp & 0xf0) + ((regs.dp - 1) & 0x0f); break; //DPDEC case 2: regs.dp = (regs.dp & 0xf0) + ((regs.dp - 1) & 0x0f); break; //DPDEC
case 3: regs.dp = (regs.dp & 0xf0); break; //DPCLR case 3: regs.dp = (regs.dp & 0xf0); break; //DPCLR
@ -289,10 +159,7 @@ void UPD77C25::exec_op(uint24 opcode) {
regs.dp ^= dphm << 4; regs.dp ^= dphm << 4;
switch(rpdcr) { if(rpdcr) regs.rp--;
case 0: break; //RPNOP
case 1: regs.rp--; break; //RPDEC
}
} }
void UPD77C25::exec_rt(uint24 opcode) { void UPD77C25::exec_rt(uint24 opcode) {
@ -357,6 +224,8 @@ void UPD77C25::exec_ld(uint24 opcode) {
uint16 id = opcode >> 6; //immediate data uint16 id = opcode >> 6; //immediate data
uint4 dst = opcode >> 0; //destination uint4 dst = opcode >> 0; //destination
regs.idb = id;
switch(dst) { switch(dst) {
case 0: break; case 0: break;
case 1: regs.a = id; break; case 1: regs.a = id; break;
@ -365,16 +234,15 @@ void UPD77C25::exec_ld(uint24 opcode) {
case 4: regs.dp = id; break; case 4: regs.dp = id; break;
case 5: regs.rp = id; break; case 5: regs.rp = id; break;
case 6: regs.dr = id; regs.sr.rqm = 1; break; case 6: regs.dr = id; regs.sr.rqm = 1; break;
case 7: regs.sr = (regs.sr & 0x9000) | (id & ~0x9000); break; case 7: regs.sr = (regs.sr & 0x907c) | (id & ~0x907c); break;
//case 8: regs.sol = id; break; //case 8: regs.sol = id; break;
//case 9: regs.som = id; break; //case 9: regs.som = id; break;
case 10: regs.k = id; break; case 10: regs.k = id; break;
case 11: regs.k = regs.idb; regs.l = dataROM[regs.rp]; break; case 11: regs.k = id; regs.l = dataROM[regs.rp]; break;
case 12: regs.k = dataRAM[regs.dp | 0x40]; regs.l = regs.idb; break; case 12: regs.l = id; regs.k = dataRAM[regs.dp | 0x40]; break;
case 13: regs.l = id; break; case 13: regs.l = id; break;
case 14: regs.trb = id; break; case 14: regs.trb = id; break;
case 15: dataRAM[regs.dp] = id; break; case 15: dataRAM[regs.dp] = id; break;
default: print("LD: unhandled dst case ", strhex<2>(dst), "\n"); break;
} }
} }
@ -394,42 +262,44 @@ void UPD77C25::stack_pull() {
} }
uint8 UPD77C25::read(bool mode) { uint8 UPD77C25::read(bool mode) {
if(mode == 0) return (unsigned)regs.sr >> 8; cpu.synchronize_coprocessor();
if(mode == 0) return regs.sr >> 8;
if(regs.sr.drc == 0) { if(regs.sr.drc == 0) {
//16-bit //16-bit
if(regs.sr.drs == 0) { if(regs.sr.drs == 0) {
regs.sr.drs = 1; regs.sr.drs = 1;
return regs.dr >> 8; return regs.dr >> 0;
} else { } else {
regs.sr.rqm = 0; regs.sr.rqm = 0;
regs.sr.drs = 0; regs.sr.drs = 0;
return regs.dr >> 0; return regs.dr >> 8;
} }
} else { } else {
//8-bit //8-bit
regs.sr.rqm = 0; regs.sr.rqm = 0;
return regs.dr; return regs.dr >> 0;
} }
} }
void UPD77C25::write(bool mode, uint8 data) { void UPD77C25::write(bool mode, uint8 data) {
cpu.synchronize_coprocessor();
if(mode == 0) return; if(mode == 0) return;
if(regs.sr.drc == 0) { if(regs.sr.drc == 0) {
//16-bit //16-bit
if(regs.sr.drs == 0) { if(regs.sr.drs == 0) {
regs.sr.drs = 1; regs.sr.drs = 1;
regs.dr = (data << 8) | (regs.dr & 0x00ff); regs.dr = (regs.dr & 0xff00) | (data << 0);
} else { } else {
regs.sr.rqm = 0; regs.sr.rqm = 0;
regs.sr.drs = 0; regs.sr.drs = 0;
regs.dr = (regs.dr & 0xff00) | (data << 0); regs.dr = (data << 8) | (regs.dr & 0x00ff);
} }
} else { } else {
//8-bit //8-bit
regs.sr.rqm = 0; regs.sr.rqm = 0;
regs.dr = data; regs.dr = (regs.dr & 0xff00) | (data << 0);
} }
} }
@ -440,43 +310,7 @@ void UPD77C25::enable() {
} }
void UPD77C25::power() { void UPD77C25::power() {
for(unsigned i = 0; i < 2048; i++) programROM[i] = 0x000000;
for(unsigned i = 0; i < 1024; i++) dataROM[i] = 0x0000;
for(unsigned i = 0; i < 256; i++) dataRAM[i] = 0x0000; for(unsigned i = 0; i < 256; i++) dataRAM[i] = 0x0000;
string filename;
file fp;
filename = string(dir(cartridge.basename()), program);
if(fp.open(filename, file::mode::read)) {
for(unsigned i = 0; i < 2048; i++) {
programROM[i] |= fp.read() << 16;
programROM[i] |= fp.read() << 8;
programROM[i] |= fp.read() << 0;
fp.read(); //skip 24-bit -> 32-bit padding
}
fp.close();
}
filename = string(dir(cartridge.basename()), data);
if(fp.open(filename, file::mode::read)) {
for(unsigned i = 0; i < 1024; i++) {
dataROM[i] |= fp.read() << 8;
dataROM[i] |= fp.read() << 0;
}
fp.close();
}
#if 0
fp.open("/home/byuu/Desktop/disassembly.txt", file::mode::write);
for(unsigned i = 0; i < 2048; i++) {
string output = disassemble(i);
fp.print(output);
fp.print("\n");
}
fp.close();
#endif
reset(); reset();
} }

View File

@ -7,16 +7,15 @@ public:
void power(); void power();
void reset(); void reset();
string disassemble(uint11 ip); void serialize(serializer &s);
string program;
string data;
private:
uint24 programROM[2048]; uint24 programROM[2048];
uint16 dataROM[1024]; uint16 dataROM[1024];
uint16 dataRAM[256]; uint16 dataRAM[256];
string disassemble(uint11 ip);
private:
struct Flag { struct Flag {
bool s1, s0, c, z, ov1, ov0; bool s1, s0, c, z, ov1, ov0;
@ -52,16 +51,16 @@ private:
uint11 stack[4]; //LIFO uint11 stack[4]; //LIFO
uint10 rp; //ROM pointer uint10 rp; //ROM pointer
uint8 dp; //data pointer uint8 dp; //data pointer
uint16 k; int16 k;
uint16 l; int16 l;
uint16 m; int16 m;
uint16 n; int16 n;
uint16 a; //accumulator int16 a; //accumulator
uint16 b; //accumulator int16 b; //accumulator
Flag flaga; Flag flaga;
Flag flagb; Flag flagb;
uint16 tr; //temporary registers uint16 tr; //temporary register
uint16 trb; uint16 trb; //temporary register
Status sr; //status register Status sr; //status register
uint16 dr; //data register uint16 dr; //data register
bool siack; bool siack;
@ -73,8 +72,10 @@ private:
void exec_rt(uint24 opcode); void exec_rt(uint24 opcode);
void exec_jp(uint24 opcode); void exec_jp(uint24 opcode);
void exec_ld(uint24 opcode); void exec_ld(uint24 opcode);
void stack_push(); void stack_push();
void stack_pull(); void stack_pull();
uint8 read(bool mode); uint8 read(bool mode);
void write(bool mode, uint8 data); void write(bool mode, uint8 data);

View File

@ -1,12 +1,12 @@
namespace SNES { namespace SNES {
namespace Info { namespace Info {
static const char Name[] = "bsnes"; static const char Name[] = "bsnes";
static const char Version[] = "072.10"; static const char Version[] = "072.11";
static const unsigned SerializerVersion = 14; static const unsigned SerializerVersion = 14;
} }
} }
#define DEBUGGER //#define DEBUGGER
#define CHEAT_SYSTEM #define CHEAT_SYSTEM
#include <libco/libco.h> #include <libco/libco.h>

View File

@ -60,6 +60,7 @@ void System::serialize_all(serializer &s) {
if(cartridge.mode() == Cartridge::Mode::SuperGameBoy) supergameboy.serialize(s); if(cartridge.mode() == Cartridge::Mode::SuperGameBoy) supergameboy.serialize(s);
if(cartridge.has_superfx()) superfx.serialize(s); if(cartridge.has_superfx()) superfx.serialize(s);
if(cartridge.has_sa1()) sa1.serialize(s); if(cartridge.has_sa1()) sa1.serialize(s);
if(cartridge.has_upd77c25()) upd77c25.serialize(s);
if(cartridge.has_srtc()) srtc.serialize(s); if(cartridge.has_srtc()) srtc.serialize(s);
if(cartridge.has_sdd1()) sdd1.serialize(s); if(cartridge.has_sdd1()) sdd1.serialize(s);
if(cartridge.has_spc7110()) spc7110.serialize(s); if(cartridge.has_spc7110()) spc7110.serialize(s);

View File

@ -217,6 +217,7 @@ void System::reset() {
if(cartridge.mode() == Cartridge::Mode::SuperGameBoy) cpu.coprocessors.append(&supergameboy); if(cartridge.mode() == Cartridge::Mode::SuperGameBoy) cpu.coprocessors.append(&supergameboy);
if(cartridge.has_superfx()) cpu.coprocessors.append(&superfx); if(cartridge.has_superfx()) cpu.coprocessors.append(&superfx);
if(cartridge.has_sa1()) cpu.coprocessors.append(&sa1); if(cartridge.has_sa1()) cpu.coprocessors.append(&sa1);
if(cartridge.has_upd77c25()) cpu.coprocessors.append(&upd77c25);
if(cartridge.has_msu1()) cpu.coprocessors.append(&msu1); if(cartridge.has_msu1()) cpu.coprocessors.append(&msu1);
if(cartridge.has_serial()) cpu.coprocessors.append(&serial); if(cartridge.has_serial()) cpu.coprocessors.append(&serial);

View File

@ -4,7 +4,7 @@ Cartridge cartridge;
bool Cartridge::loadNormal(const char *basename) { bool Cartridge::loadNormal(const char *basename) {
unload(); unload();
if(loadCartridge(SNES::memory::cartrom, baseXML, basename) == false) return false; if(loadCartridge(SNES::memory::cartrom, baseXML, basename) == false) return false;
baseName = nall::basename(basename); SNES::cartridge.basename = baseName = nall::basename(basename);
SNES::cartridge.load(SNES::Cartridge::Mode::Normal, { baseXML }); SNES::cartridge.load(SNES::Cartridge::Mode::Normal, { baseXML });
loadMemory(SNES::memory::cartram, baseName, ".srm"); loadMemory(SNES::memory::cartram, baseName, ".srm");
loadMemory(SNES::memory::cartrtc, baseName, ".rtc"); loadMemory(SNES::memory::cartrtc, baseName, ".rtc");
@ -16,7 +16,7 @@ bool Cartridge::loadBsxSlotted(const char *basename, const char *slotname) {
unload(); unload();
if(loadCartridge(SNES::memory::cartrom, baseXML, basename) == false) return false; if(loadCartridge(SNES::memory::cartrom, baseXML, basename) == false) return false;
loadCartridge(SNES::memory::bsxflash, slotAXML, slotname); loadCartridge(SNES::memory::bsxflash, slotAXML, slotname);
baseName = nall::basename(basename); SNES::cartridge.basename = baseName = nall::basename(basename);
slotAName = nall::basename(slotname); slotAName = nall::basename(slotname);
SNES::cartridge.load(SNES::Cartridge::Mode::BsxSlotted, { baseXML, slotAXML }); SNES::cartridge.load(SNES::Cartridge::Mode::BsxSlotted, { baseXML, slotAXML });
loadMemory(SNES::memory::cartram, baseName, ".srm"); loadMemory(SNES::memory::cartram, baseName, ".srm");
@ -29,7 +29,7 @@ bool Cartridge::loadBsx(const char *basename, const char *slotname) {
unload(); unload();
if(loadCartridge(SNES::memory::cartrom, baseXML, basename) == false) return false; if(loadCartridge(SNES::memory::cartrom, baseXML, basename) == false) return false;
loadCartridge(SNES::memory::bsxflash, slotAXML, slotname); loadCartridge(SNES::memory::bsxflash, slotAXML, slotname);
baseName = nall::basename(basename); SNES::cartridge.basename = baseName = nall::basename(basename);
slotAName = nall::basename(slotname); slotAName = nall::basename(slotname);
SNES::cartridge.load(SNES::Cartridge::Mode::Bsx, { baseXML, slotAXML }); SNES::cartridge.load(SNES::Cartridge::Mode::Bsx, { baseXML, slotAXML });
loadMemory(SNES::memory::bsxram, baseName, ".srm"); loadMemory(SNES::memory::bsxram, baseName, ".srm");
@ -43,7 +43,7 @@ bool Cartridge::loadSufamiTurbo(const char *basename, const char *slotAname, con
if(loadCartridge(SNES::memory::cartrom, baseXML, basename) == false) return false; if(loadCartridge(SNES::memory::cartrom, baseXML, basename) == false) return false;
loadCartridge(SNES::memory::stArom, slotAXML, slotAname); loadCartridge(SNES::memory::stArom, slotAXML, slotAname);
loadCartridge(SNES::memory::stBrom, slotBXML, slotBname); loadCartridge(SNES::memory::stBrom, slotBXML, slotBname);
baseName = nall::basename(basename); SNES::cartridge.basename = baseName = nall::basename(basename);
slotAName = nall::basename(slotAname); slotAName = nall::basename(slotAname);
slotBName = nall::basename(slotBname); slotBName = nall::basename(slotBname);
SNES::cartridge.load(SNES::Cartridge::Mode::SufamiTurbo, { baseXML, slotAXML, slotBXML }); SNES::cartridge.load(SNES::Cartridge::Mode::SufamiTurbo, { baseXML, slotAXML, slotBXML });
@ -57,7 +57,7 @@ bool Cartridge::loadSuperGameBoy(const char *basename, const char *slotname) {
unload(); unload();
if(loadCartridge(SNES::memory::cartrom, baseXML, basename) == false) return false; if(loadCartridge(SNES::memory::cartrom, baseXML, basename) == false) return false;
loadCartridge(SNES::memory::gbrom, slotAXML, slotname); loadCartridge(SNES::memory::gbrom, slotAXML, slotname);
baseName = nall::basename(basename); SNES::cartridge.basename = baseName = nall::basename(basename);
slotAName = nall::basename(slotname); slotAName = nall::basename(slotname);
SNES::cartridge.load(SNES::Cartridge::Mode::SuperGameBoy, { baseXML, slotAXML }); SNES::cartridge.load(SNES::Cartridge::Mode::SuperGameBoy, { baseXML, slotAXML });
loadMemory(SNES::memory::gbram, slotAName, ".sav"); loadMemory(SNES::memory::gbram, slotAName, ".sav");

View File

@ -92,7 +92,6 @@ void Utility::setShader() {
} }
void Utility::cartridgeLoaded() { void Utility::cartridgeLoaded() {
SNES::cartridge.basename = cartridge.baseName;
SNES::system.power(); SNES::system.power();
cheatEditor.load(cartridge.baseName); cheatEditor.load(cartridge.baseName);
stateManager.load(); stateManager.load();