예제 #1
0
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);
}
예제 #2
0
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);
    }
}
예제 #3
0
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;
}
예제 #6
0
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;
    }
}