/* this file contains the sio subsystem emulation. */ #include "psx.h" #include #include #include static u8 getPrescaler(const u32 prescaler_type) { static const u8 prescalers[] = {0,1,16,64}; return prescalers[prescaler_type]; } //information in this file is derived from observatoins in mednafen and mame void PSX::SioController::Reset() { status.TX_EMPTY = 1; status.TX_RDY = 1; status.RX_RDY = 0; status.OVERRUN = 0; status.IRQ = 0; } float PSX::SioController::CalculateBaud() { return (float)PSX_CLOCK / this->baud_reg / getPrescaler(mode.prescaler_type); } void PSX::sio_wr(const int size, const u32 addr, const u32 val) { assert(size==2); assert((addr&1)==0); DEBUG_SIO("sio write size %d addr %08X = %08X\n",size,addr,val); const u32 portnum = (addr>>4)&1; SioController &port = sio[portnum]; switch(addr&0xF) { case 0x00: break; case 0x08: port.mode.value = val; printf("baud set to approx %f\n",port.CalculateBaud()); break; case 0x0A: { SioController::ControlReg reg; reg.value = val; if(reg.RESET) { DEBUG_SIO("reset port %d\n",portnum); port.Reset(); } if(reg.IACK) { port.status.IRQ = 0; port.control.IACK = 0; //todo - irq sync } //check for rising edge of DTR signal and alert the appropriate port if(port.control.DTR == 0 && reg.DTR == 1) { sio_dtr(port.control.PORT_SEL); } //replicate stored bits port.control.TX_IENA = reg.RX_IENA; port.control.RX_IENA = reg.RX_IENA; port.control.DSR_IENA = reg.DSR_IENA; port.control.DTR = reg.DTR; port.control.PORT_SEL = reg.PORT_SEL; } break; case 0x0E: port.baud_reg = val; printf("baud set to approx %f\n",port.CalculateBaud()); break; default: DEBUG_SIO("UNHANDLED\n"); } } void PSX::sio_dtr(const u32 port) { } u32 PSX::sio_rd(const int size, const u32 addr) { assert(size==2); assert((addr&1)==0); u32 ret = 0; DEBUG_SIO("sio read size %d addr %08X = %08X\n",size,addr,ret); const u32 port = (addr>>4)&1; return 0; }