Originally ported from nullDC to libretro in commits:
2fa562db1b46c52b663b3dd4bb33a64907357458
f8eb58ac16a9e5adf662b99be5d00729264808e0
Modified for use w/ reicast per-game configuration
This commit is contained in:
Ender's Games 2018-08-22 13:10:59 -04:00
parent b1afd40d34
commit e5c0f0ee71
11 changed files with 105 additions and 30 deletions

View File

@ -178,6 +178,28 @@ void aica_Term()
}
s32 aica_pending_dma = 0;
void aica_periodical(u32 cycl)
{
if (aica_pending_dma > 0)
{
verify(SB_ADST==1);
cycl = (aica_pending_dma <= 0) ? 0 : cycl;
aica_pending_dma-=cycl;
if (aica_pending_dma <= 0)
{
//log("%u %d\n",cycl,(s32)aica_pending_dma);
asic_RaiseInterrupt(holly_SPU_DMA);
aica_pending_dma = 0;
SB_ADST=0;
}
}
}
void Write_SB_ADST(u32 addr, u32 data)
{
//0x005F7800 SB_ADSTAG RW AICA:G2-DMA G2 start address
@ -196,6 +218,8 @@ void Write_SB_ADST(u32 addr, u32 data)
u32 src=SB_ADSTAR;
u32 dst=SB_ADSTAG;
u32 len=SB_ADLEN & 0x7FFFFFFF;
u32 total_bytes=0;
if ((SB_ADDIR&1)==1)
{
@ -221,11 +245,14 @@ void Write_SB_ADST(u32 addr, u32 data)
SB_ADSTAR+=len;
SB_ADSTAG+=len;
SB_ADST = 0x00000000;//dma done
SB_ADLEN = 0x00000000;
asic_RaiseInterrupt(holly_SPU_DMA);
total_bytes+=len;
SB_ADST = settings.aica.InterruptHack ? 1 : 0x00000000;//dma done
SB_ADLEN = 0x00000000;
aica_pending_dma = ((total_bytes * 200000000) / 65536) + 1;
if (!settings.aica.InterruptHack)
asic_RaiseInterruptWait(holly_SPU_DMA);
}
}
}
@ -279,7 +306,7 @@ void Write_SB_E1ST(u32 addr, u32 data)
SB_E1LEN = 0x00000000;
asic_RaiseInterrupt(holly_EXT_DMA1);
asic_RaiseInterruptWait(holly_EXT_DMA1);
}
}
}

View File

@ -274,7 +274,7 @@ void gd_set_state(gd_states state)
GDStatus.DRQ=1;
GDStatus.BSY=0;
//(4) INTRQ is set, and a host interrupt is issued.
asic_RaiseInterrupt(holly_GDROM_CMD);
asic_RaiseInterruptWait(holly_GDROM_CMD);
/*
The number of bytes normally is the byte number in the register at the time of receiving
the command, but it may also be the total of several devices handled by the buffer at that point.
@ -332,7 +332,7 @@ void gd_set_state(gd_states state)
GDStatus.DRQ=0;
GDStatus.BSY=0;
//Make INTRQ valid
asic_RaiseInterrupt(holly_GDROM_CMD);
asic_RaiseInterruptWait(holly_GDROM_CMD);
//command finished !
gd_set_state(gds_waitcmd);
@ -477,7 +477,7 @@ void gd_process_ata_cmd()
GDStatus.BSY=0;
GDStatus.CHECK=1;
asic_RaiseInterrupt(holly_GDROM_CMD);
asic_RaiseInterruptWait(holly_GDROM_CMD);
gd_set_state(gds_waitcmd);
break;
@ -516,7 +516,7 @@ void gd_process_ata_cmd()
GDStatus.DSC=0;
GDStatus.DF=0;
GDStatus.CHECK=0;
asic_RaiseInterrupt(holly_GDROM_CMD); //???
asic_RaiseInterruptWait(holly_GDROM_CMD); //???
gd_set_state(gds_waitcmd);
break;
@ -1155,7 +1155,7 @@ int GDRomschd(int i, int c, int j)
//printf("Streamed GDMA end - %d bytes transferred\n",SB_GDLEND);
SB_GDST=0;//done
// The DMA end interrupt flag
asic_RaiseInterrupt(holly_GDROM_DMA);
asic_RaiseInterruptWait(holly_GDROM_DMA);
}
//Read ALL sectors
if (read_params.remaining_sectors==0)

View File

@ -72,21 +72,60 @@ void RaiseAsicErr(HollyInterruptID inter)
asic_RL6Pending();
}
static void asic_RaiseInterruptInternal(HollyInterruptID inter)
{
u8 m=inter>>8;
switch(m)
{
case 0:
RaiseAsicNormal(inter);
break;
case 1:
RaiseAsicExt(inter);
break;
case 2:
RaiseAsicErr(inter);
break;
}
}
static HollyInterruptID dmatmp1;
static HollyInterruptID dmatmp2;
static HollyInterruptID OldDmaId;
void asic_RaiseInterrupt(HollyInterruptID inter)
{
u8 m=inter>>8;
switch(m)
{
case 0:
RaiseAsicNormal(inter);
break;
case 1:
RaiseAsicExt(inter);
break;
case 2:
RaiseAsicErr(inter);
break;
}
asic_RaiseInterruptInternal(inter);
}
void asic_RaiseInterruptWait(HollyInterruptID inter)
{
#if 0
/* IRQ wait slots are here. This is a hack.
* Up until now, more than 3 and less than 2 wait slots
* break stuff.
*
* Currently using 2 wait slots. */
OldDmaId = dmatmp2;
dmatmp2 = dmatmp1;
dmatmp1 = inter;
switch (OldDmaId)
{
case holly_CH2_DMA:
case holly_EXT_DMA1:
case holly_GDROM_CMD:
case holly_MAPLE_DMA:
case holly_YUV_DMA:
case holly_PVR_DMA:
case holly_PVR_SortDMA:
case holly_SPU_DMA:
asic_RaiseInterruptInternal(OldDmaId);
break;
}
#else
asic_RaiseInterruptInternal(inter);
#endif
}
u32 Read_SB_ISTNRM(u32 addr)

View File

@ -2,6 +2,7 @@
#include "types.h"
void asic_RaiseInterrupt(HollyInterruptID inter);
void asic_RaiseInterruptWait(HollyInterruptID inter);
void asic_CancelInterrupt(HollyInterruptID inter);
//Init/Res/Term for regs

View File

@ -187,7 +187,7 @@ int maple_schd(int tag, int c, int j)
if (SB_MDEN&1)
{
SB_MDST=0;
asic_RaiseInterrupt(holly_MAPLE_DMA);
asic_RaiseInterruptWait(holly_MAPLE_DMA);
}
else
{

View File

@ -152,7 +152,7 @@ INLINE void YUV_ConvertMacroBlock(u8* datap)
{
YUV_init();
asic_RaiseInterrupt(holly_YUV_DMA);
asic_RaiseInterruptWait(holly_YUV_DMA);
}
}
void YUV_data(u32* data , u32 count)

View File

@ -68,7 +68,7 @@ void do_pvr_dma()
SB_PDST = 0x00000000;
//TODO : *CHECKME* is that ok here ? the docs don't say here it's used [PVR-DMA , bit 11]
asic_RaiseInterrupt(holly_PVR_DMA);
asic_RaiseInterruptWait(holly_PVR_DMA);
}
void RegWrite_SB_PDST(u32 addr, u32 data)
{
@ -122,7 +122,7 @@ void pvr_do_sort_dma()
// End of DMA :)
SB_SDST=0;
asic_RaiseInterrupt(holly_PVR_SortDMA);
asic_RaiseInterruptWait(holly_PVR_SortDMA);
}
// Auto sort DMA :|
void RegWrite_SB_SDST(u32 addr, u32 data)

View File

@ -201,6 +201,8 @@ int AicaUpdate(int tag, int c, int j)
//static int aica_sample_cycles=0;
//aica_sample_cycles+=14336*AICA_SAMPLE_GCM;
extern void aica_periodical(u32 cycl);
//if (aica_sample_cycles>=AICA_SAMPLE_CYCLES)
{
@ -209,6 +211,9 @@ int AicaUpdate(int tag, int c, int j)
//aica_sample_cycles-=AICA_SAMPLE_CYCLES;
}
if (settings.aica.InterruptHack)
aica_periodical(3584);
return AICA_TICK;
}

View File

@ -135,7 +135,7 @@ void DMAC_Ch2St()
// The DMA end interrupt flag (SB_ISTNRM - bit 19: DTDE2INT) is set to "1."
//-> fixed , holly_PVR_DMA is for different use now (fixed the interrupts enum too)
asic_RaiseInterrupt(holly_CH2_DMA);
asic_RaiseInterruptWait(holly_CH2_DMA);
}
//on demand data transfer

View File

@ -260,6 +260,7 @@ void LoadSettings()
settings.aica.LimitFPS = cfgLoadInt("config","aica.LimitFPS",1);
settings.aica.NoBatch = cfgLoadInt("config","aica.NoBatch",0);
settings.aica.NoSound = cfgLoadInt("config","aica.NoSound",0);
settings.aica.InterruptHack = cfgLoadInt("config","aica.InterruptHack",0);
settings.rend.UseMipmaps = cfgLoadInt("config","rend.UseMipmaps",1);
settings.rend.WideScreen = cfgLoadInt("config","rend.WideScreen",0);
settings.rend.ModifierVolumes = cfgLoadInt("config","rend.ModifierVolumes",1);
@ -317,6 +318,7 @@ void LoadCustom()
settings.dynarec.idleskip = cfgGameInt(reios_id,"Dynarec.idleskip", settings.dynarec.idleskip ? 1 : 0) != 0;
settings.dynarec.unstable_opt = cfgGameInt(reios_id,"Dynarec.unstable-opt", settings.dynarec.unstable_opt);
settings.dynarec.safemode = cfgGameInt(reios_id,"Dynarec.safemode", settings.dynarec.safemode);
settings.aica.InterruptHack = cfgLoadInt(reios_id,"aica.InterruptHack", settings.aica.InterruptHack);
settings.rend.ModifierVolumes = cfgGameInt(reios_id,"rend.ModifierVolumes", settings.rend.ModifierVolumes);
settings.rend.Clipping = cfgGameInt(reios_id,"rend.Clipping", settings.rend.Clipping);

View File

@ -652,7 +652,8 @@ struct settings_t
u32 GlobalMute;
u32 DSPEnabled; //0 -> no, 1 -> yes
u32 NoBatch;
u32 NoSound; //0 ->sound, 1 -> no sound
u32 NoSound; //0 ->sound, 1 -> no sound
u32 InterruptHack;
} aica;
#if USE_OMX