mirror of
https://github.com/devinacker/bsnes-plus.git
synced 2025-04-02 10:52:46 -04:00
144 lines
3.2 KiB
C++
144 lines
3.2 KiB
C++
#ifdef BSX_CPP
|
|
|
|
BSXFlash bsxflash;
|
|
|
|
void BSXFlash::init() {}
|
|
void BSXFlash::enable() {}
|
|
|
|
void BSXFlash::power() {
|
|
reset();
|
|
}
|
|
|
|
void BSXFlash::reset() {
|
|
regs.command = 0;
|
|
|
|
regs.csr = false;
|
|
regs.esr = false;
|
|
regs.vendor_info = false;
|
|
regs.writebyte = false;
|
|
regs.flash_size = min(0xC, (unsigned)log2(size() >> 10));
|
|
|
|
memory::bsxpack.write_protect(true);
|
|
}
|
|
|
|
unsigned BSXFlash::size() const {
|
|
return memory::bsxpack.size();
|
|
}
|
|
|
|
uint8 BSXFlash::read(unsigned addr) {
|
|
if(regs.esr) {
|
|
switch (addr & 0xFFFF)
|
|
{
|
|
case 0x0002: //PSR, Page Status Register
|
|
return 0xC0;
|
|
|
|
case 0x0004: //GSR, Global Status Register
|
|
return 0x82;
|
|
}
|
|
}
|
|
|
|
if(regs.csr)
|
|
{
|
|
//Read Compatible Status Register
|
|
if(!Memory::debugger_access())
|
|
regs.csr = false;
|
|
return 0x80;
|
|
}
|
|
|
|
if(regs.vendor_info && ((addr & 0x7FFF) >= 0x7F00) && ((addr & 0x7FFF) <= 0x7F13)) {
|
|
//read flash cartridge vendor information
|
|
switch(addr & 0xFF) {
|
|
case 0x00: return 0x4d;
|
|
case 0x01: return 0x00;
|
|
case 0x02: return 0x50;
|
|
case 0x03: return 0x00;
|
|
case 0x04: return 0x00;
|
|
case 0x05: return 0x00;
|
|
case 0x06: return 0x10 | regs.flash_size; //Memory Pack Type 1
|
|
case 0x07: return 0x00;
|
|
default: return 0x00;
|
|
}
|
|
}
|
|
|
|
return memory::bsxpack.read(addr);
|
|
}
|
|
|
|
void BSXFlash::write(unsigned addr, uint8 data) {
|
|
//there exist both read-only and read-write BS-X flash cartridges ...
|
|
//unfortunately, the vendor info is not stored inside memory dumps
|
|
//of BS-X flashcarts, so it is impossible to determine whether a
|
|
//given flashcart is writeable.
|
|
//however, it has been observed that LoROM-mapped BS-X carts always
|
|
//use read-write flashcarts, and HiROM-mapped BS-X carts always use
|
|
//read-only flashcarts.
|
|
//below is an unfortunately necessary workaround to this problem.
|
|
//if(cartridge.mapper() == Cartridge::BSCHiROM) return;
|
|
|
|
//If Write Byte Command is issued
|
|
if(regs.writebyte)
|
|
{
|
|
regs.writebyte = false;
|
|
memory::bsxpack.write(addr, memory::bsxpack.read(addr) & data); //AND byte
|
|
return memory::bsxpack.write_protect(true);
|
|
}
|
|
|
|
//Commands
|
|
regs.command <<= 8;
|
|
regs.command |= data;
|
|
|
|
//Single Byte Commands
|
|
switch (data)
|
|
{
|
|
case 0x00:
|
|
case 0xFF:
|
|
//Reset Array Data
|
|
regs.csr = false;
|
|
regs.esr = false;
|
|
regs.vendor_info = false;
|
|
break;
|
|
|
|
case 0x10:
|
|
case 0x40:
|
|
//Write Byte (next write will be )
|
|
regs.writebyte = true;
|
|
break;
|
|
|
|
case 0x70:
|
|
//Enable CSR
|
|
regs.csr = true;
|
|
break;
|
|
|
|
case 0x71:
|
|
//Enable ESR
|
|
regs.esr = true;
|
|
break;
|
|
|
|
case 0x75:
|
|
//Enable Page Buffer
|
|
regs.vendor_info = true;
|
|
break;
|
|
}
|
|
|
|
//Double Byte Commands
|
|
switch (regs.command)
|
|
{
|
|
case 0x20D0:
|
|
//Page Erase
|
|
memory::bsxpack.write_protect(false);
|
|
for (int i = 0; i < 0x10000; i++)
|
|
memory::bsxpack.write((addr & 0xFF0000) + i, 0xFF);
|
|
break;
|
|
|
|
case 0xA7D0:
|
|
//Chip Erase
|
|
memory::bsxpack.write_protect(false);
|
|
for (int i = 0; i < memory::bsxpack.size(); i++)
|
|
memory::bsxpack.write(i, 0xFF);
|
|
break;
|
|
}
|
|
|
|
memory::bsxpack.write_protect(!regs.writebyte);
|
|
}
|
|
|
|
#endif
|
|
|