Commit 0b6c18e9 authored by Sergio Costas's avatar Sergio Costas

Fixed io contention

Removed the DC filter in audio, and added a low-pass filter. Now the sound is extremely better
parent ce906d1e
......@@ -61,7 +61,8 @@ computer::computer() {
this->sound_bit = 0;
this->contended_zone = false;
this->memcontended_zone = 0;
this->iocontended_zone = 0;
this->cicles_counter=0;
this->interr = 0;
......@@ -128,10 +129,20 @@ void computer::emulate (int tstados) {
// check if there's contention and waits the right number of tstates
void computer::do_contention() {
void computer::do_contention(bool io, word addr) {
while(this->contended_zone) {
this->emulate(1);
if (ordenador->current_mode == MODE_P3) {
if (((addr & 0xC000) == 0x4000) && (this->memcontended_zone != 0)) {
this->emulate(this->memcontended_zone);
}
} else {
if (io && (this->iocontended_zone != 0) && ((addr & 0x0001) == 0)) {
this->emulate(this->iocontended_zone);
} else {
if (((addr & 0xC000) == 0x4000) && (this->memcontended_zone != 0)) {
this->emulate(this->memcontended_zone);
}
}
}
}
......@@ -186,9 +197,7 @@ void extra_contention() {
void Z80free_Wr (word Addr, byte Value) {
extra_contention();
if ((Addr & 0xC000) == 0x4000) {
ordenador->do_contention();
}
ordenador->do_contention(false, Addr);
ordenador->write_memory(Addr,Value);
}
......@@ -214,7 +223,6 @@ void computer::write_memory (uint16_t Addr, uint8_t Value) {
*(ordenador->block3 + Addr) = (unsigned char) Value;
break;
}
}
byte Z80free_Rd (word Addr) {
......@@ -231,9 +239,7 @@ byte Z80free_Rd (word Addr) {
break;
default:
if ((Addr & 0xC000) == 0x4000) {
ordenador->do_contention();
}
ordenador->do_contention(false, Addr);
return (ordenador->read_memory(Addr));
}
}
......@@ -270,20 +276,17 @@ void Z80free_Out (word Port, byte Value) {
register word maskport;
extra_contention();
if (((Port&0x0001)==0)||((Port>=0x4000)&&(Port<0x8000))) {
if (ordenador->current_mode != MODE_P3) {
ordenador->do_contention();
}
if (ordenador->current_mode != MODE_P3) {
ordenador->do_contention(true, Port);
}
// ULAPlus
if (Port == 0xBF3B) {
ordenador->do_contention();
screen->set_ulaplus_register(Value);
return;
}
if (Port == 0xFF3B) {
ordenador->do_contention();
screen->set_ulaplus_value(Value);
}
......@@ -340,16 +343,13 @@ byte Z80free_In (word Port) {
byte pines;
extra_contention();
if (((Port&0x0001)==0) || ((Port>=0x4000)&&(Port<0x8000))) {
if (ordenador->current_mode != MODE_P3) {
ordenador->do_contention();
}
if (ordenador->current_mode != MODE_P3) {
ordenador->do_contention(true, Port);
}
temporal_io = (unsigned int) Port;
if (Port == 0xFF3B) {
ordenador->do_contention();
return (screen->read_ulaplus_value());
}
......
......@@ -55,7 +55,8 @@ public:
bool dblscan;
bool bw;
bool contended_zone; // 0-> no contention; 1-> contention possible
int memcontended_zone; // memory contended tstates from this instant up to the next non-contended block
int iocontended_zone; // I/O contended tstates from this instant up to the next non-contended block
int cicles_counter; // counts how many pixel clock cicles passed since las interrupt
int contended_cicles; // cicles used during contention (must not be counted after ending the execution of an instruction)
......@@ -104,7 +105,7 @@ public:
bool callback_receiver(string, class Signals *);
byte bus_empty();
void emulate(int);
void do_contention();
void do_contention(bool io, word addr);
uint8_t read_memory(uint16_t Addr);
void write_memory (uint16_t Addr, uint8_t Value);
};
......
......@@ -14,7 +14,7 @@
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
*
*/
#include "llsound.hh"
......@@ -205,18 +205,18 @@ int LLSound::init_pulse() {
#ifdef D_SOUND_ALSA
int LLSound::init_alsa() {
int err;
snd_pcm_hw_params_t *hw_params;
unsigned int resample,samplerate;
snd_pcm_uframes_t bufferSize;
err = snd_pcm_open( &_soundDevice, "plughw:0,0", SND_PCM_STREAM_PLAYBACK, 0 );
if (err<0) {
return -1;
}
if ((err = snd_pcm_hw_params_malloc (&hw_params)) < 0) {
snd_pcm_close (_soundDevice);
return -2;
......@@ -227,12 +227,12 @@ int LLSound::init_alsa() {
return -2;
}
if ((err = snd_pcm_hw_params_set_access (_soundDevice, hw_params,SND_PCM_ACCESS_RW_INTERLEAVED)) < 0) {
snd_pcm_close (_soundDevice);
return -3;
}
if (snd_pcm_hw_params_set_format (_soundDevice, hw_params,SND_PCM_FORMAT_U8) >= 0) {
this->sign=0;
this->format=0;
......@@ -255,7 +255,7 @@ int LLSound::init_alsa() {
snd_pcm_close (_soundDevice);
return -3;
}
// Disable resampling.
resample = 0;
err = snd_pcm_hw_params_set_rate_resample(_soundDevice, hw_params, resample);
......@@ -263,7 +263,7 @@ int LLSound::init_alsa() {
snd_pcm_close (_soundDevice);
return -3;
}
if ((err = snd_pcm_hw_params_set_channels (_soundDevice, hw_params, 1)) >= 0) {
this->channels=1;
} else if ((err = snd_pcm_hw_params_set_channels (_soundDevice, hw_params, 2)) >= 0) {
......@@ -272,7 +272,7 @@ int LLSound::init_alsa() {
snd_pcm_close (_soundDevice);
return -3;
}
samplerate=48000;
if ((err = snd_pcm_hw_params_set_rate_near (_soundDevice, hw_params, &samplerate, 0)) < 0) {
snd_pcm_close (_soundDevice);
......@@ -286,7 +286,7 @@ int LLSound::init_alsa() {
}
this->freq=samplerate;
err = snd_pcm_hw_params (_soundDevice, hw_params);
if (err<0) {
return -3;
......@@ -294,7 +294,7 @@ int LLSound::init_alsa() {
//snd_pcm_hw_params_get_buffer_size( hw_params, &bufferSize );
this->buffer_len=bufferSize;
started_sound=0;
return 0;
......@@ -308,7 +308,7 @@ int LLSound::init_alsa() {
#ifdef D_SOUND_OSS
int LLSound::init_oss() {
int parameter;
int parameter2;
int bytes;
......@@ -328,12 +328,12 @@ int LLSound::init_oss() {
this->buffer_len=2048/(this->channels*bytes);
parameter=0x0002000C ; // two buffers with 4096 bytes each one
if(ioctl(audio_fd,SNDCTL_DSP_SETFRAGMENT, &parameter)==-1)
return (-6);
// set format
if(ioctl(audio_fd,SNDCTL_DSP_GETFMTS, &parameter2)==-1)
return (-2);
parameter = 2; // we want mono audio
......@@ -341,9 +341,9 @@ int LLSound::init_oss() {
return (-4);
this->channels = parameter;
// Priority: U8, S8, U16LE, S16LE, U16BE, U16LE
if(parameter2 & AFMT_S16_BE) {
parameter = AFMT_S16_BE;
}
......@@ -362,14 +362,14 @@ int LLSound::init_oss() {
if(parameter2 & AFMT_U8) {
parameter = AFMT_U8;
}
bytes=0; //8 bits
retval=ioctl(audio_fd,SNDCTL_DSP_SETFMT,&parameter);
if(retval != 0) {
return (-3);
}
switch(parameter) {
case AFMT_U8:
this->sign=0;
......@@ -384,7 +384,7 @@ int LLSound::init_oss() {
case AFMT_U16_LE:
this->sign=0;
this->format=1;
bytes=2;
bytes=2;
break;
case AFMT_S16_LE:
this->sign=-128;
......@@ -402,7 +402,7 @@ int LLSound::init_oss() {
bytes=2;
break;
}
parameter=48000; // we want, by default, 48000 samples per second
if(ioctl(audio_fd,SNDCTL_DSP_SPEED, &parameter)==-1)
return (-5);
......@@ -413,21 +413,39 @@ int LLSound::init_oss() {
parameter=bi.bytes/4;
this->buffer_len = parameter/(this->channels * bytes);
return(0);
return(0);
}
#endif
void LLSound::remove_dc(unsigned char *sound_buffer,int size){
static float oldsample=0.0;
static float origsample;
static int i;
static unsigned char origsamples[FILTER_SAMPLES];
int i;
int j;
int v;
int m;
unsigned char sample;
m = 0;
for (i=0;i<size;i++) {
m += sound_buffer[i];
}
m /= size;
for (i=0;i<size;i++) {
origsample=((float)(sound_buffer[i]))-128;
oldsample=(origsample+oldsample*999.0)*0.001+1e-6;
sound_buffer[i]=(int)(origsample-oldsample)*0.98+128;
sample = sound_buffer[i];
v = (int) sample;
/*v -= m;
v += 128;*/
for(j=0;j<FILTER_SAMPLES;j++) {
v += (int) origsamples[j];
if (j != 0) {
origsamples[j-1] = origsamples[j];
}
}
v /= (FILTER_SAMPLES + 1);
origsamples[FILTER_SAMPLES - 1] = sample;
sound_buffer[i] = (unsigned char) v;
}
}
......
......@@ -14,7 +14,7 @@
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
*
*/
#ifndef SOUND_H
......@@ -28,6 +28,8 @@
#define D_SOUND_OSS
#endif
#define FILTER_SAMPLES 8
enum e_soundtype {SOUND_NO, SOUND_OSS, SOUND_ALSA, SOUND_PULSEAUDIO, SOUND_AUTOMATIC};
extern class LLSound *llsound;
......
......@@ -247,20 +247,38 @@ void Screen::show_screen (int tstados) {
}
if ((this->tstados_counter < this->tstate_contention) || (this->tstados_counter >= this->tstate_contention2)) {
ordenador->contended_zone = false; // no contention here
ordenador->memcontended_zone = 0; // no contention here
ordenador->iocontended_zone = 0;
this->bus_value = 0xFF;
} else {
int p;
if (((this->tstados_counter - this->tstate_contention) % this->pixancho) < 128) {
switch(((this->tstados_counter - this->tstate_contention)% this->pixancho) % 8) {
int zone = ((this->tstados_counter - this->tstate_contention)% this->pixancho) % 8;
switch(zone) {
case 0:
case 1:
case 2:
case 3:
case 4:
case 5:
ordenador->iocontended_zone = 6 - zone;
break;
case 6:
ordenador->iocontended_zone = 0;
break;
case 7:
ordenador->iocontended_zone = 0;
break;
}
switch(zone) {
case 0:
case 5:
this->bus_value = 0xFF;
ordenador->contended_zone = true;
ordenador->memcontended_zone = 6 - zone;
break;
case 1:
case 3:
ordenador->contended_zone = true;
ordenador->memcontended_zone = 6 - zone;
p = *this->p_translt;
this->bus_value = ordenador->memoria[p + ordenador->video_offset];
this->p_translt++;
......@@ -268,6 +286,7 @@ void Screen::show_screen (int tstados) {
break;
case 2:
case 4:
ordenador->memcontended_zone = 6 - zone;
p = *this->p_translt2;
this->bus_value = ordenador->memoria[p + ordenador->video_offset]; // attributes
this->p_translt2++;
......@@ -296,11 +315,13 @@ void Screen::show_screen (int tstados) {
break;
default:
this->bus_value = 0xFF;
ordenador->contended_zone = false;
ordenador->memcontended_zone = 0;
ordenador->iocontended_zone = 0;
break;
}
} else {
ordenador->contended_zone = false; // no contention here
ordenador->memcontended_zone = 0; // no contention here
ordenador->iocontended_zone = 0;
this->bus_value = 0xFF;
}
}
......
This diff is collapsed.
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment