Added the IBM 5161 ISA expansion for PC and XT;
Cleaned up the parallel port emulation, added IRQ support, and made enabling/disabling per port; Added the Award 430NX and the Intel Classic/PCI (Alfredo, 420TX); Finished the 586MC1; Added 8087 emulation; Moved Cyrix 6x86'es to the Dev branch; Sanitized/cleaned up memregs.c/h and intel.c/h; Split the chipsets from machines and sanitized Port 92 emulation; Added support for the 15bpp mode to the Compaq ATI 28800; Moved the MR 386DX and 486 machines to the Dev branch; Ported the new dynamic recompiler from PCem, but it remains in Dev branch until after v2.00; Ported the new timer code from PCem; Cleaned up the CPU table of unused stuff and better optimized its structure; Ported the Open-XT and Open-AT from VARCem, the Open-AT is in the Dev branch; Ported the XT MFM controller rewrite and adding of more controllers (incl. two RLL ones), from VARCem; Added the AHA-1540A and the BusTek BT-542B; Moved the Sumo SCSI-AT to the Dev branch; Minor IDE, FDC, and floppy drive code clean-ups; Made NCR 5380/53C400-based cards' BIOS address configurable; Got rid of the legacy romset variable; Unified (video) buffer and buffer32 into one and make the unified buffer 32-bit; Added the Amstead PPC512 per PCem patch by John Elliott; Switched memory mapping granularity from 16k to 4k (less than 1k not possible due to internal pages); Rewrote the CL-GD 54xx blitter, fixes Win-OS/2 on the 54x6 among other thing; Added the Image Manager 1024 and Professional Graphics Controller per PCem patch by John Elliott and work done on VARCem; Added Headland HT-216, GC-205 and Video 7 VGA 1024i emulation based on PCem commit; Implemented the fuction keys for the Toshiba T1000/T1200/T3100 enhancement; Amstrad MegaPC does now works correctly with non-internal graphics card; The SLiRP code no longer casts a packed struct type to a non-packed struct type; The Xi8088 and PB410a no longer hang on 86Box when PS/2 mouse is not present; The S3 Virge on BeOS is no longer broken (was broken by build #1591); OS/2 2.0 build 6.167 now sees key presses again; Xi8088 now work on CGA again; 86F images converted from either the old or new variants of the HxC MFM format now work correctly; Hardware interrupts with a vector of 0xFF are now handled correctly; OPTi 495SX boards no longer incorrectly have 64 MB maximum RAM when 32 MB is correct; Fixed VNC keyboard input bugs; Fixed AT RTC periodic interrupt - Chicago 58s / 73f / 73g / 81 MIDI play no longer hangs with the build's own VTD driver; Fixed mouse polling with internal mice - Amstrad and Olivetti mice now work correctly; Triones ATAPI DMA driver now correctly reads a file at the end of a CD image with a sectors number not divisible by 4; Compaq Portable now works with all graphics cards; Fixed various MDSI Genius bugs; Added segment limit checks and improved page fault checks for several CPU instructions - Memphis 15xx WINSETUP and Chicago 58s WINDISK.CPL no longer issue a GPF, and some S3 drivers that used to have glitches, now work correctly; Further improved the 808x emulation, also fixes the noticably choppy sound when using 808x CPU's, also fixes #355; OS/2 installer no logner locks up on splash screen on PS/2 Model 70 and 80, fixes #400. Fixed several Amstead bugs, GEM no longer crashes on the Amstrad 1640, fixes #391. Ported John Elliott's Amstrad fixes and improvement from PCem, and fixed the default language so it's correctly Engliish, fixes #278, fixes #389. Fixed a minor IDE timing bug, fixes #388. Fixed Toshiba T1000 RAM issues, fixes #379. Fixed EGA/(S)VGA overscan border handling, fixes #378; Got rid of the now long useless IDE channel 2 auto-removal, fixes #370; Fixed the BIOS files used by the AMSTRAD PC1512, fixes #366; Ported the Unicode CD image file name fix from VARCem, fixes #365; Fixed high density floppy disks on the Xi8088, fixes #359; Fixed some bugs in the Hercules emulation, fixes #346, fixes #358; Fixed the SCSI hard disk mode sense pages, fixes #356; Removed the AMI Unknown 386SX because of impossibility to identify the chipset, closes #349; Fixed bugs in the serial mouse emulation, fixes #344; Compiled 86Box binaries now include all the required .DLL's, fixes #341; Made some combo boxes in the Settings dialog slightly wider, fixes #276.
This commit is contained in:
@@ -75,13 +75,21 @@ void ad1848_write(uint16_t addr, uint8_t val, void *p)
|
||||
case 7: freq /= 2560; break;
|
||||
}
|
||||
ad1848->freq = freq;
|
||||
ad1848->timer_latch = (int64_t)((double)TIMER_USEC * (1000000.0 / (double)ad1848->freq));
|
||||
ad1848->timer_latch = (uint64_t)((double)TIMER_USEC * (1000000.0 / (double)ad1848->freq));
|
||||
break;
|
||||
|
||||
case 9:
|
||||
if (!ad1848->enable && (val & 0x41) == 0x01) {
|
||||
if (ad1848->timer_latch)
|
||||
timer_set_delay_u64(&ad1848->timer_count, ad1848->timer_latch);
|
||||
else
|
||||
timer_set_delay_u64(&ad1848->timer_count, TIMER_USEC);
|
||||
}
|
||||
ad1848->enable = ((val & 0x41) == 0x01);
|
||||
if (!ad1848->enable)
|
||||
if (!ad1848->enable) {
|
||||
timer_disable(&ad1848->timer_count);
|
||||
ad1848->out_l = ad1848->out_r = 0;
|
||||
}
|
||||
break;
|
||||
|
||||
case 12:
|
||||
@@ -101,7 +109,7 @@ void ad1848_write(uint16_t addr, uint8_t val, void *p)
|
||||
|
||||
void ad1848_speed_changed(ad1848_t *ad1848)
|
||||
{
|
||||
ad1848->timer_latch = (int64_t)((double)TIMER_USEC * (1000000.0 / (double)ad1848->freq));
|
||||
ad1848->timer_latch = (uint64_t)((double)TIMER_USEC * (1000000.0 / (double)ad1848->freq));
|
||||
}
|
||||
|
||||
void ad1848_update(ad1848_t *ad1848)
|
||||
@@ -118,10 +126,10 @@ static void ad1848_poll(void *p)
|
||||
ad1848_t *ad1848 = (ad1848_t *)p;
|
||||
|
||||
if (ad1848->timer_latch)
|
||||
ad1848->timer_count += ad1848->timer_latch;
|
||||
timer_advance_u64(&ad1848->timer_count, ad1848->timer_latch);
|
||||
else
|
||||
ad1848->timer_count = TIMER_USEC;
|
||||
|
||||
timer_advance_u64(&ad1848->timer_count, TIMER_USEC * 1000);
|
||||
|
||||
ad1848_update(ad1848);
|
||||
|
||||
if (ad1848->enable)
|
||||
@@ -183,8 +191,6 @@ void ad1848_init(ad1848_t *ad1848)
|
||||
{
|
||||
int c;
|
||||
double attenuation;
|
||||
|
||||
ad1848->enable = 0;
|
||||
|
||||
ad1848->status = 0xcc;
|
||||
ad1848->index = ad1848->trd = 0;
|
||||
@@ -219,5 +225,5 @@ void ad1848_init(ad1848_t *ad1848)
|
||||
ad1848_vols[c] = (int)(attenuation * 65536);
|
||||
}
|
||||
|
||||
timer_add(ad1848_poll, &ad1848->timer_count, &ad1848->enable, ad1848);
|
||||
timer_add(&ad1848->timer_count, ad1848_poll, ad1848, 0);
|
||||
}
|
||||
|
||||
@@ -11,13 +11,14 @@ typedef struct ad1848_t
|
||||
|
||||
int16_t out_l, out_r;
|
||||
|
||||
int64_t enable;
|
||||
int enable;
|
||||
|
||||
int irq, dma;
|
||||
|
||||
int64_t freq;
|
||||
int freq;
|
||||
|
||||
int64_t timer_count, timer_latch;
|
||||
pc_timer_t timer_count;
|
||||
uint64_t timer_latch;
|
||||
|
||||
int16_t buffer[SOUNDBUFLEN * 2];
|
||||
int pos;
|
||||
|
||||
@@ -7,6 +7,7 @@
|
||||
#define HAVE_STDARG_H
|
||||
#include "../86box.h"
|
||||
#include "../io.h"
|
||||
#include "../timer.h"
|
||||
#include "../mca.h"
|
||||
#include "../device.h"
|
||||
#include "sound.h"
|
||||
@@ -85,6 +86,14 @@ void adlib_mca_write(int port, uint8_t val, void *p)
|
||||
adlib->pos_regs[port & 7] = val;
|
||||
}
|
||||
|
||||
uint8_t adlib_mca_feedb(void *p)
|
||||
{
|
||||
adlib_t *adlib = (adlib_t *)p;
|
||||
|
||||
return (adlib->pos_regs[2] & 1);
|
||||
}
|
||||
|
||||
|
||||
void *adlib_init(const device_t *info)
|
||||
{
|
||||
adlib_t *adlib = malloc(sizeof(adlib_t));
|
||||
@@ -102,7 +111,7 @@ void *adlib_mca_init(const device_t *info)
|
||||
adlib_t *adlib = adlib_init(info);
|
||||
|
||||
io_removehandler(0x0388, 0x0002, opl2_read, NULL, NULL, opl2_write, NULL, NULL, &adlib->opl);
|
||||
mca_add(adlib_mca_read, adlib_mca_write, adlib);
|
||||
mca_add(adlib_mca_read, adlib_mca_write, adlib_mca_feedb, adlib);
|
||||
adlib->pos_regs[0] = 0xd7;
|
||||
adlib->pos_regs[1] = 0x70;
|
||||
|
||||
|
||||
@@ -5,11 +5,11 @@
|
||||
#include <wchar.h>
|
||||
#include "../86box.h"
|
||||
#include "../io.h"
|
||||
#include "../timer.h"
|
||||
#include "../dma.h"
|
||||
#include "../pic.h"
|
||||
#include "../device.h"
|
||||
#include "../nvr.h"
|
||||
#include "../timer.h"
|
||||
#include "sound.h"
|
||||
#include "filters.h"
|
||||
#include "snd_opl.h"
|
||||
@@ -37,7 +37,7 @@ typedef struct adgold_t
|
||||
int16_t adgold_mma_out[2];
|
||||
int adgold_mma_intpos[2];
|
||||
|
||||
int64_t adgold_mma_timer_count;
|
||||
pc_timer_t adgold_mma_timer_count;
|
||||
|
||||
struct
|
||||
{
|
||||
@@ -576,67 +576,64 @@ void adgold_timer_poll(void *p)
|
||||
{
|
||||
adgold_t *adgold = (adgold_t *)p;
|
||||
|
||||
while (adgold->adgold_mma_timer_count <= 0LL)
|
||||
{
|
||||
adgold->adgold_mma_timer_count += (int64_t)((double)TIMER_USEC * 1.88964);
|
||||
if (adgold->adgold_mma_regs[0][8] & 0x01) /*Timer 0*/
|
||||
{
|
||||
adgold->adgold_mma.timer0_count--;
|
||||
if (!adgold->adgold_mma.timer0_count)
|
||||
{
|
||||
adgold->adgold_mma.timer0_count = adgold->adgold_mma.timer0_latch;
|
||||
adgold->adgold_mma_status |= 0x10;
|
||||
adgold_update_irq_status(adgold);
|
||||
}
|
||||
}
|
||||
if (adgold->adgold_mma_regs[0][8] & 0x08) /*Base timer*/
|
||||
{
|
||||
adgold->adgold_mma.timerbase_count--;
|
||||
if (!adgold->adgold_mma.timerbase_count)
|
||||
{
|
||||
adgold->adgold_mma.timerbase_count = adgold->adgold_mma.timerbase_latch;
|
||||
if (adgold->adgold_mma_regs[0][8] & 0x02) /*Timer 1*/
|
||||
{
|
||||
adgold->adgold_mma.timer1_count--;
|
||||
if (!adgold->adgold_mma.timer1_count)
|
||||
{
|
||||
adgold->adgold_mma.timer1_count = adgold->adgold_mma.timer1_latch;
|
||||
adgold->adgold_mma_status |= 0x20;
|
||||
adgold_update_irq_status(adgold);
|
||||
}
|
||||
}
|
||||
if (adgold->adgold_mma_regs[0][8] & 0x04) /*Timer 2*/
|
||||
{
|
||||
adgold->adgold_mma.timer2_count--;
|
||||
if (!adgold->adgold_mma.timer2_count)
|
||||
{
|
||||
adgold->adgold_mma.timer2_count = adgold->adgold_mma.timer2_latch;
|
||||
adgold->adgold_mma_status |= 0x40;
|
||||
adgold_update_irq_status(adgold);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
timer_advance_u64(&adgold->adgold_mma_timer_count, (uint64_t)((double)TIMER_USEC * 1.88964));
|
||||
if (adgold->adgold_mma_regs[0][8] & 0x01) /*Timer 0*/
|
||||
{
|
||||
adgold->adgold_mma.timer0_count--;
|
||||
if (!adgold->adgold_mma.timer0_count)
|
||||
{
|
||||
adgold->adgold_mma.timer0_count = adgold->adgold_mma.timer0_latch;
|
||||
adgold->adgold_mma_status |= 0x10;
|
||||
adgold_update_irq_status(adgold);
|
||||
}
|
||||
}
|
||||
if (adgold->adgold_mma_regs[0][8] & 0x08) /*Base timer*/
|
||||
{
|
||||
adgold->adgold_mma.timerbase_count--;
|
||||
if (!adgold->adgold_mma.timerbase_count)
|
||||
{
|
||||
adgold->adgold_mma.timerbase_count = adgold->adgold_mma.timerbase_latch;
|
||||
if (adgold->adgold_mma_regs[0][8] & 0x02) /*Timer 1*/
|
||||
{
|
||||
adgold->adgold_mma.timer1_count--;
|
||||
if (!adgold->adgold_mma.timer1_count)
|
||||
{
|
||||
adgold->adgold_mma.timer1_count = adgold->adgold_mma.timer1_latch;
|
||||
adgold->adgold_mma_status |= 0x20;
|
||||
adgold_update_irq_status(adgold);
|
||||
}
|
||||
}
|
||||
if (adgold->adgold_mma_regs[0][8] & 0x04) /*Timer 2*/
|
||||
{
|
||||
adgold->adgold_mma.timer2_count--;
|
||||
if (!adgold->adgold_mma.timer2_count)
|
||||
{
|
||||
adgold->adgold_mma.timer2_count = adgold->adgold_mma.timer2_latch;
|
||||
adgold->adgold_mma_status |= 0x40;
|
||||
adgold_update_irq_status(adgold);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (adgold->adgold_mma_enable[0])
|
||||
{
|
||||
adgold->adgold_mma.voice_count[0]--;
|
||||
if (!adgold->adgold_mma.voice_count[0])
|
||||
{
|
||||
adgold->adgold_mma.voice_count[0] = adgold->adgold_mma.voice_latch[0];
|
||||
adgold_mma_poll(adgold, 0);
|
||||
}
|
||||
}
|
||||
if (adgold->adgold_mma_enable[1])
|
||||
{
|
||||
adgold->adgold_mma.voice_count[1]--;
|
||||
if (!adgold->adgold_mma.voice_count[1])
|
||||
{
|
||||
adgold->adgold_mma.voice_count[1] = adgold->adgold_mma.voice_latch[1];
|
||||
adgold_mma_poll(adgold, 1);
|
||||
}
|
||||
}
|
||||
}
|
||||
if (adgold->adgold_mma_enable[0])
|
||||
{
|
||||
adgold->adgold_mma.voice_count[0]--;
|
||||
if (!adgold->adgold_mma.voice_count[0])
|
||||
{
|
||||
adgold->adgold_mma.voice_count[0] = adgold->adgold_mma.voice_latch[0];
|
||||
adgold_mma_poll(adgold, 0);
|
||||
}
|
||||
}
|
||||
if (adgold->adgold_mma_enable[1])
|
||||
{
|
||||
adgold->adgold_mma.voice_count[1]--;
|
||||
if (!adgold->adgold_mma.voice_count[1])
|
||||
{
|
||||
adgold->adgold_mma.voice_count[1] = adgold->adgold_mma.voice_latch[1];
|
||||
adgold_mma_poll(adgold, 1);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void adgold_get_buffer(int32_t *buffer, int len, void *p)
|
||||
@@ -802,7 +799,7 @@ void *adgold_init(const device_t *info)
|
||||
/*388/389 are handled by adlib_init*/
|
||||
io_sethandler(0x0388, 0x0008, adgold_read, NULL, NULL, adgold_write, NULL, NULL, adgold);
|
||||
|
||||
timer_add(adgold_timer_poll, &adgold->adgold_mma_timer_count, TIMER_ALWAYS_ENABLED, adgold);
|
||||
timer_add(&adgold->adgold_mma_timer_count, adgold_timer_poll, adgold, 1);
|
||||
|
||||
sound_add_handler(adgold_get_buffer, adgold);
|
||||
|
||||
|
||||
@@ -53,9 +53,11 @@ typedef struct {
|
||||
uint32_t addr, addr_latch;
|
||||
uint16_t count, size;
|
||||
|
||||
uint16_t samp_ct, curr_samp_ct;
|
||||
uint16_t samp_ct;
|
||||
int curr_samp_ct;
|
||||
|
||||
int64_t time, latch;
|
||||
pc_timer_t timer;
|
||||
uint64_t latch;
|
||||
|
||||
uint32_t vf, ac;
|
||||
|
||||
@@ -606,8 +608,6 @@ static void es1371_outl(uint16_t port, uint32_t val, void *p)
|
||||
case 0xc:
|
||||
es1371->dac[0].size = val & 0xffff;
|
||||
es1371->dac[0].count = val >> 16;
|
||||
if (es1371->dac[0].count)
|
||||
es1371->dac[0].count -= 4;
|
||||
break;
|
||||
|
||||
case 0xd:
|
||||
@@ -1105,8 +1105,8 @@ static void es1371_poll(void *p)
|
||||
{
|
||||
es1371_t *es1371 = (es1371_t *)p;
|
||||
|
||||
es1371->dac[1].time += es1371->dac[1].latch;
|
||||
|
||||
timer_advance_u64(&es1371->dac[1].timer, es1371->dac[1].latch);
|
||||
|
||||
es1371_update(es1371);
|
||||
|
||||
if (es1371->int_ctrl & INT_DAC1_EN)
|
||||
@@ -1120,7 +1120,6 @@ static void es1371_poll(void *p)
|
||||
|
||||
es1371->dac[0].out_l = ((samp1_l * (0x8000 - frac)) + (samp2_l * frac)) >> 15;
|
||||
es1371->dac[0].out_r = ((samp1_r * (0x8000 - frac)) + (samp2_r * frac)) >> 15;
|
||||
// audiopci_log("1Samp %i %i %08x\n", es1371->dac[0].curr_samp_ct, es1371->dac[0].samp_ct, es1371->dac[0].ac);
|
||||
es1371->dac[0].ac += es1371->dac[0].vf;
|
||||
es1371->dac[0].ac &= ((32 << 15) - 1);
|
||||
if ((es1371->dac[0].ac >> (15+4)) != es1371->dac[0].f_pos)
|
||||
@@ -1128,16 +1127,12 @@ static void es1371_poll(void *p)
|
||||
es1371_next_sample_filtered(es1371, 0, es1371->dac[0].f_pos ? 16 : 0);
|
||||
es1371->dac[0].f_pos = (es1371->dac[0].f_pos + 1) & 1;
|
||||
|
||||
es1371->dac[0].curr_samp_ct++;
|
||||
if (es1371->dac[0].curr_samp_ct == es1371->dac[0].samp_ct)
|
||||
es1371->dac[0].curr_samp_ct--;
|
||||
if (es1371->dac[0].curr_samp_ct < 0)
|
||||
{
|
||||
// audiopci_log("DAC1 IRQ\n");
|
||||
es1371->int_status |= INT_STATUS_DAC1;
|
||||
es1371_update_irqs(es1371);
|
||||
}
|
||||
if (es1371->dac[0].curr_samp_ct > es1371->dac[0].samp_ct)
|
||||
{
|
||||
es1371->dac[0].curr_samp_ct = 0;
|
||||
es1371->dac[0].curr_samp_ct = es1371->dac[0].samp_ct;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1153,7 +1148,6 @@ static void es1371_poll(void *p)
|
||||
|
||||
es1371->dac[1].out_l = ((samp1_l * (0x8000 - frac)) + (samp2_l * frac)) >> 15;
|
||||
es1371->dac[1].out_r = ((samp1_r * (0x8000 - frac)) + (samp2_r * frac)) >> 15;
|
||||
// audiopci_log("2Samp %i %i %08x\n", es1371->dac[1].curr_samp_ct, es1371->dac[1].samp_ct, es1371->dac[1].ac);
|
||||
es1371->dac[1].ac += es1371->dac[1].vf;
|
||||
es1371->dac[1].ac &= ((32 << 15) - 1);
|
||||
if ((es1371->dac[1].ac >> (15+4)) != es1371->dac[1].f_pos)
|
||||
@@ -1161,16 +1155,13 @@ static void es1371_poll(void *p)
|
||||
es1371_next_sample_filtered(es1371, 1, es1371->dac[1].f_pos ? 16 : 0);
|
||||
es1371->dac[1].f_pos = (es1371->dac[1].f_pos + 1) & 1;
|
||||
|
||||
es1371->dac[1].curr_samp_ct++;
|
||||
if (es1371->dac[1].curr_samp_ct > es1371->dac[1].samp_ct)
|
||||
es1371->dac[1].curr_samp_ct--;
|
||||
if (es1371->dac[1].curr_samp_ct < 0)
|
||||
{
|
||||
// es1371->dac[1].curr_samp_ct = 0;
|
||||
// audiopci_log("DAC2 IRQ\n");
|
||||
es1371->int_status |= INT_STATUS_DAC2;
|
||||
es1371_update_irqs(es1371);
|
||||
es1371->dac[1].curr_samp_ct = es1371->dac[1].samp_ct;
|
||||
}
|
||||
if (es1371->dac[1].curr_samp_ct > es1371->dac[1].samp_ct)
|
||||
es1371->dac[1].curr_samp_ct = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1232,8 +1223,8 @@ static void *es1371_init()
|
||||
sound_add_handler(es1371_get_buffer, es1371);
|
||||
|
||||
es1371->card = pci_add_card(PCI_ADD_NORMAL, es1371_pci_read, es1371_pci_write, es1371);
|
||||
|
||||
timer_add(es1371_poll, &es1371->dac[1].time, TIMER_ALWAYS_ENABLED, es1371);
|
||||
|
||||
timer_add(&es1371->dac[1].timer, es1371_poll, es1371, 1);
|
||||
|
||||
generate_es1371_filter();
|
||||
|
||||
@@ -1251,7 +1242,7 @@ static void es1371_speed_changed(void *p)
|
||||
{
|
||||
es1371_t *es1371 = (es1371_t *)p;
|
||||
|
||||
es1371->dac[1].latch = (int)((double)TIMER_USEC * (1000000.0 / 48000.0));
|
||||
es1371->dac[1].latch = (uint64_t)((double)TIMER_USEC * (1000000.0 / 48000.0));
|
||||
}
|
||||
|
||||
void es1371_add_status_info_dac(es1371_t *es1371, char *s, int max_len, int dac_nr)
|
||||
|
||||
@@ -21,7 +21,7 @@ static struct
|
||||
uint8_t status;
|
||||
int is_opl3;
|
||||
|
||||
void (*timer_callback)(void *param, int timer, int64_t period);
|
||||
void (*timer_callback)(void *param, int timer, uint64_t period);
|
||||
void *timer_param;
|
||||
} opl[2];
|
||||
|
||||
@@ -41,7 +41,7 @@ enum
|
||||
CTRL_TIMER1_CTRL = 0x01
|
||||
};
|
||||
|
||||
void opl_init(void (*timer_callback)(void *param, int timer, int64_t period), void *timer_param, int nr, int is_opl3)
|
||||
void opl_init(void (*timer_callback)(void *param, int timer, uint64_t period), void *timer_param, int nr, int is_opl3)
|
||||
{
|
||||
opl[nr].timer_callback = timer_callback;
|
||||
opl[nr].timer_param = timer_param;
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
void opl_init(void (*timer_callback)(void *param, int timer, int64_t period), void *timer_param, int nr, int is_opl3);
|
||||
void opl_init(void (*timer_callback)(void *param, int timer, uint64_t period), void *timer_param, int nr, int is_opl3);
|
||||
void opl_write(int nr, uint16_t addr, uint8_t val);
|
||||
uint8_t opl_read(int nr, uint16_t addr);
|
||||
void opl_timer_over(int nr, int timer);
|
||||
|
||||
@@ -47,13 +47,14 @@ typedef struct gus_t
|
||||
int16_t buffer[2][SOUNDBUFLEN];
|
||||
int pos;
|
||||
|
||||
int64_t samp_timer, samp_latch;
|
||||
pc_timer_t samp_timer;
|
||||
uint64_t samp_latch;
|
||||
|
||||
uint8_t *ram;
|
||||
|
||||
int irqnext;
|
||||
|
||||
int64_t timer_1, timer_2;
|
||||
pc_timer_t timer_1, timer_2;
|
||||
|
||||
int irq, dma, irq_midi;
|
||||
int latch_enable;
|
||||
@@ -745,7 +746,7 @@ void gus_poll_timer_1(void *p)
|
||||
{
|
||||
gus_t *gus = (gus_t *)p;
|
||||
|
||||
gus->timer_1 += (TIMER_USEC * 80LL);
|
||||
timer_advance_u64(&gus->timer_1, TIMER_USEC * 80);
|
||||
if (gus->t1on)
|
||||
{
|
||||
gus->t1++;
|
||||
@@ -776,7 +777,7 @@ void gus_poll_timer_2(void *p)
|
||||
{
|
||||
gus_t *gus = (gus_t *)p;
|
||||
|
||||
gus->timer_2 += (TIMER_USEC * 320LL);
|
||||
timer_advance_u64(&gus->timer_2, TIMER_USEC * 320);
|
||||
if (gus->t2on)
|
||||
{
|
||||
gus->t2++;
|
||||
@@ -832,7 +833,7 @@ void gus_poll_wave(void *p)
|
||||
|
||||
gus_update(gus);
|
||||
|
||||
gus->samp_timer += gus->samp_latch;
|
||||
timer_advance_u64(&gus->samp_timer, gus->samp_latch);
|
||||
|
||||
gus->out_l = gus->out_r = 0;
|
||||
|
||||
@@ -1021,8 +1022,8 @@ void *gus_init(const device_t *info)
|
||||
}
|
||||
|
||||
gus->voices=14;
|
||||
|
||||
gus->samp_timer = gus->samp_latch = (int64_t)(TIMER_USEC * (1000000.0 / 44100.0));
|
||||
|
||||
gus->samp_latch = (uint64_t)(TIMER_USEC * (1000000.0 / 44100.0));
|
||||
|
||||
gus->t1l = gus->t2l = 0xff;
|
||||
|
||||
@@ -1030,9 +1031,9 @@ void *gus_init(const device_t *info)
|
||||
io_sethandler(0x0340, 0x0010, readgus, NULL, NULL, writegus, NULL, NULL, gus);
|
||||
io_sethandler(0x0746, 0x0001, readgus, NULL, NULL, writegus, NULL, NULL, gus);
|
||||
io_sethandler(0x0388, 0x0002, readgus, NULL, NULL, writegus, NULL, NULL, gus);
|
||||
timer_add(gus_poll_wave, &gus->samp_timer, TIMER_ALWAYS_ENABLED, gus);
|
||||
timer_add(gus_poll_timer_1, &gus->timer_1, TIMER_ALWAYS_ENABLED, gus);
|
||||
timer_add(gus_poll_timer_2, &gus->timer_2, TIMER_ALWAYS_ENABLED, gus);
|
||||
timer_add(&gus->samp_timer, gus_poll_wave, gus, 1);
|
||||
timer_add(&gus->timer_1, gus_poll_timer_1, gus, 1);
|
||||
timer_add(&gus->timer_2, gus_poll_timer_2, gus, 1);
|
||||
|
||||
sound_add_handler(gus_get_buffer, gus);
|
||||
|
||||
@@ -1052,9 +1053,9 @@ void gus_speed_changed(void *p)
|
||||
gus_t *gus = (gus_t *)p;
|
||||
|
||||
if (gus->voices < 14)
|
||||
gus->samp_latch = (int)(TIMER_USEC * (1000000.0 / 44100.0));
|
||||
gus->samp_latch = (uint64_t)(TIMER_USEC * (1000000.0 / 44100.0));
|
||||
else
|
||||
gus->samp_latch = (int)(TIMER_USEC * (1000000.0 / gusfreqs[gus->voices - 14]));
|
||||
gus->samp_latch = (uint64_t)(TIMER_USEC * (1000000.0 / gusfreqs[gus->voices - 14]));
|
||||
}
|
||||
|
||||
const device_t gus_device =
|
||||
|
||||
@@ -14,6 +14,8 @@
|
||||
|
||||
typedef struct lpt_dac_t
|
||||
{
|
||||
void *lpt;
|
||||
|
||||
uint8_t dac_val_l, dac_val_r;
|
||||
|
||||
int is_stereo;
|
||||
@@ -36,8 +38,6 @@ static void dac_update(lpt_dac_t *lpt_dac)
|
||||
static void dac_write_data(uint8_t val, void *p)
|
||||
{
|
||||
lpt_dac_t *lpt_dac = (lpt_dac_t *)p;
|
||||
|
||||
timer_clock();
|
||||
|
||||
if (lpt_dac->is_stereo)
|
||||
{
|
||||
@@ -80,18 +80,20 @@ static void dac_get_buffer(int32_t *buffer, int len, void *p)
|
||||
lpt_dac->pos = 0;
|
||||
}
|
||||
|
||||
static void *dac_init()
|
||||
static void *dac_init(void *lpt)
|
||||
{
|
||||
lpt_dac_t *lpt_dac = malloc(sizeof(lpt_dac_t));
|
||||
memset(lpt_dac, 0, sizeof(lpt_dac_t));
|
||||
|
||||
lpt_dac->lpt = lpt;
|
||||
|
||||
sound_add_handler(dac_get_buffer, lpt_dac);
|
||||
|
||||
return lpt_dac;
|
||||
}
|
||||
static void *dac_stereo_init()
|
||||
static void *dac_stereo_init(void *lpt)
|
||||
{
|
||||
lpt_dac_t *lpt_dac = dac_init();
|
||||
lpt_dac_t *lpt_dac = dac_init(lpt);
|
||||
|
||||
lpt_dac->is_stereo = 1;
|
||||
|
||||
|
||||
@@ -14,12 +14,15 @@
|
||||
|
||||
typedef struct dss_t
|
||||
{
|
||||
void *lpt;
|
||||
|
||||
uint8_t fifo[16];
|
||||
int read_idx, write_idx;
|
||||
|
||||
uint8_t dac_val;
|
||||
uint8_t dac_val,
|
||||
status;
|
||||
|
||||
int64_t time;
|
||||
pc_timer_t timer;
|
||||
|
||||
int16_t buffer[SOUNDBUFLEN];
|
||||
int pos;
|
||||
@@ -32,16 +35,29 @@ static void dss_update(dss_t *dss)
|
||||
}
|
||||
|
||||
|
||||
static void dss_update_status(dss_t *dss)
|
||||
{
|
||||
uint8_t old = dss->status;
|
||||
|
||||
dss->status &= ~0x40;
|
||||
|
||||
if ((dss->write_idx - dss->read_idx) >= 16)
|
||||
dss->status |= 0x40;
|
||||
|
||||
if ((old & 0x40) && !(dss->status & 0x40))
|
||||
lpt_irq(dss->lpt, 1);
|
||||
}
|
||||
|
||||
|
||||
static void dss_write_data(uint8_t val, void *p)
|
||||
{
|
||||
dss_t *dss = (dss_t *)p;
|
||||
|
||||
timer_clock();
|
||||
|
||||
if ((dss->write_idx - dss->read_idx) < 16)
|
||||
{
|
||||
dss->fifo[dss->write_idx & 15] = val;
|
||||
dss->write_idx++;
|
||||
dss_update_status(dss);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -53,9 +69,7 @@ static uint8_t dss_read_status(void *p)
|
||||
{
|
||||
dss_t *dss = (dss_t *)p;
|
||||
|
||||
if ((dss->write_idx - dss->read_idx) >= 16)
|
||||
return 0x40;
|
||||
return 0;
|
||||
return dss->status;
|
||||
}
|
||||
|
||||
|
||||
@@ -63,12 +77,15 @@ static void dss_get_buffer(int32_t *buffer, int len, void *p)
|
||||
{
|
||||
dss_t *dss = (dss_t *)p;
|
||||
int c;
|
||||
int16_t val;
|
||||
float fval;
|
||||
|
||||
dss_update(dss);
|
||||
|
||||
for (c = 0; c < len*2; c += 2)
|
||||
{
|
||||
int16_t val = (int16_t)dss_iir((float)dss->buffer[c >> 1]);
|
||||
fval = dss_iir((float)dss->buffer[c >> 1]);
|
||||
val = (float) fval;
|
||||
|
||||
buffer[c] += val;
|
||||
buffer[c+1] += val;
|
||||
@@ -87,19 +104,22 @@ static void dss_callback(void *p)
|
||||
{
|
||||
dss->dac_val = dss->fifo[dss->read_idx & 15];
|
||||
dss->read_idx++;
|
||||
dss_update_status(dss);
|
||||
}
|
||||
|
||||
dss->time += (int64_t) (TIMER_USEC * (1000000.0 / 7000.0));
|
||||
|
||||
timer_advance_u64(&dss->timer, (TIMER_USEC * (1000000.0 / 7000.0)));
|
||||
}
|
||||
|
||||
static void *dss_init()
|
||||
static void *dss_init(void *lpt)
|
||||
{
|
||||
dss_t *dss = malloc(sizeof(dss_t));
|
||||
memset(dss, 0, sizeof(dss_t));
|
||||
|
||||
dss->lpt = lpt;
|
||||
|
||||
sound_add_handler(dss_get_buffer, dss);
|
||||
timer_add(dss_callback, &dss->time, TIMER_ALWAYS_ENABLED, dss);
|
||||
|
||||
timer_add(&dss->timer, dss_callback, dss, 1);
|
||||
|
||||
return dss;
|
||||
}
|
||||
static void dss_close(void *p)
|
||||
|
||||
@@ -47,11 +47,6 @@ enum {
|
||||
|
||||
int mpu401_standalone_enable = 0;
|
||||
|
||||
static int64_t mpu401_event_callback = 0LL;
|
||||
static int64_t mpu401_eoi_callback = 0LL;
|
||||
static int64_t mpu401_reset_callback = 0LL;
|
||||
|
||||
|
||||
static void MPU401_WriteCommand(mpu_t *mpu, uint8_t val);
|
||||
static void MPU401_EOIHandlerDispatch(void *p);
|
||||
|
||||
@@ -165,7 +160,7 @@ MPU401_ResetDone(void *priv)
|
||||
|
||||
mpu401_log("MPU-401 reset callback\n");
|
||||
|
||||
mpu401_reset_callback = 0LL;
|
||||
timer_disable(&mpu->mpu401_reset_callback);
|
||||
|
||||
mpu->state.reset = 0;
|
||||
if (mpu->state.cmd_pending) {
|
||||
@@ -204,7 +199,7 @@ MPU401_WriteCommand(mpu_t *mpu, uint8_t val)
|
||||
switch (val & 0xc) {
|
||||
case 0x4: /* Stop */
|
||||
mpu->state.playing = 0;
|
||||
mpu401_event_callback = 0LL;
|
||||
timer_disable(&mpu->mpu401_event_callback);
|
||||
|
||||
for (i = 0xb0; i < 0xbf; i++) {
|
||||
/* All notes off */
|
||||
@@ -216,7 +211,7 @@ MPU401_WriteCommand(mpu_t *mpu, uint8_t val)
|
||||
|
||||
case 0x8: /* Play */
|
||||
mpu->state.playing = 1;
|
||||
mpu401_event_callback = (MPU401_TIMECONSTANT / (mpu->clock.tempo*mpu->clock.timebase)) * 1000LL * TIMER_USEC;
|
||||
timer_set_delay_u64(&mpu->mpu401_event_callback, (MPU401_TIMECONSTANT / (mpu->clock.tempo*mpu->clock.timebase)) * 1000 * TIMER_USEC);
|
||||
ClrQueue(mpu);
|
||||
break;
|
||||
}
|
||||
@@ -334,7 +329,7 @@ MPU401_WriteCommand(mpu_t *mpu, uint8_t val)
|
||||
|
||||
case 0xff: /* Reset MPU-401 */
|
||||
mpu401_log("MPU-401:Reset %X\n",val);
|
||||
mpu401_reset_callback = MPU401_RESETBUSY * 33LL * TIMER_USEC;
|
||||
timer_set_delay_u64(&mpu->mpu401_reset_callback, MPU401_RESETBUSY * 33LL * TIMER_USEC);
|
||||
mpu->state.reset = 1;
|
||||
was_uart = (mpu->mode == M_UART);
|
||||
MPU401_Reset(mpu);
|
||||
@@ -675,7 +670,7 @@ MPU401_EOIHandler(void *priv)
|
||||
|
||||
mpu401_log("MPU-401 end of input callback\n");
|
||||
|
||||
mpu401_eoi_callback = 0LL;
|
||||
timer_disable(&mpu->mpu401_eoi_callback);
|
||||
mpu->state.eoi_scheduled = 0;
|
||||
if (mpu->state.send_now) {
|
||||
mpu->state.send_now = 0;
|
||||
@@ -707,7 +702,7 @@ MPU401_EOIHandlerDispatch(void *priv)
|
||||
mpu401_log("EOI handler dispatch\n");
|
||||
if (mpu->state.send_now) {
|
||||
mpu->state.eoi_scheduled = 1;
|
||||
mpu401_eoi_callback = 60LL * TIMER_USEC; /* Possible a bit longer */
|
||||
timer_advance_u64(&mpu->mpu401_eoi_callback, 60 * TIMER_USEC); /* Possibly a bit longer */
|
||||
} else if (!mpu->state.eoi_scheduled)
|
||||
MPU401_EOIHandler(mpu);
|
||||
}
|
||||
@@ -833,7 +828,7 @@ MPU401_Event(void *priv)
|
||||
mpu401_log("MPU-401 event callback\n");
|
||||
|
||||
if (mpu->mode == M_UART) {
|
||||
mpu401_event_callback = 0LL;
|
||||
timer_disable(&mpu->mpu401_event_callback);
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -865,11 +860,11 @@ MPU401_Event(void *priv)
|
||||
next_event:
|
||||
new_time = ((mpu->clock.tempo * mpu->clock.timebase * mpu->clock.tempo_rel) / 0x40);
|
||||
if (new_time == 0) {
|
||||
mpu401_event_callback = 0LL;
|
||||
timer_disable(&mpu->mpu401_event_callback);
|
||||
return;
|
||||
} else {
|
||||
mpu401_event_callback += (MPU401_TIMECONSTANT / new_time) * 1000LL * TIMER_USEC;
|
||||
mpu401_log("Next event after %i us (time constant: %i)\n", (int) ((MPU401_TIMECONSTANT/new_time) * 1000 * TIMER_USEC), (int) MPU401_TIMECONSTANT);
|
||||
timer_advance_u64(&mpu->mpu401_event_callback, (MPU401_TIMECONSTANT / new_time) * 1000 * TIMER_USEC);
|
||||
mpu401_log("Next event after %i us (time constant: %i)\n", (uint64_t) ((MPU401_TIMECONSTANT/new_time) * 1000 * TIMER_USEC), (int) MPU401_TIMECONSTANT);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -890,18 +885,14 @@ mpu401_init(mpu_t *mpu, uint16_t addr, int irq, int mode)
|
||||
mpu->intelligent = (mode == M_INTELLIGENT) ? 1 : 0;
|
||||
mpu401_log("Starting as %s (mode is %s)\n", mpu->intelligent ? "INTELLIGENT" : "UART", (mode == M_INTELLIGENT) ? "INTELLIGENT" : "UART");
|
||||
|
||||
mpu401_event_callback = 0LL;
|
||||
mpu401_eoi_callback = 0LL;
|
||||
mpu401_reset_callback = 0LL;
|
||||
|
||||
if (addr)
|
||||
io_sethandler(addr, 2,
|
||||
mpu401_read, NULL, NULL, mpu401_write, NULL, NULL, mpu);
|
||||
io_sethandler(0x2A20, 16,
|
||||
NULL, NULL, NULL, imf_write, NULL, NULL, mpu);
|
||||
timer_add(MPU401_Event, &mpu401_event_callback, &mpu401_event_callback, mpu);
|
||||
timer_add(MPU401_EOIHandler, &mpu401_eoi_callback, &mpu401_eoi_callback, mpu);
|
||||
timer_add(MPU401_ResetDone, &mpu401_reset_callback, &mpu401_reset_callback, mpu);
|
||||
timer_add(&mpu->mpu401_event_callback, MPU401_Event, mpu, 0);
|
||||
timer_add(&mpu->mpu401_eoi_callback, MPU401_EOIHandler, mpu, 0);
|
||||
timer_add(&mpu->mpu401_reset_callback, MPU401_ResetDone, mpu, 0);
|
||||
|
||||
MPU401_Reset(mpu);
|
||||
}
|
||||
@@ -955,6 +946,13 @@ mpu401_mca_write(int port, uint8_t val, void *p)
|
||||
}
|
||||
|
||||
|
||||
static uint8_t
|
||||
mpu401_mca_feedb(void *p)
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
||||
static void *
|
||||
mpu401_standalone_init(const device_t *info)
|
||||
{
|
||||
@@ -968,7 +966,7 @@ mpu401_standalone_init(const device_t *info)
|
||||
mpu401_log("mpu_init\n");
|
||||
|
||||
if (info->flags & DEVICE_MCA) {
|
||||
mca_add(mpu401_mca_read, mpu401_mca_write, mpu);
|
||||
mca_add(mpu401_mca_read, mpu401_mca_write, mpu401_mca_feedb, mpu);
|
||||
mpu->pos_regs[0] = 0x0F;
|
||||
mpu->pos_regs[1] = 0x6C;
|
||||
base = 0; /* Tell mpu401_init() that this is the MCA variant. */
|
||||
|
||||
@@ -93,6 +93,9 @@ typedef struct mpu_t
|
||||
cth_rate, cth_counter;
|
||||
int clock_to_host,cth_active;
|
||||
} clock;
|
||||
|
||||
pc_timer_t mpu401_event_callback, mpu401_eoi_callback,
|
||||
mpu401_reset_callback;
|
||||
} mpu_t;
|
||||
|
||||
extern int mpu401_standalone_enable;
|
||||
|
||||
@@ -22,7 +22,7 @@ uint8_t opl2_read(uint16_t a, void *priv)
|
||||
{
|
||||
opl_t *opl = (opl_t *)priv;
|
||||
|
||||
cycles -= ISA_CYCLES(8);
|
||||
sub_cycles((int)(isa_timing * 8));
|
||||
opl2_update2(opl);
|
||||
return opl_read(0, a);
|
||||
}
|
||||
@@ -39,7 +39,7 @@ uint8_t opl2_l_read(uint16_t a, void *priv)
|
||||
{
|
||||
opl_t *opl = (opl_t *)priv;
|
||||
|
||||
cycles -= ISA_CYCLES(8);
|
||||
sub_cycles((int)(isa_timing * 8));
|
||||
opl2_update2(opl);
|
||||
return opl_read(0, a);
|
||||
}
|
||||
@@ -55,7 +55,7 @@ uint8_t opl2_r_read(uint16_t a, void *priv)
|
||||
{
|
||||
opl_t *opl = (opl_t *)priv;
|
||||
|
||||
cycles -= ISA_CYCLES(8);
|
||||
sub_cycles((int)(isa_timing * 8));
|
||||
opl2_update2(opl);
|
||||
return opl_read(1, a);
|
||||
}
|
||||
@@ -71,7 +71,7 @@ uint8_t opl3_read(uint16_t a, void *priv)
|
||||
{
|
||||
opl_t *opl = (opl_t *)priv;
|
||||
|
||||
cycles -= ISA_CYCLES(8);
|
||||
sub_cycles((int)(isa_timing * 8));
|
||||
opl3_update2(opl);
|
||||
return opl_read(0, a);
|
||||
}
|
||||
@@ -111,58 +111,49 @@ void opl3_update2(opl_t *opl)
|
||||
}
|
||||
}
|
||||
|
||||
void ym3812_timer_set_0(void *param, int timer, int64_t period)
|
||||
void ym3812_timer_set_0(void *param, int timer, uint64_t period)
|
||||
{
|
||||
opl_t *opl = (opl_t *)param;
|
||||
|
||||
opl->timers[0][timer] = period * TIMER_USEC * 20LL;
|
||||
if (!opl->timers[0][timer]) opl->timers[0][timer] = 1;
|
||||
opl->timers_enable[0][timer] = period ? 1 : 0;
|
||||
if (period)
|
||||
timer_set_delay_u64(&opl->timers[0][timer], period * TIMER_USEC * 20);
|
||||
else
|
||||
timer_disable(&opl->timers[0][timer]);
|
||||
}
|
||||
void ym3812_timer_set_1(void *param, int timer, int64_t period)
|
||||
void ym3812_timer_set_1(void *param, int timer, uint64_t period)
|
||||
{
|
||||
opl_t *opl = (opl_t *)param;
|
||||
|
||||
opl->timers[1][timer] = period * TIMER_USEC * 20LL;
|
||||
if (!opl->timers[1][timer]) opl->timers[1][timer] = 1;
|
||||
opl->timers_enable[1][timer] = period ? 1 : 0;
|
||||
if (period)
|
||||
timer_set_delay_u64(&opl->timers[1][timer], period * TIMER_USEC * 20);
|
||||
else
|
||||
timer_disable(&opl->timers[1][timer]);
|
||||
}
|
||||
|
||||
void ymf262_timer_set(void *param, int timer, int64_t period)
|
||||
void ymf262_timer_set(void *param, int timer, uint64_t period)
|
||||
{
|
||||
opl_t *opl = (opl_t *)param;
|
||||
|
||||
opl->timers[0][timer] = period * TIMER_USEC * 20LL;
|
||||
if (!opl->timers[0][timer]) opl->timers[0][timer] = 1;
|
||||
opl->timers_enable[0][timer] = period ? 1 : 0;
|
||||
if (period)
|
||||
timer_set_delay_u64(&opl->timers[0][timer], period * TIMER_USEC * 20);
|
||||
else
|
||||
timer_disable(&opl->timers[0][timer]);
|
||||
}
|
||||
|
||||
static void opl_timer_callback00(void *p)
|
||||
{
|
||||
opl_t *opl = (opl_t *)p;
|
||||
|
||||
opl->timers_enable[0][0] = 0;
|
||||
opl_timer_over(0, 0);
|
||||
}
|
||||
static void opl_timer_callback01(void *p)
|
||||
{
|
||||
opl_t *opl = (opl_t *)p;
|
||||
|
||||
opl->timers_enable[0][1] = 0;
|
||||
opl_timer_over(0, 1);
|
||||
}
|
||||
static void opl_timer_callback10(void *p)
|
||||
{
|
||||
opl_t *opl = (opl_t *)p;
|
||||
|
||||
opl->timers_enable[1][0] = 0;
|
||||
opl_timer_over(1, 0);
|
||||
}
|
||||
static void opl_timer_callback11(void *p)
|
||||
{
|
||||
opl_t *opl = (opl_t *)p;
|
||||
|
||||
opl->timers_enable[1][1] = 0;
|
||||
opl_timer_over(1, 1);
|
||||
}
|
||||
|
||||
@@ -170,16 +161,16 @@ void opl2_init(opl_t *opl)
|
||||
{
|
||||
opl_init(ym3812_timer_set_0, opl, 0, 0);
|
||||
opl_init(ym3812_timer_set_1, opl, 1, 0);
|
||||
timer_add(opl_timer_callback00, &opl->timers[0][0], &opl->timers_enable[0][0], (void *)opl);
|
||||
timer_add(opl_timer_callback01, &opl->timers[0][1], &opl->timers_enable[0][1], (void *)opl);
|
||||
timer_add(opl_timer_callback10, &opl->timers[1][0], &opl->timers_enable[1][0], (void *)opl);
|
||||
timer_add(opl_timer_callback11, &opl->timers[1][1], &opl->timers_enable[1][1], (void *)opl);
|
||||
timer_add(&opl->timers[0][0], opl_timer_callback00, (void *)opl, 0);
|
||||
timer_add(&opl->timers[0][1], opl_timer_callback01, (void *)opl, 0);
|
||||
timer_add(&opl->timers[1][0], opl_timer_callback10, (void *)opl, 0);
|
||||
timer_add(&opl->timers[1][1], opl_timer_callback11, (void *)opl, 0);
|
||||
}
|
||||
|
||||
void opl3_init(opl_t *opl)
|
||||
{
|
||||
opl_init(ymf262_timer_set, opl, 0, 1);
|
||||
timer_add(opl_timer_callback00, &opl->timers[0][0], &opl->timers_enable[0][0], (void *)opl);
|
||||
timer_add(opl_timer_callback01, &opl->timers[0][1], &opl->timers_enable[0][1], (void *)opl);
|
||||
timer_add(&opl->timers[0][0], opl_timer_callback00, (void *)opl, 0);
|
||||
timer_add(&opl->timers[0][1], opl_timer_callback01, (void *)opl, 0);
|
||||
}
|
||||
|
||||
|
||||
@@ -5,8 +5,7 @@ typedef struct opl_t
|
||||
{
|
||||
int chip_nr[2];
|
||||
|
||||
int64_t timers[2][2];
|
||||
int64_t timers_enable[2][2];
|
||||
pc_timer_t timers[2][2];
|
||||
|
||||
int16_t filtbuf[2];
|
||||
|
||||
|
||||
@@ -9,9 +9,9 @@
|
||||
#include "../cpu/cpu.h"
|
||||
#include "../io.h"
|
||||
#include "../pic.h"
|
||||
#include "../timer.h"
|
||||
#include "../pit.h"
|
||||
#include "../dma.h"
|
||||
#include "../timer.h"
|
||||
#include "../device.h"
|
||||
#include "sound.h"
|
||||
#include "filters.h"
|
||||
@@ -128,6 +128,7 @@ typedef struct pas16_t
|
||||
{
|
||||
uint32_t l[3];
|
||||
int64_t c[3];
|
||||
pc_timer_t timer[3];
|
||||
uint8_t m[3];
|
||||
uint8_t ctrl, ctrls[2];
|
||||
int wp, rm[3], wm[3];
|
||||
@@ -202,9 +203,7 @@ pas16_log(const char *fmt, ...)
|
||||
static uint8_t pas16_in(uint16_t port, void *p)
|
||||
{
|
||||
pas16_t *pas16 = (pas16_t *)p;
|
||||
uint8_t temp;
|
||||
/* if (CS == 0xCA53 && pc == 0x3AFC)
|
||||
fatal("here");*/
|
||||
uint8_t temp = 0xff;
|
||||
switch ((port - pas16->base) + 0x388)
|
||||
{
|
||||
case 0x388: case 0x389: case 0x38a: case 0x38b:
|
||||
@@ -290,27 +289,15 @@ static uint8_t pas16_in(uint16_t port, void *p)
|
||||
case 0xff8b: /*Master mode read*/
|
||||
temp = 0x20 | 0x10 | 0x01; /*AT bus, XT/AT timing*/
|
||||
break;
|
||||
|
||||
default:
|
||||
temp = 0xff;
|
||||
break;
|
||||
}
|
||||
/* if (port != 0x388 && port != 0x389 && port != 0xb8b) */pas16_log("pas16_in : port %04X return %02X %04X:%04X\n", port, temp, CS,cpu_state.pc);
|
||||
/* if (CS == 0x1FF4 && pc == 0x0585)
|
||||
{
|
||||
if (output)
|
||||
fatal("here");
|
||||
output = 3;
|
||||
}*/
|
||||
pas16_log("pas16_in : port %04X return %02X %04X:%04X\n", port, temp, CS,cpu_state.pc);
|
||||
return temp;
|
||||
}
|
||||
|
||||
static void pas16_out(uint16_t port, uint8_t val, void *p)
|
||||
{
|
||||
pas16_t *pas16 = (pas16_t *)p;
|
||||
/* if (port != 0x388 && port != 0x389) */pas16_log("pas16_out : port %04X val %02X %04X:%04X\n", port, val, CS,cpu_state.pc);
|
||||
/* if (CS == 0x369 && pc == 0x2AC5)
|
||||
fatal("here\n");*/
|
||||
pas16_log("pas16_out : port %04X val %02X %04X:%04X\n", port, val, CS,cpu_state.pc);
|
||||
switch ((port - pas16->base) + 0x388)
|
||||
{
|
||||
case 0x388: case 0x389: case 0x38a: case 0x38b:
|
||||
@@ -415,8 +402,6 @@ static void pas16_out(uint16_t port, uint8_t val, void *p)
|
||||
fatal("here\n");
|
||||
output = 3;
|
||||
}
|
||||
/* if (CS == 0x1FF4 && pc == 0x0431)
|
||||
output = 3;*/
|
||||
}
|
||||
|
||||
static void pas16_pit_out(uint16_t port, uint8_t val, void *p)
|
||||
@@ -430,7 +415,7 @@ static void pas16_pit_out(uint16_t port, uint8_t val, void *p)
|
||||
{
|
||||
if (!(val & 0x20))
|
||||
{
|
||||
if (val & 2) pas16->pit.rl[0] = pas16->pit.c[0] / (PITCONST * (1 << TIMER_SHIFT));
|
||||
if (val & 2) pas16->pit.rl[0] = timer_get_remaining_u64(&pit.timer[0]) / PITCONST;;
|
||||
if (val & 4) pas16->pit.rl[1] = pas16->pit.c[1];
|
||||
if (val & 8) pas16->pit.rl[2] = pas16->pit.c[2];
|
||||
}
|
||||
@@ -440,16 +425,19 @@ static void pas16_pit_out(uint16_t port, uint8_t val, void *p)
|
||||
pas16->pit.ctrls[t] = pas16->pit.ctrl = val;
|
||||
if (t == 3)
|
||||
{
|
||||
pas16_log("PAS16: bad PIT reg select\n");
|
||||
printf("Bad PIT reg select\n");
|
||||
return;
|
||||
}
|
||||
if (!(pas16->pit.ctrl & 0x30))
|
||||
{
|
||||
pas16->pit.rl[t] = pas16->pit.c[t];
|
||||
if (!t)
|
||||
pas16->pit.rl[t] /= (PITCONST * (1 << TIMER_SHIFT));
|
||||
if (pas16->pit.c[t] < 0)
|
||||
pas16->pit.rl[t] = 0;
|
||||
if (!t)
|
||||
pas16->pit.rl[t] = timer_get_remaining_u64(&pit.timer[t]) / PITCONST;
|
||||
else
|
||||
{
|
||||
pas16->pit.rl[t] = pas16->pit.c[t];
|
||||
if (pas16->pit.c[t] < 0)
|
||||
pas16->pit.rl[t] = 0;
|
||||
}
|
||||
pas16->pit.ctrl |= 0x30;
|
||||
pas16->pit.rereadlatch[t] = 0;
|
||||
pas16->pit.rm[t] = 3;
|
||||
@@ -463,9 +451,10 @@ static void pas16_pit_out(uint16_t port, uint8_t val, void *p)
|
||||
if (!pas16->pit.rm[t])
|
||||
{
|
||||
pas16->pit.rm[t] = 3;
|
||||
pas16->pit.rl[t] = pit.c[t];
|
||||
if (!t)
|
||||
pas16->pit.rl[t] /= (PITCONST * (1 << TIMER_SHIFT));
|
||||
if (!t)
|
||||
pas16->pit.rl[t] = timer_get_remaining_u64(&pit.timer[t]) / PITCONST;
|
||||
else
|
||||
pas16->pit.rl[t] = pas16->pit.c[t];
|
||||
}
|
||||
pas16->pit.rereadlatch[t] = 1;
|
||||
}
|
||||
@@ -481,7 +470,7 @@ static void pas16_pit_out(uint16_t port, uint8_t val, void *p)
|
||||
pas16->pit.thit[t] = 0;
|
||||
pas16->pit.c[t] = pas16->pit.l[t];
|
||||
if (!t)
|
||||
pas16->pit.c[t] *= PITCONST * (1 << TIMER_SHIFT);
|
||||
timer_set_delay_u64(&pas16->pit.timer[t], pas16->pit.c[t] * PITCONST);
|
||||
pas16->pit.enable[t] = 1;
|
||||
break;
|
||||
case 2:
|
||||
@@ -489,7 +478,7 @@ static void pas16_pit_out(uint16_t port, uint8_t val, void *p)
|
||||
pas16->pit.thit[t] = 0;
|
||||
pas16->pit.c[t] = pas16->pit.l[t];
|
||||
if (!t)
|
||||
pas16->pit.c[t] *= PITCONST * (1 << TIMER_SHIFT);
|
||||
timer_set_delay_u64(&pas16->pit.timer[t], pas16->pit.c[t] * PITCONST);
|
||||
pas16->pit.enable[t] = 1;
|
||||
break;
|
||||
case 0:
|
||||
@@ -497,7 +486,7 @@ static void pas16_pit_out(uint16_t port, uint8_t val, void *p)
|
||||
pas16->pit.l[t] |= (val << 8);
|
||||
pas16->pit.c[t] = pas16->pit.l[t];
|
||||
if (!t)
|
||||
pas16->pit.c[t] *= PITCONST * (1 << TIMER_SHIFT);
|
||||
timer_set_delay_u64(&pas16->pit.timer[t], pas16->pit.c[t] * PITCONST);
|
||||
pas16->pit.thit[t] = 0;
|
||||
pas16->pit.wm[t] = 3;
|
||||
pas16->pit.enable[t] = 1;
|
||||
@@ -513,7 +502,7 @@ static void pas16_pit_out(uint16_t port, uint8_t val, void *p)
|
||||
pas16->pit.l[t] |= 0x10000;
|
||||
pas16->pit.c[t] = pas16->pit.l[t];
|
||||
if (!t)
|
||||
pas16->pit.c[t] *= PITCONST * (1 << TIMER_SHIFT);
|
||||
timer_set_delay_u64(&pas16->pit.timer[t], pas16->pit.c[t] * PITCONST);
|
||||
}
|
||||
break;
|
||||
}
|
||||
@@ -532,8 +521,8 @@ static uint8_t pas16_pit_in(uint16_t port, void *p)
|
||||
pas16->pit.rereadlatch[t] = 0;
|
||||
if (!t)
|
||||
{
|
||||
pas16->pit.rl[t] = pas16->pit.c[t] / (PITCONST * (1 << TIMER_SHIFT));
|
||||
if ((pas16->pit.c[t] / (PITCONST * (1 << TIMER_SHIFT))) > 65536)
|
||||
pas16->pit.rl[t] = timer_get_remaining_u64(&pit.timer[t]) / PITCONST;
|
||||
if ((timer_get_remaining_u64(&pit.timer[t]) / PITCONST) > 65536)
|
||||
pas16->pit.rl[t] = 0xFFFF;
|
||||
}
|
||||
else
|
||||
@@ -585,13 +574,12 @@ static void pas16_pcm_poll(void *p)
|
||||
if (pas16->pit.m[0] & 2)
|
||||
{
|
||||
if (pas16->pit.l[0])
|
||||
pas16->pit.c[0] += (pas16->pit.l[0] * PITCONST * (1 << TIMER_SHIFT));
|
||||
timer_advance_u64(&pas16->pit.timer[0], pas16->pit.l[0] * PITCONST);
|
||||
else
|
||||
pas16->pit.c[0] += (0x10000 * PITCONST * (1 << TIMER_SHIFT));
|
||||
timer_advance_u64(&pas16->pit.timer[0], 0x10000 * PITCONST);
|
||||
}
|
||||
else
|
||||
{
|
||||
pas16->pit.c[0] = -1;
|
||||
pas16->pit.enable[0] = 0;
|
||||
}
|
||||
|
||||
@@ -755,7 +743,7 @@ static void *pas16_init(const device_t *info)
|
||||
|
||||
io_sethandler(0x9a01, 0x0001, NULL, NULL, NULL, pas16_out_base, NULL, NULL, pas16);
|
||||
|
||||
timer_add(pas16_pcm_poll, &pas16->pit.c[0], &pas16->pit.enable[0], pas16);
|
||||
timer_add(&pas16->pit.timer[0], pas16_pcm_poll, pas16, 0);
|
||||
|
||||
sound_add_handler(pas16_get_buffer, pas16);
|
||||
|
||||
|
||||
@@ -25,8 +25,8 @@ typedef struct pssj_t
|
||||
int amplitude;
|
||||
|
||||
int irq;
|
||||
int64_t timer_count;
|
||||
int64_t enable;
|
||||
pc_timer_t timer_count;
|
||||
int enable;
|
||||
|
||||
int wave_pos;
|
||||
int pulse_width;
|
||||
@@ -49,7 +49,11 @@ static void pssj_write(uint16_t port, uint8_t val, void *p)
|
||||
{
|
||||
case 0:
|
||||
pssj->ctrl = val;
|
||||
if (!pssj->enable && ((val & 4) && (pssj->ctrl & 3)))
|
||||
timer_set_delay_u64(&pssj->timer_count, (TIMER_USEC * (1000000.0 / 3579545.0) * (double)(pssj->freq ? pssj->freq : 0x400)));
|
||||
pssj->enable = (val & 4) && (pssj->ctrl & 3);
|
||||
if (!pssj->enable)
|
||||
timer_disable(&pssj->timer_count);
|
||||
sn74689_set_extra_divide(&pssj->sn76489, val & 0x40);
|
||||
if (!(val & 8))
|
||||
pssj->irq = 0;
|
||||
@@ -168,7 +172,7 @@ static void pssj_callback(void *p)
|
||||
pssj->wave_pos = (pssj->wave_pos + 1) & 31;
|
||||
}
|
||||
|
||||
pssj->timer_count += (int64_t)(TIMER_USEC * (1000000.0 / 3579545.0) * (double)(pssj->freq ? pssj->freq : 0x400));
|
||||
timer_advance_u64(&pssj->timer_count, (TIMER_USEC * (1000000.0 / 3579545.0) * (double)(pssj->freq ? pssj->freq : 0x400)));
|
||||
}
|
||||
|
||||
static void pssj_get_buffer(int32_t *buffer, int len, void *p)
|
||||
@@ -192,7 +196,7 @@ void *pssj_init(const device_t *info)
|
||||
sn76489_init(&pssj->sn76489, 0x00c0, 0x0004, PSSJ, 3579545);
|
||||
|
||||
io_sethandler(0x00C4, 0x0004, pssj_read, NULL, NULL, pssj_write, NULL, NULL, pssj);
|
||||
timer_add(pssj_callback, &pssj->timer_count, &pssj->enable, pssj);
|
||||
timer_add(&pssj->timer_count, pssj_callback, pssj, pssj->enable);
|
||||
sound_add_handler(pssj_get_buffer, pssj);
|
||||
|
||||
return pssj;
|
||||
|
||||
@@ -26,6 +26,7 @@
|
||||
#define HAVE_STDARG_H
|
||||
#include "../86box.h"
|
||||
#include "../io.h"
|
||||
#include "../timer.h"
|
||||
#include "../mca.h"
|
||||
#include "../mem.h"
|
||||
#include "../rom.h"
|
||||
@@ -518,8 +519,8 @@ void sb_ct1335_mixer_write(uint16_t addr, uint8_t val, void *p)
|
||||
mixer->cd = sb_att_4dbstep_3bits[(mixer->regs[0x08] >> 1)&0x7];
|
||||
mixer->voice = sb_att_7dbstep_2bits[(mixer->regs[0x0A] >> 1)&0x3];
|
||||
|
||||
sound_set_cd_volume(((uint32_t)mixer->master * (uint32_t)mixer->cd * 4) / 65535,
|
||||
((uint32_t)mixer->master * (uint32_t)mixer->cd * 4) / 65535);
|
||||
sound_set_cd_volume(((uint32_t)mixer->master * (uint32_t)mixer->cd) / 65535,
|
||||
((uint32_t)mixer->master * (uint32_t)mixer->cd) / 65535);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -639,8 +640,8 @@ void sb_ct1345_mixer_write(uint16_t addr, uint8_t val, void *p)
|
||||
}
|
||||
|
||||
/* TODO: pcspeaker volume? Or is it not worth? */
|
||||
sound_set_cd_volume(((uint32_t)mixer->master_l * (uint32_t)mixer->cd_l * 4) / 65535,
|
||||
((uint32_t)mixer->master_r * (uint32_t)mixer->cd_r * 4) / 65535);
|
||||
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);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -805,8 +806,8 @@ void sb_ct1745_mixer_write(uint16_t addr, uint8_t val, void *p)
|
||||
mixer->treble_r = mixer->regs[0x45] >> 4;
|
||||
|
||||
/*TODO: pcspeaker volume, with "output_selector" check? or better not? */
|
||||
sound_set_cd_volume(((uint32_t)mixer->master_l * (uint32_t)mixer->cd_l * 4) / 65535,
|
||||
((uint32_t)mixer->master_r * (uint32_t)mixer->cd_r * 4) / 65535);
|
||||
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);
|
||||
sb_log("sb_ct1745: Received register WRITE: %02X\t%02X\n", mixer->index, mixer->regs[mixer->index]);
|
||||
}
|
||||
}
|
||||
@@ -963,6 +964,14 @@ void sb_mcv_write(int port, uint8_t val, void *p)
|
||||
}
|
||||
}
|
||||
|
||||
uint8_t sb_mcv_feedb(void *p)
|
||||
{
|
||||
sb_t *sb = (sb_t *)p;
|
||||
|
||||
return (sb->pos_regs[2] & 1);
|
||||
}
|
||||
|
||||
|
||||
static int sb_pro_mcv_irqs[4] = {7, 5, 3, 3};
|
||||
|
||||
uint8_t sb_pro_mcv_read(int port, void *p)
|
||||
@@ -1079,7 +1088,7 @@ void *sb_mcv_init()
|
||||
sb_dsp_setdma8(&sb->dsp, device_get_config_int("dma"));
|
||||
sound_add_handler(sb_get_buffer_sb2, sb);
|
||||
/* I/O handlers activated in sb_mcv_write */
|
||||
mca_add(sb_mcv_read, sb_mcv_write, sb);
|
||||
mca_add(sb_mcv_read, sb_mcv_write, sb_mcv_feedb, sb);
|
||||
sb->pos_regs[0] = 0x84;
|
||||
sb->pos_regs[1] = 0x50;
|
||||
return sb;
|
||||
@@ -1215,7 +1224,7 @@ void *sb_pro_mcv_init()
|
||||
sound_add_handler(sb_get_buffer_sbpro, sb);
|
||||
|
||||
/* I/O handlers activated in sb_pro_mcv_write */
|
||||
mca_add(sb_pro_mcv_read, sb_pro_mcv_write, sb);
|
||||
mca_add(sb_pro_mcv_read, sb_pro_mcv_write, sb_mcv_feedb, sb);
|
||||
sb->pos_regs[0] = 0x03;
|
||||
sb->pos_regs[1] = 0x51;
|
||||
|
||||
|
||||
@@ -182,7 +182,9 @@ void sb_irqc(sb_dsp_t *dsp, int irq8)
|
||||
|
||||
void sb_dsp_reset(sb_dsp_t *dsp)
|
||||
{
|
||||
dsp->sbenable = dsp->sb_enable_i = 0;
|
||||
timer_disable(&dsp->output_timer);
|
||||
timer_disable(&dsp->input_timer);
|
||||
|
||||
dsp->sb_command = 0;
|
||||
|
||||
dsp->sb_8_length = 0xffff;
|
||||
@@ -199,7 +201,6 @@ void sb_dsp_reset(sb_dsp_t *dsp)
|
||||
dsp->sbe2count = 0;
|
||||
|
||||
dsp->sbreset = 0;
|
||||
dsp->sbenable = dsp->sb_enable_i = dsp->sb_count_i = 0;
|
||||
|
||||
dsp->record_pos_read=0;
|
||||
dsp->record_pos_write=SB_DSP_REC_SAFEFTY_MARGIN;
|
||||
@@ -226,15 +227,15 @@ void sb_doreset(sb_dsp_t *dsp)
|
||||
|
||||
void sb_dsp_speed_changed(sb_dsp_t *dsp)
|
||||
{
|
||||
if (dsp->sb_timeo < 256LL)
|
||||
dsp->sblatcho = TIMER_USEC * (256LL - dsp->sb_timeo);
|
||||
if (dsp->sb_timeo < 256)
|
||||
dsp->sblatcho = TIMER_USEC * (256 - dsp->sb_timeo);
|
||||
else
|
||||
dsp->sblatcho = (int)(TIMER_USEC * (1000000.0f / (float)(dsp->sb_timeo - 256LL)));
|
||||
dsp->sblatcho = (uint64_t)(TIMER_USEC * (1000000.0f / (float)(dsp->sb_timeo - 256)));
|
||||
|
||||
if (dsp->sb_timei < 256LL)
|
||||
dsp->sblatchi = TIMER_USEC * (256LL - dsp->sb_timei);
|
||||
if (dsp->sb_timei < 256)
|
||||
dsp->sblatchi = TIMER_USEC * (256 - dsp->sb_timei);
|
||||
else
|
||||
dsp->sblatchi = (int)(TIMER_USEC * (1000000.0f / (float)(dsp->sb_timei - 256LL)));
|
||||
dsp->sblatchi = (uint64_t)(TIMER_USEC * (1000000.0f / (float)(dsp->sb_timei - 256)));
|
||||
}
|
||||
|
||||
void sb_add_data(sb_dsp_t *dsp, uint8_t v)
|
||||
@@ -249,7 +250,7 @@ void sb_add_data(sb_dsp_t *dsp, uint8_t v)
|
||||
|
||||
void sb_start_dma(sb_dsp_t *dsp, int dma8, int autoinit, uint8_t format, int len)
|
||||
{
|
||||
dsp->sb_pausetime = -1LL;
|
||||
dsp->sb_pausetime = -1;
|
||||
if (dma8)
|
||||
{
|
||||
dsp->sb_8_length = len;
|
||||
@@ -259,9 +260,8 @@ void sb_start_dma(sb_dsp_t *dsp, int dma8, int autoinit, uint8_t format, int len
|
||||
dsp->sb_8_enable = 1;
|
||||
if (dsp->sb_16_enable && dsp->sb_16_output) dsp->sb_16_enable = 0;
|
||||
dsp->sb_8_output = 1;
|
||||
timer_process();
|
||||
dsp->sbenable = dsp->sb_8_enable;
|
||||
timer_update_outstanding();
|
||||
if (!timer_is_enabled(&dsp->output_timer))
|
||||
timer_set_delay_u64(&dsp->output_timer, dsp->sblatcho);
|
||||
dsp->sbleftright = 0;
|
||||
dsp->sbdacpos = 0;
|
||||
}
|
||||
@@ -274,9 +274,8 @@ void sb_start_dma(sb_dsp_t *dsp, int dma8, int autoinit, uint8_t format, int len
|
||||
dsp->sb_16_enable = 1;
|
||||
if (dsp->sb_8_enable && dsp->sb_8_output) dsp->sb_8_enable = 0;
|
||||
dsp->sb_16_output = 1;
|
||||
timer_process();
|
||||
dsp->sbenable = dsp->sb_16_enable;
|
||||
timer_update_outstanding();
|
||||
if (!timer_is_enabled(&dsp->output_timer))
|
||||
timer_set_delay_u64(&dsp->output_timer, dsp->sblatcho);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -291,9 +290,8 @@ void sb_start_dma_i(sb_dsp_t *dsp, int dma8, int autoinit, uint8_t format, int l
|
||||
dsp->sb_8_enable = 1;
|
||||
if (dsp->sb_16_enable && !dsp->sb_16_output) dsp->sb_16_enable = 0;
|
||||
dsp->sb_8_output = 0;
|
||||
timer_process();
|
||||
dsp->sb_enable_i = dsp->sb_8_enable;
|
||||
timer_update_outstanding();
|
||||
if (!timer_is_enabled(&dsp->input_timer))
|
||||
timer_set_delay_u64(&dsp->input_timer, dsp->sblatchi);
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -304,9 +302,8 @@ void sb_start_dma_i(sb_dsp_t *dsp, int dma8, int autoinit, uint8_t format, int l
|
||||
dsp->sb_16_enable = 1;
|
||||
if (dsp->sb_8_enable && !dsp->sb_8_output) dsp->sb_8_enable = 0;
|
||||
dsp->sb_16_output = 0;
|
||||
timer_process();
|
||||
dsp->sb_enable_i = dsp->sb_16_enable;
|
||||
timer_update_outstanding();
|
||||
if (!timer_is_enabled(&dsp->input_timer))
|
||||
timer_set_delay_u64(&dsp->input_timer, dsp->sblatchi);
|
||||
}
|
||||
memset(dsp->record_buffer,0,sizeof(dsp->record_buffer));
|
||||
}
|
||||
@@ -387,15 +384,13 @@ void sb_exec_command(sb_dsp_t *dsp)
|
||||
sb_add_data(dsp, (dsp->record_buffer[dsp->record_pos_read]>>8) ^0x80);
|
||||
/*Due to the current implementation, I need to emulate a samplerate, even if this
|
||||
* mode does not imply such samplerate. Position is increased in sb_poll_i*/
|
||||
if (dsp->sb_enable_i==0)
|
||||
if (!timer_is_enabled(&dsp->input_timer))
|
||||
{
|
||||
dsp->sb_timei = 256LL - 22LL;
|
||||
dsp->sblatchi = TIMER_USEC * 22LL;
|
||||
dsp->sb_timei = 256 - 22;
|
||||
dsp->sblatchi = TIMER_USEC * 22;
|
||||
temp = 1000000 / 22;
|
||||
dsp->sb_freq = temp;
|
||||
timer_process();
|
||||
dsp->sb_enable_i = 1;
|
||||
timer_update_outstanding();
|
||||
timer_set_delay_u64(&dsp->input_timer, dsp->sblatchi);
|
||||
}
|
||||
break;
|
||||
case 0x24: /*8-bit single cycle DMA input*/
|
||||
@@ -435,7 +430,7 @@ void sb_exec_command(sb_dsp_t *dsp)
|
||||
case 0x41: /*Set output sampling rate*/
|
||||
case 0x42: /*Set input sampling rate*/
|
||||
if (dsp->sb_type < SB16) break;
|
||||
dsp->sblatcho = (int)(TIMER_USEC * (1000000.0f / (float)(dsp->sb_data[1] + (dsp->sb_data[0] << 8))));
|
||||
dsp->sblatcho = (uint64_t)(TIMER_USEC * (1000000.0f / (float)(dsp->sb_data[1] + (dsp->sb_data[0] << 8))));
|
||||
sb_dsp_log("Sample rate - %ihz (%i)\n",dsp->sb_data[1]+(dsp->sb_data[0]<<8), dsp->sblatcho);
|
||||
temp = dsp->sb_freq;
|
||||
dsp->sb_freq = dsp->sb_data[1] + (dsp->sb_data[0] << 8);
|
||||
@@ -482,9 +477,8 @@ void sb_exec_command(sb_dsp_t *dsp)
|
||||
break;
|
||||
case 0x80: /*Pause DAC*/
|
||||
dsp->sb_pausetime = dsp->sb_data[0] + (dsp->sb_data[1] << 8);
|
||||
timer_process();
|
||||
dsp->sbenable = 1;
|
||||
timer_update_outstanding();
|
||||
if (!timer_is_enabled(&dsp->output_timer))
|
||||
timer_set_delay_u64(&dsp->output_timer, dsp->sblatcho);
|
||||
break;
|
||||
case 0x90: /*High speed 8-bit autoinit DMA output*/
|
||||
if (dsp->sb_type < SB2) break;
|
||||
@@ -673,10 +667,7 @@ void sb_write(uint16_t a, uint8_t v, void *priv)
|
||||
dsp->onebyte_midi = 0;
|
||||
return;
|
||||
}
|
||||
timer_process();
|
||||
dsp->wb_time = TIMER_USEC * 1LL;
|
||||
dsp->wb_full = 1LL;
|
||||
timer_update_outstanding();
|
||||
timer_set_delay_u64(&dsp->wb_timer, TIMER_USEC * 1);
|
||||
if (dsp->asp_data_len)
|
||||
{
|
||||
sb_dsp_log("ASP data %i\n", dsp->asp_data_len);
|
||||
@@ -727,7 +718,7 @@ uint8_t sb_read(uint16_t a, void *priv)
|
||||
dsp->busy_count = 0;
|
||||
if (dsp->wb_full || (dsp->busy_count & 2))
|
||||
{
|
||||
dsp->wb_full = dsp->wb_time;
|
||||
dsp->wb_full = timer_is_enabled(&dsp->wb_timer);
|
||||
return 0xff;
|
||||
}
|
||||
return 0x7f;
|
||||
@@ -745,9 +736,6 @@ uint8_t sb_read(uint16_t a, void *priv)
|
||||
|
||||
static void sb_wb_clear(void *p)
|
||||
{
|
||||
sb_dsp_t *dsp = (sb_dsp_t *)p;
|
||||
|
||||
dsp->wb_time = 0LL;
|
||||
}
|
||||
|
||||
void sb_dsp_set_mpu(mpu_t *src_mpu)
|
||||
@@ -763,13 +751,13 @@ void sb_dsp_init(sb_dsp_t *dsp, int type)
|
||||
dsp->sb_irqnum = 7;
|
||||
dsp->sb_8_dmanum = 1;
|
||||
dsp->sb_16_dmanum = 5;
|
||||
mpu = NULL;
|
||||
mpu = NULL;
|
||||
|
||||
sb_doreset(dsp);
|
||||
|
||||
timer_add(pollsb, &dsp->sbcount, &dsp->sbenable, dsp);
|
||||
timer_add(sb_poll_i, &dsp->sb_count_i, &dsp->sb_enable_i, dsp);
|
||||
timer_add(sb_wb_clear, &dsp->wb_time, &dsp->wb_time, dsp);
|
||||
timer_add(&dsp->output_timer, pollsb, dsp, 0);
|
||||
timer_add(&dsp->input_timer, sb_poll_i, dsp, 0);
|
||||
timer_add(&dsp->wb_timer, sb_wb_clear, dsp, 0);
|
||||
|
||||
/*Initialise SB16 filter to same cutoff as 8-bit SBs (3.2 kHz). This will be recalculated when
|
||||
a set frequency command is sent.*/
|
||||
@@ -800,7 +788,7 @@ void pollsb(void *p)
|
||||
sb_dsp_t *dsp = (sb_dsp_t *)p;
|
||||
int tempi,ref;
|
||||
|
||||
dsp->sbcount += dsp->sblatcho;
|
||||
timer_advance_u64(&dsp->output_timer, dsp->sblatcho);
|
||||
if (dsp->sb_8_enable && !dsp->sb_8_pause && dsp->sb_pausetime < 0 && dsp->sb_8_output)
|
||||
{
|
||||
int data[2];
|
||||
@@ -962,8 +950,12 @@ void pollsb(void *p)
|
||||
|
||||
if (dsp->sb_8_length < 0)
|
||||
{
|
||||
if (dsp->sb_8_autoinit) dsp->sb_8_length = dsp->sb_8_autolen;
|
||||
else dsp->sb_8_enable = dsp->sbenable=0;
|
||||
if (dsp->sb_8_autoinit)
|
||||
dsp->sb_8_length = dsp->sb_8_autolen;
|
||||
else {
|
||||
dsp->sb_8_enable = 0;
|
||||
timer_disable(&dsp->output_timer);
|
||||
}
|
||||
sb_irq(dsp, 1);
|
||||
}
|
||||
}
|
||||
@@ -1013,17 +1005,21 @@ void pollsb(void *p)
|
||||
{
|
||||
sb_dsp_log("16DMA over %i\n",dsp->sb_16_autoinit);
|
||||
if (dsp->sb_16_autoinit) dsp->sb_16_length = dsp->sb_16_autolen;
|
||||
else dsp->sb_16_enable = dsp->sbenable = 0;
|
||||
else {
|
||||
dsp->sb_16_enable = 0;
|
||||
timer_disable(&dsp->output_timer);
|
||||
}
|
||||
sb_irq(dsp, 0);
|
||||
}
|
||||
}
|
||||
if (dsp->sb_pausetime > -1LL)
|
||||
if (dsp->sb_pausetime > -1)
|
||||
{
|
||||
dsp->sb_pausetime--;
|
||||
if (dsp->sb_pausetime < 0LL)
|
||||
if (dsp->sb_pausetime < 0)
|
||||
{
|
||||
sb_irq(dsp, 1);
|
||||
dsp->sbenable = dsp->sb_8_enable;
|
||||
if (!dsp->sb_8_enable)
|
||||
timer_disable(&dsp->output_timer);
|
||||
sb_dsp_log("SB pause over\n");
|
||||
}
|
||||
}
|
||||
@@ -1033,7 +1029,7 @@ void sb_poll_i(void *p)
|
||||
{
|
||||
sb_dsp_t *dsp = (sb_dsp_t *)p;
|
||||
int processed=0;
|
||||
dsp->sb_count_i += dsp->sblatchi;
|
||||
timer_advance_u64(&dsp->input_timer, dsp->sblatchi);
|
||||
if (dsp->sb_8_enable && !dsp->sb_8_pause && dsp->sb_pausetime < 0 && !dsp->sb_8_output)
|
||||
{
|
||||
switch (dsp->sb_8_format)
|
||||
@@ -1068,8 +1064,12 @@ void sb_poll_i(void *p)
|
||||
|
||||
if (dsp->sb_8_length < 0)
|
||||
{
|
||||
if (dsp->sb_8_autoinit) dsp->sb_8_length = dsp->sb_8_autolen;
|
||||
else dsp->sb_8_enable = dsp->sb_enable_i = 0;
|
||||
if (dsp->sb_8_autoinit)
|
||||
dsp->sb_8_length = dsp->sb_8_autolen;
|
||||
else {
|
||||
dsp->sb_8_enable = 0;
|
||||
timer_disable(&dsp->input_timer);
|
||||
}
|
||||
sb_irq(dsp, 1);
|
||||
}
|
||||
processed=1;
|
||||
@@ -1112,8 +1112,12 @@ void sb_poll_i(void *p)
|
||||
|
||||
if (dsp->sb_16_length < 0)
|
||||
{
|
||||
if (dsp->sb_16_autoinit) dsp->sb_16_length = dsp->sb_16_autolen;
|
||||
else dsp->sb_16_enable = dsp->sb_enable_i = 0;
|
||||
if (dsp->sb_16_autoinit)
|
||||
dsp->sb_16_length = dsp->sb_16_autolen;
|
||||
else {
|
||||
dsp->sb_16_enable = 0;
|
||||
timer_disable(&dsp->input_timer);
|
||||
}
|
||||
sb_irq(dsp, 0);
|
||||
}
|
||||
processed=1;
|
||||
|
||||
@@ -6,7 +6,7 @@ typedef struct sb_dsp_t
|
||||
int sb_8_dmanum;
|
||||
int sb_16_length, sb_16_format, sb_16_autoinit, sb_16_pause, sb_16_enable, sb_16_autolen, sb_16_output;
|
||||
int sb_16_dmanum;
|
||||
int64_t sb_pausetime;
|
||||
int sb_pausetime;
|
||||
|
||||
uint8_t sb_read_data[256];
|
||||
int sb_read_wp, sb_read_rp;
|
||||
@@ -42,17 +42,17 @@ typedef struct sb_dsp_t
|
||||
uint8_t sbreaddat;
|
||||
uint8_t sb_command;
|
||||
uint8_t sb_test;
|
||||
int64_t sb_timei, sb_timeo;
|
||||
int sb_timei, sb_timeo;
|
||||
|
||||
int sb_irq8, sb_irq16;
|
||||
|
||||
uint8_t sb_asp_regs[256];
|
||||
|
||||
int64_t sbenable, sb_enable_i;
|
||||
int sbenable, sb_enable_i;
|
||||
|
||||
int64_t sbcount, sb_count_i;
|
||||
pc_timer_t output_timer, input_timer;
|
||||
|
||||
int64_t sblatcho, sblatchi;
|
||||
uint64_t sblatcho, sblatchi;
|
||||
|
||||
uint16_t sb_addr;
|
||||
|
||||
@@ -60,7 +60,8 @@ typedef struct sb_dsp_t
|
||||
|
||||
int asp_data_len;
|
||||
|
||||
int64_t wb_time, wb_full;
|
||||
pc_timer_t wb_timer;
|
||||
int wb_full;
|
||||
|
||||
int busy_count;
|
||||
|
||||
|
||||
@@ -3,6 +3,7 @@
|
||||
#include <string.h>
|
||||
#include <wchar.h>
|
||||
#include "../86box.h"
|
||||
#include "../timer.h"
|
||||
#include "../pit.h"
|
||||
#include "sound.h"
|
||||
#include "snd_speaker.h"
|
||||
@@ -45,16 +46,19 @@ speaker_update(void)
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
void
|
||||
speaker_get_buffer(int32_t *buffer, int len, void *p)
|
||||
{
|
||||
int c;
|
||||
int32_t c, val;
|
||||
|
||||
speaker_update();
|
||||
|
||||
if (!speaker_mute) {
|
||||
for (c = 0; c < len * 2; c++)
|
||||
buffer[c] += speaker_buffer[c >> 1];
|
||||
for (c = 0; c < len * 2; c += 2) {
|
||||
val = speaker_buffer[c >> 1];
|
||||
buffer[c] += val;
|
||||
buffer[c + 1] += val;
|
||||
}
|
||||
}
|
||||
|
||||
speaker_pos = 0;
|
||||
|
||||
@@ -24,6 +24,7 @@
|
||||
#include <math.h>
|
||||
#include "../86box.h"
|
||||
#include "../io.h"
|
||||
#include "../timer.h"
|
||||
#include "../mca.h"
|
||||
#include "../pic.h"
|
||||
#include "../dma.h"
|
||||
@@ -150,11 +151,18 @@ static void ncr_audio_mca_write(int port, uint8_t val, void *p)
|
||||
if (wss->opl_enabled)
|
||||
io_sethandler(0x0388, 0x0004, opl3_read, NULL, NULL, opl3_write, NULL, NULL, &wss->opl);
|
||||
|
||||
io_sethandler(addr, 0x0004, wss_read, NULL, NULL, wss_write, NULL, NULL, wss);
|
||||
io_sethandler(addr+4, 0x0004, ad1848_read, NULL, NULL, ad1848_write, NULL, NULL, &wss->ad1848);
|
||||
io_sethandler(addr, 0x0004, wss_read, NULL, NULL, wss_write, NULL, NULL, wss);
|
||||
io_sethandler(addr+4, 0x0004, ad1848_read, NULL, NULL, ad1848_write, NULL, NULL, &wss->ad1848);
|
||||
}
|
||||
}
|
||||
|
||||
static uint8_t ncr_audio_mca_feedb(void *p)
|
||||
{
|
||||
wss_t *wss = (wss_t *)p;
|
||||
|
||||
return (wss->pos_regs[2] & 1);
|
||||
}
|
||||
|
||||
void *ncr_audio_init(const device_t *info)
|
||||
{
|
||||
wss_t *wss = malloc(sizeof(wss_t));
|
||||
@@ -164,14 +172,14 @@ void *ncr_audio_init(const device_t *info)
|
||||
opl3_init(&wss->opl);
|
||||
ad1848_init(&wss->ad1848);
|
||||
|
||||
ad1848_setirq(&wss->ad1848, 7);
|
||||
ad1848_setdma(&wss->ad1848, 3);
|
||||
ad1848_setirq(&wss->ad1848, 7);
|
||||
ad1848_setdma(&wss->ad1848, 3);
|
||||
|
||||
mca_add(ncr_audio_mca_read, ncr_audio_mca_write, wss);
|
||||
mca_add(ncr_audio_mca_read, ncr_audio_mca_write, ncr_audio_mca_feedb, wss);
|
||||
wss->pos_regs[0] = 0x16;
|
||||
wss->pos_regs[1] = 0x51;
|
||||
|
||||
sound_add_handler(wss_get_buffer, wss);
|
||||
sound_add_handler(wss_get_buffer, wss);
|
||||
|
||||
return wss;
|
||||
}
|
||||
|
||||
@@ -74,7 +74,8 @@ static int32_t *outbuffer;
|
||||
static float *outbuffer_ex;
|
||||
static int16_t *outbuffer_ex_int16;
|
||||
static int sound_handlers_num;
|
||||
static int64_t sound_poll_time = 0LL, sound_poll_latch;
|
||||
static pc_timer_t sound_poll_timer;
|
||||
static uint64_t sound_poll_latch;
|
||||
|
||||
static int16_t cd_buffer[CDROM_NUM][CD_BUFLEN * 2];
|
||||
static float cd_out_buffer[CD_BUFLEN * 2];
|
||||
@@ -261,6 +262,7 @@ sound_cd_thread(void *param)
|
||||
/*Apply ATAPI channel select*/
|
||||
cd_buffer_temp[0] = cd_buffer_temp[1] = 0.0;
|
||||
|
||||
#if 0
|
||||
if (channel_select[0] & 1)
|
||||
cd_buffer_temp[0] += ((float) cd_buffer[i][c]) * audio_vol_l;
|
||||
if (channel_select[0] & 2)
|
||||
@@ -269,6 +271,25 @@ sound_cd_thread(void *param)
|
||||
cd_buffer_temp[0] += ((float) cd_buffer[i][c + 1]) * audio_vol_r;
|
||||
if (channel_select[1] & 2)
|
||||
cd_buffer_temp[1] += ((float) cd_buffer[i][c + 1]) * audio_vol_r;
|
||||
#else
|
||||
if ((audio_vol_l != 0.0) && (channel_select[0] != 0)) {
|
||||
if (channel_select[0] & 1)
|
||||
cd_buffer_temp[0] += ((float) cd_buffer[i][c]); /* Channel 0 => Port 0 */
|
||||
if (channel_select[0] & 2)
|
||||
cd_buffer_temp[0] += ((float) cd_buffer[i][c + 1]); /* Channel 1 => Port 0 */
|
||||
|
||||
cd_buffer_temp[0] *= audio_vol_l; /* Multiply Port 0 by Port 0 volume */
|
||||
}
|
||||
|
||||
if ((audio_vol_r != 0.0) && (channel_select[1] != 0)) {
|
||||
if (channel_select[1] & 1)
|
||||
cd_buffer_temp[1] += ((float) cd_buffer[i][c]); /* Channel 0 => Port 1 */
|
||||
if (channel_select[1] & 2)
|
||||
cd_buffer_temp[1] += ((float) cd_buffer[i][c + 1]); /* Channel 1 => Port 1 */
|
||||
|
||||
cd_buffer_temp[1] *= audio_vol_r; /* Multiply Port 1 by Port 1 volume */
|
||||
}
|
||||
#endif
|
||||
|
||||
/*Apply sound card CD volume*/
|
||||
cd_buffer_temp[0] *= ((float) cd_vol_l) / 65535.0;
|
||||
@@ -364,7 +385,7 @@ sound_add_handler(void (*get_buffer)(int32_t *buffer, int len, void *p), void *p
|
||||
void
|
||||
sound_poll(void *priv)
|
||||
{
|
||||
sound_poll_time += sound_poll_latch;
|
||||
timer_advance_u64(&sound_poll_timer, sound_poll_latch);
|
||||
|
||||
midi_poll();
|
||||
|
||||
@@ -411,7 +432,7 @@ sound_poll(void *priv)
|
||||
void
|
||||
sound_speed_changed(void)
|
||||
{
|
||||
sound_poll_latch = (int64_t)((double)TIMER_USEC * (1000000.0 / 48000.0));
|
||||
sound_poll_latch = (uint64_t)((double)TIMER_USEC * (1000000.0 / 48000.0));
|
||||
}
|
||||
|
||||
|
||||
@@ -423,7 +444,7 @@ sound_reset(void)
|
||||
midi_device_init();
|
||||
inital();
|
||||
|
||||
timer_add(sound_poll, &sound_poll_time, TIMER_ALWAYS_ENABLED, NULL);
|
||||
timer_add(&sound_poll_timer, sound_poll, NULL, 1);
|
||||
|
||||
sound_handlers_num = 0;
|
||||
|
||||
@@ -499,6 +520,4 @@ sound_cd_thread_reset(void)
|
||||
sound_cd_thread_end();
|
||||
|
||||
cd_thread_enable = available_cdrom_drives ? 1 : 0;
|
||||
|
||||
secondary_ide_check();
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user