void GBA_DMASoundRequestData(int A, int B) { //this should check if another dma is running and return without copying if(DMA[1].starttime == START_SPECIAL) { if( (A && (DMA[1].dstaddr==FIFO_A)) || (B && (DMA[1].dstaddr==FIFO_B)) ) { //copy words int i; for(i = 0; i < 4; i++) { // if(GBA_MemoryRead32(DMA[1].srcaddr)!=0) //Debug_DebugMsgArg("%08X",DMA[1].srcaddr); // //Debug_DebugMsgArg("[%08x]= %08X",DMA[1].srcaddr,GBA_MemoryRead32(DMA[1].srcaddr)); // Debug_DebugMsgArg("%08X",GBA_MemoryRead32(DMA[1].srcaddr)); GBA_MemoryWrite32(DMA[1].dstaddr,GBA_MemoryRead32(DMA[1].srcaddr)); DMA[1].srcaddr += DMA[1].srcadd; } if(REG_DMA2CNT_H & BIT(14)) GBA_CallInterrupt(BIT(9)); } } if(DMA[2].starttime == START_SPECIAL) { if( (A && (DMA[2].dstaddr==FIFO_A)) || (B && (DMA[2].dstaddr==FIFO_B)) ) { //copy words int i; for(i = 0; i < 4; i++) { GBA_MemoryWrite32(DMA[2].dstaddr,GBA_MemoryRead32(DMA[2].srcaddr)); DMA[2].srcaddr += DMA[2].srcadd; } if(REG_DMA2CNT_H & BIT(14)) GBA_CallInterrupt(BIT(10)); } } }
inline void GBA_CheckKeypadInterrupt(void) { u16 keys = REG_KEYCNT & 0x03FF; u16 keyspressed = (~REG_KEYINPUT) & 0x03FF; if(REG_KEYCNT&BIT(15)) //AND { if((keys&keyspressed) == keys) { if(REG_KEYCNT&BIT(14)) GBA_CallInterrupt(BIT(12)); //IRQ Enable Flag if(GBA_CPUGetHalted()==2) GBA_CPUClearHalted(); } } else //OR { if(keys&keyspressed) { if(REG_KEYCNT&BIT(14)) GBA_CallInterrupt(BIT(12)); //IRQ Enable Flag if(GBA_CPUGetHalted()==2) GBA_CPUClearHalted(); } } }
static inline s32 GBA_DMA3Update(s32 clocks) //return clocks to finish transfer { if(DMA[3].enabled == 0) return 0x7FFFFFFF; if(DMA[3].starttime == START_SPECIAL) { Debug_DebugMsgArg("DMA3, MODE: START_SPECIAL -- NOT EMULATED"); GBA_ExecutionBreak(); DMA[3].enabled = 0; return 0x7FFFFFFF; } if(DMA[3].clocksremaining == DMA[3].clockstotal) { u32 copy = 0; switch(DMA[3].starttime) { case START_NOW: { copy = 1; break; } case START_VBL: { if(screenmode != SCR_VBL) return 0x7FFFFFFF; if(GBA_ScreenJustChangedMode() == 0) return 0x7FFFFFFF; copy = 1; break; } case START_HBL: { if(screenmode != SCR_HBL) return 0x7FFFFFFF; if(GBA_ScreenJustChangedMode() == 0) return 0x7FFFFFFF; copy = 1; break; } case START_SPECIAL: return 0x7FFFFFFF; // TODO: NOT EMULATED ***************************** default: break; } if(copy) { //MessageBox(NULL, "DMA 3 copy", "EMULATION", MB_OK); //GBA_ExecutionBreak(); //char text[64]; snprintf(text,sizeof(text),"DMA3\nSRC: %08X\nDST: %08X\nCHUNCKS: %08X", // DMA[3].srcaddr,DMA[3].dstaddr,DMA[3].num_chunks); //MessageBox(NULL, text, "EMULATION", MB_OK); //GBA_ExecutionBreak(); if(DMA[3].copywords) //copy words { int i; for(i = 0; i < DMA[3].num_chunks; i++) { GBA_MemoryWrite32(DMA[3].dstaddr,GBA_MemoryRead32(DMA[3].srcaddr)); DMA[3].srcaddr += DMA[3].srcadd; DMA[3].dstaddr += DMA[3].dstadd; } } else //copy halfwords { int i; for(i = 0; i < DMA[3].num_chunks; i++) { GBA_MemoryWrite16(DMA[3].dstaddr,GBA_MemoryRead16(DMA[3].srcaddr)); DMA[3].srcaddr += DMA[3].srcadd; DMA[3].dstaddr += DMA[3].dstadd; } } } } DMA[3].clocksremaining -= clocks; if(DMA[3].clocksremaining <= 0) { gba_dma_extra_clocks_elapsed = -DMA[3].clocksremaining; if(DMA[3].dst_reload) DMA[3].dstaddr = REG_DMA3DAD & (DMA[3].copywords ? ~3 : ~1); if(REG_DMA3CNT_H & BIT(14)) GBA_CallInterrupt(BIT(11)); //interrupt if(DMA[3].repeat == 0) { REG_DMA3CNT_H &= ~BIT(15); DMA[3].enabled = 0; //MessageBox(NULL, "DMA 3 clear", "EMULATION", MB_OK); //GBA_ExecutionBreak(); } else { DMA[3].clocksremaining = DMA[3].clockstotal; if(DMA[3].starttime == START_NOW) { //Debug_DebugMsgArg("WARNING: DMA 3, immediate mode with repeat bit set."); //GBA_ExecutionBreak(); REG_DMA3CNT_H &= ~BIT(15); DMA[3].enabled = 0; return 0x7FFFFFFF; } } return 0x7FFFFFFF; } gba_dmaworking = 1; return DMA[3].clocksremaining; }
static inline s32 GBA_DMA0Update(s32 clocks) //return clocks to finish transfer { if(DMA[0].enabled == 0) return 0x7FFFFFFF; if(DMA[0].starttime == START_SPECIAL) { Debug_DebugMsgArg("DMA0, MODE: START_SPECIAL (?)"); GBA_ExecutionBreak(); DMA[0].enabled = 0; return 0x7FFFFFFF; } if(DMA[0].clocksremaining == DMA[0].clockstotal) { u32 copy = 0; switch(DMA[0].starttime) { case START_NOW: { copy = 1; break; } case START_VBL: { if(screenmode != SCR_VBL) return 0x7FFFFFFF; if(GBA_ScreenJustChangedMode() == 0) return 0x7FFFFFFF; copy = 1; break; } case START_HBL: { if(screenmode != SCR_HBL) return 0x7FFFFFFF; if(GBA_ScreenJustChangedMode() == 0) return 0x7FFFFFFF; copy = 1; break; } case START_SPECIAL: return 0x7FFFFFFF; //NOT EMULATED ***************************** default: break; } if(copy) { if(DMA[0].copywords) //copy words { int i; for(i = 0; i < DMA[0].num_chunks; i++) { GBA_MemoryWrite32(DMA[0].dstaddr,GBA_MemoryRead32(DMA[0].srcaddr)); DMA[0].srcaddr += DMA[0].srcadd; DMA[0].dstaddr += DMA[0].dstadd; } } else //copy halfwords { int i; for(i = 0; i < DMA[0].num_chunks; i++) { GBA_MemoryWrite16(DMA[0].dstaddr,GBA_MemoryRead16(DMA[0].srcaddr)); DMA[0].srcaddr += DMA[0].srcadd; DMA[0].dstaddr += DMA[0].dstadd; } } } } DMA[0].clocksremaining -= clocks; if(DMA[0].clocksremaining <= 0) { gba_dma_extra_clocks_elapsed = -DMA[0].clocksremaining; if(DMA[0].dst_reload) DMA[0].dstaddr = REG_DMA0DAD & (DMA[0].copywords ? ~3 : ~1); if(REG_DMA0CNT_H & BIT(14)) GBA_CallInterrupt(BIT(8)); //interrupt if(DMA[0].repeat == 0) { REG_DMA0CNT_H &= ~BIT(15); DMA[0].enabled = 0; } else { DMA[0].clocksremaining = DMA[0].clockstotal; if(DMA[0].starttime == START_NOW) { //Debug_DebugMsgArg("DMA 0 immediate mode with repeat bit set."); //GBA_ExecutionBreak(); REG_DMA0CNT_H &= ~BIT(15); DMA[0].enabled = 0; return 0x7FFFFFFF; } } return 0x7FFFFFFF; } gba_dmaworking = 1; return DMA[0].clocksremaining; }