git @ Cat's Eye Technologies JaC64 / master com / dreamfabric / jac64 / SIDChip.java
master

Tree @master (Download .tar.gz)

SIDChip.java @masterraw · history · blame

/**
 * This file is a part of JaC64 - a Java C64 Emulator
 * Main Developer: Joakim Eriksson (JaC64.com Dreamfabric.com)
 * Contact: joakime@sics.se
 * Web: http://www.jac64.com/ 
 * http://www.dreamfabric.com/c64
 * ---------------------------------------------------
 */

package com.dreamfabric.jac64;

/**
 * SIDChip - implements all neccessary control and set-up for the SID
 * chip emulation.
 * @author Joakim
 */
public class SIDChip extends ExtChip {

  public static final boolean SOUND_AVAIABLE = true;
  public static final int IO_OFFSET = CPU.IO_OFFSET;

  SIDVoice6581 sid[];
  SIDMixer mixer;
  private int sidUpdate = 1000;
  private boolean killEvent = false;
  
  private TimeEvent sidEvent = new TimeEvent(0, "JaC SID Chip") {
    public void execute(long cycles) {
      mixer.updateSound(cycles);
      time = time + sidUpdate; // Each milli second (1000) at 50 fps
      if (time < cpu.cycles)
        time = cpu.cycles + 10;
      if (!killEvent) 
        cpu.scheduler.addEvent(this);
    }
  };
  
  public SIDChip(MOS6510Core cpu, AudioDriver driver) {
    init(cpu);
    if (SOUND_AVAIABLE) {
      try {
        System.out.println("Creating SID configuration");
        sid = new SIDVoice6581[3];
        sid[0] = new SIDVoice6581(cpu.memory, IO_OFFSET + 0xd400 );
        sid[0].init();
        sid[1] = new SIDVoice6581(cpu.memory, IO_OFFSET + 0xd400 + 7);
        sid[1].init();
        sid[2] = new SIDVoice6581(cpu.memory, IO_OFFSET + 0xd400 + 14);
        sid[2].init();
        sid[0].next = sid[2];
        sid[1].next = sid[0];
        sid[2].next = sid[1];
        mixer = new SIDMixer(sid, null, driver);
        driver.setMasterVolume(100);
        sidEvent.time = cpu.cycles + 10;
        cpu.scheduler.addEvent(sidEvent);
      } catch (Throwable e) {
        e.printStackTrace();
        sid = null;
      }
    }
  }
  
  public void clock(long cycles) {
  }

  public int performRead(int address, long cycles) {
    switch (address - IO_OFFSET) {
    case 0xd41b: //
      return (sid[2].lastSample()) & 0xff;
    case 0xd41c: //
      return sid[2].adsrVol & 0xff;
      // Pot XY taken care of in C64Screen for now...
    }
    return 0;
  }

  public void performWrite(int address, int data, long cycles) {    
    switch(address - IO_OFFSET) {
    case 0xd404 :
      sid[0].setControl(data, cpu.cycles);
      break;
    case 0xd400 + 5:
      sid[0].setAD(data, cpu.cycles);
      break;
    case 0xd400 + 6:
      sid[0].setSR(data, cpu.cycles);
      break;
    case 0xd402:
    case 0xd403:
      sid[0].updatePulseWidth(cycles);
      break;

    case 0xd40b :
      sid[1].setControl(data, cpu.cycles);
      break;
    case 0xd407 + 5:
      sid[1].setAD(data, cpu.cycles);
      break;
    case 0xd407 + 6:
      sid[1].setSR(data, cpu.cycles);
      break;
    case 0xd402 + 7:
    case 0xd403 + 7:
      sid[1].updatePulseWidth(cycles);
      break;

    case 0xd412 :
      sid[2].setControl(data, cpu.cycles);
      break;
    case 0xd40e + 5:
      sid[2].setAD(data, cpu.cycles);
      break;
    case 0xd40e + 6:
      sid[2].setSR(data, cpu.cycles);
      break;

    case 0xd402 + 14:
    case 0xd403 + 14:
      sid[2].updatePulseWidth(cycles);
      break;


      // Controls for the SID Mixer
    case 0xd415:
      mixer.setFilterCutoffLO(data & 7);
      break;
    case 0xd416:
      mixer.setFilterCutoffHI(data);
      break;
    case 0xd417:
      mixer.setFilterResonance(data >> 4);
      mixer.setFilterOn(data & 0x0f);
      break;
    case 0xd418 :
      mixer.setVolume(data & 0x0f, cpu.cycles);
      mixer.setFilterCtrl(data);
      break;
   }
  }
    
  public void reset() {
    mixer.reset();
    sidEvent.time = cpu.cycles;
  }

  public void stop() {
    killEvent = true;
  }
}