Fixed several bugs in the emulation of the National Semiconductors PC87306 Super I/O chip;

Attempt to fix sound fluttering in waiting for a better fix from mainline PCem;
Attempt to make the Sound Blaster louder;
Removed excess logging from cdrom_ioctl.c.
This commit is contained in:
OBattler
2017-02-03 23:24:56 +01:00
parent 6ab214a2b0
commit 3c61b80a34
8 changed files with 187 additions and 94 deletions

View File

@@ -692,7 +692,7 @@ static int ioctl_media_type_id(uint8_t id)
SCSICommand(id, cdb, msbuf, &len, 1);
pclog("Returned length: %i, media type: %i\n", len, msbuf[2]);
// pclog("Returned length: %i, media type: %i\n", len, msbuf[2]);
ioctl_close(id);

View File

@@ -102,6 +102,8 @@ typedef struct FDC
int fintr;
int rw_drive;
uint16_t base_address;
} FDC;
static FDC fdc;
@@ -591,7 +593,8 @@ void fdc_implied_seek()
void fdc_write(uint16_t addr, uint8_t val, void *priv)
{
// fdc_log("Write FDC %04X %02X %04X:%04X %i %02X %i rate=%i %i\n",addr,val,cs>>4,pc,ins,fdc.st0,ins,fdc.rate, fdc.data_ready);
fdc_log("Write FDC %04X %02X\n",addr,val);
// fdc_log("Write FDC %04X %02X %04X:%04X %i %02X %i rate=%i %i\n",addr,val,cs>>4,pc,ins,fdc.st0,ins,fdc.rate, fdc.data_ready);
int drive, i, drive_num;
int seek_time, seek_time_base;
@@ -1256,7 +1259,6 @@ bad_command:
disc_3f7=val;
return;
}
// printf("Write FDC %04X %02X\n",addr,val);
// dumpregs();
// exit(-1);
}
@@ -1266,7 +1268,8 @@ uint8_t fdc_read(uint16_t addr, void *priv)
{
uint8_t temp;
int drive;
// /*if (addr!=0x3f4) */printf("Read FDC %04X %04X:%04X %04X %i %02X %02x %i ",addr,cs>>4,pc,BX,fdc.pos,fdc.st0,fdc.stat,ins);
fdc_log("Read FDC %04X\n",addr);
// /*if (addr!=0x3f4) */printf("Read FDC %04X %04X:%04X %04X %i %02X %02x %i ",addr,cs>>4,pc,BX,fdc.pos,fdc.st0,fdc.stat,ins);
switch (addr&7)
{
case 0: /* STA */
@@ -2168,6 +2171,8 @@ void fdc_indexpulse()
void fdc_hard_reset()
{
int base_address = fdc.base_address;
memset(&fdc, 0, sizeof(FDC));
fdc.dskchg_activelow = 0;
fdc.enable_3f1 = 1;
@@ -2205,6 +2210,9 @@ void fdc_hard_reset()
disc_reset();
fdc_reset();
fdc.max_track = 79;
fdc.base_address = base_address;
}
void fdc_init()
@@ -2222,6 +2230,16 @@ void fdc_add()
fdc.ps1 = 0;
fdc.max_track = 79;
fdc.perp = 0;
fdc.base_address = 0x03f0;
fdc_log("FDC Added (%04X)\n", fdc.base_address);
}
void fdc_set_base(int base, int super_io)
{
io_sethandler(base + (super_io ? 2 : 0), super_io ? 0x0004 : 0x0006, fdc_read, NULL, NULL, fdc_write, NULL, NULL, NULL);
io_sethandler(base + 7, 0x0001, fdc_read, NULL, NULL, fdc_write, NULL, NULL, NULL);
fdc.base_address = base;
fdc_log("FDC Base address set%s (%04X)\n", super_io ? " for Super I/O" : "", fdc.base_address);
}
void fdc_add_for_superio()
@@ -2230,6 +2248,8 @@ void fdc_add_for_superio()
io_sethandler(0x03f7, 0x0001, fdc_read, NULL, NULL, fdc_write, NULL, NULL, NULL);
fdc.pcjr = 0;
fdc.ps1 = 0;
fdc.base_address = 0x03f0;
fdc_log("FDC Added for Super I/O (%04X)\n", fdc.base_address);
}
void fdc_add_pcjr()
@@ -2240,12 +2260,15 @@ void fdc_add_pcjr()
fdc.ps1 = 0;
fdc.max_track = 79;
fdc.perp = 0;
fdc.base_address = 0x03f0;
fdc_log("FDC Added for PCjr (%04X)\n", fdc.base_address);
}
void fdc_remove()
{
io_removehandler(0x03f0, 0x0006, fdc_read, NULL, NULL, fdc_write, NULL, NULL, NULL);
io_removehandler(0x03f7, 0x0001, fdc_read, NULL, NULL, fdc_write, NULL, NULL, NULL);
fdc_log("FDC Removed (%04X)\n", fdc.base_address);
io_removehandler(fdc.base_address, 0x0006, fdc_read, NULL, NULL, fdc_write, NULL, NULL, NULL);
io_removehandler(fdc.base_address + 7, 0x0001, fdc_read, NULL, NULL, fdc_write, NULL, NULL, NULL);
}
void fdc_discchange_clear(int drive)

View File

@@ -496,7 +496,8 @@ float VGACONST1,VGACONST2;
float RTCCONST;
int gated,speakval,speakon;
#define SOUNDBUFLEN (48000/40)
// #define SOUNDBUFLEN (48000/40)
#define SOUNDBUFLEN (32000/20)
/*Sound Blaster*/

View File

@@ -39,18 +39,19 @@ void pc87306_gpio_write(uint16_t port, uint8_t val, void *priv)
uint8_t uart_int1()
{
/* 0: IRQ3, 1: IRQ4 */
return ((pc87306_regs[0x1C] >> 2) & 1) ? 3 : 4;
return ((pc87306_regs[0x1C] >> 2) & 1) ? 4 : 3;
}
uint8_t uart_int2()
{
return ((pc87306_regs[0x1C] >> 6) & 1) ? 3 : 4;
/* 0: IRQ3, 1: IRQ4 */
return ((pc87306_regs[0x1C] >> 6) & 1) ? 4 : 3;
}
uint8_t uart1_int()
{
uint8_t temp;
temp = ((pc87306_regs[1] >> 2) & 1) ? 3 : 4; /* 0 = IRQ 4, 1 = IRQ 3 */
temp = ((pc87306_regs[1] >> 2) & 1) ? 3 : 4; /* 0 = COM1 (IRQ 4), 1 = COM2 (IRQ 3), 2 = COM3 (IRQ 4), 3 = COM4 (IRQ 3) */
// pclog("UART 1 set to IRQ %i\n", (pc87306_regs[0x1C] & 1) ? uart_int1() : temp);
return (pc87306_regs[0x1C] & 1) ? uart_int1() : temp;
}
@@ -58,7 +59,7 @@ uint8_t uart1_int()
uint8_t uart2_int()
{
uint8_t temp;
temp = ((pc87306_regs[1] >> 4) & 1) ? 3 : 4; /* 0 = IRQ 4, 1 = IRQ 3 */
temp = ((pc87306_regs[1] >> 4) & 1) ? 3 : 4; /* 0 = COM1 (IRQ 4), 1 = COM2 (IRQ 3), 2 = COM3 (IRQ 4), 3 = COM4 (IRQ 3) */
// pclog("UART 2 set to IRQ %i\n", (pc87306_regs[0x1C] & 1) ? uart_int2() : temp);
return (pc87306_regs[0x1C] & 1) ? uart_int2() : temp;
}
@@ -66,30 +67,27 @@ uint8_t uart2_int()
void lpt1_handler()
{
int temp;
if (pc87306_regs[0x1B] & 0x10)
temp = pc87306_regs[0x01] & 3;
switch (temp)
{
temp = (pc87306_regs[0x1B] & 0x20) >> 5;
if (temp)
{
case 0:
lpt_port = 0x378;
}
else
{
break;
case 1:
if (pc87306_regs[0x1B] & 0x40)
{
lpt_port = ((uint16_t) pc87306_regs[0x19]) << 2;
}
else
{
lpt_port = 0x3bc;
}
break;
case 2:
lpt_port = 0x278;
}
}
else
{
temp = pc87306_regs[0x01] & 3;
switch (temp)
{
case 0: lpt_port = 0x378;
case 1: lpt_port = 0x3bc;
case 2: lpt_port = 0x278;
}
break;
}
lpt1_init(lpt_port);
pc87306_regs[0x19] = lpt_port >> 2;
}
void serial1_handler()
@@ -171,13 +169,17 @@ void pc87306_write(uint16_t port, uint8_t val, void *priv)
{
if (pc87306_curreg <= 28) valxor = val ^ pc87306_regs[pc87306_curreg];
tries = 0;
if ((pc87306_curreg == 0x19) && !(pc87306_regs[0x1B] & 0x40))
{
return;
}
if ((pc87306_curreg <= 28) && (pc87306_curreg != 8) && (pc87306_curreg != 0x18))
{
if (pc87306_curreg == 0)
{
val &= 0x5f;
}
if ((pc87306_curreg == 0x0F) || (pc87306_curreg == 0x12))
if (((pc87306_curreg == 0x0F) || (pc87306_curreg == 0x12)) && valxor)
{
pc87306_gpio_remove();
}
@@ -198,13 +200,14 @@ process_value:
switch(pc87306_curreg)
{
case 0:
// pclog("Register 0\n");
if (valxor & 1)
{
lpt1_remove();
}
if ((valxor & 1) && (val & 1))
{
lpt1_handler();
if (val & 1)
{
lpt1_handler();
}
}
if (valxor & 2)
@@ -223,6 +226,14 @@ process_value:
serial2_handler();
}
}
if ((valxor & 8) || (valxor & 0x20))
{
fdc_remove();
if (val & 8)
{
fdc_set_base((val & 0x20) ? 0x370 : 0x3f0, 0);
}
}
break;
case 1:
@@ -256,29 +267,81 @@ process_value:
}
break;
case 2:
lpt1_remove();
serial1_remove();
serial2_remove();
if (val & 1)
if (valxor & 1)
{
pc87306_regs[0] &= 0xb0;
}
else
{
lpt1_handler();
serial1_handler();
// serial2_handler();
pc87306_regs[0] |= 0x4b;
if (val & 1)
{
// pclog("Powering down functions...\n");
lpt1_remove();
serial1_remove();
serial2_remove();
fdc_remove();
}
else
{
// pclog("Powering up functions...\n");
if (pc87306_regs[0] & 1)
{
lpt1_handler();
}
if (pc87306_regs[0] & 2)
{
serial1_handler();
}
if (pc87306_regs[0] & 4)
{
serial2_handler();
}
if (pc87306_regs[0] & 8)
{
fdc_set_base((pc87306_regs[0] & 0x20) ? 0x370 : 0x3f0, 0);
}
}
}
break;
case 9:
// pclog("Setting DENSEL polarity to: %i (before: %i)\n", (val & 0x40 ? 1 : 0), fdc_get_densel_polarity());
fdc_update_enh_mode((val & 4) ? 1 : 0);
fdc_update_densel_polarity((val & 0x40) ? 1 : 0);
if (valxor & 0x44)
{
// pclog("Setting DENSEL polarity to: %i (before: %i)\n", (val & 0x40 ? 1 : 0), fdc_get_densel_polarity());
fdc_update_enh_mode((val & 4) ? 1 : 0);
fdc_update_densel_polarity((val & 0x40) ? 1 : 0);
}
break;
case 0xF:
if (valxor)
{
pc87306_gpio_init();
}
break;
case 0x12:
pc87306_gpio_init();
if (valxor & 0x30)
{
pc87306_gpio_init();
}
break;
case 0x19:
if (valxor)
{
lpt1_remove();
if (pc87306_regs[0] & 1)
{
lpt1_handler();
}
}
break;
case 0x1B:
if (valxor & 0x40)
{
lpt1_remove();
if (!(val & 0x40))
{
pc87306_regs[0x19] = 0xEF;
}
if (pc87306_regs[0] & 1)
{
lpt1_handler();
}
}
break;
case 0x1C:
// if (valxor & 0x25)
@@ -290,7 +353,10 @@ process_value:
{
serial1_handler();
}
if (pc87306_regs[0] & 4) serial2_handler();
if (pc87306_regs[0] & 4)
{
serial2_handler();
}
}
break;
}
@@ -373,9 +439,7 @@ void pc87306_reset(void)
pc87306_regs[9] = 0xFF;
pc87306_regs[0xF] = 0x1E;
pc87306_regs[0x12] = 0x30;
pc87306_regs[0x19] = 0xDE;
pc87306_regs[0x1B] = 0x10;
pc87306_regs[0x1C] = 0;
pc87306_regs[0x19] = 0xEF;
/*
0 = 360 rpm @ 500 kbps for 3.5"
1 = Default, 300 rpm @ 500,300,250,1000 kbps for 3.5"
@@ -384,7 +448,13 @@ void pc87306_reset(void)
fdc_update_enh_mode(0);
fdc_update_densel_polarity(1);
fdc_update_max_track(85);
fdc_remove();
fdc_add(0x3f0, 0);
fdd_swap = 0;
serial1_remove();
serial2_remove();
serial1_handler();
serial2_handler();
}
void pc87306_init()

View File

@@ -20,8 +20,8 @@ SERIAL serial1, serial2;
void serial_reset()
{
serial1.iir = serial1.ier = serial1.lcr = 0;
serial2.iir = serial2.ier = serial2.lcr = 0;
serial1.iir = serial1.ier = serial1.lcr = serial1.mctrl = 0;
serial2.iir = serial2.ier = serial2.lcr = serial2.mctrl = 0;
serial1.fifo_read = serial1.fifo_write = 0;
serial2.fifo_read = serial2.fifo_write = 0;
}

View File

@@ -332,16 +332,16 @@ void sound_cd_thread_reset()
}
if (available_cdrom_drives && !cd_thread_enable)
{
sound_cd_event = thread_create_event();
sound_cd_thread_h = thread_create(sound_cd_thread, NULL);
}
else if (!available_cdrom_drives && cd_thread_enable)
{
thread_destroy_event(sound_cd_event);
thread_kill(sound_cd_thread_h);
sound_cd_thread_h = NULL;
}
else if (!available_cdrom_drives && cd_thread_enable)
{
sound_cd_event = thread_create_event();
sound_cd_thread_h = thread_create(sound_cd_thread, NULL);
}
cd_thread_enable = available_cdrom_drives ? 1 : 0;
}

View File

@@ -54,22 +54,22 @@ static void sb_get_buffer_opl2(int32_t *buffer, int len, void *p)
{
int32_t out_l, out_r;
out_l = ((sb->opl.buffer[c] * mixer->fm_l) >> 16);
out_r = ((sb->opl.buffer[c + 1] * mixer->fm_r) >> 16);
out_l = ((sb->opl.buffer[c] * mixer->fm_l) >> 13);
out_r = ((sb->opl.buffer[c + 1] * mixer->fm_r) >> 13);
if (sb->mixer.filter)
{
out_l += (int)(((sb_iir(0, (float)sb->dsp.buffer[c]) / 1.3) * mixer->voice_l) / 3) >> 16;
out_r += (int)(((sb_iir(1, (float)sb->dsp.buffer[c + 1]) / 1.3) * mixer->voice_r) / 3) >> 16;
out_l += (int)(((sb_iir(0, (float)sb->dsp.buffer[c]) / 1.3) * mixer->voice_l) / 3) >> 13;
out_r += (int)(((sb_iir(1, (float)sb->dsp.buffer[c + 1]) / 1.3) * mixer->voice_r) / 3) >> 13;
}
else
{
out_l += ((int32_t)(sb->dsp.buffer[c] * mixer->voice_l) / 3) >> 16;
out_r += ((int32_t)(sb->dsp.buffer[c + 1] * mixer->voice_r) / 3) >> 16;
out_l += ((int32_t)(sb->dsp.buffer[c] * mixer->voice_l) / 3) >> 13;
out_r += ((int32_t)(sb->dsp.buffer[c + 1] * mixer->voice_r) / 3) >> 13;
}
out_l = (out_l * mixer->master_l) >> 16;
out_r = (out_r * mixer->master_r) >> 16;
out_l = (out_l * mixer->master_l) >> 13;
out_r = (out_r * mixer->master_r) >> 13;
if (mixer->bass_l != 8 || mixer->bass_r != 8 || mixer->treble_l != 8 || mixer->treble_r != 8)
{
@@ -103,25 +103,25 @@ static void sb_get_buffer_opl3(int32_t *buffer, int len, void *p)
sb_dsp_update(&sb->dsp);
for (c = 0; c < len * 2; c += 2)
{
int c_emu8k = (((c/2) * 44100) / 48000)*2;
// int c_emu8k = (((c/2) * 44100) / 48000)*2;
int32_t out_l, out_r;
out_l = ((sb->opl.buffer[c] * mixer->fm_l) >> 16);
out_r = ((sb->opl.buffer[c + 1] * mixer->fm_r) >> 16);
out_l = ((sb->opl.buffer[c] * mixer->fm_l) >> 13);
out_r = ((sb->opl.buffer[c + 1] * mixer->fm_r) >> 13);
if (sb->mixer.filter)
{
out_l += (int)(((sb_iir(0, (float)sb->dsp.buffer[c]) / 1.3) * mixer->voice_l) / 3) >> 16;
out_r += (int)(((sb_iir(1, (float)sb->dsp.buffer[c + 1]) / 1.3) * mixer->voice_r) / 3) >> 16;
out_l += (int)(((sb_iir(0, (float)sb->dsp.buffer[c]) / 1.3) * mixer->voice_l) / 3) >> 13;
out_r += (int)(((sb_iir(1, (float)sb->dsp.buffer[c + 1]) / 1.3) * mixer->voice_r) / 3) >> 13;
}
else
{
out_l += ((int32_t)(sb->dsp.buffer[c] * mixer->voice_l) / 3) >> 16;
out_r += ((int32_t)(sb->dsp.buffer[c + 1] * mixer->voice_r) / 3) >> 16;
out_l += ((int32_t)(sb->dsp.buffer[c] * mixer->voice_l) / 3) >> 13;
out_r += ((int32_t)(sb->dsp.buffer[c + 1] * mixer->voice_r) / 3) >> 13;
}
out_l = (out_l * mixer->master_l) >> 16;
out_r = (out_r * mixer->master_r) >> 16;
out_l = (out_l * mixer->master_l) >> 13;
out_r = (out_r * mixer->master_r) >> 13;
if (mixer->bass_l != 8 || mixer->bass_r != 8 || mixer->treble_l != 8 || mixer->treble_r != 8)
{
@@ -160,25 +160,25 @@ static void sb_get_buffer_emu8k(int32_t *buffer, int len, void *p)
int c_emu8k = (((c/2) * 44100) / 48000)*2;
int32_t out_l, out_r;
out_l = (((int32_t)sb->opl.buffer[c] * (int32_t)mixer->fm_l) >> 16);
out_r = (((int32_t)sb->opl.buffer[c + 1] * (int32_t)mixer->fm_r) >> 16);
out_l = (((int32_t)sb->opl.buffer[c] * (int32_t)mixer->fm_l) >> 13);
out_r = (((int32_t)sb->opl.buffer[c + 1] * (int32_t)mixer->fm_r) >> 13);
out_l += ((sb->emu8k.buffer[c_emu8k] * mixer->fm_l) >> 16);
out_r += ((sb->emu8k.buffer[c_emu8k + 1] * mixer->fm_l) >> 16);
out_l += ((sb->emu8k.buffer[c_emu8k] * mixer->fm_l) >> 13);
out_r += ((sb->emu8k.buffer[c_emu8k + 1] * mixer->fm_l) >> 13);
if (sb->mixer.filter)
{
out_l += (int)(((sb_iir(0, (float)sb->dsp.buffer[c]) / 1.3) * mixer->voice_l) / 3) >> 16;
out_r += (int)(((sb_iir(1, (float)sb->dsp.buffer[c + 1]) / 1.3) * mixer->voice_r) / 3) >> 16;
out_l += (int)(((sb_iir(0, (float)sb->dsp.buffer[c]) / 1.3) * mixer->voice_l) / 3) >> 13;
out_r += (int)(((sb_iir(1, (float)sb->dsp.buffer[c + 1]) / 1.3) * mixer->voice_r) / 3) >> 13;
}
else
{
out_l += ((int32_t)(sb->dsp.buffer[c] * mixer->voice_l) / 3) >> 16;
out_r += ((int32_t)(sb->dsp.buffer[c + 1] * mixer->voice_r) / 3) >> 16;
out_l += ((int32_t)(sb->dsp.buffer[c] * mixer->voice_l) / 3) >> 13;
out_r += ((int32_t)(sb->dsp.buffer[c + 1] * mixer->voice_r) / 3) >> 13;
}
out_l = (out_l * mixer->master_l) >> 16;
out_r = (out_r * mixer->master_r) >> 16;
out_l = (out_l * mixer->master_l) >> 13;
out_r = (out_r * mixer->master_r) >> 13;
if (mixer->bass_l != 8 || mixer->bass_r != 8 || mixer->treble_l != 8 || mixer->treble_r != 8)
{
@@ -224,8 +224,8 @@ void sb_pro_mixer_write(uint16_t addr, uint8_t val, void *p)
mixer->filter = !(mixer->regs[0xe] & 0x20);
mixer->bass_l = mixer->bass_r = 8;
mixer->treble_l = mixer->treble_r = 8;
sound_set_cd_volume(((uint32_t)mixer->master_l * (uint32_t)mixer->cd_l) / 65535,
((uint32_t)mixer->master_r * (uint32_t)mixer->cd_r) / 65535);
sound_set_cd_volume(((uint32_t)mixer->master_l * (uint32_t)mixer->cd_l) / 8191,
((uint32_t)mixer->master_r * (uint32_t)mixer->cd_r) / 8191);
// pclog("%02X %02X %02X\n", mixer->regs[0x04], mixer->regs[0x22], mixer->regs[0x26]);
// pclog("Mixer - %04X %04X %04X %04X %04X %04X\n", mixer->master_l, mixer->master_r, mixer->voice_l, mixer->voice_r, mixer->fm_l, mixer->fm_r);
if (mixer->index == 0xe)
@@ -299,8 +299,8 @@ void sb_16_mixer_write(uint16_t addr, uint8_t val, void *p)
mixer->treble_l = mixer->regs[0x44] >> 4;
mixer->treble_r = mixer->regs[0x45] >> 4;
mixer->filter = 0;
sound_set_cd_volume(((uint32_t)mixer->master_l * (uint32_t)mixer->cd_l) / 65535,
((uint32_t)mixer->master_r * (uint32_t)mixer->cd_r) / 65535);
sound_set_cd_volume(((uint32_t)mixer->master_l * (uint32_t)mixer->cd_l) / 8191,
((uint32_t)mixer->master_r * (uint32_t)mixer->cd_r) / 8191);
// pclog("%02X %02X %02X %02X %02X %02X\n", mixer->regs[0x30], mixer->regs[0x31], mixer->regs[0x32], mixer->regs[0x33], mixer->regs[0x34], mixer->regs[0x35]);
// pclog("Mixer - %04X %04X %04X %04X %04X %04X\n", mixer->master_l, mixer->master_r, mixer->voice_l, mixer->voice_r, mixer->fm_l, mixer->fm_r);
}

View File

@@ -123,7 +123,6 @@ void inital()
for (c = 0; c < 4; c++)
{
alBufferData(buffers[c], AL_FORMAT_STEREO_FLOAT32, buf, BUFLEN*2*sizeof(float), FREQ);
alBufferData(buffers_cd[c], AL_FORMAT_STEREO_FLOAT32, buf, CD_BUFLEN*2*sizeof(float), CD_FREQ);
alBufferData(buffers_cd[c], AL_FORMAT_STEREO_FLOAT32, cd_buf, CD_BUFLEN*2*sizeof(float), CD_FREQ);
}