BizHawk/PsxHawk.Core/psx.sio.cpp

103 lines
2.0 KiB
C++

/*
this file contains the sio subsystem emulation.
*/
#include "psx.h"
#include <assert.h>
#include <stdio.h>
#include <stddef.h>
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;
}