diff --git a/desmume/src/MMU.cpp b/desmume/src/MMU.cpp index f15d828f5..20fb4cf99 100644 --- a/desmume/src/MMU.cpp +++ b/desmume/src/MMU.cpp @@ -913,6 +913,7 @@ void MMU_Reset() memset(MMU.reg_IME, 0, sizeof(u32) * 2); memset(MMU.reg_IE, 0, sizeof(u32) * 2); memset(MMU.reg_IF_bits, 0, sizeof(u32) * 2); + memset(MMU.reg_IF_pending, 0, sizeof(u32) * 2); memset(MMU.dscard, 0, sizeof(nds_dscard) * 2); @@ -3461,7 +3462,9 @@ u16 FASTCALL _MMU_ARM9_read16(u32 adr) { nds.ensataHandshake = ENSATA_HANDSHAKE_ack; return 270; - } else return nds.VCount; + } + else + return nds.VCount; // ============================================= 3D case eng_3D_RAM_COUNT: diff --git a/desmume/src/MMU.h b/desmume/src/MMU.h index ea7262f2a..8589e4916 100644 --- a/desmume/src/MMU.h +++ b/desmume/src/MMU.h @@ -390,6 +390,8 @@ struct MMU_struct //these are the user-controlled IF bits. some IF bits are generated as necessary from hardware conditions u32 reg_IF_bits[2]; + //these flags are set occasionally to indicate that an irq should have entered the pipeline, and processing will be deferred a tiny bit to help emulate things + u32 reg_IF_pending[2]; u32 reg_DISP3DCNT_bits; diff --git a/desmume/src/NDSSystem.cpp b/desmume/src/NDSSystem.cpp index 7173ab74e..cfe85f7b7 100644 --- a/desmume/src/NDSSystem.cpp +++ b/desmume/src/NDSSystem.cpp @@ -1050,7 +1050,7 @@ void NDS_OmitFrameSkip(int force) { enum ESI_DISPCNT { - ESI_DISPCNT_HStart, ESI_DISPCNT_HBlank + ESI_DISPCNT_HStart, ESI_DISPCNT_HStartIRQ, ESI_DISPCNT_HDraw, ESI_DISPCNT_HBlank }; u64 nds_timer; @@ -1505,8 +1505,8 @@ static void execHardware_hstart_vblankEnd() sequencer.reschedule = true; //turn off vblank status bit - T1WriteWord(MMU.ARM9_REG, 4, T1ReadWord(MMU.ARM9_REG, 4) & 0xFFFE); - T1WriteWord(MMU.ARM7_REG, 4, T1ReadWord(MMU.ARM7_REG, 4) & 0xFFFE); + T1WriteWord(MMU.ARM9_REG, 4, T1ReadWord(MMU.ARM9_REG, 4) & ~1); + T1WriteWord(MMU.ARM7_REG, 4, T1ReadWord(MMU.ARM7_REG, 4) & ~1); //some emulation housekeeping frameSkipper.Advance(); @@ -1516,16 +1516,13 @@ static void execHardware_hstart_vblankStart() { //printf("--------VBLANK!!!--------\n"); - //turn on vblank status bit - T1WriteWord(MMU.ARM9_REG, 4, T1ReadWord(MMU.ARM9_REG, 4) | 1); - T1WriteWord(MMU.ARM7_REG, 4, T1ReadWord(MMU.ARM7_REG, 4) | 1); - //fire vblank interrupts if necessary - if(T1ReadWord(MMU.ARM9_REG, 4) & 0x8) NDS_makeIrq(ARMCPU_ARM9,IRQ_BIT_LCD_VBLANK); - if(T1ReadWord(MMU.ARM7_REG, 4) & 0x8) NDS_makeIrq(ARMCPU_ARM7,IRQ_BIT_LCD_VBLANK); - - //some emulation housekeeping - gfx3d_VBlankSignal(); + for(int i=0;i<2;i++) + if(MMU.reg_IF_pending[i] & (1<>8)|((vmatch<<1)&(1<<8))); + return vmatch; +} + +static void execHardware_hstart_vcount_irq() +{ + //trigger pending VMATCH irqs + if(MMU.reg_IF_pending[ARMCPU_ARM9] & (1<