Files
2014-03-22 22:16:57 +01:00

323 lines
6.4 KiB
C++

/*
www.freedo.org
The first and only working 3DO multiplayer emulator.
The FreeDO licensed under modified GNU LGPL, with following notes:
* The owners and original authors of the FreeDO have full right to develop closed source derivative work.
* Any non-commercial uses of the FreeDO sources or any knowledge obtained by studying or reverse engineering
of the sources, or any other material published by FreeDO have to be accompanied with full credits.
* Any commercial uses of FreeDO sources or any knowledge obtained by studying or reverse engineering of the sources,
or any other material published by FreeDO is strictly forbidden without owners approval.
The above notes are taking precedence over GNU LGPL in conflicting situations.
Project authors:
Alexander Troosh
Maxim Grishin
Allen Wright
John Sammons
Felix Lazarev
*/
// XBUS.cpp: implementation of the CXBUS class.
//
//////////////////////////////////////////////////////////////////////
#include "freedoconfig.h"
//#include "astring.h"
#include "XBUS.h"
#include "Clio.h"
//////////////////////////////////////////////////////////////////////
// Construction/Destruction
//////////////////////////////////////////////////////////////////////
#pragma pack(push,1)
struct XBUSDatum
{
unsigned char XBSEL;
unsigned char XBSELH;
unsigned char POLF;
unsigned char POLDEVF;
unsigned char STDEVF[255]; //status of devices
unsigned char STLENF; //pointer in fifo
unsigned char CmdF[7];
unsigned char CmdPtrF;
};
#pragma pack(pop)
#define XBSEL xbus.XBSEL
#define XBSELH xbus.XBSELH
#define POLF xbus.POLF
#define POLDEVF xbus.POLDEVF
#define STDEVF xbus.STDEVF
#define STLENF xbus.STLENF
#define CmdF xbus.CmdF
#define CmdPtrF xbus.CmdPtrF
static XBUSDatum xbus;
static _xbus_device xdev[16];
#define POLSTMASK 0x01
#define POLDTMASK 0x02
#define POLMAMASK 0x04
#define POLREMASK 0x08
#define POLST 0x10
#define POLDT 0x20
#define POLMA 0x40
#define POLRE 0x80
void ExecuteCommandF();
void _xbus_SetCommandFIFO(unsigned int val)
{
if(xdev[XBSEL])
{
(*xdev[XBSEL])(XBP_SET_COMMAND,(void*)val);
if((*xdev[XBSEL])(XBP_FIQ,NULL)) _clio_GenerateFiq(4,0);
}
else if(XBSEL==0xf)
{
if (CmdPtrF<7)
{
CmdF[CmdPtrF]=(unsigned char)val;
CmdPtrF++;
}
if(CmdPtrF>=7)
{
ExecuteCommandF();
CmdPtrF=0;
}
}
}
unsigned int _xbus_GetDataFIFO()
{
if(xdev[XBSEL])
{
return (uintptr_t)(*xdev[XBSEL])(XBP_GET_DATA,NULL);
}
else
return 0;
}
unsigned int _xbus_GetPoll()
{
unsigned int res;
if(XBSEL==0xf)
res=POLF;
else if(xdev[XBSEL])res=(uintptr_t)(*xdev[XBSEL])(XBP_GET_POLL, NULL);
else res=0x30;
if(XBSELH&0x80)
res&=0xf;
return res;
}
unsigned int _xbus_GetRes()
{
if(xdev[XBSEL])return (uintptr_t)(*xdev[XBSEL])(XBP_RESERV, NULL);
return 0;
}
void ExecuteCommandF()
{
if(CmdF[0]==0x83)
{
STLENF=12;
STDEVF[0]=0x83;
STDEVF[1]=0x01;
STDEVF[2]=0x01;
STDEVF[3]=0x01;
STDEVF[4]=0x01;
STDEVF[5]=0x01;
STDEVF[6]=0x01;
STDEVF[7]=0x01;
STDEVF[8]=0x01;
STDEVF[9]=0x01;
STDEVF[10]=0x01;
STDEVF[11]=0x01;
POLDEVF|=POLST;
}
if(((POLDEVF&POLST) && (POLDEVF&POLSTMASK)) || ((POLDEVF&POLDT) && (POLDEVF&POLDTMASK)))
{
_clio_GenerateFiq(4,0);
}
}
unsigned int _xbus_GetStatusFIFO()
{
unsigned int res=0;
if(xdev[XBSEL])
{
res=(uintptr_t)(*xdev[XBSEL])(XBP_GET_STATUS,NULL);
}
else if(XBSEL==0xf)
{
if(STLENF>0)
{
res=STDEVF[0];
STLENF--;
if(STLENF>0)
{
for(int i=0;i<STLENF;i++)
STDEVF[i]=STDEVF[i+1];
}
else
{
POLDEVF&=~POLST;
}
}
return res;
}
return res;
}
void _xbus_SetDataFIFO(unsigned int val)
{
if(xdev[XBSEL])(*xdev[XBSEL])(XBP_SET_DATA,(void*)val);
}
void _xbus_SetPoll(unsigned int val)
{
if(XBSEL==0xf)
{
POLF&=0xF0;
POLF|=(val&0xf);
}
if(xdev[XBSEL])
{
(*xdev[XBSEL])(XBP_SET_POLL,(void*)val);
if((*xdev[XBSEL])(XBP_FIQ,NULL)) _clio_GenerateFiq(4,0);
}
}
void _xbus_SetSEL(unsigned int val)
{
XBSEL=(unsigned char)val&0xf;
XBSELH=(unsigned char)val&0xf0;
}
void _xbus_Init(_xbus_device zero_dev)
{
int i;
POLF=0xf;
for(i=0;i<15;i++)
{
xdev[i]=NULL;
}
_xbus_Attach(zero_dev);
}
int _xbus_Attach(_xbus_device dev)
{
int i;
for(i=0;i<16;i++)if(!xdev[i])break;
if(i==16)return -1;
xdev[i]=dev;
(*xdev[i])(XBP_INIT,NULL);
return i;
}
void _xbus_DevLoad(int dev, const char * name)
{
(*xdev[dev])(XBP_RESET,(void*)name);
}
void _xbus_DevEject(int dev)
{
(*xdev[dev])(XBP_RESET,NULL);
}
void _xbus_Destroy()
{
for(int i=0;i<16;i++)if(xdev[i]){(*xdev[i])(XBP_DESTROY,NULL);xdev[i]=NULL;}
}
unsigned int _xbus_SaveSize()
{
unsigned int tmp=sizeof(XBUSDatum);
int i;
tmp+=16*4;
for(i=0;i<15;i++)
{
if(!xdev[i])continue;
tmp+=(uintptr_t)(*xdev[i])(XBP_GET_SAVESIZE,NULL);
}
return tmp;
}
#include <memory.h>
void _xbus_Save(void *buff)
{
int i,off,j,tmp;
memcpy(buff,&xbus,sizeof(XBUSDatum));
j=off=sizeof(XBUSDatum);
off+=16*4;
for(i=0;i<15;i++)
{
if(!xdev[i])
{
tmp=0;
memcpy(&((unsigned char*)buff)[j+i*4],&tmp,4);
}
else
{
(*xdev[i])(XBP_GET_SAVEDATA,&((unsigned char*)buff)[off]);
memcpy(&((unsigned char*)buff)[j+i*4],&off,4);
off+=(uintptr_t)(*xdev[i])(XBP_GET_SAVESIZE,NULL);
}
}
}
void _xbus_Load(void *buff)
{
//AString tstr;
int i,offd,j;
j=sizeof(XBUSDatum);
memcpy(&xbus,buff,j);
for(i=0;i<15;i++)
{
memcpy(&offd,&((unsigned char*)buff)[j+i*4],4);
if(xdev[i])
{
if(!offd)
{
(*xdev[i])(XBP_RESET,NULL);
}
else
{
(*xdev[i])(XBP_SET_SAVEDATA,&((unsigned char*)buff)[offd]);
}
}
}
}