/**
* 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;
}
}