Update to v073r05 release.

Added uPD96050 emulation, but it's not working right now. I'm totally
stumped. The ST-0010 player cars aren't moving right, and it crashes
sometimes on exit like it's going out of bounds.

I had decided to try and avoid duplicating the 20KB uPD7725 core, so
I made a new folder:
snes/chip/necdsp
snes/chip/necdsp/upd7725
snes/chip/necdsp/upd96050

The latter two derive from the former, and they specify the PC, RP and
DP sizes, which allocates appropriate memory.
I use simple runtime-masked registers (to avoid template hell on every
uPDcore function), and then I derive from that to complete each actual
DSP. The uPD7725 seems to work great, but the uPD96050 is fucked and
I don't know why :(
Help would be appreciated, it must be something simple because I am
certain the cars were working before.

Kinda wish I didn't scrap the old code now :(
This commit is contained in:
Tim Allen 2011-01-08 21:20:59 +11:00
parent 1c6a8543cd
commit a7ffc31282
19 changed files with 531 additions and 261 deletions

View File

@ -408,7 +408,7 @@ SNESCartridge::SNESCartridge(const uint8_t *data, unsigned size) {
}
if(has_dsp1) {
xml << " <upd77c25 program='dsp1b.bin' sha256='4d42db0f36faef263d6b93f508e8c1c4ae8fc2605fd35e3390ecc02905cd420c'>\n";
xml << " <upd7725 program='dsp1b.bin' sha256='4d42db0f36faef263d6b93f508e8c1c4ae8fc2605fd35e3390ecc02905cd420c'>\n";
if(dsp1_mapper == DSP1LoROM1MB) {
xml << " <dr>\n";
xml << " <map address='20-3f:8000-bfff'/>\n";
@ -437,11 +437,11 @@ SNESCartridge::SNESCartridge(const uint8_t *data, unsigned size) {
xml << " <map address='80-9f:7000-7fff'/>\n";
xml << " </sr>\n";
}
xml << " </upd77c25>\n";
xml << " </upd7725>\n";
}
if(has_dsp2) {
xml << " <upd77c25 program='dsp2.bin' sha256='5efbdf96ed0652790855225964f3e90e6a4d466cfa64df25b110933c6cf94ea1'>\n";
xml << " <upd7725 program='dsp2.bin' sha256='5efbdf96ed0652790855225964f3e90e6a4d466cfa64df25b110933c6cf94ea1'>\n";
xml << " <dr>\n";
xml << " <map address='20-3f:8000-bfff'/>\n";
xml << " <map address='a0-bf:8000-bfff'/>\n";
@ -450,11 +450,11 @@ SNESCartridge::SNESCartridge(const uint8_t *data, unsigned size) {
xml << " <map address='20-3f:c000-ffff'/>\n";
xml << " <map address='a0-bf:c000-ffff'/>\n";
xml << " </sr>\n";
xml << " </upd77c25>\n";
xml << " </upd7725>\n";
}
if(has_dsp3) {
xml << " <upd77c25 program='dsp3.bin' sha256='2e635f72e4d4681148bc35429421c9b946e4f407590e74e31b93b8987b63ba90'>\n";
xml << " <upd7725 program='dsp3.bin' sha256='2e635f72e4d4681148bc35429421c9b946e4f407590e74e31b93b8987b63ba90'>\n";
xml << " <dr>\n";
xml << " <map address='20-3f:8000-bfff'/>\n";
xml << " <map address='a0-bf:8000-bfff'/>\n";
@ -463,11 +463,11 @@ SNESCartridge::SNESCartridge(const uint8_t *data, unsigned size) {
xml << " <map address='20-3f:c000-ffff'/>\n";
xml << " <map address='a0-bf:c000-ffff'/>\n";
xml << " </sr>\n";
xml << " </upd77c25>\n";
xml << " </upd7725>\n";
}
if(has_dsp4) {
xml << " <upd77c25 program='dsp4.bin' sha256='63ede17322541c191ed1fdf683872554a0a57306496afc43c59de7c01a6e764a'>\n";
xml << " <upd7725 program='dsp4.bin' sha256='63ede17322541c191ed1fdf683872554a0a57306496afc43c59de7c01a6e764a'>\n";
xml << " <dr>\n";
xml << " <map address='30-3f:8000-bfff'/>\n";
xml << " <map address='b0-bf:8000-bfff'/>\n";
@ -476,7 +476,7 @@ SNESCartridge::SNESCartridge(const uint8_t *data, unsigned size) {
xml << " <map address='30-3f:c000-ffff'/>\n";
xml << " <map address='b0-bf:c000-ffff'/>\n";
xml << " </sr>\n";
xml << " </upd77c25>\n";
xml << " </upd7725>\n";
}
if(has_obc1) {
@ -489,12 +489,10 @@ SNESCartridge::SNESCartridge(const uint8_t *data, unsigned size) {
}
if(has_st010) {
xml << " <setadsp program='ST-0010'>\n";
xml << " <mmio>\n";
xml << " <map address='68-6f:0000-0fff'/>\n";
xml << " <map address='e8-ef:0000-0fff'/>\n";
xml << " </mmio>\n";
xml << " </setadsp>\n";
xml << " <upd96050 program='st0010.bin' sha256='55c697e864562445621cdf8a7bf6e84ae91361e393d382a3704e9aa55559041e'>\n";
xml << " <map address='68-6f:0000-0fff'/>\n";
xml << " <map address='e8-ef:0000-0fff'/>\n";
xml << " </upd96050>\n";
}
if(has_st011) {

View File

@ -2,7 +2,8 @@ snes_objects := snes-system
snes_objects += snes-cartridge snes-cheat
snes_objects += snes-memory snes-cpucore snes-smpcore
snes_objects += snes-cpu snes-smp snes-dsp snes-ppu
snes_objects += snes-icd2 snes-superfx snes-sa1 snes-upd77c25
snes_objects += snes-icd2 snes-superfx snes-sa1
snes_objects += snes-necdsp snes-upd7725 snes-upd96050
snes_objects += snes-bsx snes-srtc snes-sdd1 snes-spc7110 snes-cx4
snes_objects += snes-obc1 snes-st0010 snes-st0011 snes-st0018
snes_objects += snes-msu1 snes-serial
@ -44,7 +45,9 @@ obj/snes-cheat.o : $(snes)/cheat/cheat.cpp $(call rwildcard,$(snes)/cheat/)
obj/snes-icd2.o : $(snes)/chip/icd2/icd2.cpp $(call rwildcard,$(snes)/chip/icd2/)
obj/snes-superfx.o : $(snes)/chip/superfx/superfx.cpp $(call rwildcard,$(snes)/chip/superfx/)
obj/snes-sa1.o : $(snes)/chip/sa1/sa1.cpp $(call rwildcard,$(snes)/chip/sa1/)
obj/snes-upd77c25.o: $(snes)/chip/upd77c25/upd77c25.cpp $(call rwildcard,$(snes)/chip/upd77c25/)
obj/snes-necdsp.o : $(snes)/chip/necdsp/core/core.cpp $(call rwildcard,$(snes)/chip/necdsp/core/)
obj/snes-upd7725.o : $(snes)/chip/necdsp/upd7725/upd7725.cpp $(call rwildcard,$(snes)/chip/necdsp/)
obj/snes-upd96050.o: $(snes)/chip/necdsp/upd96050/upd96050.cpp $(call rwildcard,$(snes)/chip/necdsp/)
obj/snes-bsx.o : $(snes)/chip/bsx/bsx.cpp $(snes)/chip/bsx/*
obj/snes-srtc.o : $(snes)/chip/srtc/srtc.cpp $(snes)/chip/srtc/*
obj/snes-sdd1.o : $(snes)/chip/sdd1/sdd1.cpp $(snes)/chip/sdd1/*

View File

@ -28,7 +28,8 @@ void Cartridge::load(Mode cartridge_mode, const lstring &xml_list) {
has_bsx_slot = false;
has_superfx = false;
has_sa1 = false;
has_upd77c25 = false;
has_upd7725 = false;
has_upd96050 = false;
has_srtc = false;
has_sdd1 = false;
has_spc7110 = false;

View File

@ -35,7 +35,8 @@ public:
readonly<bool> has_bsx_slot;
readonly<bool> has_superfx;
readonly<bool> has_sa1;
readonly<bool> has_upd77c25;
readonly<bool> has_upd7725;
readonly<bool> has_upd96050;
readonly<bool> has_srtc;
readonly<bool> has_sdd1;
readonly<bool> has_spc7110;
@ -84,7 +85,8 @@ private:
void xml_parse_icd2(xml_element&);
void xml_parse_superfx(xml_element&);
void xml_parse_sa1(xml_element&);
void xml_parse_upd77c25(xml_element&);
void xml_parse_upd7725(xml_element&);
void xml_parse_upd96050(xml_element&);
void xml_parse_bsx(xml_element&);
void xml_parse_sufamiturbo(xml_element&);
void xml_parse_supergameboy(xml_element&);

View File

@ -35,7 +35,8 @@ void Cartridge::parse_xml_cartridge(const char *data) {
if(node.name == "icd2") xml_parse_icd2(node);
if(node.name == "superfx") xml_parse_superfx(node);
if(node.name == "sa1") xml_parse_sa1(node);
if(node.name == "upd77c25") xml_parse_upd77c25(node);
if(node.name == "upd7725") xml_parse_upd7725(node);
if(node.name == "upd96050") xml_parse_upd96050(node);
if(node.name == "bsx") xml_parse_bsx(node);
if(node.name == "sufamiturbo") xml_parse_sufamiturbo(node);
if(node.name == "srtc") xml_parse_srtc(node);
@ -229,16 +230,16 @@ void Cartridge::xml_parse_sa1(xml_element &root) {
}
}
void Cartridge::xml_parse_upd77c25(xml_element &root) {
has_upd77c25 = true;
void Cartridge::xml_parse_upd7725(xml_element &root) {
has_upd7725 = true;
bool program = false;
bool sha256 = false;
string xml_hash;
string rom_hash;
for(unsigned n = 0; n < 2048; n++) upd77c25.programROM[n] = 0;
for(unsigned n = 0; n < 1024; n++) upd77c25.dataROM[n] = 0;
for(unsigned n = 0; n < 2048; n++) upd7725.programROM[n] = 0;
for(unsigned n = 0; n < 1024; n++) upd7725.dataROM[n] = 0;
foreach(attr, root.attribute) {
if(attr.name == "program") {
@ -248,10 +249,10 @@ void Cartridge::xml_parse_upd77c25(xml_element &root) {
program = true;
for(unsigned n = 0; n < 2048; n++) {
upd77c25.programROM[n] = fp.readm(3);
upd7725.programROM[n] = fp.readm(3);
}
for(unsigned n = 0; n < 1024; n++) {
upd77c25.dataROM[n] = fp.readm(2);
upd7725.dataROM[n] = fp.readm(2);
}
fp.seek(0);
@ -277,7 +278,7 @@ void Cartridge::xml_parse_upd77c25(xml_element &root) {
if(node.name == "dr") {
foreach(leaf, node.element) {
if(leaf.name == "map") {
Mapping m(upd77c25dr);
Mapping m(upd7725dr);
foreach(attr, leaf.attribute) {
if(attr.name == "address") xml_parse_address(m, attr.content);
}
@ -287,7 +288,7 @@ void Cartridge::xml_parse_upd77c25(xml_element &root) {
} else if(node.name == "sr") {
foreach(leaf, node.element) {
if(leaf.name == "map") {
Mapping m(upd77c25sr);
Mapping m(upd7725sr);
foreach(attr, leaf.attribute) {
if(attr.name == "address") xml_parse_address(m, attr.content);
}
@ -298,10 +299,75 @@ void Cartridge::xml_parse_upd77c25(xml_element &root) {
}
if(program == false) {
system.interface->message("Warning: uPD77C25 program is missing.");
system.interface->message("Warning: uPD7725 program is missing.");
} else if(sha256 == true && xml_hash != rom_hash) {
system.interface->message({
"Warning: uPD77C25 program SHA256 is incorrect.\n\n"
"Warning: uPD7725 program SHA256 is incorrect.\n\n"
"Expected:\n", xml_hash, "\n\n"
"Actual:\n", rom_hash
});
}
}
void Cartridge::xml_parse_upd96050(xml_element &root) {
has_upd96050 = true;
bool program = false;
bool sha256 = false;
string xml_hash;
string rom_hash;
for(unsigned n = 0; n < 16384; n++) upd96050.programROM[n] = 0;
for(unsigned n = 0; n < 2048; n++) upd96050.dataROM[n] = 0;
foreach(attr, root.attribute) {
if(attr.name == "program") {
file fp;
fp.open(string(dir(basename()), attr.content), file::mode::read);
if(fp.open() && fp.size() == 52 * 1024) {
program = true;
for(unsigned n = 0; n < 16384; n++) {
upd96050.programROM[n] = fp.readm(3);
}
for(unsigned n = 0; n < 1024; n++) {
upd96050.dataROM[n] = fp.readm(2);
}
fp.seek(0);
uint8 data[52 * 1024];
fp.read(data, 52 * 1024);
fp.close();
sha256_ctx sha;
uint8 shahash[32];
sha256_init(&sha);
sha256_chunk(&sha, data, 52 * 1024);
sha256_final(&sha);
sha256_hash(&sha, shahash);
foreach(n, shahash) rom_hash.append(hex<2>(n));
}
} else if(attr.name == "sha256") {
sha256 = true;
xml_hash = attr.content;
}
}
foreach(node, root.element) {
if(node.name == "map") {
Mapping m(upd96050);
foreach(attr, node.attribute) {
if(attr.name == "address") xml_parse_address(m, attr.content);
}
mapping.append(m);
}
}
if(program == false) {
system.interface->message("Warning: uPD96050 program is missing.");
} else if(sha256 == true && xml_hash != rom_hash) {
system.interface->message({
"Warning: uPD96050 program SHA256 is incorrect.\n\n"
"Expected:\n", xml_hash, "\n\n"
"Actual:\n", rom_hash
});

View File

@ -6,7 +6,9 @@ struct Coprocessor : Processor {
#include <snes/chip/icd2/icd2.hpp>
#include <snes/chip/superfx/superfx.hpp>
#include <snes/chip/sa1/sa1.hpp>
#include <snes/chip/upd77c25/upd77c25.hpp>
#include <snes/chip/necdsp/core/core.hpp>
#include <snes/chip/necdsp/upd7725/upd7725.hpp>
#include <snes/chip/necdsp/upd96050/upd96050.hpp>
#include <snes/chip/bsx/bsx.hpp>
#include <snes/chip/srtc/srtc.hpp>
#include <snes/chip/sdd1/sdd1.hpp>

View File

@ -1,50 +1,27 @@
//NEC uPD77C25 emulation core
//author: byuu
//license: public domain
//unsupported components:
//* serial input/output
//* interrupts
//* DMA
#include <snes/snes.hpp>
#define UPD77C25_CPP
#define UPDCORE_CPP
namespace SNES {
#include "serialization.cpp"
#include "disassembler.cpp"
#include "serialization.cpp"
UPD77C25 upd77c25;
UPD77C25SR upd77c25sr;
UPD77C25DR upd77c25dr;
void UPD77C25::Enter() { upd77c25.enter(); }
void UPD77C25::enter() {
while(true) {
if(scheduler.sync == Scheduler::SynchronizeMode::All) {
scheduler.exit(Scheduler::ExitReason::SynchronizeEvent);
}
uint24 opcode = programROM[regs.pc++];
switch(opcode >> 22) {
case 0: exec_op(opcode); break;
case 1: exec_rt(opcode); break;
case 2: exec_jp(opcode); break;
case 3: exec_ld(opcode); break;
}
int32 result = (int32)regs.k * regs.l; //sign + 30-bit result
regs.m = result >> 15; //store sign + top 15-bits
regs.n = result << 1; //store low 15-bits + zero
step(1);
synchronize_cpu();
void uPDcore::exec() {
uint24 opcode = programROM[regs.pc];
regs.pc = regs.pc + 1;
switch(opcode >> 22) {
case 0: exec_op(opcode); break;
case 1: exec_rt(opcode); break;
case 2: exec_jp(opcode); break;
case 3: exec_ld(opcode); break;
}
int32 result = (int32)regs.k * regs.l; //sign + 30-bit result
regs.m = result >> 15; //store sign + top 15-bits
regs.n = result << 1; //store low 15-bits + zero
}
void UPD77C25::exec_op(uint24 opcode) {
void uPDcore::exec_op(uint24 opcode) {
uint2 pselect = opcode >> 20; //P select
uint4 alu = opcode >> 16; //ALU operation mode
uint1 asl = opcode >> 15; //accumulator select
@ -162,17 +139,17 @@ void UPD77C25::exec_op(uint24 opcode) {
case 3: regs.dp = (regs.dp & 0xf0); break; //DPCLR
}
regs.dp ^= dphm << 4;
regs.dp = regs.dp ^ (dphm << 4);
if(rpdcr) regs.rp--;
if(rpdcr) regs.rp = regs.rp - 1;
}
void UPD77C25::exec_rt(uint24 opcode) {
void uPDcore::exec_rt(uint24 opcode) {
exec_op(opcode);
stack_pull();
}
void UPD77C25::exec_jp(uint24 opcode) {
void uPDcore::exec_jp(uint24 opcode) {
uint9 brch = opcode >> 13; //branch
uint11 na = opcode >> 2; //next address
@ -225,7 +202,7 @@ void UPD77C25::exec_jp(uint24 opcode) {
if(r) regs.pc = na;
}
void UPD77C25::exec_ld(uint24 opcode) {
void uPDcore::exec_ld(uint24 opcode) {
uint16 id = opcode >> 6; //immediate data
uint4 dst = opcode >> 0; //destination
@ -251,94 +228,47 @@ void UPD77C25::exec_ld(uint24 opcode) {
}
}
void UPD77C25::stack_push() {
void uPDcore::stack_push() {
regs.stack[7] = regs.stack[6];
regs.stack[6] = regs.stack[5];
regs.stack[5] = regs.stack[4];
regs.stack[4] = regs.stack[3];
regs.stack[3] = regs.stack[2];
regs.stack[2] = regs.stack[1];
regs.stack[1] = regs.stack[0];
regs.stack[0] = regs.pc;
}
void UPD77C25::stack_pull() {
void uPDcore::stack_pull() {
regs.pc = regs.stack[0];
regs.stack[0] = regs.stack[1];
regs.stack[1] = regs.stack[2];
regs.stack[2] = regs.stack[3];
regs.stack[3] = 0x000;
regs.stack[3] = regs.stack[4];
regs.stack[4] = regs.stack[5];
regs.stack[5] = regs.stack[6];
regs.stack[6] = regs.stack[7];
regs.stack[7] = 0x0000;
}
uint8 UPD77C25::read(bool mode) {
cpu.synchronize_coprocessor();
if(mode == 0) return regs.sr >> 8;
uPDcore::uPDcore(unsigned pcbits, unsigned rpbits, unsigned dpbits) {
programROMSize = 1 << pcbits;
dataROMSize = 1 << rpbits;
dataRAMSize = 1 << dpbits;
if(regs.sr.drc == 0) {
//16-bit
if(regs.sr.drs == 0) {
regs.sr.drs = 1;
return regs.dr >> 0;
} else {
regs.sr.rqm = 0;
regs.sr.drs = 0;
return regs.dr >> 8;
}
} else {
//8-bit
regs.sr.rqm = 0;
return regs.dr >> 0;
}
programROM = new uint24[programROMSize];
dataROM = new uint16[dataROMSize];
dataRAM = new uint16[dataRAMSize];
regs.pc.mask = programROMSize - 1;
regs.rp.mask = dataROMSize - 1;
regs.dp.mask = dataRAMSize - 1;
}
void UPD77C25::write(bool mode, uint8 data) {
cpu.synchronize_coprocessor();
if(mode == 0) return;
if(regs.sr.drc == 0) {
//16-bit
if(regs.sr.drs == 0) {
regs.sr.drs = 1;
regs.dr = (regs.dr & 0xff00) | (data << 0);
} else {
regs.sr.rqm = 0;
regs.sr.drs = 0;
regs.dr = (data << 8) | (regs.dr & 0x00ff);
}
} else {
//8-bit
regs.sr.rqm = 0;
regs.dr = (regs.dr & 0xff00) | (data << 0);
}
uPDcore::~uPDcore() {
delete[] programROM;
delete[] dataROM;
delete[] dataRAM;
}
void UPD77C25::init() {
}
void UPD77C25::enable() {
}
void UPD77C25::power() {
for(unsigned i = 0; i < 256; i++) dataRAM[i] = 0x0000;
reset();
}
void UPD77C25::reset() {
create(UPD77C25::Enter, 8 * 1024 * 1024); //8.192MHz
regs.pc = 0x000;
regs.stack[0] = 0x000;
regs.stack[1] = 0x000;
regs.stack[2] = 0x000;
regs.stack[3] = 0x000;
regs.flaga = 0x00;
regs.flagb = 0x00;
regs.sr = 0x0000;
regs.rp = 0x3ff;
regs.siack = 0;
regs.soack = 0;
}
uint8 UPD77C25SR::read(unsigned) { return upd77c25.read(0); }
void UPD77C25SR::write(unsigned, uint8 data) { upd77c25.write(0, data); }
uint8 UPD77C25DR::read(unsigned) { return upd77c25.read(1); }
void UPD77C25DR::write(unsigned, uint8 data) { upd77c25.write(1, data); }
}

View File

@ -0,0 +1,26 @@
class uPDcore {
public:
#include "registers.hpp"
uint24 *programROM;
uint16 *dataROM;
uint16 *dataRAM;
unsigned programROMSize;
unsigned dataROMSize;
unsigned dataRAMSize;
void exec();
void exec_op(uint24 opcode);
void exec_rt(uint24 opcode);
void exec_jp(uint24 opcode);
void exec_ld(uint24 opcode);
void stack_push();
void stack_pull();
string disassemble(uint11 ip);
void serialize(serializer&);
uPDcore(unsigned pcbits, unsigned rpbits, unsigned dpbits);
~uPDcore();
};

View File

@ -1,4 +1,6 @@
string UPD77C25::disassemble(uint11 ip) {
#ifdef UPDCORE_CPP
string uPDcore::disassemble(uint11 ip) {
string output = { hex<3>(ip), " " };
uint24 opcode = programROM[ip];
uint2 type = opcode >> 22;
@ -203,3 +205,5 @@ string UPD77C25::disassemble(uint11 ip) {
return output;
}
#endif

View File

@ -0,0 +1,66 @@
struct Pointer {
uint16 data;
uint16 mask;
inline operator unsigned() const {
return data;
}
inline unsigned operator=(unsigned d) {
return data = d & mask;
}
};
struct Flag {
bool s1, s0, c, z, ov1, ov0;
inline operator unsigned() const {
return (s1 << 5) + (s0 << 4) + (c << 3) + (z << 2) + (ov1 << 1) + (ov0 << 0);
}
inline unsigned operator=(unsigned d) {
s1 = d & 0x20; s0 = d & 0x10; c = d & 0x08; z = d & 0x04; ov1 = d & 0x02; ov0 = d & 0x01;
return d;
}
};
struct Status {
bool rqm, usf1, usf0, drs, dma, drc, soc, sic, ei, p1, p0;
inline operator unsigned() const {
return (rqm << 15) + (usf1 << 14) + (usf0 << 13) + (drs << 12)
+ (dma << 11) + (drc << 10) + (soc << 9) + (sic << 8)
+ (ei << 7) + (p1 << 1) + (p0 << 0);
}
inline unsigned operator=(unsigned d) {
rqm = d & 0x8000; usf1 = d & 0x4000; usf0 = d & 0x2000; drs = d & 0x1000;
dma = d & 0x0800; drc = d & 0x0400; soc = d & 0x0200; sic = d & 0x0100;
ei = d & 0x0080; p1 = d & 0x0002; p0 = d & 0x0001;
return d;
}
};
//11,11,10,8 and 14,14,11,11
struct Regs {
Pointer pc; //program counter
Pointer rp; //ROM pointer
Pointer dp; //data pointer
uint16 stack[8]; //LIFO
int16 k;
int16 l;
int16 m;
int16 n;
int16 a; //accumulator
int16 b; //accumulator
Flag flaga;
Flag flagb;
uint16 tr; //temporary register
uint16 trb; //temporary register
Status sr; //status register
uint16 dr; //data register
bool siack;
bool soack;
uint16 idb;
} regs;

View File

@ -1,12 +1,19 @@
#ifdef UPD77C25_CPP
#ifdef UPDCORE_CPP
void UPD77C25::serialize(serializer &s) {
s.array(dataRAM);
void uPDcore::serialize(serializer &s) {
s.array(dataRAM, dataRAMSize);
s.integer(regs.pc.data);
s.integer(regs.pc.mask);
s.integer(regs.rp.data);
s.integer(regs.rp.mask);
s.integer(regs.dp.data);
s.integer(regs.dp.mask);
s.array(regs.stack);
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);

View File

@ -0,0 +1,112 @@
#include <snes/snes.hpp>
#define UPD7725_CPP
namespace SNES {
uPD7725 upd7725;
uPD7725SR upd7725sr;
uPD7725DR upd7725dr;
void uPD7725::Enter() { upd7725.enter(); }
void uPD7725::enter() {
while(true) {
if(scheduler.sync == Scheduler::SynchronizeMode::All) {
scheduler.exit(Scheduler::ExitReason::SynchronizeEvent);
}
uPDcore::exec();
step(1);
synchronize_cpu();
}
}
uint8 uPD7725::read(bool mode) {
cpu.synchronize_coprocessor();
if(mode == 0) return regs.sr >> 8;
if(regs.sr.drc == 0) {
//16-bit
if(regs.sr.drs == 0) {
regs.sr.drs = 1;
return regs.dr >> 0;
} else {
regs.sr.rqm = 0;
regs.sr.drs = 0;
return regs.dr >> 8;
}
} else {
//8-bit
regs.sr.rqm = 0;
return regs.dr >> 0;
}
}
void uPD7725::write(bool mode, uint8 data) {
cpu.synchronize_coprocessor();
if(mode == 0) return;
if(regs.sr.drc == 0) {
//16-bit
if(regs.sr.drs == 0) {
regs.sr.drs = 1;
regs.dr = (regs.dr & 0xff00) | (data << 0);
} else {
regs.sr.rqm = 0;
regs.sr.drs = 0;
regs.dr = (data << 8) | (regs.dr & 0x00ff);
}
} else {
//8-bit
regs.sr.rqm = 0;
regs.dr = (regs.dr & 0xff00) | (data << 0);
}
}
void uPD7725::init() {
}
void uPD7725::enable() {
}
void uPD7725::power() {
for(unsigned i = 0; i < 256; i++) dataRAM[i] = 0x0000;
reset();
}
void uPD7725::reset() {
create(uPD7725::Enter, 8 * 1024 * 1024); //8.192MHz
regs.pc = 0x000;
regs.stack[0] = 0x000;
regs.stack[1] = 0x000;
regs.stack[2] = 0x000;
regs.stack[3] = 0x000;
regs.flaga = 0x00;
regs.flagb = 0x00;
regs.sr = 0x0000;
regs.rp = 0x3ff;
regs.siack = 0;
regs.soack = 0;
}
void uPD7725::serialize(serializer &s) {
Coprocessor::serialize(s);
uPDcore::serialize(s);
}
uPD7725::uPD7725() : uPDcore(11, 10, 8) {
//NEC uPD7725:
//8.192 MIPS (8.192MHz / 1)
//11-bit ProgramROM (2048 x 24-bit) w/4-level stack
//10-bit DataROM (1024 x 16-bit)
// 8-bit DataRAM ( 256 x 16-bit)
}
uint8 uPD7725SR::read(unsigned) { return upd7725.read(0); }
void uPD7725SR::write(unsigned, uint8 data) { upd7725.write(0, data); }
uint8 uPD7725DR::read(unsigned) { return upd7725.read(1); }
void uPD7725DR::write(unsigned, uint8 data) { upd7725.write(1, data); }
}

View File

@ -0,0 +1,33 @@
class uPD7725 : public Coprocessor, public uPDcore {
public:
static void Enter();
void enter();
void init();
void enable();
void power();
void reset();
void serialize(serializer&);
uPD7725();
private:
uint8 read(bool mode);
void write(bool mode, uint8 data);
friend class uPD7725SR;
friend class uPD7725DR;
};
class uPD7725SR : public Memory {
uint8 read(unsigned addr);
void write(unsigned addr, uint8 data);
};
class uPD7725DR : public Memory {
uint8 read(unsigned addr);
void write(unsigned addr, uint8 data);
};
extern uPD7725 upd7725;
extern uPD7725SR upd7725sr;
extern uPD7725DR upd7725dr;

View File

@ -0,0 +1,94 @@
#include <snes/snes.hpp>
#define UPD96050_CPP
namespace SNES {
uPD96050 upd96050;
void uPD96050::Enter() { upd96050.enter(); }
void uPD96050::enter() {
while(true) {
if(scheduler.sync == Scheduler::SynchronizeMode::All) {
scheduler.exit(Scheduler::ExitReason::SynchronizeEvent);
}
uPDcore::exec();
step(2);
synchronize_cpu();
}
}
uint8 uPD96050::read(unsigned addr) {
cpu.synchronize_coprocessor();
regs.sr.rqm = 0;
bool hi = addr & 1;
addr = (addr >> 1) & 2047;
if(hi == false) {
return dataRAM[addr] >> 0;
} else {
return dataRAM[addr] >> 8;
}
}
void uPD96050::write(unsigned addr, uint8 data) {
cpu.synchronize_coprocessor();
regs.sr.rqm = 0;
bool hi = addr & 1;
addr = (addr >> 1) & 2047;
if(hi == false) {
dataRAM[addr] = (dataRAM[addr] & 0xff00) | (data << 0);
} else {
dataRAM[addr] = (dataRAM[addr] & 0x00ff) | (data << 8);
}
}
void uPD96050::init() {
}
void uPD96050::enable() {
}
void uPD96050::power() {
for(unsigned i = 0; i < 2048; i++) dataRAM[i] = 0x0000;
reset();
}
void uPD96050::reset() {
create(uPD96050::Enter, 20 * 1000 * 1000); //20MHz
regs.pc = 0x0000;
regs.stack[0] = 0x0000;
regs.stack[1] = 0x0000;
regs.stack[2] = 0x0000;
regs.stack[3] = 0x0000;
regs.stack[4] = 0x0000;
regs.stack[5] = 0x0000;
regs.stack[6] = 0x0000;
regs.stack[7] = 0x0000;
regs.flaga = 0x00;
regs.flagb = 0x00;
regs.sr = 0x0000;
regs.rp = 0x03ff;
regs.siack = 0;
regs.soack = 0;
}
void uPD96050::serialize(serializer &s) {
Coprocessor::serialize(s);
uPDcore::serialize(s);
}
uPD96050::uPD96050() : uPDcore(14, 11, 11) {
//NEC uPD96050:
//10MIPS (20MHz / 2)
//14-bit ProgramROM (16384 x 24-bit) w/8-level stack
//11-bit DataROM ( 2048 x 16-bit)
//11-bit DataRAM ( 2048 x 16-bit) w/battery backup
}
}

View File

@ -0,0 +1,17 @@
class uPD96050 : public Coprocessor, public uPDcore, public Memory {
public:
static void Enter();
void enter();
void init();
void enable();
void power();
void reset();
uint8 read(unsigned addr);
void write(unsigned addr, uint8 data);
void serialize(serializer&);
uPD96050();
};
extern uPD96050 upd96050;

View File

@ -1,98 +0,0 @@
class UPD77C25 : public Coprocessor {
public:
static void Enter();
void enter();
void init();
void enable();
void power();
void reset();
void serialize(serializer &s);
uint24 programROM[2048];
uint16 dataROM[1024];
uint16 dataRAM[256];
string disassemble(uint11 ip);
private:
struct Flag {
bool s1, s0, c, z, ov1, ov0;
inline operator unsigned() const {
return (s1 << 5) + (s0 << 4) + (c << 3) + (z << 2) + (ov1 << 1) + (ov0 << 0);
}
inline unsigned operator=(unsigned d) {
s1 = d & 0x20; s0 = d & 0x10; c = d & 0x08; z = d & 0x04; ov1 = d & 0x02; ov0 = d & 0x01;
return d;
}
};
struct Status {
bool rqm, usf1, usf0, drs, dma, drc, soc, sic, ei, p1, p0;
inline operator unsigned() const {
return (rqm << 15) + (usf1 << 14) + (usf0 << 13) + (drs << 12)
+ (dma << 11) + (drc << 10) + (soc << 9) + (sic << 8)
+ (ei << 7) + (p1 << 1) + (p0 << 0);
}
inline unsigned operator=(unsigned d) {
rqm = d & 0x8000; usf1 = d & 0x4000; usf0 = d & 0x2000; drs = d & 0x1000;
dma = d & 0x0800; drc = d & 0x0400; soc = d & 0x0200; sic = d & 0x0100;
ei = d & 0x0080; p1 = d & 0x0002; p0 = d & 0x0001;
return d;
}
};
struct Regs {
uint11 pc; //program counter
uint11 stack[4]; //LIFO
uint10 rp; //ROM pointer
uint8 dp; //data pointer
int16 k;
int16 l;
int16 m;
int16 n;
int16 a; //accumulator
int16 b; //accumulator
Flag flaga;
Flag flagb;
uint16 tr; //temporary register
uint16 trb; //temporary register
Status sr; //status register
uint16 dr; //data register
bool siack;
bool soack;
uint16 idb;
} regs;
void exec_op(uint24 opcode);
void exec_rt(uint24 opcode);
void exec_jp(uint24 opcode);
void exec_ld(uint24 opcode);
void stack_push();
void stack_pull();
uint8 read(bool mode);
void write(bool mode, uint8 data);
friend class UPD77C25SR;
friend class UPD77C25DR;
};
class UPD77C25SR : public Memory {
uint8 read(unsigned addr);
void write(unsigned addr, uint8 data);
};
class UPD77C25DR : public Memory {
uint8 read(unsigned addr);
void write(unsigned addr, uint8 data);
};
extern UPD77C25 upd77c25;
extern UPD77C25SR upd77c25sr;
extern UPD77C25DR upd77c25dr;

View File

@ -1,7 +1,7 @@
namespace SNES {
namespace Info {
static const char Name[] = "bsnes";
static const char Version[] = "073.04";
static const char Version[] = "073.05";
static const unsigned SerializerVersion = 16;
}
}

View File

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

View File

@ -71,7 +71,8 @@ void System::init(Interface *interface_) {
icd2.init();
superfx.init();
sa1.init();
upd77c25.init();
upd7725.init();
upd96050.init();
bsxbase.init();
bsxcart.init();
bsxflash.init();
@ -123,7 +124,8 @@ void System::power() {
if(cartridge.has_superfx()) superfx.enable();
if(cartridge.has_sa1()) sa1.enable();
if(cartridge.has_upd77c25()) upd77c25.enable();
if(cartridge.has_upd7725()) upd7725.enable();
if(cartridge.has_upd96050()) upd96050.enable();
if(cartridge.has_srtc()) srtc.enable();
if(cartridge.has_sdd1()) sdd1.enable();
if(cartridge.has_spc7110()) spc7110.enable();
@ -147,7 +149,8 @@ void System::power() {
if(cartridge.has_superfx()) superfx.power();
if(cartridge.has_sa1()) sa1.power();
if(cartridge.has_upd77c25()) upd77c25.power();
if(cartridge.has_upd7725()) upd7725.power();
if(cartridge.has_upd96050()) upd96050.power();
if(cartridge.has_srtc()) srtc.power();
if(cartridge.has_sdd1()) sdd1.power();
if(cartridge.has_spc7110()) spc7110.power();
@ -162,7 +165,8 @@ void System::power() {
if(cartridge.mode() == Cartridge::Mode::SuperGameBoy) cpu.coprocessors.append(&icd2);
if(cartridge.has_superfx()) cpu.coprocessors.append(&superfx);
if(cartridge.has_sa1()) cpu.coprocessors.append(&sa1);
if(cartridge.has_upd77c25()) cpu.coprocessors.append(&upd77c25);
if(cartridge.has_upd7725()) cpu.coprocessors.append(&upd7725);
if(cartridge.has_upd96050()) cpu.coprocessors.append(&upd96050);
if(cartridge.has_msu1()) cpu.coprocessors.append(&msu1);
if(cartridge.has_serial()) cpu.coprocessors.append(&serial);
@ -187,7 +191,8 @@ void System::reset() {
if(cartridge.has_superfx()) superfx.reset();
if(cartridge.has_sa1()) sa1.reset();
if(cartridge.has_upd77c25()) upd77c25.reset();
if(cartridge.has_upd7725()) upd7725.reset();
if(cartridge.has_upd96050()) upd96050.reset();
if(cartridge.has_srtc()) srtc.reset();
if(cartridge.has_sdd1()) sdd1.reset();
if(cartridge.has_spc7110()) spc7110.reset();
@ -202,7 +207,8 @@ void System::reset() {
if(cartridge.mode() == Cartridge::Mode::SuperGameBoy) cpu.coprocessors.append(&icd2);
if(cartridge.has_superfx()) cpu.coprocessors.append(&superfx);
if(cartridge.has_sa1()) cpu.coprocessors.append(&sa1);
if(cartridge.has_upd77c25()) cpu.coprocessors.append(&upd77c25);
if(cartridge.has_upd7725()) cpu.coprocessors.append(&upd7725);
if(cartridge.has_upd96050()) cpu.coprocessors.append(&upd96050);
if(cartridge.has_msu1()) cpu.coprocessors.append(&msu1);
if(cartridge.has_serial()) cpu.coprocessors.append(&serial);