static void do_dma(struct ai_controller* ai, struct ai_dma* dma) { /* lazy initialization of sample format */ if (ai->samples_format_changed) { unsigned int frequency = (ai->regs[AI_DACRATE_REG] == 0) ? 44100 /* default sample rate */ : ai->vi->clock / (1 + ai->regs[AI_DACRATE_REG]); unsigned int bits = (ai->regs[AI_BITRATE_REG] == 0) ? 16 /* default bit rate */ : 1 + ai->regs[AI_BITRATE_REG]; ai->iaout->set_format(ai->aout, frequency, bits); ai->samples_format_changed = 0; } ai->last_read = dma->length; if (ai->delayed_carry) dma->address += 0x2000; if (((dma->address + dma->length) & 0x1FFF) == 0) ai->delayed_carry = 1; else ai->delayed_carry = 0; /* schedule end of dma event */ cp0_update_count(ai->mi->r4300); add_interrupt_event(&ai->mi->r4300->cp0, AI_INT, dma->duration); }
static void dma_si_read(struct si_controller* si) { int i; if (si->regs[SI_PIF_ADDR_RD64B_REG] != 0x1FC007C0) { DebugMessage(M64MSG_ERROR, "dma_si_read(): unknown SI use"); return; } update_pif_read(si); for (i = 0; i < PIF_RAM_SIZE; i += 4) { si->ri->rdram.dram[(si->regs[SI_DRAM_ADDR_REG]+i)/4] = sl(*(uint32_t*)(&si->pif.ram[i])); } cp0_update_count(); if (g_delay_si) { add_interupt_event(SI_INT, /*0x100*/0x900); } else { si->regs[SI_STATUS_REG] |= 0x1000; // INTERRUPT signal_rcp_interrupt(si->r4300, MI_INTR_SI); } }
int write_mi_regs(void* opaque, uint32_t address, uint32_t value, uint32_t mask) { struct r4300_core* r4300 = (struct r4300_core*)opaque; uint32_t reg = mi_reg(address); const uint32_t* cp0_regs = r4300_cp0_regs(); switch(reg) { case MI_INIT_MODE_REG: if (update_mi_init_mode(&r4300->mi.regs[MI_INIT_MODE_REG], value & mask) != 0) { clear_rcp_interrupt(r4300, MI_INTR_DP); } break; case MI_INTR_MASK_REG: update_mi_intr_mask(&r4300->mi.regs[MI_INTR_MASK_REG], value & mask); check_interupt(); cp0_update_count(); if (next_interupt <= cp0_regs[CP0_COUNT_REG]) gen_interupt(); break; } return 0; }
static void do_dma(struct ai_controller* ai, const struct ai_dma* dma) { /* lazy initialization of sample format */ if (ai->samples_format_changed) { unsigned int frequency = (ai->regs[AI_DACRATE_REG] == 0) ? 44100 /* default sample rate */ : ai->vi->clock / (1 + ai->regs[AI_DACRATE_REG]); unsigned int bits = (ai->regs[AI_BITRATE_REG] == 0) ? 16 /* default bit rate */ : 1 + ai->regs[AI_BITRATE_REG]; ai->set_audio_format(ai, frequency, bits); ai->samples_format_changed = 0; ai->last_read = 0; } ai->last_read = dma->length; /* schedule end of dma event */ cp0_update_count(); add_interrupt_event(AI_INT, dma->duration); }
static uint32_t get_remaining_dma_length(struct ai_controller* ai) { uint64_t dma_length; unsigned int next_ai_event; unsigned int remaining_dma_duration; const uint32_t* cp0_regs; if (ai->fifo[0].duration == 0) return 0; cp0_update_count(); next_ai_event = get_event(AI_INT); if (next_ai_event == 0) return 0; cp0_regs = r4300_cp0_regs(); if (next_ai_event <= cp0_regs[CP0_COUNT_REG]) return 0; remaining_dma_duration = next_ai_event - cp0_regs[CP0_COUNT_REG]; dma_length = (uint64_t)remaining_dma_duration * ai->fifo[0].length / ai->fifo[0].duration; return dma_length & ~7; }
void do_SP_Task(struct rsp_core* sp) { uint32_t save_pc = sp->regs2[SP_PC_REG] & ~0xfff; if (sp->mem[0xfc0/4] == 1) { if (sp->dp->dpc_regs[DPC_STATUS_REG] & DPC_STATUS_FREEZE) // DP frozen (DK64, BC) { // don't do the task now // the task will be done when DP is unfreezed (see update_dpc_status) return; } unprotect_framebuffers(sp->dp); //gfx.processDList(); sp->regs2[SP_PC_REG] &= 0xfff; timed_section_start(TIMED_SECTION_GFX); rsp.doRspCycles(0xffffffff); timed_section_end(TIMED_SECTION_GFX); sp->regs2[SP_PC_REG] |= save_pc; new_frame(); cp0_update_count(); if (sp->r4300->mi.regs[MI_INTR_REG] & MI_INTR_SP) add_interupt_event(SP_INT, 1000); if (sp->r4300->mi.regs[MI_INTR_REG] & MI_INTR_DP) add_interupt_event(DP_INT, 1000); sp->r4300->mi.regs[MI_INTR_REG] &= ~(MI_INTR_SP | MI_INTR_DP); sp->regs[SP_STATUS_REG] &= ~SP_STATUS_TASKDONE; protect_framebuffers(sp->dp); } else if (sp->mem[0xfc0/4] == 2) { //audio.processAList(); sp->regs2[SP_PC_REG] &= 0xfff; timed_section_start(TIMED_SECTION_AUDIO); rsp.doRspCycles(0xffffffff); timed_section_end(TIMED_SECTION_AUDIO); sp->regs2[SP_PC_REG] |= save_pc; cp0_update_count(); if (sp->r4300->mi.regs[MI_INTR_REG] & MI_INTR_SP) add_interupt_event(SP_INT, 4000/*500*/); sp->r4300->mi.regs[MI_INTR_REG] &= ~MI_INTR_SP; sp->regs[SP_STATUS_REG] &= ~(SP_STATUS_TASKDONE | SP_STATUS_YIELDED); } else { sp->regs2[SP_PC_REG] &= 0xfff; rsp.doRspCycles(0xffffffff); sp->regs2[SP_PC_REG] |= save_pc; cp0_update_count(); if (sp->r4300->mi.regs[MI_INTR_REG] & MI_INTR_SP) add_interupt_event(SP_INT, 0/*100*/); sp->r4300->mi.regs[MI_INTR_REG] &= ~MI_INTR_SP; sp->regs[SP_STATUS_REG] &= ~SP_STATUS_TASKDONE; } }