mirror of
https://github.com/ares-emulator/ares.git
synced 2026-10-12 02:11:04 +00:00
fc: reuse shared X24C01 for Datach EEPROM
This commit is contained in:
@@ -157,7 +157,6 @@ ares_add_sources(
|
||||
CORE #
|
||||
fc
|
||||
INCLUDED #
|
||||
cartridge/board/ic/bandai-24c01.hpp
|
||||
cartridge/board/ic/jv001.hpp
|
||||
cartridge/board/ic/txc05-00002-010.hpp
|
||||
)
|
||||
|
||||
@@ -5,20 +5,20 @@ struct BandaiDatach : BandaiLZ93D50 {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
Bandai24C01 external;
|
||||
bool hasExternal = false;
|
||||
M24C external;
|
||||
|
||||
auto load() -> void override {
|
||||
BandaiLZ93D50::load();
|
||||
if(auto fp = pak->read("external.eeprom")) {
|
||||
if(hasExternal = fp->size() == 128) fp->read(external.memory, 128);
|
||||
if(fp->size() == 128) external.load(M24C::Type::X24C01);
|
||||
if(external) fp->read(external.memory, external.size());
|
||||
}
|
||||
}
|
||||
|
||||
auto save() -> void override {
|
||||
BandaiLZ93D50::save();
|
||||
if(hasExternal) {
|
||||
if(auto fp = pak->write("external.eeprom")) fp->write(external.memory, 128);
|
||||
if(external) {
|
||||
if(auto fp = pak->write("external.eeprom")) fp->write(external.memory, external.size());
|
||||
}
|
||||
}
|
||||
|
||||
@@ -26,7 +26,7 @@ struct BandaiDatach : BandaiLZ93D50 {
|
||||
data = BandaiLZ93D50::readPRG(address, data);
|
||||
if(address >= 0x6000 && address < 0x8000) {
|
||||
data.bit(3) = 0; //idle barcode signal
|
||||
if(hasExternal) data.bit(4) = data.bit(4) && external.read();
|
||||
if(external) data.bit(4) = data.bit(4) && external.read();
|
||||
}
|
||||
return data;
|
||||
}
|
||||
@@ -35,11 +35,19 @@ struct BandaiDatach : BandaiLZ93D50 {
|
||||
if(address < 0x8000) return;
|
||||
auto reg = address & 15;
|
||||
if(reg <= 7) {
|
||||
if(reg <= 3 && hasExternal) external.write(data.bit(3), external.data);
|
||||
if(reg <= 3 && external) {
|
||||
external.clock = data.bit(3);
|
||||
external.data = external.data();
|
||||
external.write();
|
||||
}
|
||||
return;
|
||||
}
|
||||
BandaiLZ93D50::writePRG(address, data);
|
||||
if(reg == 13 && hasExternal) external.write(external.clock, data.bit(6));
|
||||
if(reg == 13 && external) {
|
||||
external.clock = external.clock();
|
||||
external.data = data.bit(6);
|
||||
external.write();
|
||||
}
|
||||
}
|
||||
|
||||
auto power() -> void override {
|
||||
@@ -49,6 +57,6 @@ struct BandaiDatach : BandaiLZ93D50 {
|
||||
|
||||
auto serialize(serializer& s) -> void override {
|
||||
BandaiLZ93D50::serialize(s);
|
||||
if(hasExternal) s(external);
|
||||
s(external);
|
||||
}
|
||||
};
|
||||
|
||||
@@ -1,5 +1,4 @@
|
||||
namespace Board {
|
||||
#include "ic/bandai-24c01.hpp"
|
||||
#include "ic/jv001.hpp"
|
||||
#include "ic/txc05-00002-010.hpp"
|
||||
|
||||
|
||||
@@ -1,127 +0,0 @@
|
||||
#pragma once
|
||||
|
||||
//LSB-first 24C01 serial interface used by Bandai Datach cartridges.
|
||||
struct Bandai24C01 {
|
||||
auto power() -> void {
|
||||
mode = Mode::Standby;
|
||||
clock = data = response = 1;
|
||||
counter = address = input = output = reading = pending = 0;
|
||||
for(auto& byte : page) byte = 0;
|
||||
}
|
||||
auto read() const -> bool {
|
||||
return response;
|
||||
}
|
||||
auto write(bool scl, bool sda) -> void {
|
||||
if(clock && scl && data && !sda) {
|
||||
mode = Mode::Address;
|
||||
counter = address = pending = 0;
|
||||
response = 1;
|
||||
} else if(clock && scl && !data && sda) {
|
||||
//The four-byte page buffer is programmed on STOP. Programming is instantaneous.
|
||||
for(u32 index : range(4)) {
|
||||
if(pending.bit(index)) memory[(address & 0x7c) | index] = page[index];
|
||||
}
|
||||
pending = 0;
|
||||
mode = Mode::Standby;
|
||||
response = 1;
|
||||
} else if(!clock && scl) {
|
||||
switch(mode) {
|
||||
case Mode::Address:
|
||||
if(counter < 7) address.bit(counter++) = sda;
|
||||
else if(counter == 7) reading = sda, counter++;
|
||||
break;
|
||||
case Mode::Read:
|
||||
if(counter < 8) counter++;
|
||||
break;
|
||||
case Mode::ReadAck:
|
||||
reading = !sda;
|
||||
break;
|
||||
case Mode::Write:
|
||||
if(counter < 8) input.bit(counter++) = sda;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
} else if(clock && !scl) {
|
||||
switch(mode) {
|
||||
case Mode::Address:
|
||||
if(counter == 8) mode = Mode::AddressAck, response = 0;
|
||||
break;
|
||||
case Mode::AddressAck:
|
||||
counter = 0;
|
||||
mode = reading ? Mode::Read : Mode::Write;
|
||||
output = memory[address];
|
||||
response = reading ? output.bit(0) : 1;
|
||||
break;
|
||||
case Mode::Read:
|
||||
if(counter == 8) {
|
||||
mode = Mode::ReadAck;
|
||||
response = 1;
|
||||
} else {
|
||||
response = output.bit(counter);
|
||||
}
|
||||
break;
|
||||
case Mode::ReadAck:
|
||||
if(reading) {
|
||||
address++;
|
||||
counter = 0;
|
||||
output = memory[address];
|
||||
response = output.bit(0);
|
||||
mode = Mode::Read;
|
||||
} else {
|
||||
mode = Mode::Standby;
|
||||
response = 1;
|
||||
}
|
||||
break;
|
||||
case Mode::Write:
|
||||
if(counter == 8) {
|
||||
page[address.bit(0,1)] = input;
|
||||
pending.bit(address.bit(0,1)) = 1;
|
||||
address.bit(0,1)++;
|
||||
mode = Mode::WriteAck;
|
||||
response = 0;
|
||||
}
|
||||
break;
|
||||
case Mode::WriteAck:
|
||||
mode = Mode::Write;
|
||||
counter = 0;
|
||||
response = 1;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
clock = scl;
|
||||
data = sda;
|
||||
}
|
||||
auto serialize(serializer& s) -> void {
|
||||
s(memory);
|
||||
s(clock);
|
||||
s(data);
|
||||
s((u32&)mode);
|
||||
s(counter);
|
||||
s(address);
|
||||
s(input);
|
||||
s(output);
|
||||
s(reading);
|
||||
s(response);
|
||||
s(page);
|
||||
s(pending);
|
||||
}
|
||||
|
||||
n8 memory[128];
|
||||
n1 clock = 1;
|
||||
n1 data = 1;
|
||||
|
||||
private:
|
||||
enum class Mode : u32 { Standby, Address, AddressAck, Read, ReadAck, Write, WriteAck };
|
||||
Mode mode = Mode::Standby;
|
||||
n4 counter;
|
||||
n7 address;
|
||||
n8 input;
|
||||
n8 output;
|
||||
n1 reading;
|
||||
n1 response = 1;
|
||||
n8 page[4];
|
||||
n4 pending;
|
||||
};
|
||||
Reference in New Issue
Block a user