예제 #1
0
파일: memory.cpp 프로젝트: zeromus/dasShiny
void SA1::bus_write(unsigned addr, uint8 data) {
  if((addr & 0x40fe00) == 0x002200) {  //$00-3f|80-bf:2200-23ff
    return mmio_write(addr, data);
  }

  if((addr & 0x40e000) == 0x006000) {  //$00-3f|80-bf:6000-7fff
    return mmc_sa1_write(addr, data);
  }

  if((addr & 0x40f800) == 0x000000) {  //$00-3f|80-bf:0000-07ff
    synchronize_cpu();
    return iram.write(addr & 2047, data);
  }

  if((addr & 0x40f800) == 0x003000) {  //$00-3f|80-bf:3000-37ff
    synchronize_cpu();
    return iram.write(addr & 2047, data);
  }

  if((addr & 0xf00000) == 0x400000) {  //$40-4f:0000-ffff
    synchronize_cpu();
    return bwram.write(addr & (bwram.size() - 1), data);
  }

  if((addr & 0xf00000) == 0x600000) {  //$60-6f:0000-ffff
    synchronize_cpu();
    return bitmap_write(addr & 0x0fffff, data);
  }
}
예제 #2
0
void HitachiDSP::enter() {
  while(true) {
    // exit requested due to savestate
    if(scheduler.sync == Scheduler::SynchronizeMode::All) {
      scheduler.exit(Scheduler::ExitReason::SynchronizeEvent);
    }

    // if we bail out due to savestating, the first thing we'll try afterwards is synchronize_cpu() again
    synchronize_cpu();

    switch(state) {
    case State::Idle:
      step(1);
      break;
    case State::DMA:
      for(unsigned n = 0; n < regs.dma_length; n++) {
        bus.write(regs.dma_target + n, bus.read(regs.dma_source + n));
        step(2);
      }
      state = State::Idle;
      break;
    case State::Execute:
      unsigned offset = regs.program_offset + regs.pc * 2;
      opcode  = bus_read(offset + 0) << 0;
      opcode |= bus_read(offset + 1) << 8;
      regs.pc = (regs.pc & 0xffff00) | ((regs.pc + 1) & 0x0000ff);
      exec();
      step(1);
      break;
    }

    // this call is gone, but it's the first thing we try at the top of the loop AFTER we bail out
    //synchronize_cpu();
  }
}
예제 #3
0
void MSU1::enter() {
  while(true) {
    if(scheduler.sync.i == Scheduler::SynchronizeMode::All) {
      scheduler.exit(Scheduler::ExitReason::SynchronizeEvent);
    }

    int16 left = 0, right = 0;

    if(mmio.audio_play) {
      if(audiofile.open()) {
        if(audiofile.end()) {
          if(!mmio.audio_repeat) {
            mmio.audio_play = false;
            audiofile.seek(mmio.audio_offset = 8);
          } else {
            audiofile.seek(mmio.audio_offset = mmio.audio_loop_offset);
          }
        } else {
          mmio.audio_offset += 4;
          left  = audiofile.readl(2);
          right = audiofile.readl(2);
        }
      } else {
        mmio.audio_play = false;
      }
    }

    left  = sclamp<16>(static_cast<signed>((double)left  * (double)mmio.audio_volume / 255.0));
    right = sclamp<16>(static_cast<signed>((double)right * (double)mmio.audio_volume / 255.0));

    audio.coprocessor_sample(left, right);
    step(1);
    synchronize_cpu();
  }
}
예제 #4
0
파일: link.cpp 프로젝트: IcooN/OpenEmu
void Link::enter() {
  while(true) {
    cpu.synchronize_coprocessors();
    unsigned clocks = 1;
    if(link_run) clocks = link_run();
    step(clocks);
    synchronize_cpu();
  }
}
예제 #5
0
파일: necdsp.cpp 프로젝트: IcooN/OpenEmu
void NECDSP::enter() {
  while(true) {
    if(scheduler.sync == Scheduler::SynchronizeMode::All) {
      scheduler.exit(Scheduler::ExitReason::SynchronizeEvent);
    }

    exec();
    step(1);
    synchronize_cpu();
  }
}
예제 #6
0
void SuperFX::enter() {
    while(true) {
        if(scheduler.sync.i == Scheduler::SynchronizeMode::All) {
            scheduler.exit(Scheduler::ExitReason::SynchronizeEvent);
        }

        if(regs.sfr.g == 0) {
            add_clocks(6);
            synchronize_cpu();
            continue;
        }

        (this->*opcode_table[(regs.sfr & 0x0300) + peekpipe()])();
        if(r15_modified == false) regs.r[15]++;

        if(++instruction_counter >= 128) {
            instruction_counter = 0;
            synchronize_cpu();
        }
    }
}
예제 #7
0
void SharpRTC::enter() {
  while(true) {
    if(scheduler.sync == Scheduler::SynchronizeMode::All) {
      scheduler.exit(Scheduler::ExitReason::SynchronizeEvent);
    }

    tick_second();

    step(1);
    synchronize_cpu();
  }
}
예제 #8
0
파일: memory.cpp 프로젝트: zeromus/dasShiny
uint8 SA1::bus_read(unsigned addr) {
  if((addr & 0x40fe00) == 0x002200) {  //$00-3f|80-bf:2200-23ff
    return mmio_read(addr);
  }

  if((addr & 0x408000) == 0x008000) {  //$00-3f|80-bf:8000-ffff
    return mmc_read(addr);
  }

  if((addr & 0xc00000) == 0xc00000) {  //$c0-ff:0000-ffff
    return mmc_read(addr);
  }

  if((addr & 0x40e000) == 0x006000) {  //$00-3f|80-bf:6000-7fff
    return mmc_sa1_read(addr);
  }

  if((addr & 0x40f800) == 0x000000) {  //$00-3f|80-bf:0000-07ff
    synchronize_cpu();
    return iram.read(addr & 2047);
  }

  if((addr & 0x40f800) == 0x003000) {  //$00-3f|80-bf:3000-37ff
    synchronize_cpu();
    return iram.read(addr & 2047);
  }

  if((addr & 0xf00000) == 0x400000) {  //$40-4f:0000-ffff
    synchronize_cpu();
    return bwram.read(addr & (bwram.size() - 1));
  }

  if((addr & 0xf00000) == 0x600000) {  //$60-6f:0000-ffff
    synchronize_cpu();
    return bitmap_read(addr & 0x0fffff);
  }
}
예제 #9
0
void SMPDebugger::op_step() {
  bool break_event = false;

  usage[regs.pc] |= UsageExec;
  opcode_pc = regs.pc;

  opcode_edge = true;
  debugger.breakpoint_test(Debugger::Breakpoint::Source::APURAM, Debugger::Breakpoint::Mode::Exec, regs.pc, 0x00);
  if(step_event && step_event() == true) {
    debugger.break_event = Debugger::BreakEvent::SMPStep;
    scheduler.exit(Scheduler::ExitReason::DebuggerEvent);
  }
  opcode_edge = false;

  SMP::op_step();
  synchronize_cpu();
}
예제 #10
0
파일: msu1.cpp 프로젝트: PGGB/Higan-Core
void MSU1::enter() {
  if(boot == true) {
    boot = false;
    for(unsigned addr = 0x2000; addr <= 0x2007; addr++) mmio_write(addr, 0x00);
  }

  while(true) {
    if(scheduler.sync == Scheduler::SynchronizeMode::All) {
      scheduler.exit(Scheduler::ExitReason::SynchronizeEvent);
    }

    int16 left = 0, right = 0;

    if(mmio.audio_play) {
      if(audiofile.open()) {
        if(audiofile.end()) {
          if(!mmio.audio_repeat) {
            mmio.audio_play = false;
            audiofile.seek(mmio.audio_offset = 8);
          } else {
            audiofile.seek(mmio.audio_offset = mmio.audio_loop_offset);
          }
        } else {
          mmio.audio_offset += 4;
          left  = audiofile.readl(2);
          right = audiofile.readl(2);
        }
      } else {
        mmio.audio_play = false;
      }
    }

    signed lchannel = (double)left  * (double)mmio.audio_volume / 255.0;
    signed rchannel = (double)right * (double)mmio.audio_volume / 255.0;
    left  = sclamp<16>(lchannel);
    right = sclamp<16>(rchannel);
    if(dsp.mute()) left = 0, right = 0;

    audio.coprocessor_sample(left, right);
    step(1);
    synchronize_cpu();
  }
}
예제 #11
0
void SuperFX::add_clocks(unsigned clocks) {
  if(regs.romcl) {
    regs.romcl -= min(clocks, regs.romcl);
    if(regs.romcl == 0) {
      regs.sfr.r = 0;
      regs.romdr = superfxbus.read((regs.rombr << 16) + regs.r[14]);
    }
  }

  if(regs.ramcl) {
    regs.ramcl -= min(clocks, regs.ramcl);
    if(regs.ramcl == 0) {
      superfxbus.write(0x700000 + (regs.rambr << 16) + regs.ramar, regs.ramdr);
    }
  }

  step(clocks);
  synchronize_cpu();
}
예제 #12
0
void SMP::add_clocks(unsigned clocks) {
  step(clocks);
  synchronize_dsp();

  #if defined(DEBUGGER)
  #error -DDEBUGGER SMP runtosave() correctness not checked
  synchronize_cpu();
  #else
  //forcefully sync S-SMP to S-CPU in case chips are not communicating
  //sync if S-SMP is more than 24 samples ahead of S-CPU
/*
our new smp design guarantees that there is at most one required synchronize_cpu() per uop,
inside an op_busread() or op_buswrite().  this extra synchronize can cause problems if we
swap out of the SMP at the beginning of a uop with an add_clocks() call when there is an
important op_busread() / op_buswrite() later on.  the SMP will need to finish that uop in
order to reach a savable state, but it might never get to do so until it's too late (ie,
scheduler.sync == Scheduler.SynchronizeMode::All).  so we remove this call and instead
do catchup sync in the main Enter() loop.
*/
  //if(clock > +(768 * 24 * (int64)24000000)) synchronize_cpu();
  #endif
}
예제 #13
0
파일: sa1.cpp 프로젝트: Stranho/bsnes-plus
void SA1::tick() {
    step(2);
    if(++status.tick_counter == 0) synchronize_cpu();

    //adjust counters:
    //note that internally, status counters are in clocks;
    //whereas MMIO register counters are in dots (4 clocks = 1 dot)
    if(mmio.hvselb == 0) {
        //HV timer
        status.hcounter += 2;
        if(status.hcounter >= 1364) {
            status.hcounter = 0;
            if(++status.vcounter >= status.scanlines) status.vcounter = 0;
        }
    } else {
        //linear timer
        status.hcounter += 2;
        status.vcounter += (status.hcounter >> 11);
        status.hcounter &= 0x07ff;
        status.vcounter &= 0x01ff;
    }

    //test counters for timer IRQ
    switch((mmio.ven << 1) + (mmio.hen << 0)) {
    case 0:
        break;
    case 1:
        if(status.hcounter == (mmio.hcnt << 2)) trigger_irq();
        break;
    case 2:
        if(status.vcounter == mmio.vcnt && status.hcounter == 0) trigger_irq();
        break;
    case 3:
        if(status.vcounter == mmio.vcnt && status.hcounter == (mmio.hcnt << 2)) trigger_irq();
        break;
    }
}
예제 #14
0
파일: armdsp.cpp 프로젝트: IcooN/OpenEmu
void ArmDSP::step(unsigned clocks) {
  if(bridge.timer && --bridge.timer == 0);
  Coprocessor::step(clocks);
  synchronize_cpu();
}
예제 #15
0
alwaysinline uint8 SMP::op_busread(uint16 addr) {
  uint8 r;
  if((addr & 0xfff0) == 0x00f0) {  //00f0-00ff
    switch(addr) {
      case 0xf0: {  //TEST -- write-only register
        r = 0x00;
      } break;

      case 0xf1: {  //CONTROL -- write-only register
        r = 0x00;
      } break;

      case 0xf2: {  //DSPADDR
        r = status.dsp_addr;
      } break;

      case 0xf3: {  //DSPDATA
        //0x80-0xff are read-only mirrors of 0x00-0x7f
        r = dsp.read(status.dsp_addr & 0x7f);
      } break;

      case 0xf4:    //CPUIO0
      case 0xf5:    //CPUIO1
      case 0xf6:    //CPUIO2
      case 0xf7: {  //CPUIO3
        synchronize_cpu();
        r = port.cpu_to_smp[addr & 3];
      } break;

      case 0xf8:    //PORT4
      case 0xf9: {  //PORT5
        r = port.aux[addr & 1];
      } break;

      case 0xfa:    //T0TARGET
      case 0xfb:    //T1TARGET
      case 0xfc: {  //T2TARGET -- write-only registers
        r = 0x00;
      } break;

      case 0xfd: {  //T0OUT -- 4-bit counter value
        r = t0.stage3_ticks & 15;
        t0.stage3_ticks = 0;
      } break;

      case 0xfe: {  //T1OUT -- 4-bit counter value
        r = t1.stage3_ticks & 15;
        t1.stage3_ticks = 0;
      } break;

      case 0xff: {  //T2OUT -- 4-bit counter value
        r = t2.stage3_ticks & 15;
        t2.stage3_ticks = 0;
      } break;
    }
  } else {
    r = ram_read(addr);
  }

  return r;
}
예제 #16
0
void PPU::add_clocks(unsigned clocks) {
  tick(clocks);
  step(clocks);
  synchronize_cpu();
}
예제 #17
0
alwaysinline void SMP::op_buswrite(uint16 addr, uint8 data) {
  if((addr & 0xfff0) == 0x00f0) {  //$00f0-00ff
    switch(addr) {
      case 0xf0: {  //TEST
        if(regs.p.p) break;  //writes only valid when P flag is clear

        status.clock_speed     = (data >> 6) & 3;
        status.timer_speed     = (data >> 4) & 3;
        status.timers_enabled  = data & 0x08;
        status.ram_disabled    = data & 0x04;
        status.ram_writable    = data & 0x02;
        status.timers_disabled = data & 0x01;

        status.timer_step = (1 << status.clock_speed) + (2 << status.timer_speed);

        t0.sync_stage1();
        t1.sync_stage1();
        t2.sync_stage1();
      } break;

      case 0xf1: {  //CONTROL
        status.iplrom_enabled = data & 0x80;

        if(data & 0x30) {
          //one-time clearing of APU port read registers
          synchronize_cpu();
          if(data & 0x20) {
            port.cpu_to_smp[2] = 0;
            port.cpu_to_smp[3] = 0;
          }
          if(data & 0x10) {
            port.cpu_to_smp[0] = 0;
            port.cpu_to_smp[1] = 0;
          }
        }

        //0->1 transistion resets timers
        if(t2.enabled == false && (data & 0x04)) {
          t2.stage2_ticks = 0;
          t2.stage3_ticks = 0;
        }
        t2.enabled = data & 0x04;

        if(t1.enabled == false && (data & 0x02)) {
          t1.stage2_ticks = 0;
          t1.stage3_ticks = 0;
        }
        t1.enabled = data & 0x02;

        if(t0.enabled == false && (data & 0x01)) {
          t0.stage2_ticks = 0;
          t0.stage3_ticks = 0;
        }
        t0.enabled = data & 0x01;
      } break;

      case 0xf2: {  //DSPADDR
        status.dsp_addr = data;
      } break;

      case 0xf3: {  //DSPDATA
        //0x80-0xff are read-only mirrors of 0x00-0x7f
        if(!(status.dsp_addr & 0x80)) {
          dsp.write(status.dsp_addr & 0x7f, data);
        }
        
        if (dump_spc && status.dsp_addr == 0x4c /* r_kon */ && data) {
          save_spc_dump();
        }
      } break;

      case 0xf4:    //CPUIO0
      case 0xf5:    //CPUIO1
      case 0xf6:    //CPUIO2
      case 0xf7: {  //CPUIO3
        synchronize_cpu();
        port.smp_to_cpu[addr & 3] = data;
      } break;

      case 0xf8:    //PORT4
      case 0xf9: {  //PORT5
        port.aux[addr & 1] = data;
      } break;

      case 0xfa: {  //T0TARGET
        t0.target = data;
      } break;

      case 0xfb: {  //T1TARGET
        t1.target = data;
      } break;

      case 0xfc: {  //T2TARGET
        t2.target = data;
      } break;

      case 0xfd:    //T0OUT
      case 0xfe:    //T1OUT
      case 0xff: {  //T2OUT -- read-only registers
      } break;
    }
  }

  //all writes, even to MMIO registers, appear on bus
  ram_write(addr, data);
}