Update to v089r06 release.

[Yes, the release number is re-used. -Ed.]

byuu says:

I had some bugs in r07 that I couldn't track down, DKJM2's clock was
getting all out of sync.
So I just reverted to r05, blew away both RTCs entirely, and wrote them
cleanly from scratch (obviously looking off the old code.) A bit
extreme, but it worked.
I believe I found the error in the process, day and month were resetting
the counter to 0 instead of 1, it wasn't handling leap year, etc.
While I was at it, I fixed the day-of-week calculation. The SharpRTC
epoch is actually 1000-01-01, and not 1900-01-01.
I'm sure you guys will be really happy that if it ever becomes 1000AD
again and you're playing a ROM hack that uses the SharpRTC and relies on
its weekday value that it will show the correct day now ...
Kind of a pain to compute, but nothing compared to the seventh circle of
hell that was my IBM dBase III Julian<>Gregorian conversion functions :/
Also found a few bugs in the Epson code this way. And I moved the round
seconds actions and flag clear to +125us after flag set.

So, if you had the old r06 or r07, please delete those.

Unfortunately, this took all of my energy today, so the file names
inside manifest changes will have to be in the next WIP.

EDIT: ran a diff against old r07 and new r06.
- added if(days == 31) case twice in EpsonRTC::tick_day()
- forgot weekday = 0; in SharpRTC::load()
- need to move the cartridge+cheat objects up in sfc/Makefile again
- System::init() needs assert(interface != nullptr /* not 0 */)
This commit is contained in:
Tim Allen
2012-05-25 09:26:06 +10:00
parent 5dbd5f4d0f
commit d418eda97c
15 changed files with 166 additions and 155 deletions

View File

@@ -3,7 +3,7 @@
namespace Emulator { namespace Emulator {
static const char Name[] = "bsnes"; static const char Name[] = "bsnes";
static const char Version[] = "089.07"; static const char Version[] = "089.06";
static const char Author[] = "byuu"; static const char Author[] = "byuu";
static const char License[] = "GPLv3"; static const char License[] = "GPLv3";
} }

View File

@@ -32,13 +32,13 @@ endif
obj/sfc-interface.o : $(sfc)/interface/interface.cpp $(call rwildcard,$(sfc)/interface) obj/sfc-interface.o : $(sfc)/interface/interface.cpp $(call rwildcard,$(sfc)/interface)
obj/sfc-system.o : $(sfc)/system/system.cpp $(call rwildcard,$(sfc)/system/) obj/sfc-system.o : $(sfc)/system/system.cpp $(call rwildcard,$(sfc)/system/)
obj/sfc-controller.o: $(sfc)/controller/controller.cpp $(call rwildcard,$(sfc)/controller/) obj/sfc-controller.o: $(sfc)/controller/controller.cpp $(call rwildcard,$(sfc)/controller/)
obj/sfc-cartridge.o : $(sfc)/cartridge/cartridge.cpp $(sfc)/cartridge/*
obj/sfc-cheat.o : $(sfc)/cheat/cheat.cpp $(sfc)/cheat/*
obj/sfc-memory.o : $(sfc)/memory/memory.cpp $(call rwildcard,$(sfc)/memory/) obj/sfc-memory.o : $(sfc)/memory/memory.cpp $(call rwildcard,$(sfc)/memory/)
obj/sfc-cpu.o : $(sfccpu)/cpu.cpp $(call rwildcard,$(sfccpu)/) obj/sfc-cpu.o : $(sfccpu)/cpu.cpp $(call rwildcard,$(sfccpu)/)
obj/sfc-smp.o : $(sfcsmp)/smp.cpp $(call rwildcard,$(sfcsmp)/) obj/sfc-smp.o : $(sfcsmp)/smp.cpp $(call rwildcard,$(sfcsmp)/)
obj/sfc-dsp.o : $(sfcdsp)/dsp.cpp $(call rwildcard,$(sfcdsp)/) obj/sfc-dsp.o : $(sfcdsp)/dsp.cpp $(call rwildcard,$(sfcdsp)/)
obj/sfc-ppu.o : $(sfcppu)/ppu.cpp $(call rwildcard,$(sfcppu)/) obj/sfc-ppu.o : $(sfcppu)/ppu.cpp $(call rwildcard,$(sfcppu)/)
obj/sfc-cartridge.o : $(sfc)/cartridge/cartridge.cpp $(sfc)/cartridge/*
obj/sfc-cheat.o : $(sfc)/cheat/cheat.cpp $(sfc)/cheat/*
obj/sfc-icd2.o : $(sfc)/chip/icd2/icd2.cpp $(call rwildcard,$(sfc)/chip/icd2/) obj/sfc-icd2.o : $(sfc)/chip/icd2/icd2.cpp $(call rwildcard,$(sfc)/chip/icd2/)
obj/sfc-bsx.o : $(sfc)/chip/bsx/bsx.cpp $(call rwildcard,$(sfc)/chip/bsx/) obj/sfc-bsx.o : $(sfc)/chip/bsx/bsx.cpp $(call rwildcard,$(sfc)/chip/bsx/)
@@ -52,8 +52,8 @@ obj/sfc-armdsp.o : $(sfc)/chip/armdsp/armdsp.cpp $(call rwildcard,$(sfc)/chi
obj/sfc-hitachidsp.o : $(sfc)/chip/hitachidsp/hitachidsp.cpp $(call rwildcard,$(sfc)/chip/hitachidsp/) obj/sfc-hitachidsp.o : $(sfc)/chip/hitachidsp/hitachidsp.cpp $(call rwildcard,$(sfc)/chip/hitachidsp/)
obj/sfc-necdsp.o : $(sfc)/chip/necdsp/necdsp.cpp $(call rwildcard,$(sfc)/chip/necdsp/) obj/sfc-necdsp.o : $(sfc)/chip/necdsp/necdsp.cpp $(call rwildcard,$(sfc)/chip/necdsp/)
obj/sfc-epsonrtc.o : $(sfc)/chip/epsonrtc/epsonrtc.cpp $(sfc)/chip/epsonrtc/* obj/sfc-epsonrtc.o : $(sfc)/chip/epsonrtc/epsonrtc.cpp $(call rwildcard,$(sfc)/chip/epsonrtc/)
obj/sfc-sharprtc.o : $(sfc)/chip/sharprtc/sharprtc.cpp $(sfc)/chip/sharprtc/* obj/sfc-sharprtc.o : $(sfc)/chip/sharprtc/sharprtc.cpp $(call rwildcard,$(sfc)/chip/sharprtc/)
obj/sfc-spc7110.o : $(sfc)/chip/spc7110/spc7110.cpp $(sfc)/chip/spc7110/* obj/sfc-spc7110.o : $(sfc)/chip/spc7110/spc7110.cpp $(sfc)/chip/spc7110/*
obj/sfc-sdd1.o : $(sfc)/chip/sdd1/sdd1.cpp $(sfc)/chip/sdd1/* obj/sfc-sdd1.o : $(sfc)/chip/sdd1/sdd1.cpp $(sfc)/chip/sdd1/*

View File

@@ -18,18 +18,17 @@ void EpsonRTC::enter() {
scheduler.exit(Scheduler::ExitReason::SynchronizeEvent); scheduler.exit(Scheduler::ExitReason::SynchronizeEvent);
} }
if(wait) { if(--wait == 0) ready = true; } if(wait) { if(--wait == 0) ready = 1; }
clocks++; clocks++;
if((clocks & ~0x03fff) == 0) duty(); //1/128th second (frequency / 128 - 1) if((clocks & ~0x00ff) == 0) round_seconds(); //125 microseconds
if((clocks & ~0x07fff) == 0) irq(0); //1/ 64th second (frequency / 64 - 1) if((clocks & ~0x3fff) == 0) duty(); //1/128th second
if((clocks & ~0x3ffff) == 0) roundseconds = 0; //1/ 8th second (frequency / 8 - 1) if((clocks & ~0x7fff) == 0) irq(0); //1/64th second
if(clocks == 0) { //1 second if(clocks == 0) { //1 second
seconds++; seconds++;
irq(1); irq(1);
if(seconds % 60 == 0) irq(2); //1 minute if(seconds % 60 == 0) irq(2); //1 minute
if(seconds % 1440 == 0) irq(3); //1 hour if(seconds % 1440 == 0) irq(3), seconds = 0; //1 hour
if(seconds == 1440) seconds = 0;
tick(); tick();
} }
@@ -42,7 +41,7 @@ void EpsonRTC::init() {
} }
void EpsonRTC::load() { void EpsonRTC::load() {
if(cartridge.has_epsonrtc()) interface->memory.append({ID::EpsonRTC, "rtc.ram"}); interface->memory.append({ID::EpsonRTC, "rtc.ram"});
secondlo = 0; secondlo = 0;
secondhi = 0; secondhi = 0;
@@ -100,15 +99,15 @@ void EpsonRTC::reset() {
state = State::Mode; state = State::Mode;
offset = 0; offset = 0;
wait = 0; wait = 0;
ready = false; ready = 0;
holdtick = false; holdtick = 0;
} }
void EpsonRTC::sync() { void EpsonRTC::sync() {
time_t systime = time(0); time_t systime = time(0);
tm *timeinfo = localtime(&systime); tm *timeinfo = localtime(&systime);
unsigned second = min(59, timeinfo->tm_sec); //round down leap second unsigned second = min(59, timeinfo->tm_sec);
secondlo = second % 10; secondlo = second % 10;
secondhi = second / 10; secondhi = second / 10;
@@ -123,14 +122,10 @@ void EpsonRTC::sync() {
} else { } else {
meridian = hour >= 12; meridian = hour >= 12;
hour %= 12; hour %= 12;
if(hour == 0) { if(hour == 0) hour = 12;
hourlo = 2;
hourhi = 1;
} else {
hourlo = hour % 10; hourlo = hour % 10;
hourhi = hour / 10; hourhi = hour / 10;
} }
}
unsigned day = timeinfo->tm_mday; unsigned day = timeinfo->tm_mday;
daylo = day % 10; daylo = day % 10;
@@ -146,7 +141,7 @@ void EpsonRTC::sync() {
weekday = timeinfo->tm_wday; weekday = timeinfo->tm_wday;
resync = true; //alert RTC that time has changed resync = true; //alert program that time has changed
} }
uint8 EpsonRTC::read(unsigned addr) { uint8 EpsonRTC::read(unsigned addr) {
@@ -159,10 +154,10 @@ uint8 EpsonRTC::read(unsigned addr) {
if(addr == 1) { if(addr == 1) {
if(chipselect != 1) return 0; if(chipselect != 1) return 0;
if(ready == false) return 0; if(ready == 0) return 0;
if(state == State::Write) return mdr; if(state == State::Write) return mdr;
if(state != State::Read) return 0; if(state != State::Read) return 0;
ready = false; ready = 0;
wait = 8; wait = 8;
return rtc_read(offset++); return rtc_read(offset++);
} }
@@ -179,17 +174,17 @@ void EpsonRTC::write(unsigned addr, uint8 data) {
if(addr == 0) { if(addr == 0) {
chipselect = data; chipselect = data;
if(chipselect != 1) rtc_reset(); if(chipselect != 1) rtc_reset();
ready = true; ready = 1;
} }
if(addr == 1) { if(addr == 1) {
if(chipselect != 1) return; if(chipselect != 1) return;
if(ready == false) return; if(ready == 0) return;
if(state == State::Mode) { if(state == State::Mode) {
if(data != 0x03 && data != 0x0c) return; if(data != 0x03 && data != 0x0c) return;
state = State::Seek; state = State::Seek;
ready = false; ready = 0;
wait = 8; wait = 8;
mdr = data; mdr = data;
} }
@@ -197,16 +192,15 @@ void EpsonRTC::write(unsigned addr, uint8 data) {
else if(state == State::Seek) { else if(state == State::Seek) {
if(mdr == 0x03) state = State::Write; if(mdr == 0x03) state = State::Write;
if(mdr == 0x0c) state = State::Read; if(mdr == 0x0c) state = State::Read;
offset = data; offset = data;
ready = false; ready = 0;
wait = 8; wait = 8;
mdr = data; mdr = data;
} }
else if(state == State::Write) { else if(state == State::Write) {
rtc_write(offset++, data); rtc_write(offset++, data);
ready = false; ready = 0;
wait = 8; wait = 8;
mdr = data; mdr = data;
} }

View File

@@ -24,7 +24,7 @@ struct EpsonRTC : Coprocessor {
uint4 mdr; uint4 mdr;
uint4 offset; uint4 offset;
unsigned wait; unsigned wait;
bool ready; uint1 ready;
uint1 holdtick; uint1 holdtick;
uint4 secondlo; uint4 secondlo;
@@ -77,7 +77,9 @@ struct EpsonRTC : Coprocessor {
//time.cpp //time.cpp
void irq(uint2 period); void irq(uint2 period);
void duty(); void duty();
void round_seconds();
void tick(); void tick();
void tick_second(); void tick_second();
void tick_minute(); void tick_minute();
void tick_hour(); void tick_hour();

View File

@@ -10,7 +10,7 @@ void EpsonRTC::rtc_reset() {
} }
uint4 EpsonRTC::rtc_read(uint4 addr) { uint4 EpsonRTC::rtc_read(uint4 addr) {
switch(addr) { switch(addr) { default:
case 0: return secondlo; case 0: return secondlo;
case 1: return secondhi | batteryfailure << 3; case 1: return secondhi | batteryfailure << 3;
case 2: return minutelo; case 2: return minutelo;
@@ -85,19 +85,12 @@ void EpsonRTC::rtc_write(uint4 addr, uint4 data) {
bool held = hold; bool held = hold;
hold = data; hold = data;
calendar = data >> 1; calendar = data >> 1;
//irqflag cannot be set manually
roundseconds = data >> 3; roundseconds = data >> 3;
if(held == 1 && hold == 0 && holdtick) { if(held == 1 && hold == 0 && holdtick == 1) {
//if a second has passed during hold; increment one second upon resuming //if a second has passed during hold, increment one second upon resuming
holdtick = false; holdtick = 0;
tick_second(); tick_second();
} }
if(roundseconds) {
roundseconds = 0;
if(secondhi >= 3) tick_minute();
secondlo = 0;
secondhi = 0;
}
} break; } break;
case 14: case 14:
irqmask = data; irqmask = data;

View File

@@ -1,8 +1,7 @@
#ifdef EPSONRTC_CPP #ifdef EPSONRTC_CPP
void EpsonRTC::irq(uint2 period) { void EpsonRTC::irq(uint2 period) {
if(stop) return; if(stop || pause) return;
if(pause) return;
if(period == irqperiod) irqflag = 1; if(period == irqperiod) irqflag = 1;
} }
@@ -11,20 +10,29 @@ void EpsonRTC::duty() {
if(irqduty) irqflag = 0; if(irqduty) irqflag = 0;
} }
void EpsonRTC::round_seconds() {
if(roundseconds == 0) return;
roundseconds = 0;
if(secondhi >= 3) tick_minute();
secondlo = 0;
secondhi = 0;
}
void EpsonRTC::tick() { void EpsonRTC::tick() {
if(stop) return; if(stop || pause) return;
if(pause) return;
if(hold) { if(hold) {
holdtick = true; holdtick = 1;
return; return;
} }
resync = true; resync = 1;
tick_second(); tick_second();
} }
//below code provides bit-perfect emulation of invalid BCD values on the RTC-4513 //below code provides bit-perfect emulation of invalid BCD values on the RTC-4513
//code makes extensive use of variable-length integers (see epsonrtc.hpp for sizes)
void EpsonRTC::tick_second() { void EpsonRTC::tick_second() {
if(secondlo <= 8 || secondlo == 12) { if(secondlo <= 8 || secondlo == 12) {
@@ -99,7 +107,7 @@ void EpsonRTC::tick_hour() {
} }
void EpsonRTC::tick_day() { void EpsonRTC::tick_day() {
if(calendar == false) return; if(calendar == 0) return;
weekday = (weekday + 1) + (weekday == 6); weekday = (weekday + 1) + (weekday == 6);
//January - December = 0x01 - 0x09; 0x10 - 0x12 //January - December = 0x01 - 0x09; 0x10 - 0x12
@@ -139,6 +147,12 @@ void EpsonRTC::tick_day() {
return tick_month(); return tick_month();
} }
if(days == 31 && (dayhi == 3 && (daylo & 3))) {
daylo = 1;
dayhi = 0;
return tick_month();
}
if(daylo <= 8 || daylo == 12) { if(daylo <= 8 || daylo == 12) {
daylo++; daylo++;
} else { } else {

View File

@@ -13,8 +13,8 @@ uint4 SharpRTC::rtc_read(uint4 addr) {
case 10: return year / 10 % 10; case 10: return year / 10 % 10;
case 11: return year / 100; case 11: return year / 100;
case 12: return weekday; case 12: return weekday;
default: return 0;
} }
return 0;
} }
void SharpRTC::rtc_write(uint4 addr, uint4 data) { void SharpRTC::rtc_write(uint4 addr, uint4 data) {

View File

@@ -1,7 +1,9 @@
#ifdef SHARPRTC_CPP #ifdef SHARPRTC_CPP
void SharpRTC::serialize(serializer &s) { void SharpRTC::serialize(serializer &s) {
s.integer(rtc_mode); Thread::serialize(s);
s.integer((unsigned&)rtc_state);
s.integer(rtc_index); s.integer(rtc_index);
s.integer(second); s.integer(second);

View File

@@ -37,7 +37,6 @@ void SharpRTC::load() {
day = 0; day = 0;
month = 0; month = 0;
year = 0; year = 0;
weekday = 0;
} }
void SharpRTC::unload() { void SharpRTC::unload() {
@@ -49,7 +48,7 @@ void SharpRTC::power() {
void SharpRTC::reset() { void SharpRTC::reset() {
create(SharpRTC::Enter, 1); create(SharpRTC::Enter, 1);
rtc_mode = RtcRead; rtc_state = State::Read;
rtc_index = -1; rtc_index = -1;
} }
@@ -57,7 +56,7 @@ void SharpRTC::sync() {
time_t systime = time(0); time_t systime = time(0);
tm *timeinfo = localtime(&systime); tm *timeinfo = localtime(&systime);
second = min(59, timeinfo->tm_sec); //round leap second down second = min(59, timeinfo->tm_sec);
minute = timeinfo->tm_min; minute = timeinfo->tm_min;
hour = timeinfo->tm_hour; hour = timeinfo->tm_hour;
day = timeinfo->tm_mday; day = timeinfo->tm_mday;
@@ -67,17 +66,17 @@ void SharpRTC::sync() {
} }
uint8 SharpRTC::read(unsigned addr) { uint8 SharpRTC::read(unsigned addr) {
addr &= 0xffff; addr &= 1;
if(addr == 0x2800) { if(addr == 0) {
if(rtc_mode != RtcRead) return 0x00; if(rtc_state != State::Read) return 0;
if(rtc_index < 0) { if(rtc_index < 0) {
rtc_index++; rtc_index++;
return 0x0f; return 15;
} else if(rtc_index > 12) { } else if(rtc_index > 12) {
rtc_index = -1; rtc_index = -1;
return 0x0f; return 15;
} else { } else {
return rtc_read(rtc_index++); return rtc_read(rtc_index++);
} }
@@ -87,41 +86,29 @@ uint8 SharpRTC::read(unsigned addr) {
} }
void SharpRTC::write(unsigned addr, uint8 data) { void SharpRTC::write(unsigned addr, uint8 data) {
addr &= 0xffff; addr &= 1, data &= 15;
if(addr == 0x2801) {
data &= 0x0f; //only the low four bits are used
if(addr == 1) {
if(data == 0x0d) { if(data == 0x0d) {
rtc_mode = RtcRead; rtc_state = State::Read;
rtc_index = -1; rtc_index = -1;
return; return;
} }
if(data == 0x0e) { if(data == 0x0e) {
rtc_mode = RtcCommand; rtc_state = State::Command;
return; return;
} }
if(data == 0x0f) return; //unknown behavior if(data == 0x0f) return; //unknown behavior
if(rtc_mode == RtcWrite) { if(rtc_state == State::Command) {
if(rtc_index >= 0 && rtc_index < 12) {
rtc_write(rtc_index++, data);
if(rtc_index == 12) {
//day of week is automatically calculated and written
weekday = calculate_weekday(1000 + year, month, day);
}
}
} else if(rtc_mode == RtcCommand) {
if(data == 0) { if(data == 0) {
rtc_mode = RtcWrite; rtc_state = State::Write;
rtc_index = 0; rtc_index = 0;
} else if(data == 4) { } else if(data == 4) {
rtc_mode = RtcReady; rtc_state = State::Ready;
rtc_index = -1; rtc_index = -1;
//reset time //reset time
second = 0; second = 0;
minute = 0; minute = 0;
@@ -132,8 +119,20 @@ void SharpRTC::write(unsigned addr, uint8 data) {
weekday = 0; weekday = 0;
} else { } else {
//unknown behavior //unknown behavior
rtc_mode = RtcReady; rtc_state = State::Ready;
} }
return;
}
if(rtc_state == State::Write) {
if(rtc_index >= 0 && rtc_index < 12) {
rtc_write(rtc_index++, data);
if(rtc_index == 12) {
//day of week is automatically calculated and written
weekday = calculate_weekday(1000 + year, month, day);
}
}
return;
} }
} }
} }

View File

@@ -14,8 +14,7 @@ struct SharpRTC : Coprocessor {
void serialize(serializer&); void serialize(serializer&);
enum RtcMode { RtcReady, RtcCommand, RtcRead, RtcWrite }; enum class State : unsigned { Ready, Command, Read, Write } rtc_state;
unsigned rtc_mode;
signed rtc_index; signed rtc_index;
unsigned second; unsigned second;

View File

@@ -20,14 +20,20 @@ void SharpRTC::tick_hour() {
void SharpRTC::tick_day() { void SharpRTC::tick_day() {
unsigned days = daysinmonth[month % 12]; unsigned days = daysinmonth[month % 12];
//add one day for leap years
if(year % 400 == 0) days++;
else if(year % 100 == 0);
else if(year % 4 == 0) days++;
if(day++ < days) return; if(day++ < days) return;
day = 0; day = 1;
tick_month(); tick_month();
} }
void SharpRTC::tick_month() { void SharpRTC::tick_month() {
if(month++ < 12) return; if(month++ < 12) return;
month = 0; month = 1;
tick_year(); tick_year();
} }
@@ -38,39 +44,38 @@ void SharpRTC::tick_year() {
//returns day of week for specified date //returns day of week for specified date
//eg 0 = Sunday, 1 = Monday, ... 6 = Saturday //eg 0 = Sunday, 1 = Monday, ... 6 = Saturday
//usage: weekday(2008, 1, 1) returns weekday of January 1st, 2008 //usage: calculate_weekday(2008, 1, 1) returns weekday of January 1st, 2008
unsigned SharpRTC::calculate_weekday(unsigned year, unsigned month, unsigned day) { unsigned SharpRTC::calculate_weekday(unsigned year, unsigned month, unsigned day) {
unsigned y = 1900, m = 1; //epoch is 1900-01-01 unsigned y = 1000, m = 1; //SharpRTC epoch is 1000-01-01
unsigned sum = 0; //number of days passed since epoch unsigned sum = 0; //number of days passed since epoch
year = max(1900, year); year = max(1000, year);
month = max(1, min(12, month)); month = max(1, min(12, month));
day = max(1, min(31, day)); day = max(1, min(31, day));
while(y < year) { while(y < year) {
bool leapyear = false; bool leapyear = false;
if((y % 4) == 0) { if(y % 4 == 0) {
leapyear = true; leapyear = true;
if((y % 100) == 0 && (y % 400) != 0) leapyear = false; if(y % 100 == 0 && y % 400 != 0) leapyear = false;
} }
sum += leapyear ? 366 : 365; sum += 365 + leapyear;
y++; y++;
} }
while(m < month) { while(m < month) {
unsigned days = daysinmonth[m - 1]; unsigned days = daysinmonth[m - 1];
bool leapyearmonth = false;
if(days == 28) { if(days == 28) {
bool leapyear = false; if(y % 4 == 0) {
if((y % 4) == 0) { leapyearmonth = true;
leapyear = true; if(y % 100 == 0 && y % 400 != 0) leapyearmonth = false;
if((y % 100) == 0 && (y % 400) != 0) leapyear = false;
} }
if(leapyear) days++;
} }
sum += days; sum += days + leapyearmonth;
m++; m++;
} }
sum += day - 1; sum += day - 1;
return (sum + 1) % 7; //1900-01-01 was a Monday return (sum + 3) % 7; //1000-01-01 was a Wednesday
} }

View File

@@ -25,21 +25,18 @@ string Interface::sha256() {
unsigned Interface::group(unsigned id) { unsigned Interface::group(unsigned id) {
switch(id) { switch(id) {
case ID::Nec7725DSP:
case ID::Nec96050DSP:
case ID::HitachiDSP:
case ID::ArmDSP:
case ID::ROM: case ID::ROM:
case ID::RAM: case ID::RAM:
case ID::ArmDSP:
case ID::HitachiDSP:
case ID::Nec7725DSP:
case ID::Nec96050DSP:
case ID::NecDSPRAM: case ID::NecDSPRAM:
case ID::EpsonRTC:
case ID::SharpRTC:
case ID::BsxRAM: case ID::BsxRAM:
case ID::BsxPSRAM: case ID::BsxPSRAM:
return 0; return 0;
case ID::SuperGameBoyROM: case ID::SuperGameBoyROM:
case ID::SuperGameBoyRAM: case ID::SuperGameBoyRAM:
case ID::SuperGameBoyRTC:
return 1; return 1;
case ID::BsxFlashROM: case ID::BsxFlashROM:
return 2; return 2;
@@ -58,6 +55,23 @@ void Interface::load(unsigned id, const stream &stream, const string &markup) {
stream.read(smp.iplrom, min(64u, stream.size())); stream.read(smp.iplrom, min(64u, stream.size()));
} }
if(id == ID::ROM) {
cartridge.load(markup, stream);
system.power();
}
if(id == ID::RAM) {
stream.read(cartridge.ram.data(), min(cartridge.ram.size(), stream.size()));
}
if(id == ID::ArmDSP) {
stream.read(armdsp.firmware, stream.size());
}
if(id == ID::HitachiDSP) {
for(unsigned n = 0; n < 1024; n++) hitachidsp.dataROM[n] = stream.readl(3);
}
if(id == ID::Nec7725DSP) { if(id == ID::Nec7725DSP) {
for(unsigned n = 0; n < 2048; n++) necdsp.programROM[n] = stream.readl(3); for(unsigned n = 0; n < 2048; n++) necdsp.programROM[n] = stream.readl(3);
for(unsigned n = 0; n < 1024; n++) necdsp.dataROM[n] = stream.readl(2); for(unsigned n = 0; n < 1024; n++) necdsp.dataROM[n] = stream.readl(2);
@@ -68,39 +82,6 @@ void Interface::load(unsigned id, const stream &stream, const string &markup) {
for(unsigned n = 0; n < 2048; n++) necdsp.dataROM[n] = stream.readl(2); for(unsigned n = 0; n < 2048; n++) necdsp.dataROM[n] = stream.readl(2);
} }
if(id == ID::HitachiDSP) {
for(unsigned n = 0; n < 1024; n++) hitachidsp.dataROM[n] = stream.readl(3);
}
if(id == ID::ArmDSP) {
stream.read(armdsp.firmware, stream.size());
}
if(id == ID::ROM) {
cartridge.load(markup, stream);
system.power();
}
if(id == ID::SuperGameBoyROM) {
GameBoy::cartridge.load(GameBoy::System::Revision::SuperGameBoy, markup, stream);
}
if(id == ID::BsxFlashROM) {
bsxflash.memory.copy(stream);
}
if(id == ID::SufamiTurboSlotAROM) {
sufamiturbo.slotA.rom.copy(stream);
}
if(id == ID::SufamiTurboSlotBROM) {
sufamiturbo.slotB.rom.copy(stream);
}
if(id == ID::RAM) {
stream.read(cartridge.ram.data(), min(cartridge.ram.size(), stream.size()));
}
if(id == ID::NecDSPRAM) { if(id == ID::NecDSPRAM) {
for(unsigned n = 0; n < 2048; n++) necdsp.dataRAM[n] = stream.readl(2); for(unsigned n = 0; n < 2048; n++) necdsp.dataRAM[n] = stream.readl(2);
} }
@@ -117,6 +98,18 @@ void Interface::load(unsigned id, const stream &stream, const string &markup) {
sharprtc.load(data); sharprtc.load(data);
} }
if(id == ID::SuperGameBoyROM) {
GameBoy::cartridge.load(GameBoy::System::Revision::SuperGameBoy, markup, stream);
}
if(id == ID::SuperGameBoyRAM) {
stream.read(GameBoy::cartridge.ramdata, GameBoy::cartridge.ramsize);
}
if(id == ID::BsxFlashROM) {
bsxflash.memory.copy(stream);
}
if(id == ID::BsxRAM) { if(id == ID::BsxRAM) {
stream.read(bsxcartridge.sram.data(), min(stream.size(), bsxcartridge.sram.size())); stream.read(bsxcartridge.sram.data(), min(stream.size(), bsxcartridge.sram.size()));
} }
@@ -125,8 +118,12 @@ void Interface::load(unsigned id, const stream &stream, const string &markup) {
stream.read(bsxcartridge.psram.data(), min(stream.size(), bsxcartridge.psram.size())); stream.read(bsxcartridge.psram.data(), min(stream.size(), bsxcartridge.psram.size()));
} }
if(id == ID::SuperGameBoyRAM) { if(id == ID::SufamiTurboSlotAROM) {
stream.read(GameBoy::cartridge.ramdata, GameBoy::cartridge.ramsize); sufamiturbo.slotA.rom.copy(stream);
}
if(id == ID::SufamiTurboSlotBROM) {
sufamiturbo.slotB.rom.copy(stream);
} }
if(id == ID::SufamiTurboSlotARAM) { if(id == ID::SufamiTurboSlotARAM) {
@@ -159,6 +156,10 @@ void Interface::save(unsigned id, const stream &stream) {
stream.write(data, sizeof data); stream.write(data, sizeof data);
} }
if(id == ID::SuperGameBoyRAM) {
stream.write(GameBoy::cartridge.ramdata, GameBoy::cartridge.ramsize);
}
if(id == ID::BsxRAM) { if(id == ID::BsxRAM) {
stream.write(bsxcartridge.sram.data(), bsxcartridge.sram.size()); stream.write(bsxcartridge.sram.data(), bsxcartridge.sram.size());
} }
@@ -167,9 +168,6 @@ void Interface::save(unsigned id, const stream &stream) {
stream.write(bsxcartridge.psram.data(), bsxcartridge.psram.size()); stream.write(bsxcartridge.psram.data(), bsxcartridge.psram.size());
} }
if(id == ID::SuperGameBoyRAM) {
stream.write(GameBoy::cartridge.ramdata, GameBoy::cartridge.ramsize);
}
if(id == ID::SufamiTurboSlotARAM) { if(id == ID::SufamiTurboSlotARAM) {
stream.write(sufamiturbo.slotA.ram.data(), sufamiturbo.slotA.ram.size()); stream.write(sufamiturbo.slotA.ram.data(), sufamiturbo.slotA.ram.size());

View File

@@ -5,23 +5,28 @@ namespace SuperFamicom {
struct ID { struct ID {
enum : unsigned { enum : unsigned {
IPLROM, IPLROM,
ROM,
RAM,
ArmDSP,
HitachiDSP,
Nec7725DSP, Nec7725DSP,
Nec96050DSP, Nec96050DSP,
HitachiDSP,
ArmDSP,
ROM,
SuperGameBoyROM,
BsxFlashROM,
SufamiTurboSlotAROM,
SufamiTurboSlotBROM,
RAM,
NecDSPRAM, NecDSPRAM,
EpsonRTC, EpsonRTC,
SharpRTC, SharpRTC,
SuperGameBoyROM,
SuperGameBoyRAM,
BsxFlashROM,
BsxRAM, BsxRAM,
BsxPSRAM, BsxPSRAM,
SuperGameBoyRAM,
SuperGameBoyRTC, SufamiTurboSlotAROM,
SufamiTurboSlotBROM,
SufamiTurboSlotARAM, SufamiTurboSlotARAM,
SufamiTurboSlotBRAM, SufamiTurboSlotBRAM,
}; };

View File

@@ -62,7 +62,7 @@ void System::runthreadtosave() {
} }
void System::init() { void System::init() {
assert(interface != nullptr); assert(interface != 0);
bsxsatellaview.init(); bsxsatellaview.init();
icd2.init(); icd2.init();
@@ -172,8 +172,8 @@ void System::power() {
if(cartridge.has_armdsp()) armdsp.power(); if(cartridge.has_armdsp()) armdsp.power();
if(cartridge.has_hitachidsp()) hitachidsp.power(); if(cartridge.has_hitachidsp()) hitachidsp.power();
if(cartridge.has_necdsp()) necdsp.power(); if(cartridge.has_necdsp()) necdsp.power();
if(cartridge.has_sharprtc()) sharprtc.power();
if(cartridge.has_epsonrtc()) epsonrtc.power(); if(cartridge.has_epsonrtc()) epsonrtc.power();
if(cartridge.has_sharprtc()) sharprtc.power();
if(cartridge.has_spc7110()) spc7110.power(); if(cartridge.has_spc7110()) spc7110.power();
if(cartridge.has_sdd1()) sdd1.power(); if(cartridge.has_sdd1()) sdd1.power();
if(cartridge.has_obc1()) obc1.power(); if(cartridge.has_obc1()) obc1.power();

View File

@@ -120,7 +120,7 @@ Presentation::Presentation() : active(nullptr) {
configurationSettings.onActivate = [&] { settings->setVisible(); settings->panelList.setFocused(); }; configurationSettings.onActivate = [&] { settings->setVisible(); settings->panelList.setFocused(); };
for(unsigned n = 0; n < 5; n++) saveStateItem[n].onActivate = [=] { utility->saveState(1 + n); }; for(unsigned n = 0; n < 5; n++) saveStateItem[n].onActivate = [=] { utility->saveState(1 + n); };
for(unsigned n = 0; n < 5; n++) loadStateItem[n].onActivate = [=] { utility->loadState(1 + n); }; for(unsigned n = 0; n < 5; n++) loadStateItem[n].onActivate = [=] { utility->loadState(1 + n); };
synchronizeTime.onActivate = [&] { if(application->active) system().rtcsync(); }; synchronizeTime.onActivate = [&] { system().rtcsync(); };
resizeWindow.onActivate = [&] { utility->resize(true); }; resizeWindow.onActivate = [&] { utility->resize(true); };
cheatEditor.onActivate = [&] { ::cheatEditor->setVisible(); }; cheatEditor.onActivate = [&] { ::cheatEditor->setVisible(); };
stateManager.onActivate = [&] { ::stateManager->setVisible(); }; stateManager.onActivate = [&] { ::stateManager->setVisible(); };