mirror of https://github.com/bsnes-emu/bsnes.git
237 lines
6.0 KiB
C++
237 lines
6.0 KiB
C++
//U1: TAMA7: Mask ROM (512KB)
|
|
//U2: TAMA5: Game Boy cartridge connector interface
|
|
//U3: TAMA6: Toshiba TMP47C243M (4-bit MCU)
|
|
//U4: RTC: Toshiba TC8521AM
|
|
|
|
//note: the TMP47C243M's 2048 x 8-bit program ROM is currently undumped
|
|
//as such, high level emulation is used as a necessary evil
|
|
|
|
auto Cartridge::TAMA::second() -> void {
|
|
if(++rtc.second >= 60) {
|
|
rtc.second = 0;
|
|
|
|
if(++rtc.minute >= 60) {
|
|
rtc.minute = 0;
|
|
|
|
if(rtc.hourMode == 0 && ++rtc.hour >= 12) {
|
|
rtc.hour = 0;
|
|
rtc.meridian++;
|
|
}
|
|
|
|
if(rtc.hourMode == 1 && ++rtc.hour >= 24) {
|
|
rtc.hour = 0;
|
|
rtc.meridian = rtc.hour >= 12;
|
|
}
|
|
|
|
if((rtc.hourMode == 0 && rtc.hour == 0 && rtc.meridian == 0)
|
|
|| (rtc.hourMode == 1 && rtc.hour == 0)
|
|
) {
|
|
uint days[12] = {31, 28, 31, 30, 31, 30, 30, 31, 30, 31, 30, 31};
|
|
if(rtc.leapYear == 0) days[1] = 29; //extra day in February for leap years
|
|
|
|
if(++rtc.day > days[(rtc.month - 1) % 12]) {
|
|
rtc.day = 1;
|
|
|
|
if(++rtc.month > 12) {
|
|
rtc.month = 1;
|
|
rtc.leapYear++;
|
|
|
|
if(++rtc.year >= 100) {
|
|
rtc.year = 0;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
auto Cartridge::TAMA::read(uint16 address) -> uint8 {
|
|
if((address & 0xc000) == 0x0000) { //$0000-3fff
|
|
return cartridge.rom.read(address.bits(0,13));
|
|
}
|
|
|
|
if((address & 0xc000) == 0x4000) { //$4000-7fff
|
|
return cartridge.rom.read(io.rom.bank << 14 | address.bits(0,13));
|
|
}
|
|
|
|
if((address & 0xe001) == 0xa000) { //$a000-bfff (even)
|
|
if(io.select == 0x0a) {
|
|
return 0xf0 | io.ready;
|
|
}
|
|
|
|
if(io.mode == 0 || io.mode == 1) {
|
|
if(io.select == 0x0c) {
|
|
return 0xf0 | io.output.bits(0,3);
|
|
}
|
|
|
|
if(io.select == 0x0d) {
|
|
return 0xf0 | io.output.bits(4,7);
|
|
}
|
|
}
|
|
|
|
if(io.mode == 2 || io.mode == 4) {
|
|
if(io.select == 0x0c || io.select == 0x0d) {
|
|
uint4 data;
|
|
if(rtc.index == 0) data = rtc.minute % 10;
|
|
if(rtc.index == 1) data = rtc.minute / 10;
|
|
if(rtc.index == 2) data = rtc.hour % 10;
|
|
if(rtc.index == 3) data = rtc.hour / 10;
|
|
if(rtc.index == 4) data = rtc.day / 10;
|
|
if(rtc.index == 5) data = rtc.day % 10;
|
|
if(rtc.index == 6) data = rtc.month / 10;
|
|
if(rtc.index == 7) data = rtc.month % 10;
|
|
rtc.index++;
|
|
return 0xf0 | data;
|
|
}
|
|
}
|
|
|
|
return 0xff;
|
|
}
|
|
|
|
if((address & 0xe001) == 0xa001) { //$a000-bfff (odd)
|
|
return 0xff;
|
|
}
|
|
|
|
return 0xff;
|
|
}
|
|
|
|
auto Cartridge::TAMA::write(uint16 address, uint8 data) -> void {
|
|
auto toBCD = [](uint8 data) -> uint8 { return (data / 10) * 16 + (data % 10); };
|
|
auto fromBCD = [](uint8 data) -> uint8 { return (data / 16) * 10 + (data % 16); };
|
|
|
|
if((address & 0xe001) == 0xa000) { //$a000-bfff (even)
|
|
if(io.select == 0x00) {
|
|
io.rom.bank.bits(0,3) = data.bits(0,3);
|
|
}
|
|
|
|
if(io.select == 0x01) {
|
|
io.rom.bank.bit(4) = data.bit(0);
|
|
}
|
|
|
|
if(io.select == 0x04) {
|
|
io.input.bits(0,3) = data.bits(0,3);
|
|
}
|
|
|
|
if(io.select == 0x05) {
|
|
io.input.bits(4,7) = data.bits(0,3);
|
|
}
|
|
|
|
if(io.select == 0x06) {
|
|
io.index.bit(4) = data.bit(0);
|
|
io.mode = data.bits(1,3);
|
|
}
|
|
|
|
if(io.select == 0x07) {
|
|
io.index.bits(0,3) = data.bits(0,3);
|
|
|
|
if(io.mode == 0) {
|
|
cartridge.ram.write(io.index, io.input);
|
|
}
|
|
|
|
if(io.mode == 1) {
|
|
io.output = cartridge.ram.read(io.index);
|
|
}
|
|
|
|
if(io.mode == 2 && io.index == 0x04) {
|
|
rtc.minute = fromBCD(io.input);
|
|
}
|
|
|
|
if(io.mode == 2 && io.index == 0x05) {
|
|
rtc.hour = fromBCD(io.input);
|
|
rtc.meridian = rtc.hour >= 12;
|
|
}
|
|
|
|
if(io.mode == 4 && io.index == 0x00 && io.input.bits(0,3) == 0x7) {
|
|
uint8 day = toBCD(rtc.day);
|
|
day.bits(0,3) = io.input.bits(4,7);
|
|
rtc.day = fromBCD(day);
|
|
}
|
|
|
|
if(io.mode == 4 && io.index == 0x00 && io.input.bits(0,3) == 0x8) {
|
|
uint8 day = toBCD(rtc.day);
|
|
day.bits(4,7) = io.input.bits(4,7);
|
|
rtc.day = fromBCD(day);
|
|
}
|
|
|
|
if(io.mode == 4 && io.index == 0x00 && io.input.bits(0,3) == 0x9) {
|
|
uint8 month = toBCD(rtc.month);
|
|
month.bits(0,3) = io.input.bits(4,7);
|
|
rtc.month = fromBCD(month);
|
|
}
|
|
|
|
if(io.mode == 4 && io.index == 0x00 && io.input.bits(0,3) == 0xa) {
|
|
uint8 month = toBCD(rtc.month);
|
|
month.bits(4,7) = io.input.bits(4,7);
|
|
rtc.month = fromBCD(month);
|
|
}
|
|
|
|
if(io.mode == 4 && io.index == 0x00 && io.input.bits(0,3) == 0xb) {
|
|
uint8 year = toBCD(rtc.year);
|
|
year.bits(0,3) = io.input.bits(4,7);
|
|
rtc.year = fromBCD(year);
|
|
}
|
|
|
|
if(io.mode == 4 && io.index == 0x00 && io.input.bits(0,3) == 0xc) {
|
|
uint8 year = toBCD(rtc.year);
|
|
year.bits(4,7) = io.input.bits(4,7);
|
|
rtc.year = fromBCD(year);
|
|
}
|
|
|
|
if(io.mode == 4 && io.index == 0x02 && io.input.bits(0,3) == 0xa) {
|
|
rtc.hourMode = io.input.bit(4);
|
|
rtc.second = 0; //hack: unclear where this is really being set (if it is at all)
|
|
}
|
|
|
|
if(io.mode == 4 && io.index == 0x02 && io.input.bits(0,3) == 0xb) {
|
|
rtc.leapYear = data.bits(4,5);
|
|
}
|
|
|
|
if(io.mode == 4 && io.index == 0x02 && io.input.bits(0,3) == 0xe) {
|
|
rtc.test = io.input.bits(4,7);
|
|
}
|
|
|
|
if(io.mode == 2 && io.index == 0x06) {
|
|
rtc.index = 0;
|
|
}
|
|
}
|
|
|
|
return;
|
|
}
|
|
|
|
if((address & 0xe001) == 0xa001) { //$a000-bfff (odd)
|
|
io.select = data.bits(0,3);
|
|
|
|
if(io.select == 0x0a) {
|
|
io.ready = true;
|
|
}
|
|
|
|
return;
|
|
}
|
|
}
|
|
|
|
auto Cartridge::TAMA::power() -> void {
|
|
io = {};
|
|
}
|
|
|
|
auto Cartridge::TAMA::serialize(serializer& s) -> void {
|
|
s.integer(io.ready);
|
|
s.integer(io.select);
|
|
s.integer(io.mode);
|
|
s.integer(io.index);
|
|
s.integer(io.input);
|
|
s.integer(io.output);
|
|
s.integer(io.rom.bank);
|
|
|
|
s.integer(rtc.year);
|
|
s.integer(rtc.month);
|
|
s.integer(rtc.day);
|
|
s.integer(rtc.hour);
|
|
s.integer(rtc.minute);
|
|
s.integer(rtc.second);
|
|
s.integer(rtc.meridian);
|
|
s.integer(rtc.leapYear);
|
|
s.integer(rtc.hourMode);
|
|
s.integer(rtc.test);
|
|
}
|