diff --git a/core/hw/aica/aica_if.cpp b/core/hw/aica/aica_if.cpp index a3306146d..39dd69ecc 100644 --- a/core/hw/aica/aica_if.cpp +++ b/core/hw/aica/aica_if.cpp @@ -9,6 +9,7 @@ #include "hw/holly/sb.h" #include "types.h" #include "hw/holly/holly_intc.h" +#include "hw/sh4/sh4_sched.h" #include @@ -16,6 +17,8 @@ VArray2 aica_ram; u32 VREG;//video reg =P u32 ARMRST;//arm reset reg u32 rtc_EN=0; +int dma_sched_id; + u32 GetRTC_now() { @@ -178,6 +181,28 @@ void aica_Term() } +int dma_end_sched(int tag, int cycl, int jitt) +{ + u32 len=SB_ADLEN & 0x7FFFFFFF; + + if (SB_ADLEN & 0x80000000) + SB_ADEN=1;// + else + SB_ADEN=0;// + + SB_ADSTAR+=len; + SB_ADSTAG+=len; + SB_ADST = 0x00000000;//dma done + SB_ADLEN = 0x00000000; + + // indicate that dma is not happening, or has been paused + SB_ADSUSP |= 0x10; + + asic_RaiseInterrupt(holly_SPU_DMA); + + return 0; +} + void Write_SB_ADST(u32 addr, u32 data) { //0x005F7800 SB_ADSTAG RW AICA:G2-DMA G2 start address @@ -214,18 +239,24 @@ void Write_SB_ADST(u32 addr, u32 data) WriteMem32_nommu(dst+i,data); } */ - if (SB_ADLEN & 0x80000000) - SB_ADEN=1;// + + // idicate that dma is in progress + SB_ADSUSP &= ~0x10; + + if (!settings.aica.OldSyncronousDma) + { + + // Schedule the end of DMA transfer interrupt + int cycles = len * (SH4_MAIN_CLOCK / 2 / 25000000); // 16 bits @ 25 MHz + if (cycles < 4096) + dma_end_sched(0, 0, 0); + else + sh4_sched_request(dma_sched_id, cycles); + } else - SB_ADEN=0;// - - SB_ADSTAR+=len; - SB_ADSTAG+=len; - SB_ADST = 0x00000000;//dma done - SB_ADLEN = 0x00000000; - - - asic_RaiseInterrupt(holly_SPU_DMA); + { + dma_end_sched(0, 0, 0); + } } } } @@ -299,6 +330,7 @@ void aica_sb_Init() //sb_regs[((SB_E1ST_addr-SB_BASE)>>2)].flags=REG_32BIT_READWRITE | REG_READ_DATA; //sb_regs[((SB_E1ST_addr-SB_BASE)>>2)].writeFunction=Write_SB_E1ST; + dma_sched_id = sh4_sched_register(0, &dma_end_sched); } void aica_sb_Reset(bool Manual) @@ -307,4 +339,4 @@ void aica_sb_Reset(bool Manual) void aica_sb_Term() { -} \ No newline at end of file +} diff --git a/core/nullDC.cpp b/core/nullDC.cpp index 5a7fcb869..1d9d44370 100755 --- a/core/nullDC.cpp +++ b/core/nullDC.cpp @@ -297,6 +297,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.OldSyncronousDma = cfgLoadBool("config", "aica.OldSyncronousDma", false); settings.rend.UseMipmaps = cfgLoadInt("config", "rend.UseMipmaps", 1); settings.rend.WideScreen = cfgLoadInt("config", "rend.WideScreen", 0); settings.rend.Clipping = cfgLoadInt("config", "rend.Clipping", 1); diff --git a/core/types.h b/core/types.h index dadb01cab..a9b705553 100644 --- a/core/types.h +++ b/core/types.h @@ -654,6 +654,7 @@ struct settings_t u32 DSPEnabled; //0 -> no, 1 -> yes u32 NoBatch; u32 NoSound; //0 ->sound, 1 -> no sound + bool OldSyncronousDma; // 0 -> sync dma (old behavior), 1 -> async dma (fixes some games, partial implementation) } aica; #if USE_OMX