static INLINE bool ChCan(void) { #if 0 if(ch != 3) { if((DMACH[3].WordCounter || (DMACH[3].ChanControl & (1 << 24))) && !(DMACH[3].ChanControl & 0x100)) { return(false); } } #endif switch(ch) { case 0: return(true); // MDEC IN case 1: return(MDEC_DMACanRead()); // MDEC out case 2: if(write_mode) return(GPU->DMACanWrite()); else return(true); // GPU /* case 3: return(true); // CDC case 4: return(true); // SPU case 5: return(true); // ?? case 6: return(true); // OT */ case 3: case 4: case 5: case 6: return true; } abort(); }
static INLINE bool ChCan(const unsigned ch, const uint32 CRModeCache) { switch(ch) { default: abort(); case CH_MDEC_IN: return(MDEC_DMACanWrite()); case CH_MDEC_OUT: return(MDEC_DMACanRead()); case CH_GPU: if(CRModeCache & 0x1) return(GPU->DMACanWrite()); else return(true); case CH_CDC: return(true); case CH_SPU: return(true); case CH_FIVE: return(false); case CH_OT: return((bool)(DMACH[ch].ChanControl & (1U << 28))); } }
static void RecalcHalt(void) { bool Halt = false; if((DMACH[0].WordCounter || (DMACH[0].ChanControl & (1 << 24))) && (DMACH[0].ChanControl & 0x200) /*&& MDEC_DMACanWrite()*/) Halt = true; if((DMACH[1].WordCounter || (DMACH[1].ChanControl & (1 << 24))) && (DMACH[1].ChanControl & 0x200) && (DMACH[1].WordCounter || MDEC_DMACanRead())) Halt = true; if((DMACH[2].WordCounter || (DMACH[2].ChanControl & (1 << 24))) && (DMACH[2].ChanControl & 0x200) && ((DMACH[2].ChanControl & 0x1) && (DMACH[2].WordCounter || GPU->DMACanWrite()))) Halt = true; if((DMACH[3].WordCounter || (DMACH[3].ChanControl & (1 << 24))) && !(DMACH[3].ChanControl & 0x100)) Halt = true; if(DMACH[6].WordCounter || (DMACH[6].ChanControl & (1 << 24))) Halt = true; //printf("Halt: %d\n", Halt); CPU->SetHalt(Halt); }
static void RecalcHalt(void) { bool Halt = false; unsigned ch, tmp; ch = 0; tmp = 0; for(ch = 0; ch < 7; ch++) { if(DMACH[ch].ChanControl & (1U << 24)) { if(!(DMACH[ch].ChanControl & (7U << 8))) { if(DMACH[ch].WordCounter > 0) { Halt = true; break; } } #if 0 if(DMACH[ch].ChanControl & 0x100) // DMA doesn't hog the bus when this bit is set, though the DMA takes longer. continue; if(ch == 4 || ch == 5) // Not sure if these channels will typically hog the bus or not...investigate. continue; if(!(DMACH[ch].ChanControl & (1U << 10))) // Not sure about HOGGERYNESS with linked-list mode, and it likely wouldn't work well either in regards // to GPU commands due to the rather large DMA update granularity. { if((DMACH[ch].WordCounter > 0) || ChCan(ch, DMACH[ch].ChanControl & 0x1)) { Halt = true; break; } } #endif } } #if 0 if((DMACH[0].WordCounter || (DMACH[0].ChanControl & (1 << 24))) && (DMACH[0].ChanControl & 0x200) /*&& MDEC_DMACanWrite()*/) Halt = true; if((DMACH[1].WordCounter || (DMACH[1].ChanControl & (1 << 24))) && (DMACH[1].ChanControl & 0x200) && (DMACH[1].WordCounter || MDEC_DMACanRead())) Halt = true; if((DMACH[2].WordCounter || (DMACH[2].ChanControl & (1 << 24))) && (DMACH[2].ChanControl & 0x200) && ((DMACH[2].ChanControl & 0x1) && (DMACH[2].WordCounter || GPU->DMACanWrite()))) Halt = true; if((DMACH[3].WordCounter || (DMACH[3].ChanControl & (1 << 24))) && !(DMACH[3].ChanControl & 0x100)) Halt = true; if(DMACH[6].WordCounter || (DMACH[6].ChanControl & (1 << 24))) Halt = true; #endif //printf("Halt: %d\n", Halt); if(!Halt && (DMACH[2].ChanControl & (1U << 24)) && ((DMACH[2].ChanControl & 0x700) == 0x200) && ChCan(2, DMACH[2].ChanControl)) { tmp = DMACH[2].BlockControl & 0xFFFF; if(tmp > 0) tmp--; if(tmp > 200) // Due to 8-bit limitations in the CPU core. tmp = 200; } PSX_SetDMASuckSuck(tmp); CPU->SetHalt(Halt); }