mirror of
https://github.com/devinacker/bsnes-plus.git
synced 2025-04-02 10:52:46 -04:00
fixed bug where floppy data buffer from previous session would be saved to next session's floppy buffer when cartridge loaded. added xml parsing option for remapping dos added FDC_RESET_STANDBY debugging output, however standby and clock functionality are not implemented yet. added debugging output detecting whether a floppy disk image already exists for a current rom, and creates a new disk only if one doesn't exist.
154 lines
2.9 KiB
C++
154 lines
2.9 KiB
C++
#ifdef DOS_CPP
|
|
|
|
DOSSerial::DOSSerial() {
|
|
reset();
|
|
}
|
|
|
|
DOSSerial::~DOSSerial() {
|
|
}
|
|
|
|
|
|
void DOSSerial::init() {
|
|
reset();
|
|
}
|
|
|
|
void DOSSerial::reset() {
|
|
reset(0);
|
|
reset(1);
|
|
|
|
irq_enable = false;
|
|
}
|
|
|
|
void DOSSerial::power() {
|
|
reset();
|
|
}
|
|
|
|
void DOSSerial::unload() {
|
|
|
|
}
|
|
|
|
void DOSSerial::reset(bool channel) {
|
|
memset(&channels[channel], 0, sizeof(channels[0]));
|
|
}
|
|
|
|
uint8 DOSSerial::read(uint3 addr) {
|
|
auto& channel = channels[!(addr & 2)];
|
|
uint8 data = 0;
|
|
|
|
if (addr & 1) {
|
|
// reading data from peripheral
|
|
data = channel.rx_buffer[0];
|
|
if (channel.rx_count
|
|
&& !Memory::debugger_access()) {
|
|
channel.rx_buffer[0] = channel.rx_buffer[1];
|
|
channel.rx_buffer[1] = channel.rx_buffer[2];
|
|
channel.rx_buffer[2] = 0;
|
|
channel.rx_count--;
|
|
|
|
if (!channel.rx_count)
|
|
channel.rx_irq_pending = false;
|
|
dos.irq_process();
|
|
}
|
|
} else {
|
|
// reading register
|
|
switch (channel.nreg) {
|
|
case 0x00:
|
|
data = ((!!channel.rx_count) << 0)
|
|
| ((!channel.tx_count) << 2);
|
|
break;
|
|
|
|
case 0x01:
|
|
data = (channel.rx_overflow << 5);
|
|
break;
|
|
|
|
case 0x03:
|
|
data = irq_status();
|
|
break;
|
|
}
|
|
|
|
if (!Memory::debugger_access())
|
|
channel.nreg = 0;
|
|
}
|
|
|
|
return data;
|
|
}
|
|
|
|
void DOSSerial::write(uint3 addr, uint8 data) {
|
|
if (Memory::debugger_access())
|
|
return;
|
|
|
|
auto& channel = channels[!(addr & 2)];
|
|
|
|
if (addr & 1) {
|
|
// writing data to peripheral (TODO)
|
|
} else if (channel.nreg == 0) {
|
|
// selecting register
|
|
channel.nreg = data & 7;
|
|
|
|
// SCC command codes
|
|
switch ((data >> 3) & 7) {
|
|
case 1: // point high
|
|
channel.nreg |= 8;
|
|
break;
|
|
|
|
case 6: // error reset
|
|
channel.rx_overflow = false;
|
|
break;
|
|
|
|
case 7: // interrupt reset
|
|
dos.irq_process();
|
|
break;
|
|
}
|
|
|
|
} else {
|
|
// writing to register
|
|
switch (channel.nreg) {
|
|
case 1: // TX/RX interrupt control
|
|
channel.tx_irq_enable = (data & 0x2);
|
|
channel.rx_irq_enable = (data >> 3) & 0x3;
|
|
break;
|
|
|
|
case 3: // RX control
|
|
channel.rx_enable = (data & 0x1);
|
|
break;
|
|
|
|
case 5: // TX control
|
|
channel.tx_enable = (data & 0x8);
|
|
break;
|
|
|
|
case 9: // master interrupt control
|
|
irq_enable = (data & 0x8);
|
|
if (data & 0x80) reset(0);
|
|
if (data & 0x40) reset(1);
|
|
dos.irq_process();
|
|
break;
|
|
}
|
|
|
|
channel.nreg = 0;
|
|
}
|
|
}
|
|
|
|
void DOSSerial::send_data(bool num, uint8 data) {
|
|
auto& channel = channels[num];
|
|
|
|
if (channel.rx_enable) {
|
|
if (channel.rx_count < 3) {
|
|
channel.rx_buffer[channel.rx_count++] = data;
|
|
} else {
|
|
channel.rx_overflow = true;
|
|
}
|
|
if (channel.rx_irq_enable) {
|
|
channel.rx_irq_pending = true;
|
|
dos.irq_process();
|
|
}
|
|
}
|
|
}
|
|
|
|
uint8 DOSSerial::irq_status() const {
|
|
return (channels[1].tx_irq_pending << 1)
|
|
| (channels[1].rx_irq_pending << 2)
|
|
| (channels[0].tx_irq_pending << 4)
|
|
| (channels[0].rx_irq_pending << 5);
|
|
}
|
|
|
|
#endif
|