コード例 #1
0
ファイル: controller.c プロジェクト: ChunHungLiu/cen64
// Writes a word to the PI MMIO register space.
int write_pi_regs(void *opaque, uint32_t address, uint32_t word, uint32_t dqm) {
  struct pi_controller *pi = (struct pi_controller *) opaque;
  unsigned offset = address - PI_REGS_BASE_ADDRESS;
  enum pi_register reg = (offset >> 2);

  debug_mmio_write(pi, pi_register_mnemonics[reg], word, dqm);

  if (reg == PI_STATUS_REG) {
    if (word & 0x1)
      pi->regs[reg] = 0;

    if (word & 0x2) {
      clear_rcp_interrupt(pi->bus->vr4300, MI_INTR_PI);
      pi->regs[reg] &= ~0x8;
    }
  }

  else {
    pi->regs[reg] &= ~dqm;
    pi->regs[reg] |= word;

    if (reg == PI_CART_ADDR_REG)
      dd_pi_write(pi->bus->dd, word);

    else if (reg == PI_WR_LEN_REG) {
      if (pi->regs[PI_DRAM_ADDR_REG] == 0xFFFFFFFF) {
        pi->regs[PI_STATUS_REG] &= ~0x1;
        pi->regs[PI_STATUS_REG] |= 0x8;

        signal_rcp_interrupt(pi->bus->vr4300, MI_INTR_PI);
        return 0;
      }

      pi->bytes_to_copy = (pi->regs[PI_WR_LEN_REG] & 0xFFFFFF) + 1;
      pi->counter = pi->bytes_to_copy / 2 + 100; // Assume ~2 bytes/clock?
      pi->regs[PI_STATUS_REG] |= 0x9; // I'm busy!
      pi->is_dma_read = false;
    }

    else if (reg == PI_RD_LEN_REG) {
      if (pi->regs[PI_DRAM_ADDR_REG] == 0xFFFFFFFF) {
        pi->regs[PI_STATUS_REG] &= ~0x1;
        pi->regs[PI_STATUS_REG] |= 0x8;

        signal_rcp_interrupt(pi->bus->vr4300, MI_INTR_PI);
        return 0;
      }

      pi->bytes_to_copy = (pi->regs[PI_RD_LEN_REG] & 0xFFFFFF) + 1;
      pi->counter = pi->bytes_to_copy / 2 + 100; // Assume ~2 bytes/clock?
      pi->regs[PI_STATUS_REG] |= 0x9; // I'm busy!
      pi->is_dma_read = true;
    }
  }

  return 0;
}
コード例 #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
ファイル: si_controller.c プロジェクト: derselbst/lazyusf2
static void dma_si_write(struct si_controller* si)
{
    int i;

    if (si->regs[SI_PIF_ADDR_WR64B_REG] != 0x1FC007C0)
    {
        DebugMessage(si->r4300->state, M64MSG_ERROR, "dma_si_write(): unknown SI use");
        si->r4300->state->stop=1;
    }

    for (i = 0; i < PIF_RAM_SIZE; i += 4)
    {
        *((uint32_t*)(&si->pif.ram[i])) = sl(si->ri->rdram.dram[(si->regs[SI_DRAM_ADDR_REG]+i)/4]);
    }
    
    if (si->r4300->state->enable_trimming_mode)
    {
        for (i = 0; i < PIF_RAM_SIZE; i += 4)
        {
            unsigned int ram_address = si->regs[SI_DRAM_ADDR_REG] + i;
            if (!bit_array_test(si->r4300->state->barray_ram_written_first, ram_address / 4))
                bit_array_set(si->r4300->state->barray_ram_read, ram_address / 4);
        }
    }

    update_pif_write(si);
    update_count(si->r4300->state);

    if (si->r4300->state->g_delay_si) {
        add_interupt_event(si->r4300->state, SI_INT, /*0x100*/0x900);
    } else {
        si->regs[SI_STATUS_REG] |= 0x1000; // INTERRUPT
        signal_rcp_interrupt(si->r4300, MI_INTR_SI);
    }
}
コード例 #4
0
int write_dpc_regs(void* opaque, uint32_t address, uint32_t value, uint32_t mask)
{
   struct rdp_core* dp = (struct rdp_core*)opaque;
   uint32_t reg        = dpc_reg(address);

   switch(reg)
   {
      case DPC_STATUS_REG:
         if (update_dpc_status(dp, value & mask) != 0)
            do_SP_Task(dp->sp);
      case DPC_CURRENT_REG:
      case DPC_CLOCK_REG:
      case DPC_BUFBUSY_REG:
      case DPC_PIPEBUSY_REG:
      case DPC_TMEM_REG:
         return 0;
   }

   masked_write(&dp->dpc_regs[reg], value, mask);

   switch(reg)
   {
      case DPC_START_REG:
         dp->dpc_regs[DPC_CURRENT_REG] = dp->dpc_regs[DPC_START_REG];
         break;
      case DPC_END_REG:
         gfx.processRDPList();
         signal_rcp_interrupt(dp->r4300, MI_INTR_DP);
         break;
   }

   return 0;
}
コード例 #5
0
ファイル: n64.c プロジェクト: joolswills/advancemame
void sp_set_status(UINT32 status)
{
	if (status & 0x1)
	{
		cpunum_set_input_line(1, INPUT_LINE_HALT, ASSERT_LINE);
		rsp_sp_status |= SP_STATUS_HALT;
	}
	if (status & 0x2)
	{
		rsp_sp_status |= SP_STATUS_BROKE;

		if (rsp_sp_status & SP_STATUS_INT_ON_BRK)
		{
			signal_rcp_interrupt(SP_INTERRUPT);
		}
	}
}
コード例 #6
0
ファイル: controller.c プロジェクト: stevendschmidt/cen64
// Advances the controller by one clock cycle.
void ai_cycle(struct ai_controller *ai) {
  if (likely(ai->counter-- != 0))
    return;

  // DMA engine is finishing up with one entry.
  if (ai->fifo_count > 0) {
    struct bus_controller *bus;

    memcpy(&bus, ai, sizeof(bus));
    signal_rcp_interrupt(bus->vr4300, MI_INTR_AI);

    ai->fifo_ri = (ai->fifo_ri == 1) ? 0 : 1;
    ai->regs[AI_STATUS_REG] &= ~0xC0000001;
    ai->counter = 0xFFFFFFFFU;
    ai->fifo_count--;

    if (ai->fifo_count > 0)
      ai_dma(ai);
  }
}
コード例 #7
0
ファイル: n64.c プロジェクト: broftkd/historic-mame
static void sp_set_status(UINT32 status)
{
	if (status & 0x1)
	{
		//cpu_trigger(6789);

		cpunum_set_input_line(1, INPUT_LINE_HALT, ASSERT_LINE);
        cpunum_set_info_int(1, CPUINFO_INT_REGISTER + RSP_SR, cpunum_get_info_int(1, CPUINFO_INT_REGISTER + RSP_SR) | RSP_STATUS_HALT);
		//rsp_sp_status |= SP_STATUS_HALT;
	}
	if (status & 0x2)
	{
		//rsp_sp_status |= SP_STATUS_BROKE;
        cpunum_set_info_int(1, CPUINFO_INT_REGISTER + RSP_SR, cpunum_get_info_int(1, CPUINFO_INT_REGISTER + RSP_SR) | RSP_STATUS_BROKE);

        if (cpunum_get_info_int(1, CPUINFO_INT_REGISTER + RSP_SR) & RSP_STATUS_INTR_BREAK)
		{
			signal_rcp_interrupt(SP_INTERRUPT);
		}
	}
}
コード例 #8
0
ファイル: controller.c プロジェクト: ChunHungLiu/cen64
// Advances the controller by one clock cycle.
void pi_cycle_(struct pi_controller *pi) {

  // DMA engine is finishing up with one entry.
  if (pi->bytes_to_copy > 0) {
    uint32_t bytes = pi->bytes_to_copy;

    // XXX: Defer actual movement of bytes until... now.
    // This is a giant hack; bytes should be DMA'd slowly.
    // Also, why the heck does the OR do? I know the &
    // clears the busy bit, but...
    pi->is_dma_read ? pi_dma_read(pi) : pi_dma_write(pi);

    pi->regs[PI_DRAM_ADDR_REG] += bytes;
    pi->regs[PI_CART_ADDR_REG] += bytes;
    pi->regs[PI_STATUS_REG] &= ~0x1;
    pi->regs[PI_STATUS_REG] |= 0x8;

    signal_rcp_interrupt(pi->bus->vr4300, MI_INTR_PI);

    pi->bytes_to_copy = 0;
    return;
  }
}
コード例 #9
0
ファイル: aleck64.c プロジェクト: Paulodx/sdl-mame-wii
static INTERRUPT_GEN( n64_vblank )
{
	signal_rcp_interrupt(device->machine, VI_INTERRUPT);
}
コード例 #10
0
ファイル: controller.c プロジェクト: stevendschmidt/cen64
// Performs an (instantaneous) DMA.
void ai_dma(struct ai_controller *ai) {
  struct bus_controller *bus;

  // Shove things into the audio context, slide the window.
  memcpy(&bus, ai, sizeof(bus));

  // Need to raise an interrupt when the DMA engine
  // is doing the last 8-byte data bus transfer...
  if (likely(ai->fifo[ai->fifo_ri].length > 0)) {
    unsigned freq = (double) NTSC_DAC_FREQ / (ai->regs[AI_DACRATE_REG] + 1);
    unsigned samples = ai->fifo[ai->fifo_ri].length / 4;// - 1;

    // Shovel things into the audio context.
    uint8_t buf[0x40000];
    unsigned i;

    ALuint buffer;
    ALint val;

    alGetSourcei(ai->ctx.source, AL_BUFFERS_PROCESSED, &val);

    if (val) {
      for (i = 0; i < ai->fifo[ai->fifo_ri].length / 4; i++) {
        uint32_t word;

        // Byteswap audio buffer to native format.
        // TODO: Can we specify endian-ness somehow?
        memcpy(&word, bus->ri->ram + (ai->fifo[
          ai->fifo_ri].address + sizeof(word) * i), sizeof(word));
        word = byteswap_32(word);
        memcpy(buf + sizeof(word) * i, &word, sizeof(word));
      }

      alSourceUnqueueBuffers(ai->ctx.source, 1, &buffer);
      alBufferData(buffer, AL_FORMAT_STEREO16, buf,
        ai->fifo[ai->fifo_ri].length, 44100 /* ai->ctx.frequency */);
      alSourceQueueBuffers(ai->ctx.source, 1, &buffer);

      alGetSourcei(ai->ctx.source, AL_SOURCE_STATE, &val);

      if(val != AL_PLAYING)
        alSourcePlay(ai->ctx.source);

      if (alGetError() != AL_NO_ERROR) {
        fprintf(stderr, "OpenAL is angry!\n");
        exit(255);
      }
    }

    ai->counter = (62500000.0 / freq) * samples;
    //printf("Wait %lu cycles to raise interrupt.\n", ai->counter);
  }

  // If the length was zero, just interrupt now?
  else {
    signal_rcp_interrupt(bus->vr4300, MI_INTR_AI);

    ai->fifo_ri = (ai->fifo_ri == 1) ? 0 : 1;
    ai->regs[AI_STATUS_REG] &= ~0x80000001;
    ai->counter = 0xFFFFFFFFU;
    ai->fifo_count--;
  }

  if (ai->fifo_count > 0)
    ai->regs[AI_STATUS_REG] |= 0x40000000;
}
コード例 #11
0
ファイル: rsp_core.c プロジェクト: fzurita/mupen64plus-ae
static void update_sp_status(struct rsp_core* sp, uint32_t w)
{
    /* clear / set halt */
    if (w & 0x1) sp->regs[SP_STATUS_REG] &= ~SP_STATUS_HALT;
    if (w & 0x2) sp->regs[SP_STATUS_REG] |= SP_STATUS_HALT;

    /* clear broke */
    if (w & 0x4) sp->regs[SP_STATUS_REG] &= ~SP_STATUS_BROKE;

    /* clear SP interrupt */
    if (w & 0x8)
    {
        clear_rcp_interrupt(sp->r4300, MI_INTR_SP);
    }
    /* set SP interrupt */
    if (w & 0x10)
    {
        signal_rcp_interrupt(sp->r4300, MI_INTR_SP);
    }

    /* clear / set single step */
    if (w & 0x20) sp->regs[SP_STATUS_REG] &= ~SP_STATUS_SSTEP;
    if (w & 0x40) sp->regs[SP_STATUS_REG] |= SP_STATUS_SSTEP;

    /* clear / set interrupt on break */
    if (w & 0x80) sp->regs[SP_STATUS_REG] &= ~SP_STATUS_INTR_BREAK;
    if (w & 0x100) sp->regs[SP_STATUS_REG] |= SP_STATUS_INTR_BREAK;

    /* clear / set signal 0 */
    if (w & 0x200) sp->regs[SP_STATUS_REG] &= ~SP_STATUS_SIG0;
    if (w & 0x400) sp->regs[SP_STATUS_REG] |= SP_STATUS_SIG0;

    /* clear / set signal 1 */
    if (w & 0x800) sp->regs[SP_STATUS_REG] &= ~SP_STATUS_SIG1;
    if (w & 0x1000) sp->regs[SP_STATUS_REG] |= SP_STATUS_SIG1;

    /* clear / set signal 2 */
    if (w & 0x2000) sp->regs[SP_STATUS_REG] &= ~SP_STATUS_SIG2;
    if (w & 0x4000) sp->regs[SP_STATUS_REG] |= SP_STATUS_SIG2;

    /* clear / set signal 3 */
    if (w & 0x8000) sp->regs[SP_STATUS_REG] &= ~SP_STATUS_SIG3;
    if (w & 0x10000) sp->regs[SP_STATUS_REG] |= SP_STATUS_SIG3;

    /* clear / set signal 4 */
    if (w & 0x20000) sp->regs[SP_STATUS_REG] &= ~SP_STATUS_SIG4;
    if (w & 0x40000) sp->regs[SP_STATUS_REG] |= SP_STATUS_SIG4;

    /* clear / set signal 5 */
    if (w & 0x80000) sp->regs[SP_STATUS_REG] &= ~SP_STATUS_SIG5;
    if (w & 0x100000) sp->regs[SP_STATUS_REG] |= SP_STATUS_SIG5;

    /* clear / set signal 6 */
    if (w & 0x200000) sp->regs[SP_STATUS_REG] &= ~SP_STATUS_SIG6;
    if (w & 0x400000) sp->regs[SP_STATUS_REG] |= SP_STATUS_SIG6;

    /* clear / set signal 7 */
    if (w & 0x800000) sp->regs[SP_STATUS_REG] &= ~SP_STATUS_SIG7;
    if (w & 0x1000000) sp->regs[SP_STATUS_REG] |= SP_STATUS_SIG7;

    //if (get_event(SP_INT)) return;
    if (!(w & 0x1) && !(w & 0x4))
        return;

    if (!(sp->regs[SP_STATUS_REG] & (SP_STATUS_HALT | SP_STATUS_BROKE)))
        do_SP_Task(sp);
}
コード例 #12
0
ファイル: n64.c プロジェクト: broftkd/historic-mess
static INTERRUPT_GEN( n64_vblank )
{
	signal_rcp_interrupt(VI_INTERRUPT);
}
コード例 #13
0
ファイル: rsp_core.c プロジェクト: ricrpi/mupen64plus-core
static void update_sp_status(struct rsp_core* sp, uint32_t w)
{
    /* clear / set halt */
    if (w & 0x1) sp->regs[SP_STATUS_REG] &= ~0x1;
    if (w & 0x2) sp->regs[SP_STATUS_REG] |= 0x1;

    /* clear broke */
    if (w & 0x4) sp->regs[SP_STATUS_REG] &= ~0x2;

    /* clear SP interrupt */
    if (w & 0x8)
    {
        clear_rcp_interrupt(sp->r4300, MI_INTR_SP);
    }
    /* set SP interrupt */
    if (w & 0x10)
    {
        signal_rcp_interrupt(sp->r4300, MI_INTR_SP);
    }

    /* clear / set single step */
    if (w & 0x20) sp->regs[SP_STATUS_REG] &= ~0x20;
    if (w & 0x40) sp->regs[SP_STATUS_REG] |= 0x20;

    /* clear / set interrupt on break */
    if (w & 0x80) sp->regs[SP_STATUS_REG] &= ~0x40;
    if (w & 0x100) sp->regs[SP_STATUS_REG] |= 0x40;

    /* clear / set signal 0 */
    if (w & 0x200) sp->regs[SP_STATUS_REG] &= ~0x80;
    if (w & 0x400) sp->regs[SP_STATUS_REG] |= 0x80;

    /* clear / set signal 1 */
    if (w & 0x800) sp->regs[SP_STATUS_REG] &= ~0x100;
    if (w & 0x1000) sp->regs[SP_STATUS_REG] |= 0x100;

    /* clear / set signal 2 */
    if (w & 0x2000) sp->regs[SP_STATUS_REG] &= ~0x200;
    if (w & 0x4000) sp->regs[SP_STATUS_REG] |= 0x200;

    /* clear / set signal 3 */
    if (w & 0x8000) sp->regs[SP_STATUS_REG] &= ~0x400;
    if (w & 0x10000) sp->regs[SP_STATUS_REG] |= 0x400;

    /* clear / set signal 4 */
    if (w & 0x20000) sp->regs[SP_STATUS_REG] &= ~0x800;
    if (w & 0x40000) sp->regs[SP_STATUS_REG] |= 0x800;

    /* clear / set signal 5 */
    if (w & 0x80000) sp->regs[SP_STATUS_REG] &= ~0x1000;
    if (w & 0x100000) sp->regs[SP_STATUS_REG] |= 0x1000;

    /* clear / set signal 6 */
    if (w & 0x200000) sp->regs[SP_STATUS_REG] &= ~0x2000;
    if (w & 0x400000) sp->regs[SP_STATUS_REG] |= 0x2000;

    /* clear / set signal 7 */
    if (w & 0x800000) sp->regs[SP_STATUS_REG] &= ~0x4000;
    if (w & 0x1000000) sp->regs[SP_STATUS_REG] |= 0x4000;

    //if (get_event(SP_INT)) return;
    if (!(w & 0x1) && !(w & 0x4))
        return;

    if (!(sp->regs[SP_STATUS_REG] & 0x3)) // !halt && !broke
        do_SP_Task(sp);
}