Formatting updates in src/sound + related includes

This commit is contained in:
Jasmine Iwanek
2022-02-22 20:28:56 -05:00
parent 6e8d4356df
commit f7084993c3
53 changed files with 17085 additions and 17827 deletions

18
.clang-format Normal file
View File

@@ -0,0 +1,18 @@
BasedOnStyle: WebKit
AlignAfterOpenBracket: Align
AlignArrayOfStructures: Left
AlignConsecutiveMacros: AcrossEmptyLines
AlignConsecutiveAssignments: Consecutive
AlignConsecutiveBitFields: AcrossEmptyLines
AlignConsecutiveDeclarations: Consecutive
AlignEscapedNewlines: Left
AlignTrailingComments: true
AlwaysBreakAfterReturnType: TopLevelDefinitions
BreakBeforeTernaryOperators: true
IndentCaseLabels: true
IndentCaseBlocks: true
IndentGotoLabels: false
IndentPPDirectives: AfterHash
IndentExternBlock: NoIndent
PointerAlignment: Right
SpaceAfterCStyleCast: true

View File

@@ -1,21 +1,21 @@
[*]
charset = utf-8
end_of_line = lf
indent_style = tab
indent_size = 8
tab_width = 8
indent_style = space
indent_size = 4
tab_width = 4
# Disabled for now since not all editors support setting a tab_width value different from indent_size
# Relevant VSCode extension issue: https://github.com/editorconfig/editorconfig-vscode/issues/190
# [*.rc]
# indent_style = space
# indent_size = 4
# tab_width = 8
# tab_width = 4
# [Makefile.*]
# indent_style = space
# indent_size = 4
# tab_width = 8
# tab_width = 4
[*.manifest]
indent_style = space

View File

@@ -1,6 +1,5 @@
#ifndef EMU_SOUND_MIDI_H
# define EMU_SOUND_MIDI_H
#define EMU_SOUND_MIDI_H
#define SYSEX_SIZE 8192
@@ -14,34 +13,31 @@ extern void (*input_msg)(void *p, uint8_t *msg, uint32_t len);
extern int (*input_sysex)(void *p, uint8_t *buf, uint32_t len, int abort);
extern void *midi_in_p;
extern int midi_device_available(int card);
extern int midi_in_device_available(int card);
extern int midi_device_available(int card);
extern int midi_in_device_available(int card);
#ifdef EMU_DEVICE_H
const device_t *midi_device_getdevice(int card);
const device_t *midi_in_device_getdevice(int card);
#endif
extern int midi_device_has_config(int card);
extern int midi_in_device_has_config(int card);
extern char * midi_device_get_internal_name(int card);
extern char * midi_in_device_get_internal_name(int card);
extern int midi_device_get_from_internal_name(char *s);
extern int midi_in_device_get_from_internal_name(char *s);
extern void midi_device_init();
extern void midi_in_device_init();
extern int midi_device_has_config(int card);
extern int midi_in_device_has_config(int card);
extern char *midi_device_get_internal_name(int card);
extern char *midi_in_device_get_internal_name(int card);
extern int midi_device_get_from_internal_name(char *s);
extern int midi_in_device_get_from_internal_name(char *s);
extern void midi_device_init();
extern void midi_in_device_init();
typedef struct midi_device_t
{
typedef struct midi_device_t {
void (*play_sysex)(uint8_t *sysex, unsigned int len);
void (*play_msg)(uint8_t *msg);
void (*poll)();
int (*write)(uint8_t val);
} midi_device_t;
typedef struct midi_in_handler_t
{
typedef struct midi_in_handler_t {
uint8_t *buf;
int cnt;
int cnt;
uint32_t len;
void (*msg)(void *p, uint8_t *msg, uint32_t len);
@@ -50,60 +46,59 @@ typedef struct midi_in_handler_t
struct midi_in_handler_t *prev, *next;
} midi_in_handler_t;
typedef struct midi_t
{
typedef struct midi_t {
uint8_t midi_rt_buf[8], midi_cmd_buf[8],
midi_status, midi_sysex_data[SYSEX_SIZE];
midi_status, midi_sysex_data[SYSEX_SIZE];
int midi_cmd_pos, midi_cmd_len, midi_cmd_r,
midi_realtime, thruchan, midi_clockout;
midi_realtime, thruchan, midi_clockout;
unsigned int midi_sysex_start, midi_sysex_delay,
midi_pos;
midi_device_t *m_out_device, *m_in_device;
midi_pos;
midi_device_t *m_out_device, *m_in_device;
} midi_t;
extern midi_t *midi, *midi_in;
extern void midi_init(midi_device_t* device);
extern void midi_in_init(midi_device_t* device, midi_t **mididev);
extern void midi_close();
extern void midi_in_close(void);
extern void midi_raw_out_rt_byte(uint8_t val);
extern void midi_raw_out_thru_rt_byte(uint8_t val);
extern void midi_raw_out_byte(uint8_t val);
extern void midi_clear_buffer(void);
extern void midi_poll();
extern void midi_init(midi_device_t *device);
extern void midi_in_init(midi_device_t *device, midi_t **mididev);
extern void midi_close();
extern void midi_in_close(void);
extern void midi_raw_out_rt_byte(uint8_t val);
extern void midi_raw_out_thru_rt_byte(uint8_t val);
extern void midi_raw_out_byte(uint8_t val);
extern void midi_clear_buffer(void);
extern void midi_poll();
extern void midi_in_handler(int set, void (*msg)(void *p, uint8_t *msg, uint32_t len), int (*sysex)(void *p, uint8_t *buffer, uint32_t len, int abort), void *p);
extern void midi_in_handlers_clear(void);
extern void midi_in_msg(uint8_t *msg, uint32_t len);
extern void midi_in_sysex(uint8_t *buffer, uint32_t len);
extern void midi_in_handler(int set, void (*msg)(void *p, uint8_t *msg, uint32_t len), int (*sysex)(void *p, uint8_t *buffer, uint32_t len, int abort), void *p);
extern void midi_in_handlers_clear(void);
extern void midi_in_msg(uint8_t *msg, uint32_t len);
extern void midi_in_sysex(uint8_t *buffer, uint32_t len);
#if 0
#ifdef _WIN32
#define SYSTEM_MIDI_NAME "Windows MIDI"
#define SYSTEM_MIDI_INTERNAL_NAME "windows_midi"
# ifdef _WIN32
# define SYSTEM_MIDI_NAME "Windows MIDI"
# define SYSTEM_MIDI_INTERNAL_NAME "windows_midi"
# else
# define SYSTEM_MIDI_NAME "System MIDI"
# define SYSTEM_MIDI_INTERNAL_NAME "system_midi"
# endif
#else
#define SYSTEM_MIDI_NAME "System MIDI"
#define SYSTEM_MIDI_INTERNAL_NAME "system_midi"
#endif
#else
#define SYSTEM_MIDI_NAME "System MIDI"
#define SYSTEM_MIDI_INTERNAL_NAME "system_midi"
# define SYSTEM_MIDI_NAME "System MIDI"
# define SYSTEM_MIDI_INTERNAL_NAME "system_midi"
#endif
#define MIDI_INPUT_NAME "MIDI Input Device"
#define MIDI_INPUT_NAME "MIDI Input Device"
#define MIDI_INPUT_INTERNAL_NAME "midi_in"
#ifdef EMU_DEVICE_H
extern const device_t rtmidi_device;
extern const device_t rtmidi_input_device;
#ifdef USE_FLUIDSYNTH
# ifdef USE_FLUIDSYNTH
extern const device_t fluidsynth_device;
#endif
#ifdef USE_MUNT
# endif
# ifdef USE_MUNT
extern const device_t mt32_device;
extern const device_t cm32l_device;
#endif
# endif
#endif
#endif /*EMU_SOUND_MIDI_H*/
#endif /*EMU_SOUND_MIDI_H*/

View File

@@ -1,15 +1,14 @@
#ifndef EMU_SOUND_RTMIDI_H
# define EMU_SOUND_RTMIDI_H
#define EMU_SOUND_RTMIDI_H
#ifdef __cplusplus
extern "C"
{
extern "C" {
#endif
extern int rtmidi_get_num_devs(void);
extern void rtmidi_get_dev_name(int num, char *s);
extern int rtmidi_in_get_num_devs(void);
extern void rtmidi_in_get_dev_name(int num, char *s);
extern int rtmidi_get_num_devs(void);
extern void rtmidi_get_dev_name(int num, char *s);
extern int rtmidi_in_get_num_devs(void);
extern void rtmidi_in_get_dev_name(int num, char *s);
#ifdef __cplusplus
}

View File

@@ -15,82 +15,81 @@
* Copyright 2021 RichardG.
*/
#ifndef SOUND_AC97_H
# define SOUND_AC97_H
#define SOUND_AC97_H
#define AC97_VENDOR_ID(f, s, t, dev) ((((f) & 0xff) << 24) | (((s) & 0xff) << 16) | (((t) & 0xff) << 8) | ((dev) & 0xff))
#define AC97_VENDOR_ID(f, s, t, dev) ((((f) &0xff) << 24) | (((s) &0xff) << 16) | (((t) &0xff) << 8) | ((dev) &0xff))
/* Misc support bits (misc_flags). Most of these are not part of any
registers, but control enabling/disabling of registers and bits. */
#define AC97_MASTER_6B (1 << 0) /* register 02 bits [13,5] (ML5/MR5) */
#define AC97_AUXOUT (1 << 1) /* register 04 */
#define AC97_AUXOUT_6B (1 << 2) /* register 04 bits [13,5] (ML5/MR5) */
#define AC97_MONOOUT (1 << 3) /* register 06 */
#define AC97_MONOOUT_6B (1 << 4) /* register 06 bit 5 (MM5) */
#define AC97_PCBEEP (1 << 5) /* register 0A */
#define AC97_PCBEEP_GEN (1 << 6) /* register 0A bits [12:5] (F[7:0]) */
#define AC97_PHONE (1 << 9) /* register 0C */
#define AC97_VIDEO (1 << 10) /* register 14 */
#define AC97_AUXIN (1 << 11) /* register 16 */
#define AC97_POP (1 << 15) /* register 20 bit 15 (POP) - definition shared with General Purpose bits */
#define AC97_MS (1 << 8) /* register 20 bit 8 (MS) - definition shared with General Purpose bits */
#define AC97_LPBK (1 << 7) /* register 20 bit 7 (LPBK) - definition shared with General Purpose bits */
#define AC97_DSA (1 << 12) /* register 28 bits [5:4] (DSA[1:0]) */
#define AC97_LFE_6B (1 << 13) /* register 36 bit 13 (LFE5) */
#define AC97_CENTER_6B (1 << 14) /* register 36 bit 5 (CNT5) */
#define AC97_SURR_6B (1 << 16) /* register 38 bits [13,5] (LSR5/RSR5) */
#define AC97_MASTER_6B (1 << 0) /* register 02 bits [13,5] (ML5/MR5) */
#define AC97_AUXOUT (1 << 1) /* register 04 */
#define AC97_AUXOUT_6B (1 << 2) /* register 04 bits [13,5] (ML5/MR5) */
#define AC97_MONOOUT (1 << 3) /* register 06 */
#define AC97_MONOOUT_6B (1 << 4) /* register 06 bit 5 (MM5) */
#define AC97_PCBEEP (1 << 5) /* register 0A */
#define AC97_PCBEEP_GEN (1 << 6) /* register 0A bits [12:5] (F[7:0]) */
#define AC97_PHONE (1 << 9) /* register 0C */
#define AC97_VIDEO (1 << 10) /* register 14 */
#define AC97_AUXIN (1 << 11) /* register 16 */
#define AC97_POP (1 << 15) /* register 20 bit 15 (POP) - definition shared with General Purpose bits */
#define AC97_MS (1 << 8) /* register 20 bit 8 (MS) - definition shared with General Purpose bits */
#define AC97_LPBK (1 << 7) /* register 20 bit 7 (LPBK) - definition shared with General Purpose bits */
#define AC97_DSA (1 << 12) /* register 28 bits [5:4] (DSA[1:0]) */
#define AC97_LFE_6B (1 << 13) /* register 36 bit 13 (LFE5) */
#define AC97_CENTER_6B (1 << 14) /* register 36 bit 5 (CNT5) */
#define AC97_SURR_6B (1 << 16) /* register 38 bits [13,5] (LSR5/RSR5) */
/* Reset bits (reset_flags), register 00. */
#define AC97_MICPCM (1 << 0)
#define AC97_MODEMLINE (1 << 1)
#define AC97_TONECTL (1 << 2)
#define AC97_SIMSTEREO (1 << 3)
#define AC97_HPOUT (1 << 4)
#define AC97_LOUDNESS (1 << 5)
#define AC97_DAC_18B (1 << 6)
#define AC97_DAC_20B (1 << 7)
#define AC97_ADC_18B (1 << 8)
#define AC97_ADC_20B (1 << 9)
#define AC97_3D_SHIFT 10
#define AC97_MICPCM (1 << 0)
#define AC97_MODEMLINE (1 << 1)
#define AC97_TONECTL (1 << 2)
#define AC97_SIMSTEREO (1 << 3)
#define AC97_HPOUT (1 << 4)
#define AC97_LOUDNESS (1 << 5)
#define AC97_DAC_18B (1 << 6)
#define AC97_DAC_20B (1 << 7)
#define AC97_ADC_18B (1 << 8)
#define AC97_ADC_20B (1 << 9)
#define AC97_3D_SHIFT 10
/* Extended Audio ID bits (extid_flags), register 28. */
#define AC97_VRA (1 << 0)
#define AC97_DRA (1 << 1)
#define AC97_SPDIF (1 << 2)
#define AC97_VRM (1 << 3)
#define AC97_CDAC (1 << 6)
#define AC97_SDAC (1 << 7)
#define AC97_LDAC (1 << 8)
#define AC97_AMAP (1 << 9)
#define AC97_REV_2_1 (0 << 10)
#define AC97_REV_2_2 (1 << 10)
#define AC97_REV_2_3 (2 << 10)
#define AC97_REV_MASK (3 << 10)
#define AC97_VRA (1 << 0)
#define AC97_DRA (1 << 1)
#define AC97_SPDIF (1 << 2)
#define AC97_VRM (1 << 3)
#define AC97_CDAC (1 << 6)
#define AC97_SDAC (1 << 7)
#define AC97_LDAC (1 << 8)
#define AC97_AMAP (1 << 9)
#define AC97_REV_2_1 (0 << 10)
#define AC97_REV_2_2 (1 << 10)
#define AC97_REV_2_3 (2 << 10)
#define AC97_REV_MASK (3 << 10)
/* Volume bits. */
#define AC97_MUTE (1 << 15)
#define AC97_MUTE_L (1 << 15)
#define AC97_MUTE_R (1 << 7)
#define AC97_MUTE (1 << 15)
#define AC97_MUTE_L (1 << 15)
#define AC97_MUTE_R (1 << 7)
/* General Purpose bits, register 20. */
/* POP already defined */
#define AC97_ST (1 << 14)
#define AC97_3D (1 << 13)
#define AC97_LD (1 << 12)
#define AC97_DRSS_MASK (3 << 10)
#define AC97_MIX (1 << 9)
#define AC97_ST (1 << 14)
#define AC97_3D (1 << 13)
#define AC97_LD (1 << 12)
#define AC97_DRSS_MASK (3 << 10)
#define AC97_MIX (1 << 9)
/* MS already defined */
/* LPBK already defined */
/* Extended Audio Status/Control bits, register 2A. */
#define AC97_SPSA_SHIFT 4
#define AC97_SPSA_MASK 3
#define AC97_MADC (1 << 9)
#define AC97_SPCV (1 << 10)
#define AC97_PRI (1 << 11)
#define AC97_PRJ (1 << 12)
#define AC97_PRK (1 << 13)
#define AC97_PRL (1 << 14)
#define AC97_SPSA_SHIFT 4
#define AC97_SPSA_MASK 3
#define AC97_MADC (1 << 9)
#define AC97_SPCV (1 << 10)
#define AC97_PRI (1 << 11)
#define AC97_PRJ (1 << 12)
#define AC97_PRK (1 << 13)
#define AC97_PRL (1 << 14)
/* New codecs should be added to the end of this enum to avoid breaking configs. */
enum {
@@ -104,52 +103,49 @@ enum {
AC97_CODEC_AK4540
};
typedef struct {
const uint16_t index, value, write_mask;
} ac97_vendor_reg_t;
typedef struct {
uint32_t vendor_id, min_rate, max_rate, misc_flags;
uint16_t reset_flags, extid_flags,
powerdown_mask, regs[64];
uint8_t codec_id, vendor_reg_page_max;
uint32_t vendor_id, min_rate, max_rate, misc_flags;
uint16_t reset_flags, extid_flags,
powerdown_mask, regs[64];
uint8_t codec_id, vendor_reg_page_max;
const ac97_vendor_reg_t *vendor_regs;
uint16_t *vendor_reg_pages;
uint16_t *vendor_reg_pages;
} ac97_codec_t;
extern uint16_t ac97_codec_readw(ac97_codec_t *dev, uint8_t reg);
extern void ac97_codec_writew(ac97_codec_t *dev, uint8_t reg, uint16_t val);
extern void ac97_codec_reset(void *priv);
extern void ac97_codec_getattn(void *priv, uint8_t reg, int *l, int *r);
extern uint32_t ac97_codec_getrate(void *priv, uint8_t reg);
extern uint16_t ac97_codec_readw(ac97_codec_t *dev, uint8_t reg);
extern void ac97_codec_writew(ac97_codec_t *dev, uint8_t reg, uint16_t val);
extern void ac97_codec_reset(void *priv);
extern void ac97_codec_getattn(void *priv, uint8_t reg, int *l, int *r);
extern uint32_t ac97_codec_getrate(void *priv, uint8_t reg);
extern const device_t *ac97_codec_get(int model);
extern void ac97_via_set_slot(void *priv, int slot, int irq_pin);
extern uint8_t ac97_via_read_status(void *priv, uint8_t modem);
extern void ac97_via_write_control(void *priv, uint8_t modem, uint8_t val);
extern void ac97_via_remap_audio_sgd(void *priv, uint16_t new_io_base, uint8_t enable);
extern void ac97_via_remap_modem_sgd(void *priv, uint16_t new_io_base, uint8_t enable);
extern void ac97_via_remap_audio_codec(void *priv, uint16_t new_io_base, uint8_t enable);
extern void ac97_via_remap_modem_codec(void *priv, uint16_t new_io_base, uint8_t enable);
extern void ac97_via_set_slot(void *priv, int slot, int irq_pin);
extern uint8_t ac97_via_read_status(void *priv, uint8_t modem);
extern void ac97_via_write_control(void *priv, uint8_t modem, uint8_t val);
extern void ac97_via_remap_audio_sgd(void *priv, uint16_t new_io_base, uint8_t enable);
extern void ac97_via_remap_modem_sgd(void *priv, uint16_t new_io_base, uint8_t enable);
extern void ac97_via_remap_audio_codec(void *priv, uint16_t new_io_base, uint8_t enable);
extern void ac97_via_remap_modem_codec(void *priv, uint16_t new_io_base, uint8_t enable);
extern ac97_codec_t **ac97_codec, **ac97_modem_codec;
extern int ac97_codec_count, ac97_modem_codec_count,
ac97_codec_id, ac97_modem_codec_id;
extern ac97_codec_t **ac97_codec, **ac97_modem_codec;
extern int ac97_codec_count, ac97_modem_codec_count,
ac97_codec_id, ac97_modem_codec_id;
#ifdef EMU_DEVICE_H
extern const device_t ad1881_device;
extern const device_t ak4540_device;
extern const device_t alc100_device;
extern const device_t cs4297_device;
extern const device_t cs4297a_device;
extern const device_t stac9708_device;
extern const device_t stac9721_device;
extern const device_t wm9701a_device;
extern const device_t ad1881_device;
extern const device_t ak4540_device;
extern const device_t alc100_device;
extern const device_t cs4297_device;
extern const device_t cs4297a_device;
extern const device_t stac9708_device;
extern const device_t stac9721_device;
extern const device_t wm9701a_device;
extern const device_t ac97_via_device;
extern const device_t ac97_via_device;
#endif
#endif /*SOUND_AC97_H*/

View File

@@ -20,7 +20,7 @@
*/
#ifndef SOUND_AD1848_H
# define SOUND_AD1848_H
#define SOUND_AD1848_H
enum {
AD1848_TYPE_DEFAULT = 0,
@@ -30,44 +30,42 @@ enum {
AD1848_TYPE_CS4236
};
typedef struct {
uint8_t type, index, xindex, regs[32], xregs[32], status; /* 16 original registers + 16 CS4231A extensions + 32 CS4236 extensions */
uint8_t type, index, xindex, regs[32], xregs[32], status; /* 16 original registers + 16 CS4231A extensions + 32 CS4236 extensions */
int count;
uint8_t trd, mce, wten: 1;
int count;
uint8_t trd, mce, wten : 1;
int16_t out_l, out_r;
double cd_vol_l, cd_vol_r;
int fm_vol_l, fm_vol_r;
uint8_t fmt_mask, wave_vol_mask;
int16_t out_l, out_r;
double cd_vol_l, cd_vol_r;
int fm_vol_l, fm_vol_r;
uint8_t fmt_mask, wave_vol_mask;
uint8_t enable: 1, irq: 4, dma: 3;
int freq;
uint8_t enable : 1, irq : 4, dma : 3;
int freq;
pc_timer_t timer_count;
uint64_t timer_latch;
pc_timer_t timer_count;
uint64_t timer_latch;
int16_t buffer[SOUNDBUFLEN * 2];
int pos;
int16_t buffer[SOUNDBUFLEN * 2];
int pos;
void *cram_priv,
(*cram_write)(uint16_t addr, uint8_t val, void *priv);
uint8_t (*cram_read)(uint16_t addr, void *priv);
void *cram_priv,
(*cram_write)(uint16_t addr, uint8_t val, void *priv);
uint8_t (*cram_read)(uint16_t addr, void *priv);
} ad1848_t;
extern void ad1848_setirq(ad1848_t *ad1848, int irq);
extern void ad1848_setdma(ad1848_t *ad1848, int dma);
extern void ad1848_updatevolmask(ad1848_t *ad1848);
extern void ad1848_setirq(ad1848_t *ad1848, int irq);
extern void ad1848_setdma(ad1848_t *ad1848, int dma);
extern void ad1848_updatevolmask(ad1848_t *ad1848);
extern uint8_t ad1848_read(uint16_t addr, void *priv);
extern void ad1848_write(uint16_t addr, uint8_t val, void *priv);
extern uint8_t ad1848_read(uint16_t addr, void *priv);
extern void ad1848_write(uint16_t addr, uint8_t val, void *priv);
extern void ad1848_update(ad1848_t *ad1848);
extern void ad1848_speed_changed(ad1848_t *ad1848);
extern void ad1848_filter_cd_audio(int channel, double *buffer, void *priv);
extern void ad1848_update(ad1848_t *ad1848);
extern void ad1848_speed_changed(ad1848_t *ad1848);
extern void ad1848_filter_cd_audio(int channel, double *buffer, void *priv);
extern void ad1848_init(ad1848_t *ad1848, uint8_t type);
extern void ad1848_init(ad1848_t *ad1848, uint8_t type);
#endif /*SOUND_AD1848_H*/

View File

@@ -1,5 +1,5 @@
#ifndef SOUND_AZT2316A_H
# define SOUND_AZT2316A_H
#define SOUND_AZT2316A_H
extern void azt2316a_enable_wss(uint8_t enable, void *p);

View File

@@ -1,35 +1,33 @@
#ifndef SOUND_CMS_H
# define SOUND_CMS_H
#define SOUND_CMS_H
#include <stdint.h>
#include <86box/sound.h>
#include <stdint.h>
#define MASTER_CLOCK 7159090
typedef struct cms_t
{
int addrs[2];
uint8_t regs[2][32];
uint16_t latch[2][6];
int freq[2][6];
float count[2][6];
int vol[2][6][2];
int stat[2][6];
uint16_t noise[2][2];
uint16_t noisefreq[2][2];
int noisecount[2][2];
int noisetype[2][2];
typedef struct cms_t {
int addrs[2];
uint8_t regs[2][32];
uint16_t latch[2][6];
int freq[2][6];
float count[2][6];
int vol[2][6][2];
int stat[2][6];
uint16_t noise[2][2];
uint16_t noisefreq[2][2];
int noisecount[2][2];
int noisetype[2][2];
uint8_t latched_data;
uint8_t latched_data;
int16_t buffer[SOUNDBUFLEN * 2];
int16_t buffer[SOUNDBUFLEN * 2];
int pos;
int pos;
} cms_t;
extern void cms_update(cms_t *cms);
extern void cms_write(uint16_t addr, uint8_t val, void *p);
extern void cms_update(cms_t *cms);
extern void cms_write(uint16_t addr, uint8_t val, void *p);
extern uint8_t cms_read(uint16_t addr, void *p);
#endif /*SOUND_CMS_H*/
#endif /*SOUND_CMS_H*/

View File

@@ -1,37 +1,37 @@
#ifndef SOUND_EMU8K_H
# define SOUND_EMU8K_H
#define SOUND_EMU8K_H
/* All these defines are in samples, not in bytes. */
#define EMU8K_MEM_ADDRESS_MASK 0xFFFFFF
#define EMU8K_RAM_MEM_START 0x200000
#define EMU8K_FM_MEM_ADDRESS 0xFFFFE0
#define EMU8K_MEM_ADDRESS_MASK 0xFFFFFF
#define EMU8K_RAM_MEM_START 0x200000
#define EMU8K_FM_MEM_ADDRESS 0xFFFFE0
#define EMU8K_RAM_POINTERS_MASK 0x3F
#define EMU8K_LFOCHORUS_SIZE 0x4000
#define EMU8K_LFOCHORUS_SIZE 0x4000
/*
* Everything in this file assumes little endian
*/
/* used for the increment of oscillator position*/
typedef struct emu8k_mem_internal_t {
union {
uint64_t addr;
struct {
uint16_t fract_lw_address;
uint16_t fract_address;
uint32_t int_address;
};
union {
uint64_t addr;
struct {
uint16_t fract_lw_address;
uint16_t fract_address;
uint32_t int_address;
};
};
} emu8k_mem_internal_t;
/* used for access to ram pointers from oscillator position. */
typedef struct emu8k_mem_pointers_t {
union {
uint32_t addr;
struct {
uint16_t lw_address;
uint8_t hb_address;
uint8_t unused_address;
};
union {
uint32_t addr;
struct {
uint16_t lw_address;
uint8_t hb_address;
uint8_t unused_address;
};
};
} emu8k_mem_pointers_t;
/*
@@ -84,33 +84,30 @@ typedef struct emu8k_mem_pointers_t {
* This allows to operate db values by simply adding them.
*/
typedef struct emu8k_envelope_t {
int state;
int32_t delay_samples, hold_samples, attack_samples;
int32_t value_amp_hz, value_db_oct;
int32_t sustain_value_db_oct;
int32_t attack_amount_amp_hz, ramp_amount_db_oct;
int state;
int32_t delay_samples, hold_samples, attack_samples;
int32_t value_amp_hz, value_db_oct;
int32_t sustain_value_db_oct;
int32_t attack_amount_amp_hz, ramp_amount_db_oct;
} emu8k_envelope_t;
typedef struct emu8k_chorus_eng_t {
int32_t write;
int32_t feedback;
int32_t delay_samples_central;
double lfodepth_multip;
double delay_offset_samples_right;
emu8k_mem_internal_t lfo_inc;
emu8k_mem_internal_t lfo_pos;
int32_t write;
int32_t feedback;
int32_t delay_samples_central;
double lfodepth_multip;
double delay_offset_samples_right;
emu8k_mem_internal_t lfo_inc;
emu8k_mem_internal_t lfo_pos;
int32_t chorus_left_buffer[EMU8K_LFOCHORUS_SIZE];
int32_t chorus_right_buffer[EMU8K_LFOCHORUS_SIZE];
int32_t chorus_left_buffer[EMU8K_LFOCHORUS_SIZE];
int32_t chorus_right_buffer[EMU8K_LFOCHORUS_SIZE];
} emu8k_chorus_eng_t;
/* 32 * 242. 32 comes from the "right" room resso case.*/
#define MAX_REFL_SIZE 7744
/* Reverb parameters description, extracted from AST sources.
Mix level
Decay
@@ -133,267 +130,258 @@ typedef struct emu8k_chorus_eng_t {
Ref 6 feedback L&R
*/
typedef struct emu8k_reverb_combfilter_t {
int read_pos;
int32_t reflection[MAX_REFL_SIZE];
float output_gain;
float feedback;
float damp1;
float damp2;
int bufsize;
int32_t filterstore;
int read_pos;
int32_t reflection[MAX_REFL_SIZE];
float output_gain;
float feedback;
float damp1;
float damp2;
int bufsize;
int32_t filterstore;
} emu8k_reverb_combfilter_t;
typedef struct emu8k_reverb_eng_t {
int16_t out_mix;
int16_t link_return_amp; /* tail part output gain ? */
int8_t link_return_type;
int16_t out_mix;
int16_t link_return_amp; /* tail part output gain ? */
int8_t link_return_type;
uint8_t refl_in_amp;
uint8_t refl_in_amp;
emu8k_reverb_combfilter_t reflections[6];
emu8k_reverb_combfilter_t allpass[8];
emu8k_reverb_combfilter_t tailL;
emu8k_reverb_combfilter_t tailR;
emu8k_reverb_combfilter_t reflections[6];
emu8k_reverb_combfilter_t allpass[8];
emu8k_reverb_combfilter_t tailL;
emu8k_reverb_combfilter_t tailR;
emu8k_reverb_combfilter_t damper;
emu8k_reverb_combfilter_t damper;
} emu8k_reverb_eng_t;
typedef struct emu8k_slide_t {
int32_t last;
int32_t last;
} emu8k_slide_t;
typedef struct emu8k_voice_t
{
union {
uint32_t cpf;
struct {
uint16_t cpf_curr_frac_addr; /* fractional part of the playing cursor. */
uint16_t cpf_curr_pitch; /* 0x4000 = no shift. Linear increment */
};
typedef struct emu8k_voice_t {
union {
uint32_t cpf;
struct {
uint16_t cpf_curr_frac_addr; /* fractional part of the playing cursor. */
uint16_t cpf_curr_pitch; /* 0x4000 = no shift. Linear increment */
};
union {
uint32_t ptrx;
struct {
uint8_t ptrx_pan_aux;
uint8_t ptrx_revb_send;
uint16_t ptrx_pit_target; /* target pitch to which slide at curr_pitch speed. */
};
};
union {
uint32_t ptrx;
struct {
uint8_t ptrx_pan_aux;
uint8_t ptrx_revb_send;
uint16_t ptrx_pit_target; /* target pitch to which slide at curr_pitch speed. */
};
union {
uint32_t cvcf;
struct {
uint16_t cvcf_curr_filt_ctoff;
uint16_t cvcf_curr_volume;
};
};
union {
uint32_t cvcf;
struct {
uint16_t cvcf_curr_filt_ctoff;
uint16_t cvcf_curr_volume;
};
emu8k_slide_t volumeslide;
union {
uint32_t vtft;
struct {
uint16_t vtft_filter_target;
uint16_t vtft_vol_target; /* written to by the envelope engine. */
};
};
emu8k_slide_t volumeslide;
union {
uint32_t vtft;
struct {
uint16_t vtft_filter_target;
uint16_t vtft_vol_target; /* written to by the envelope engine. */
};
/* These registers are used at least by the Windows drivers, and seem to be resetting
* something, similarly to targets and current, but... of what?
* what is curious is that if they are already zero, they are not written to, so it really
* looks like they are information about the status of the channel. (lfo position maybe?) */
uint32_t unknown_data0_4;
uint32_t unknown_data0_5;
union {
uint32_t psst;
struct {
uint16_t psst_lw_address;
uint8_t psst_hw_address;
uint8_t psst_pan;
};
#define PSST_LOOP_START_MASK 0x00FFFFFF /* In samples, i.e. uint16_t array[BOARD_RAM/2]; */
};
/* These registers are used at least by the Windows drivers, and seem to be resetting
* something, similarly to targets and current, but... of what?
* what is curious is that if they are already zero, they are not written to, so it really
* looks like they are information about the status of the channel. (lfo position maybe?) */
uint32_t unknown_data0_4;
uint32_t unknown_data0_5;
union {
uint32_t psst;
struct {
uint16_t psst_lw_address;
uint8_t psst_hw_address;
uint8_t psst_pan;
};
union {
uint32_t csl;
struct {
uint16_t csl_lw_address;
uint8_t csl_hw_address;
uint8_t csl_chor_send;
};
#define CSL_LOOP_END_MASK 0x00FFFFFF /* In samples, i.e. uint16_t array[BOARD_RAM/2]; */
#define PSST_LOOP_START_MASK 0x00FFFFFF /* In samples, i.e. uint16_t array[BOARD_RAM/2]; */
};
union {
uint32_t csl;
struct {
uint16_t csl_lw_address;
uint8_t csl_hw_address;
uint8_t csl_chor_send;
};
union {
uint32_t ccca;
struct {
uint16_t ccca_lw_addr;
uint8_t ccca_hb_addr;
uint8_t ccca_qcontrol;
};
#define CSL_LOOP_END_MASK 0x00FFFFFF /* In samples, i.e. uint16_t array[BOARD_RAM/2]; */
};
union {
uint32_t ccca;
struct {
uint16_t ccca_lw_addr;
uint8_t ccca_hb_addr;
uint8_t ccca_qcontrol;
};
#define CCCA_FILTQ_GET(ccca) (ccca>>28)
#define CCCA_FILTQ_SET(ccca,q) ccca = (ccca&0x0FFFFFFF) | (q<<28)
/* Bit 27 should always be zero */
#define CCCA_DMA_ACTIVE(ccca) (ccca&0x04000000)
#define CCCA_DMA_WRITE_MODE(ccca) (ccca&0x02000000)
#define CCCA_DMA_WRITE_RIGHT(ccca) (ccca&0x01000000)
};
#define CCCA_FILTQ_GET(ccca) (ccca >> 28)
#define CCCA_FILTQ_SET(ccca, q) ccca = (ccca & 0x0FFFFFFF) | (q << 28)
/* Bit 27 should always be zero */
#define CCCA_DMA_ACTIVE(ccca) (ccca & 0x04000000)
#define CCCA_DMA_WRITE_MODE(ccca) (ccca & 0x02000000)
#define CCCA_DMA_WRITE_RIGHT(ccca) (ccca & 0x01000000)
uint16_t envvol;
#define ENVVOL_NODELAY(envol) (envvol&0x8000)
/* Verified with a soundfont bank. 7FFF is the minimum delay time, and 0 is the max delay time */
#define ENVVOL_TO_EMU_SAMPLES(envvol) (envvol&0x8000) ? 0 : ((0x8000-(envvol&0x7FFF)) <<5)
uint16_t envvol;
#define ENVVOL_NODELAY(envol) (envvol & 0x8000)
/* Verified with a soundfont bank. 7FFF is the minimum delay time, and 0 is the max delay time */
#define ENVVOL_TO_EMU_SAMPLES(envvol) (envvol & 0x8000) ? 0 : ((0x8000 - (envvol & 0x7FFF)) << 5)
uint16_t dcysusv;
#define DCYSUSV_IS_RELEASE(dcysusv) (dcysusv&0x8000)
#define DCYSUSV_GENERATOR_ENGINE_ON(dcysusv) !(dcysusv&0x0080)
#define DCYSUSV_SUSVALUE_GET(dcysusv) ((dcysusv>>8)&0x7F)
/* Inverting the range compared to documentation because the envelope runs from 0dBFS = 0 to -96dBFS = (1 <<21) */
#define DCYSUSV_SUS_TO_ENV_RANGE(susvalue) (((0x7F-susvalue) << 21)/0x7F)
#define DCYSUSV_DECAYRELEASE_GET(dcysusv) (dcysusv&0x7F)
uint16_t dcysusv;
#define DCYSUSV_IS_RELEASE(dcysusv) (dcysusv & 0x8000)
#define DCYSUSV_GENERATOR_ENGINE_ON(dcysusv) !(dcysusv & 0x0080)
#define DCYSUSV_SUSVALUE_GET(dcysusv) ((dcysusv >> 8) & 0x7F)
/* Inverting the range compared to documentation because the envelope runs from 0dBFS = 0 to -96dBFS = (1 <<21) */
#define DCYSUSV_SUS_TO_ENV_RANGE(susvalue) (((0x7F - susvalue) << 21) / 0x7F)
#define DCYSUSV_DECAYRELEASE_GET(dcysusv) (dcysusv & 0x7F)
uint16_t envval;
#define ENVVAL_NODELAY(enval) (envval&0x8000)
/* Verified with a soundfont bank. 7FFF is the minimum delay time, and 0 is the max delay time */
#define ENVVAL_TO_EMU_SAMPLES(envval)(envval&0x8000) ? 0 : ((0x8000-(envval&0x7FFF)) <<5)
uint16_t envval;
#define ENVVAL_NODELAY(enval) (envval & 0x8000)
/* Verified with a soundfont bank. 7FFF is the minimum delay time, and 0 is the max delay time */
#define ENVVAL_TO_EMU_SAMPLES(envval) (envval & 0x8000) ? 0 : ((0x8000 - (envval & 0x7FFF)) << 5)
uint16_t dcysus;
#define DCYSUS_IS_RELEASE(dcysus) (dcysus&0x8000)
#define DCYSUS_SUSVALUE_GET(dcysus) ((dcysus>>8)&0x7F)
#define DCYSUS_SUS_TO_ENV_RANGE(susvalue) ((susvalue << 21)/0x7F)
#define DCYSUS_DECAYRELEASE_GET(dcysus) (dcysus&0x7F)
uint16_t dcysus;
#define DCYSUS_IS_RELEASE(dcysus) (dcysus & 0x8000)
#define DCYSUS_SUSVALUE_GET(dcysus) ((dcysus >> 8) & 0x7F)
#define DCYSUS_SUS_TO_ENV_RANGE(susvalue) ((susvalue << 21) / 0x7F)
#define DCYSUS_DECAYRELEASE_GET(dcysus) (dcysus & 0x7F)
uint16_t atkhldv;
#define ATKHLDV_TRIGGER(atkhldv) !(atkhldv&0x8000)
#define ATKHLDV_HOLD(atkhldv) ((atkhldv>>8)&0x7F)
#define ATKHLDV_HOLD_TO_EMU_SAMPLES(atkhldv) (4096*(0x7F-((atkhldv>>8)&0x7F)))
#define ATKHLDV_ATTACK(atkhldv) (atkhldv&0x7F)
uint16_t atkhldv;
#define ATKHLDV_TRIGGER(atkhldv) !(atkhldv & 0x8000)
#define ATKHLDV_HOLD(atkhldv) ((atkhldv >> 8) & 0x7F)
#define ATKHLDV_HOLD_TO_EMU_SAMPLES(atkhldv) (4096 * (0x7F - ((atkhldv >> 8) & 0x7F)))
#define ATKHLDV_ATTACK(atkhldv) (atkhldv & 0x7F)
uint16_t lfo1val, lfo2val;
#define LFOxVAL_NODELAY(lfoxval) (lfoxval&0x8000)
#define LFOxVAL_TO_EMU_SAMPLES(lfoxval) (lfoxval&0x8000) ? 0 : ((0x8000-(lfoxval&0x7FFF)) <<5)
uint16_t lfo1val, lfo2val;
#define LFOxVAL_NODELAY(lfoxval) (lfoxval & 0x8000)
#define LFOxVAL_TO_EMU_SAMPLES(lfoxval) (lfoxval & 0x8000) ? 0 : ((0x8000 - (lfoxval & 0x7FFF)) << 5)
uint16_t atkhld;
#define ATKHLD_TRIGGER(atkhld) !(atkhld&0x8000)
#define ATKHLD_HOLD(atkhld) ((atkhld>>8)&0x7F)
#define ATKHLD_HOLD_TO_EMU_SAMPLES(atkhld) (4096*(0x7F-((atkhld>>8)&0x7F)))
#define ATKHLD_ATTACK(atkhld) (atkhld&0x7F)
uint16_t atkhld;
#define ATKHLD_TRIGGER(atkhld) !(atkhld & 0x8000)
#define ATKHLD_HOLD(atkhld) ((atkhld >> 8) & 0x7F)
#define ATKHLD_HOLD_TO_EMU_SAMPLES(atkhld) (4096 * (0x7F - ((atkhld >> 8) & 0x7F)))
#define ATKHLD_ATTACK(atkhld) (atkhld & 0x7F)
uint16_t ip;
#define INTIAL_PITCH_CENTER 0xE000
#define INTIAL_PITCH_OCTAVE 0x1000
uint16_t ip;
#define INTIAL_PITCH_CENTER 0xE000
#define INTIAL_PITCH_OCTAVE 0x1000
union {
uint16_t ifatn;
struct{
uint8_t ifatn_attenuation;
uint8_t ifatn_init_filter;
};
union {
uint16_t ifatn;
struct {
uint8_t ifatn_attenuation;
uint8_t ifatn_init_filter;
};
union {
uint16_t pefe;
struct {
int8_t pefe_modenv_filter_height;
int8_t pefe_modenv_pitch_height;
};
};
union {
uint16_t pefe;
struct {
int8_t pefe_modenv_filter_height;
int8_t pefe_modenv_pitch_height;
};
union {
uint16_t fmmod;
struct {
int8_t fmmod_lfo1_filt_mod;
int8_t fmmod_lfo1_vibrato;
};
};
union {
uint16_t fmmod;
struct {
int8_t fmmod_lfo1_filt_mod;
int8_t fmmod_lfo1_vibrato;
};
union {
uint16_t tremfrq;
struct {
uint8_t tremfrq_lfo1_freq;
int8_t tremfrq_lfo1_tremolo;
};
};
union {
uint16_t tremfrq;
struct {
uint8_t tremfrq_lfo1_freq;
int8_t tremfrq_lfo1_tremolo;
};
union {
uint16_t fm2frq2;
struct {
uint8_t fm2frq2_lfo2_freq;
int8_t fm2frq2_lfo2_vibrato;
};
};
union {
uint16_t fm2frq2;
struct {
uint8_t fm2frq2_lfo2_freq;
int8_t fm2frq2_lfo2_vibrato;
};
};
int env_engine_on;
int env_engine_on;
emu8k_mem_internal_t addr, loop_start, loop_end;
emu8k_mem_internal_t addr, loop_start, loop_end;
int32_t initial_att;
int32_t initial_filter;
int32_t initial_att;
int32_t initial_filter;
emu8k_envelope_t vol_envelope;
emu8k_envelope_t mod_envelope;
emu8k_envelope_t vol_envelope;
emu8k_envelope_t mod_envelope;
int64_t lfo1_speed, lfo2_speed;
emu8k_mem_internal_t lfo1_count, lfo2_count;
int32_t lfo1_delay_samples, lfo2_delay_samples;
int vol_l, vol_r;
int64_t lfo1_speed, lfo2_speed;
emu8k_mem_internal_t lfo1_count, lfo2_count;
int32_t lfo1_delay_samples, lfo2_delay_samples;
int vol_l, vol_r;
int16_t fixed_modenv_filter_height;
int16_t fixed_modenv_pitch_height;
int16_t fixed_lfo1_filt_mod;
int16_t fixed_lfo1_vibrato;
int16_t fixed_lfo1_tremolo;
int16_t fixed_lfo2_vibrato;
int16_t fixed_modenv_filter_height;
int16_t fixed_modenv_pitch_height;
int16_t fixed_lfo1_filt_mod;
int16_t fixed_lfo1_vibrato;
int16_t fixed_lfo1_tremolo;
int16_t fixed_lfo2_vibrato;
/* filter internal data. */
int filterq_idx;
int32_t filt_att;
int64_t filt_buffer[5];
/* filter internal data. */
int filterq_idx;
int32_t filt_att;
int64_t filt_buffer[5];
} emu8k_voice_t;
typedef struct emu8k_t
{
emu8k_voice_t voice[32];
typedef struct emu8k_t {
emu8k_voice_t voice[32];
uint16_t hwcf1, hwcf2, hwcf3;
uint32_t hwcf4, hwcf5, hwcf6, hwcf7;
uint16_t hwcf1, hwcf2, hwcf3;
uint32_t hwcf4, hwcf5, hwcf6, hwcf7;
uint16_t init1[32], init2[32], init3[32], init4[32];
uint16_t init1[32], init2[32], init3[32], init4[32];
uint32_t smalr, smarr, smalw, smarw;
uint16_t smld_buffer, smrd_buffer;
uint32_t smalr, smarr, smalw, smarw;
uint16_t smld_buffer, smrd_buffer;
uint16_t wc;
uint16_t wc;
uint16_t id;
uint16_t id;
/* The empty block is used to act as an unallocated memory returning zero. */
int16_t *ram, *rom, *empty;
/* The empty block is used to act as an unallocated memory returning zero. */
int16_t *ram, *rom, *empty;
/* RAM pointers are a way to avoid checking ram boundaries on read */
int16_t *ram_pointers[0x100];
uint32_t ram_end_addr;
/* RAM pointers are a way to avoid checking ram boundaries on read */
int16_t *ram_pointers[0x100];
uint32_t ram_end_addr;
int cur_reg, cur_voice;
int cur_reg, cur_voice;
int16_t out_l, out_r;
int16_t out_l, out_r;
emu8k_chorus_eng_t chorus_engine;
int32_t chorus_in_buffer[SOUNDBUFLEN];
emu8k_reverb_eng_t reverb_engine;
int32_t reverb_in_buffer[SOUNDBUFLEN];
emu8k_chorus_eng_t chorus_engine;
int32_t chorus_in_buffer[SOUNDBUFLEN];
emu8k_reverb_eng_t reverb_engine;
int32_t reverb_in_buffer[SOUNDBUFLEN];
int pos;
int32_t buffer[SOUNDBUFLEN * 2];
int pos;
int32_t buffer[SOUNDBUFLEN * 2];
uint16_t addr;
uint16_t addr;
} emu8k_t;
void emu8k_change_addr(emu8k_t *emu8k, uint16_t emu_addr);
void emu8k_init(emu8k_t *emu8k, uint16_t emu_addr, int onboard_ram);
void emu8k_close(emu8k_t *emu8k);
void emu8k_update(emu8k_t *emu8k);
/*
Section E - Introduction to the EMU8000 Chip
@@ -656,12 +644,12 @@ Short Delay Short Delay + Feedback
// Chorus Params
typedef struct {
WORD FbkLevel; // Feedback Level (0xE600-0xE6FF)
WORD Delay; // Delay (0-0x0DA3) [1/44100 sec]
WORD LfoDepth; // LFO Depth (0xBC00-0xBCFF)
DWORD DelayR; // Right Delay (0-0xFFFFFFFF) [1/256/44100 sec]
DWORD LfoFreq; // LFO Frequency (0-0xFFFFFFFF)
} CHORUS_TYPE;
WORD FbkLevel; // Feedback Level (0xE600-0xE6FF)
WORD Delay; // Delay (0-0x0DA3) [1/44100 sec]
WORD LfoDepth; // LFO Depth (0xBC00-0xBCFF)
DWORD DelayR; // Right Delay (0-0xFFFFFFFF) [1/256/44100 sec]
DWORD LfoFreq; // LFO Frequency (0-0xFFFFFFFF)
} CHORUS_TYPE;
Registers to write the Reverb Parameters to (they are all 16-bit):

View File

@@ -21,30 +21,28 @@
*/
#ifndef SOUND_MPU401_H
# define SOUND_MPU401_H
#define SOUND_MPU401_H
#define MPU401_VERSION 0x15
#define MPU401_REVISION 0x01
#define MPU401_QUEUE 64
#define MPU401_INPUT_QUEUE 1024
#define MPU401_TIMECONSTANT (60000000/1000.0f)
#define MPU401_RESETBUSY 27.0f
#define MPU401_VERSION 0x15
#define MPU401_REVISION 0x01
#define MPU401_QUEUE 64
#define MPU401_INPUT_QUEUE 1024
#define MPU401_TIMECONSTANT (60000000 / 1000.0f)
#define MPU401_RESETBUSY 27.0f
/*helpers*/
#define M_GETKEY key[key/32]&(1<<(key%32))
#define M_SETKEY key[key/32]|=(1<<(key%32))
#define M_DELKEY key[key/32]&=~(1<<(key%32))
#define M_GETKEY key[key / 32] & (1 << (key % 32))
#define M_SETKEY key[key / 32] |= (1 << (key % 32))
#define M_DELKEY key[key / 32] &= ~(1 << (key % 32))
typedef enum MpuMode
{
typedef enum MpuMode {
M_UART,
M_INTELLIGENT
} MpuMode;
#define M_MCA 0x10
typedef enum MpuDataType
{
typedef enum MpuDataType {
T_OVERFLOW,
T_MARK,
T_MIDI_SYS,
@@ -52,116 +50,112 @@ typedef enum MpuDataType
T_COMMAND
} MpuDataType;
typedef enum RecState
{
M_RECOFF,
M_RECSTB,
M_RECON
typedef enum RecState {
M_RECOFF,
M_RECSTB,
M_RECON
} RecState;
/* Messages sent to MPU-401 from host */
#define MSG_EOX 0xf7
#define MSG_OVERFLOW 0xf8
#define MSG_MARK 0xfc
#define MSG_EOX 0xf7
#define MSG_OVERFLOW 0xf8
#define MSG_MARK 0xfc
/* Messages sent to host from MPU-401 */
#define MSG_MPU_OVERFLOW 0xf8
#define MSG_MPU_COMMAND_REQ 0xf9
#define MSG_MPU_END 0xfc
#define MSG_MPU_CLOCK 0xfd
#define MSG_MPU_ACK 0xfe
#define MSG_MPU_OVERFLOW 0xf8
#define MSG_MPU_COMMAND_REQ 0xf9
#define MSG_MPU_END 0xfc
#define MSG_MPU_CLOCK 0xfd
#define MSG_MPU_ACK 0xfe
typedef struct mpu_t
{
typedef struct mpu_t {
uint16_t addr;
int uart_mode, intelligent,
irq, midi_thru,
queue_pos, queue_used;
int uart_mode, intelligent,
irq, midi_thru,
queue_pos, queue_used;
uint8_t rx_data, is_mca,
status,
queue[MPU401_QUEUE], pos_regs[8];
MpuMode mode;
uint8_t rec_queue[MPU401_INPUT_QUEUE];
int rec_queue_pos, rec_queue_used;
uint32_t ch_toref[16];
struct track
{
int counter;
uint8_t value[3], sys_val,
vlength,length;
MpuDataType type;
status,
queue[MPU401_QUEUE], pos_regs[8];
MpuMode mode;
uint8_t rec_queue[MPU401_INPUT_QUEUE];
int rec_queue_pos, rec_queue_used;
uint32_t ch_toref[16];
struct track {
int counter;
uint8_t value[3], sys_val,
vlength, length;
MpuDataType type;
} playbuf[8], condbuf;
struct {
int conductor, cond_req,
cond_set, block_ack,
playing, reset,
wsd, wsm, wsd_start,
run_irq, irq_pending,
track_req,
send_now, eoi_scheduled,
data_onoff, clock_to_host,
sync_in, sysex_in_finished,
rec_copy;
RecState rec;
uint8_t tmask, cmask,
amask,
last_rtcmd;
uint16_t midi_mask, req_mask;
uint32_t command_byte, cmd_pending,
track, old_track;
int conductor, cond_req,
cond_set, block_ack,
playing, reset,
wsd, wsm, wsd_start,
run_irq, irq_pending,
track_req,
send_now, eoi_scheduled,
data_onoff, clock_to_host,
sync_in, sysex_in_finished,
rec_copy;
RecState rec;
uint8_t tmask, cmask,
amask,
last_rtcmd;
uint16_t midi_mask, req_mask;
uint32_t command_byte, cmd_pending,
track, old_track;
} state;
struct {
uint8_t timebase, old_timebase,
tempo, old_tempo,
tempo_rel, old_tempo_rel,
tempo_grad, cth_rate[4],
cth_mode, midimetro,
metromeas;
uint32_t cth_counter, cth_old,
rec_counter;
int32_t measure_counter, meas_old,
freq;
int ticks_in, active;
float freq_mod;
uint8_t timebase, old_timebase,
tempo, old_tempo,
tempo_rel, old_tempo_rel,
tempo_grad, cth_rate[4],
cth_mode, midimetro,
metromeas;
uint32_t cth_counter, cth_old,
rec_counter;
int32_t measure_counter, meas_old,
freq;
int ticks_in, active;
float freq_mod;
} clock;
struct {
int all_thru, midi_thru,
sysex_thru, commonmsgs_thru,
modemsgs_in, commonmsgs_in,
bender_in, sysex_in,
allnotesoff_out, rt_affection,
rt_out, rt_in,
timing_in_stop, data_in_stop,
rec_measure_end;
uint8_t prchg_buf[16];
uint16_t prchg_mask;
} filter;
struct {
int on;
uint8_t chan, trmask;
uint32_t key[4];
} chanref[5], inputref[16];
pc_timer_t mpu401_event_callback, mpu401_eoi_callback,
mpu401_reset_callback;
void (*ext_irq_update)(void *priv, int set);
int (*ext_irq_pending)(void *priv);
void *priv;
struct {
int all_thru, midi_thru,
sysex_thru, commonmsgs_thru,
modemsgs_in, commonmsgs_in,
bender_in, sysex_in,
allnotesoff_out, rt_affection,
rt_out, rt_in,
timing_in_stop, data_in_stop,
rec_measure_end;
uint8_t prchg_buf[16];
uint16_t prchg_mask;
} filter;
struct {
int on;
uint8_t chan, trmask;
uint32_t key[4];
} chanref[5], inputref[16];
pc_timer_t mpu401_event_callback, mpu401_eoi_callback,
mpu401_reset_callback;
void (*ext_irq_update)(void *priv, int set);
int (*ext_irq_pending)(void *priv);
void *priv;
} mpu_t;
extern int mpu401_standalone_enable, mpu401_already_loaded;
extern int mpu401_standalone_enable, mpu401_already_loaded;
extern const device_t mpu401_device;
extern const device_t mpu401_mca_device;
extern const device_t mpu401_device;
extern const device_t mpu401_mca_device;
extern uint8_t MPU401_ReadData(mpu_t *mpu);
extern void mpu401_setirq(mpu_t *mpu, int irq);
extern void mpu401_change_addr(mpu_t *mpu, uint16_t addr);
extern void mpu401_init(mpu_t *mpu, uint16_t addr, int irq, int mode, int receive_input);
extern void mpu401_device_add(void);
extern void mpu401_irq_attach(mpu_t *mpu, void (*ext_irq_update)(void *priv, int set), int (*ext_irq_pending)(void *priv), void *priv);
extern uint8_t MPU401_ReadData(mpu_t *mpu);
extern void mpu401_setirq(mpu_t *mpu, int irq);
extern void mpu401_change_addr(mpu_t *mpu, uint16_t addr);
extern void mpu401_init(mpu_t *mpu, uint16_t addr, int irq, int mode, int receive_input);
extern void mpu401_device_add(void);
extern void mpu401_irq_attach(mpu_t *mpu, void (*ext_irq_update)(void *priv, int set), int (*ext_irq_pending)(void *priv), void *priv);
extern int MPU401_InputSysex(void *p, uint8_t *buffer, uint32_t len, int abort);
extern void MPU401_InputMsg(void *p, uint8_t *msg, uint32_t len);
extern int MPU401_InputSysex(void *p, uint8_t *buffer, uint32_t len, int abort);
extern void MPU401_InputMsg(void *p, uint8_t *msg, uint32_t len);
#endif /*SOUND_MPU401_H*/
#endif /*SOUND_MPU401_H*/

View File

@@ -15,41 +15,40 @@
* Copyright 2016-2020 Miran Grca.
*/
#ifndef SOUND_OPL_H
# define SOUND_OPL_H
#define SOUND_OPL_H
typedef void (*tmrfunc)(void *priv, int timer, uint64_t period);
typedef void (*tmrfunc)(void *priv, int timer, uint64_t period);
/* Define an OPLx chip. */
typedef struct {
#ifdef SOUND_OPL_NUKED_H
nuked_t *opl;
nuked_t *opl;
#else
void *opl;
void *opl;
#endif
int8_t flags, pad;
int8_t flags, pad;
uint16_t port;
uint8_t status, timer_ctrl;
uint16_t timer_count[2],
timer_cur_count[2];
uint16_t port;
uint8_t status, timer_ctrl;
uint16_t timer_count[2],
timer_cur_count[2];
pc_timer_t timers[2];
pc_timer_t timers[2];
int pos;
int32_t buffer[SOUNDBUFLEN * 2];
int pos;
int32_t buffer[SOUNDBUFLEN * 2];
} opl_t;
extern void opl_set_do_cycles(opl_t *dev, int8_t do_cycles);
extern void opl_set_do_cycles(opl_t *dev, int8_t do_cycles);
extern uint8_t opl2_read(uint16_t port, void *);
extern void opl2_write(uint16_t port, uint8_t val, void *);
extern void opl2_init(opl_t *);
extern void opl2_update(opl_t *);
extern uint8_t opl2_read(uint16_t port, void *);
extern void opl2_write(uint16_t port, uint8_t val, void *);
extern void opl2_init(opl_t *);
extern void opl2_update(opl_t *);
extern uint8_t opl3_read(uint16_t port, void *);
extern void opl3_write(uint16_t port, uint8_t val, void *);
extern void opl3_init(opl_t *);
extern void opl3_update(opl_t *);
extern uint8_t opl3_read(uint16_t port, void *);
extern void opl3_write(uint16_t port, uint8_t val, void *);
extern void opl3_init(opl_t *);
extern void opl3_update(opl_t *);
#endif /*SOUND_OPL_H*/
#endif /*SOUND_OPL_H*/

View File

@@ -18,18 +18,17 @@
*/
#ifndef SOUND_OPL_NUKED_H
# define SOUND_OPL_NUKED_H
#define SOUND_OPL_NUKED_H
extern void *nuked_init(uint32_t sample_rate);
extern void nuked_close(void *);
extern void * nuked_init(uint32_t sample_rate);
extern void nuked_close(void *);
extern uint16_t nuked_write_addr(void *, uint16_t port, uint8_t val);
extern void nuked_write_reg(void *, uint16_t reg, uint8_t v);
extern void nuked_write_reg_buffered(void *, uint16_t reg, uint8_t v);
extern uint16_t nuked_write_addr(void *, uint16_t port, uint8_t val);
extern void nuked_write_reg(void *, uint16_t reg, uint8_t v);
extern void nuked_write_reg_buffered(void *, uint16_t reg, uint8_t v);
extern void nuked_generate(void *, int32_t *buf);
extern void nuked_generate_resampled(void *, int32_t *buf);
extern void nuked_generate_stream(void *, int32_t *sndptr, uint32_t num);
extern void nuked_generate(void *, int32_t *buf);
extern void nuked_generate_resampled(void *, int32_t *buf);
extern void nuked_generate_stream(void *, int32_t *sndptr, uint32_t num);
#endif /*SOUND_OPL_NUKED_H*/
#endif /*SOUND_OPL_NUKED_H*/

View File

@@ -1,15 +1,15 @@
#ifndef SOUND_RESID_H
# define SOUND_RESID_H
#define SOUND_RESID_H
#ifdef __cplusplus
extern "C" {
#endif
void *sid_init();
void sid_close(void *p);
void sid_reset(void *p);
uint8_t sid_read(uint16_t addr, void *p);
void sid_write(uint16_t addr, uint8_t val, void *p);
void sid_fillbuf(int16_t *buf, int len, void *p);
void *sid_init();
void sid_close(void *p);
void sid_reset(void *p);
uint8_t sid_read(uint16_t addr, void *p);
void sid_write(uint16_t addr, uint8_t val, void *p);
void sid_fillbuf(int16_t *buf, int len, void *p);
#ifdef __cplusplus
}
#endif

View File

@@ -1,145 +1,159 @@
/*
* 86Box A hypervisor and IBM PC system emulator that specializes in
* running old operating systems and software designed for IBM
* PC systems and compatibles from 1981 through fairly recent
* system designs based on the PCI bus.
* 86Box A hypervisor and IBM PC system emulator that specializes in
* running old operating systems and software designed for IBM
* PC systems and compatibles from 1981 through fairly recent
* system designs based on the PCI bus.
*
* This file is part of the 86Box distribution.
* This file is part of the 86Box distribution.
*
* Sound Blaster emulation.
* Sound Blaster emulation.
*
* Authors: Sarah Walker, <http://pcem-emulator.co.uk/>
* Miran Grca, <mgrca8@gmail.com>
* TheCollector1995, <mariogplayer@gmail.com>
* Authors: Sarah Walker, <http://pcem-emulator.co.uk/>
* Miran Grca, <mgrca8@gmail.com>
* TheCollector1995, <mariogplayer@gmail.com>
*
* Copyright 2008-2018 Sarah Walker.
* Copyright 2016-2018 Miran Grca.
* Copyright 2008-2018 Sarah Walker.
* Copyright 2016-2018 Miran Grca.
*/
#ifndef SOUND_SND_SB_H
# define SOUND_SND_SB_H
#define SOUND_SND_SB_H
#include <86box/snd_cms.h>
#include <86box/snd_emu8k.h>
#include <86box/snd_mpu401.h>
#include <86box/snd_opl.h>
#include <86box/snd_sb_dsp.h>
#include <86box/snd_cms.h>
#define SADLIB 1 /* No DSP */
#define SB1 2 /* DSP v1.05 */
#define SB15 3 /* DSP v2.00 */
#define SB2 4 /* DSP v2.01 - needed for high-speed DMA */
#define SBPRO 5 /* DSP v3.00 */
#define SBPRO2 6 /* DSP v3.02 + OPL3 */
#define SB16 7 /* DSP v4.05 + OPL3 */
#define SBAWE32 8 /* DSP v4.13 + OPL3 */
#define SBAWE64 9 /* DSP v4.16 + OPL3 */
#define SADLIB 1 /* No DSP */
#define SB1 2 /* DSP v1.05 */
#define SB15 3 /* DSP v2.00 */
#define SB2 4 /* DSP v2.01 - needed for high-speed DMA */
#define SBPRO 5 /* DSP v3.00 */
#define SBPRO2 6 /* DSP v3.02 + OPL3 */
#define SB16 7 /* DSP v4.05 + OPL3 */
#define SBAWE32 8 /* DSP v4.13 + OPL3 */
#define SBAWE64 9 /* DSP v4.16 + OPL3 */
/* SB 2.0 CD version */
typedef struct sb_ct1335_mixer_t
{
double master;
double voice;
double fm;
double cd;
typedef struct sb_ct1335_mixer_t {
double master;
double voice;
double fm;
double cd;
uint8_t index;
uint8_t regs[256];
uint8_t index;
uint8_t regs[256];
} sb_ct1335_mixer_t;
/* SB PRO */
typedef struct sb_ct1345_mixer_t
{
double master_l, master_r;
double voice_l, voice_r;
double fm_l, fm_r;
double cd_l, cd_r;
double line_l, line_r;
double mic;
/*see sb_ct1745_mixer for values for input selector*/
int32_t input_selector;
typedef struct sb_ct1345_mixer_t {
double master_l,
master_r;
double voice_l,
voice_r;
double fm_l,
fm_r;
double cd_l,
cd_r;
double line_l,
line_r;
double mic;
/*see sb_ct1745_mixer for values for input selector*/
int32_t input_selector;
int input_filter;
int in_filter_freq;
int output_filter;
int input_filter;
int in_filter_freq;
int output_filter;
int stereo;
int stereo_isleft;
int stereo;
int stereo_isleft;
uint8_t index;
uint8_t regs[256];
uint8_t index;
uint8_t regs[256];
} sb_ct1345_mixer_t;
/* SB16 and AWE32 */
typedef struct sb_ct1745_mixer_t
{
double master_l, master_r;
double voice_l, voice_r;
double fm_l, fm_r;
double cd_l, cd_r;
double line_l, line_r;
double mic;
double speaker;
typedef struct sb_ct1745_mixer_t {
double master_l,
master_r;
double voice_l,
voice_r;
double fm_l,
fm_r;
double cd_l,
cd_r;
double line_l,
line_r;
double mic;
double speaker;
int bass_l, bass_r;
int treble_l, treble_r;
int bass_l,
bass_r;
int treble_l,
treble_r;
int output_selector;
#define OUTPUT_MIC 1
#define OUTPUT_CD_R 2
#define OUTPUT_CD_L 4
#define OUTPUT_LINE_R 8
#define OUTPUT_LINE_L 16
int output_selector;
#define OUTPUT_MIC 1
#define OUTPUT_CD_R 2
#define OUTPUT_CD_L 4
#define OUTPUT_LINE_R 8
#define OUTPUT_LINE_L 16
int input_selector_left;
int input_selector_right;
#define INPUT_MIC 1
#define INPUT_CD_R 2
#define INPUT_CD_L 4
#define INPUT_LINE_R 8
#define INPUT_LINE_L 16
#define INPUT_MIDI_R 32
#define INPUT_MIDI_L 64
int input_selector_left;
int input_selector_right;
#define INPUT_MIC 1
#define INPUT_CD_R 2
#define INPUT_CD_L 4
#define INPUT_LINE_R 8
#define INPUT_LINE_L 16
#define INPUT_MIDI_R 32
#define INPUT_MIDI_L 64
int mic_agc;
int mic_agc;
int32_t input_gain_L;
int32_t input_gain_R;
double output_gain_L;
double output_gain_R;
int32_t input_gain_L;
int32_t input_gain_R;
double output_gain_L;
double output_gain_R;
uint8_t index;
uint8_t regs[256];
uint8_t index;
uint8_t regs[256];
} sb_ct1745_mixer_t;
typedef struct sb_t
{
uint8_t cms_enabled, opl_enabled, mixer_enabled;
cms_t cms;
opl_t opl, opl2;
sb_dsp_t dsp;
union {
sb_ct1335_mixer_t mixer_sb2;
sb_ct1345_mixer_t mixer_sbpro;
sb_ct1745_mixer_t mixer_sb16;
};
mpu_t *mpu;
emu8k_t emu8k;
void *gameport;
typedef struct sb_t {
uint8_t cms_enabled,
opl_enabled,
mixer_enabled;
cms_t cms;
opl_t opl,
opl2;
sb_dsp_t dsp;
union {
sb_ct1335_mixer_t mixer_sb2;
sb_ct1345_mixer_t mixer_sbpro;
sb_ct1745_mixer_t mixer_sb16;
};
mpu_t *mpu;
emu8k_t emu8k;
void *gameport;
int pos;
int pos;
uint8_t pos_regs[8], pnp_rom[512];
uint8_t pos_regs[8],
pnp_rom[512];
uint16_t opl_pnp_addr;
uint16_t opl_pnp_addr;
} sb_t;
extern void sb_ct1345_mixer_write(uint16_t addr, uint8_t val, void *p);
extern void sb_ct1345_mixer_write(uint16_t addr, uint8_t val, void *p);
extern uint8_t sb_ct1345_mixer_read(uint16_t addr, void *p);
extern void sb_ct1345_mixer_reset(sb_t* sb);
extern void sb_ct1345_mixer_reset(sb_t *sb);
extern void sb_get_buffer_sbpro(int32_t *buffer, int len, void *p);
extern void sbpro_filter_cd_audio(int channel, double *buffer, void *p);
extern void sb_close(void *p);
extern void sb_speed_changed(void *p);
#endif /*SOUND_SND_SB_H*/
#endif /*SOUND_SND_SB_H*/

View File

@@ -1,5 +1,5 @@
#ifndef SOUND_SND_SB_DSP_H
# define SOUND_SND_SB_DSP_H
#define SOUND_SND_SB_DSP_H
/*Sound Blaster Clones, for quirks*/
#define SB_SUBTYPE_DEFAULT 0 /*Handle as a Creative card*/
@@ -7,101 +7,99 @@
#define SB_SUBTYPE_CLONE_AZT1605_0X0C 2 /*Aztech Sound Galaxy Nova 16 Extra / Packard Bell Forte 16, DSP 2.1 - SBPRO2 clone*/
/* aztech-related */
#define IS_AZTECH(dsp) ((dsp)->sb_subtype == SB_SUBTYPE_CLONE_AZT2316A_0X11 || (dsp)->sb_subtype == SB_SUBTYPE_CLONE_AZT1605_0X0C) /* check for future AZT cards here */
#define AZTECH_EEPROM_SIZE 16
#define IS_AZTECH(dsp) ((dsp)->sb_subtype == SB_SUBTYPE_CLONE_AZT2316A_0X11 || (dsp)->sb_subtype == SB_SUBTYPE_CLONE_AZT1605_0X0C) /* check for future AZT cards here */
#define AZTECH_EEPROM_SIZE 16
typedef struct sb_dsp_t
{
int sb_type;
int sb_subtype; /* which clone */
void *parent; /* "sb_t *" if default subtype, "azt2316a_t *" if aztech. */
typedef struct sb_dsp_t {
int sb_type;
int sb_subtype; /* which clone */
void *parent; /* "sb_t *" if default subtype, "azt2316a_t *" if aztech. */
int sb_8_length, sb_8_format, sb_8_autoinit, sb_8_pause, sb_8_enable, sb_8_autolen, sb_8_output;
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;
int sb_pausetime;
int sb_8_length, sb_8_format, sb_8_autoinit, sb_8_pause, sb_8_enable, sb_8_autolen, sb_8_output;
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;
int sb_pausetime;
uint8_t sb_read_data[256];
int sb_read_wp, sb_read_rp;
int sb_speaker;
int muted;
uint8_t sb_read_data[256];
int sb_read_wp, sb_read_rp;
int sb_speaker;
int muted;
int sb_data_stat;
int sb_data_stat;
int midi_in_sysex;
int midi_in_poll;
int uart_midi;
int uart_irq;
int onebyte_midi;
int midi_in_timestamp;
int midi_in_sysex;
int midi_in_poll;
int uart_midi;
int uart_irq;
int onebyte_midi;
int midi_in_timestamp;
int sb_irqnum;
int sb_irqnum;
uint8_t sbe2;
int sbe2count;
uint8_t sbe2;
int sbe2count;
uint8_t sb_data[8];
uint8_t sb_data[8];
int sb_freq;
int sb_freq;
int16_t sbdat;
int sbdat2;
int16_t sbdatl, sbdatr;
int16_t sbdat;
int sbdat2;
int16_t sbdatl, sbdatr;
uint8_t sbref;
int8_t sbstep;
uint8_t sbref;
int8_t sbstep;
int sbdacpos;
int sbdacpos;
int sbleftright;
int sbleftright;
int sbreset;
uint8_t sbreaddat;
uint8_t sb_command;
uint8_t sb_test;
int sb_timei, sb_timeo;
int sbreset;
uint8_t sbreaddat;
uint8_t sb_command;
uint8_t sb_test;
int sb_timei, sb_timeo;
int sb_irq8, sb_irq16, sb_irq401;
int sb_irqm8, sb_irqm16, sb_irqm401;
int sb_irq8, sb_irq16, sb_irq401;
int sb_irqm8, sb_irqm16, sb_irqm401;
uint8_t sb_asp_regs[256];
uint8_t sb_asp_mode;
uint8_t sb_asp_regs[256];
uint8_t sb_asp_mode;
uint8_t sb_asp_ram[2048];
int sb_asp_ram_index;
uint8_t sb_asp_ram[2048];
int sb_asp_ram_index;
uint8_t sb_8051_ram[256];
uint8_t sb_8051_ram[256];
int sbenable, sb_enable_i;
int sbenable, sb_enable_i;
pc_timer_t output_timer, input_timer;
pc_timer_t output_timer, input_timer;
uint64_t sblatcho, sblatchi;
uint64_t sblatcho, sblatchi;
uint16_t sb_addr;
uint16_t sb_addr;
int stereo;
int stereo;
int asp_data_len;
int asp_data_len;
pc_timer_t wb_timer;
int wb_full;
pc_timer_t wb_timer;
int wb_full;
int busy_count;
int busy_count;
int record_pos_read;
int record_pos_write;
int16_t record_buffer[0xFFFF];
int16_t buffer[SOUNDBUFLEN * 2];
int pos;
int record_pos_read;
int record_pos_write;
int16_t record_buffer[0xFFFF];
int16_t buffer[SOUNDBUFLEN * 2];
int pos;
uint8_t azt_eeprom[AZTECH_EEPROM_SIZE]; /* the eeprom in the Aztech cards is attached to the DSP */
uint8_t azt_eeprom[AZTECH_EEPROM_SIZE]; /* the eeprom in the Aztech cards is attached to the DSP */
mpu_t *mpu;
mpu_t *mpu;
} sb_dsp_t;
void sb_dsp_input_msg(void *p, uint8_t *msg, uint32_t len);
int sb_dsp_input_sysex(void *p, uint8_t *buffer, uint32_t len, int abort);

View File

@@ -1,11 +1,10 @@
#ifndef SOUND_SN76489_H
# define SOUND_SN76489_H
#define SOUND_SN76489_H
enum
{
SN76496,
NCR8496,
PSSJ
enum {
SN76496,
NCR8496,
PSSJ
};
extern const device_t sn76489_device;
@@ -13,23 +12,22 @@ extern const device_t ncr8496_device;
extern int sn76489_mute;
typedef struct sn76489_t
{
int stat[4];
int latch[4], count[4];
int freqlo[4], freqhi[4];
int vol[4];
uint32_t shift;
uint8_t noise;
int lasttone;
uint8_t firstdat;
int type;
int extra_divide;
typedef struct sn76489_t {
int stat[4];
int latch[4], count[4];
int freqlo[4], freqhi[4];
int vol[4];
uint32_t shift;
uint8_t noise;
int lasttone;
uint8_t firstdat;
int type;
int extra_divide;
int16_t buffer[SOUNDBUFLEN];
int pos;
int16_t buffer[SOUNDBUFLEN];
int pos;
double psgconst;
double psgconst;
} sn76489_t;
void sn76489_init(sn76489_t *sn76489, uint16_t base, uint16_t size, int type, int freq);

View File

@@ -18,17 +18,16 @@
*/
#ifndef SOUND_SPEAKER_H
# define SOUND_SPEAKER_H
#define SOUND_SPEAKER_H
extern int speaker_mute;
extern int speaker_mute;
extern int speaker_gated;
extern int speaker_enable, was_speaker_enable;
extern int speaker_gated;
extern int speaker_enable, was_speaker_enable;
extern void speaker_init();
extern void speaker_init();
extern void speaker_set_count(uint8_t new_m, int new_count);
extern void speaker_update(void);
extern void speaker_set_count(uint8_t new_m, int new_count);
extern void speaker_update(void);
#endif /*SOUND_SPEAKER_H*/

View File

@@ -1,26 +1,25 @@
#ifndef SOUND_YM7128_H
# define SOUND_YM7128_H
#define SOUND_YM7128_H
typedef struct ym7128_t
{
int a0, sci;
uint8_t dat;
typedef struct ym7128_t {
int a0, sci;
uint8_t dat;
int reg_sel;
uint8_t regs[32];
int reg_sel;
uint8_t regs[32];
int gl[8], gr[8];
int vm, vc, vl, vr;
int c0, c1;
int t[9];
int gl[8], gr[8];
int vm, vc, vl, vr;
int c0, c1;
int t[9];
int16_t filter_dat;
int16_t prev_l, prev_r;
int16_t filter_dat;
int16_t prev_l, prev_r;
int16_t delay_buffer[2400];
int delay_pos;
int16_t delay_buffer[2400];
int delay_pos;
int16_t last_samp;
int16_t last_samp;
} ym7128_t;
void ym7128_init(ym7128_t *ym7128);

View File

@@ -1,78 +1,76 @@
/*
* 86Box A hypervisor and IBM PC system emulator that specializes in
* running old operating systems and software designed for IBM
* PC systems and compatibles from 1981 through fairly recent
* system designs based on the PCI bus.
* 86Box A hypervisor and IBM PC system emulator that specializes in
* running old operating systems and software designed for IBM
* PC systems and compatibles from 1981 through fairly recent
* system designs based on the PCI bus.
*
* This file is part of the 86Box distribution.
* This file is part of the 86Box distribution.
*
* Sound emulation core.
* Sound emulation core.
*
*
*
* Authors: Sarah Walker, <http://pcem-emulator.co.uk/>
* Miran Grca, <mgrca8@gmail.com>
* Authors: Sarah Walker, <http://pcem-emulator.co.uk/>
* Miran Grca, <mgrca8@gmail.com>
*
* Copyright 2008-2018 Sarah Walker.
* Copyright 2016-2018 Miran Grca.
* Copyright 2008-2018 Sarah Walker.
* Copyright 2016-2018 Miran Grca.
*/
#ifndef EMU_SOUND_H
# define EMU_SOUND_H
#define EMU_SOUND_H
extern int sound_gain;
#define SOUNDBUFLEN (48000/50)
#define CD_FREQ 44100
#define CD_BUFLEN (CD_FREQ / 10)
#define SOUNDBUFLEN (48000 / 50)
#define CD_FREQ 44100
#define CD_BUFLEN (CD_FREQ / 10)
enum {
SOUND_NONE = 0,
SOUND_INTERNAL
};
extern int ppispeakon;
extern int gated,
speakval,
speakon;
extern int ppispeakon;
extern int gated,
speakval,
speakon;
extern int sound_pos_global;
extern int sound_card_current;
extern int sound_pos_global;
extern int sound_card_current;
extern void sound_add_handler(void (*get_buffer)(int32_t *buffer,
int len, void *p),
void *p);
extern void sound_set_cd_audio_filter(void (*filter)(int channel,
double *buffer, void *p),
void *p);
extern void sound_add_handler(void (*get_buffer)(int32_t *buffer, \
int len, void *p), void *p);
extern void sound_set_cd_audio_filter(void (*filter)(int channel, \
double *buffer, void *p), void *p);
extern int sound_card_available(int card);
extern int sound_card_available(int card);
#ifdef EMU_DEVICE_H
extern const device_t *sound_card_getdevice(int card);
extern const device_t *sound_card_getdevice(int card);
#endif
extern int sound_card_has_config(int card);
extern char *sound_card_get_internal_name(int card);
extern int sound_card_get_from_internal_name(char *s);
extern void sound_card_init(void);
extern void sound_set_cd_volume(unsigned int vol_l, unsigned int vol_r);
extern int sound_card_has_config(int card);
extern char *sound_card_get_internal_name(int card);
extern int sound_card_get_from_internal_name(char *s);
extern void sound_card_init(void);
extern void sound_set_cd_volume(unsigned int vol_l, unsigned int vol_r);
extern void sound_speed_changed(void);
extern void sound_speed_changed(void);
extern void sound_init(void);
extern void sound_reset(void);
extern void sound_init(void);
extern void sound_reset(void);
extern void sound_card_reset(void);
extern void sound_card_reset(void);
extern void sound_cd_thread_end(void);
extern void sound_cd_thread_reset(void);
extern void closeal(void);
extern void inital(void);
extern void givealbuffer(void *buf);
extern void givealbuffer_cd(void *buf);
extern void sound_cd_thread_end(void);
extern void sound_cd_thread_reset(void);
extern void closeal(void);
extern void inital(void);
extern void givealbuffer(void *buf);
extern void givealbuffer_cd(void *buf);
#ifdef EMU_DEVICE_H
/* AdLib and AdLib Gold */
@@ -94,20 +92,20 @@ extern const device_t cms_device;
/* Gravis UltraSound and UltraSound Max */
extern const device_t gus_device;
#if defined(DEV_BRANCH) && defined(USE_PAS16)
# if defined(DEV_BRANCH) && defined(USE_PAS16)
/* Pro Audio Spectrum 16 */
extern const device_t pas16_device;
#endif
# endif
/* IBM PS/1 Audio Card */
extern const device_t ps1snd_device;
/* Tandy PSSJ */
extern const device_t pssj_device;
#if defined(DEV_BRANCH) && defined(USE_TANDY_ISA)
# if defined(DEV_BRANCH) && defined(USE_TANDY_ISA)
extern const device_t pssj_isa_device;
extern const device_t tndy_device;
#endif
# endif
/* Creative Labs Sound Blaster */
extern const device_t sb_1_device;
@@ -142,4 +140,4 @@ extern const device_t cs4237b_device;
extern const device_t cs4238b_device;
#endif
#endif /*EMU_SOUND_H*/
#endif /*EMU_SOUND_H*/

View File

@@ -1,69 +1,69 @@
/*
* 86Box A hypervisor and IBM PC system emulator that specializes in
* running old operating systems and software designed for IBM
* PC systems and compatibles from 1981 through fairly recent
* system designs based on the PCI bus.
* 86Box A hypervisor and IBM PC system emulator that specializes in
* running old operating systems and software designed for IBM
* PC systems and compatibles from 1981 through fairly recent
* system designs based on the PCI bus.
*
* This file is part of the 86Box distribution.
* This file is part of the 86Box distribution.
*
* MIDI device core module.
* MIDI device core module.
*
*
*
* Authors: Sarah Walker, <http://pcem-emulator.co.uk/>
* Miran Grca, <mgrca8@gmail.com>
* Bit,
* DOSBox Team,
* Authors: Sarah Walker, <http://pcem-emulator.co.uk/>
* Miran Grca, <mgrca8@gmail.com>
* Bit,
* DOSBox Team,
*
* Copyright 2008-2020 Sarah Walker.
* Copyright 2016-2020 Miran Grca.
* Copyright 2016-2020 Bit.
* Copyright 2008-2020 DOSBox Team.
* Copyright 2008-2020 Sarah Walker.
* Copyright 2016-2020 Miran Grca.
* Copyright 2016-2020 Bit.
* Copyright 2008-2020 DOSBox Team.
*/
#include <stdio.h>
#include <stdint.h>
#include <string.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <wchar.h>
#include <86box/86box.h>
#include <86box/device.h>
#include <86box/plat.h>
#include <86box/midi.h>
#include <86box/plat.h>
int midi_device_current = 0;
static int midi_device_last = 0;
int midi_input_device_current = 0;
static int midi_input_device_last = 0;
int midi_device_current = 0;
static int midi_device_last = 0;
int midi_input_device_current = 0;
static int midi_input_device_last = 0;
midi_t *midi = NULL, *midi_in = NULL;
midi_in_handler_t *mih_first = NULL, *mih_last = NULL,
*mih_cur = NULL;
*mih_cur = NULL;
uint8_t MIDI_InSysexBuf[SYSEX_SIZE];
uint8_t MIDI_evt_len[256] = {
0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0, /* 0x00 */
0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0, /* 0x10 */
0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0, /* 0x20 */
0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0, /* 0x30 */
0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0, /* 0x40 */
0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0, /* 0x50 */
0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0, /* 0x60 */
0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0, /* 0x70 */
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 0x00 */
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 0x10 */
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 0x20 */
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 0x30 */
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 0x40 */
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 0x50 */
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 0x60 */
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 0x70 */
3,3,3,3, 3,3,3,3, 3,3,3,3, 3,3,3,3, /* 0x80 */
3,3,3,3, 3,3,3,3, 3,3,3,3, 3,3,3,3, /* 0x90 */
3,3,3,3, 3,3,3,3, 3,3,3,3, 3,3,3,3, /* 0xa0 */
3,3,3,3, 3,3,3,3, 3,3,3,3, 3,3,3,3, /* 0xb0 */
3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, /* 0x80 */
3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, /* 0x90 */
3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, /* 0xa0 */
3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, /* 0xb0 */
2,2,2,2, 2,2,2,2, 2,2,2,2, 2,2,2,2, /* 0xc0 */
2,2,2,2, 2,2,2,2, 2,2,2,2, 2,2,2,2, /* 0xd0 */
2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, /* 0xc0 */
2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, /* 0xd0 */
3,3,3,3, 3,3,3,3, 3,3,3,3, 3,3,3,3, /* 0xe0 */
3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, /* 0xe0 */
0,2,3,2, 0,0,1,0, 1,0,1,1, 1,0,1,0 /* 0xf0 */
0, 2, 3, 2, 0, 0, 1, 0, 1, 0, 1, 1, 1, 0, 1, 0 /* 0xf0 */
};
typedef struct
@@ -72,104 +72,109 @@ typedef struct
} MIDI_DEVICE, MIDI_IN_DEVICE;
static const device_t midi_none_device = {
"None",
"none",
0, 0,
NULL, NULL, NULL,
{ NULL }, NULL, NULL,
NULL
"None",
"none",
0,
0,
NULL,
NULL,
NULL,
{ NULL },
NULL,
NULL,
NULL
};
static const MIDI_DEVICE devices[] =
{
{ &midi_none_device },
static const MIDI_DEVICE devices[] = {
// clang-format off
{ &midi_none_device },
#ifdef USE_FLUIDSYNTH
{ &fluidsynth_device },
{ &fluidsynth_device },
#endif
#ifdef USE_MUNT
{ &mt32_device },
{ &cm32l_device },
{ &mt32_device },
{ &cm32l_device },
#endif
{ &rtmidi_device },
{ NULL }
{ &rtmidi_device },
{ NULL }
// clang-format on
};
static const device_t midi_in_none_device = {
"None",
"none",
0, 0,
NULL, NULL, NULL,
{ NULL }, NULL, NULL,
NULL
"None",
"none",
0,
0,
NULL,
NULL,
NULL,
{ NULL },
NULL,
NULL,
NULL
};
static const MIDI_IN_DEVICE midi_in_devices[] =
{
{ &midi_in_none_device },
{ &rtmidi_input_device },
{ NULL }
static const MIDI_IN_DEVICE midi_in_devices[] = {
// clang-format off
{ &midi_in_none_device },
{ &rtmidi_input_device },
{ NULL }
// clang-format on
};
int
midi_device_available(int card)
{
if (devices[card].device)
return device_available(devices[card].device);
return device_available(devices[card].device);
return 1;
}
const device_t *
midi_device_getdevice(int card)
{
return devices[card].device;
}
int
midi_device_has_config(int card)
{
if (!devices[card].device)
return 0;
return 0;
return devices[card].device->config ? 1 : 0;
}
char *
midi_device_get_internal_name(int card)
{
return device_get_internal_name(devices[card].device);
}
int
midi_device_get_from_internal_name(char *s)
{
int c = 0;
while (devices[c].device != NULL) {
if (!strcmp(devices[c].device->internal_name, s))
return c;
c++;
if (!strcmp(devices[c].device->internal_name, s))
return c;
c++;
}
return 0;
}
void
midi_device_init()
{
if (devices[midi_device_current].device)
device_add(devices[midi_device_current].device);
device_add(devices[midi_device_current].device);
midi_device_last = midi_device_current;
}
void
midi_init(midi_device_t* device)
midi_init(midi_device_t *device)
{
midi = (midi_t *) malloc(sizeof(midi_t));
memset(midi, 0, sizeof(midi_t));
@@ -178,26 +183,25 @@ midi_init(midi_device_t* device)
}
void
midi_in_init(midi_device_t* device, midi_t **mididev)
midi_in_init(midi_device_t *device, midi_t **mididev)
{
*mididev = (midi_t *)malloc(sizeof(midi_t));
*mididev = (midi_t *) malloc(sizeof(midi_t));
memset(*mididev, 0, sizeof(midi_t));
(*mididev)->m_in_device = device;
}
void
midi_close(void)
{
if (midi && midi->m_out_device) {
free(midi->m_out_device);
midi->m_out_device = NULL;
free(midi->m_out_device);
midi->m_out_device = NULL;
}
if (midi) {
free(midi);
midi = NULL;
free(midi);
midi = NULL;
}
}
@@ -205,416 +209,394 @@ void
midi_in_close(void)
{
if (midi_in && midi_in->m_in_device) {
free(midi_in->m_in_device);
midi_in->m_in_device = NULL;
free(midi_in->m_in_device);
midi_in->m_in_device = NULL;
}
if (midi_in) {
free(midi_in);
midi_in = NULL;
free(midi_in);
midi_in = NULL;
}
}
void
midi_poll(void)
{
if (midi && midi->m_out_device && midi->m_out_device->poll)
midi->m_out_device->poll();
midi->m_out_device->poll();
}
void
play_msg(uint8_t *msg)
{
if (midi->m_out_device->play_msg)
midi->m_out_device->play_msg(msg);
midi->m_out_device->play_msg(msg);
}
void
play_sysex(uint8_t *sysex, unsigned int len)
{
if (midi->m_out_device->play_sysex)
midi->m_out_device->play_sysex(sysex, len);
midi->m_out_device->play_sysex(sysex, len);
}
int
midi_in_device_available(int card)
{
if (midi_in_devices[card].device)
return device_available(midi_in_devices[card].device);
return device_available(midi_in_devices[card].device);
return 1;
}
const device_t *
midi_in_device_getdevice(int card)
{
return midi_in_devices[card].device;
}
int
midi_in_device_has_config(int card)
{
if (!midi_in_devices[card].device)
return 0;
return 0;
return midi_in_devices[card].device->config ? 1 : 0;
}
char *
midi_in_device_get_internal_name(int card)
{
return device_get_internal_name(midi_in_devices[card].device);
}
int
midi_in_device_get_from_internal_name(char *s)
{
int c = 0;
while (midi_in_devices[c].device != NULL) {
if (!strcmp(midi_in_devices[c].device->internal_name, s))
return c;
c++;
if (!strcmp(midi_in_devices[c].device->internal_name, s))
return c;
c++;
}
return 0;
}
void
midi_in_device_init()
{
if (midi_in_devices[midi_input_device_current].device)
device_add(midi_in_devices[midi_input_device_current].device);
device_add(midi_in_devices[midi_input_device_current].device);
midi_input_device_last = midi_input_device_current;
}
void
midi_raw_out_rt_byte(uint8_t val)
{
if (!midi_in)
return;
return;
if (!midi_in->midi_realtime)
return;
return;
if ((!midi_in->midi_clockout && (val == 0xf8)))
return;
return;
midi_in->midi_cmd_r = val << 24;
/* pclog("Play RT Byte msg\n"); */
play_msg((uint8_t *)&midi_in->midi_cmd_r);
play_msg((uint8_t *) &midi_in->midi_cmd_r);
}
void
midi_raw_out_thru_rt_byte(uint8_t val)
{
if (midi_in && midi_in->thruchan)
midi_raw_out_rt_byte(val);
midi_raw_out_rt_byte(val);
}
void
midi_raw_out_byte(uint8_t val)
{
uint32_t passed_ticks;
if (!midi || !midi->m_out_device)
return;
return;
if ((midi->m_out_device->write && midi->m_out_device->write(val)))
return;
return;
if (midi->midi_sysex_start) {
passed_ticks = plat_get_ticks() - midi->midi_sysex_start;
if (passed_ticks < midi->midi_sysex_delay)
plat_delay_ms(midi->midi_sysex_delay - passed_ticks);
passed_ticks = plat_get_ticks() - midi->midi_sysex_start;
if (passed_ticks < midi->midi_sysex_delay)
plat_delay_ms(midi->midi_sysex_delay - passed_ticks);
}
/* Test for a realtime MIDI message */
if (val >= 0xf8) {
midi->midi_rt_buf[0] = val;
play_msg(midi->midi_rt_buf);
return;
midi->midi_rt_buf[0] = val;
play_msg(midi->midi_rt_buf);
return;
}
/* Test for a active sysex transfer */
if (midi->midi_status == 0xf0) {
if (!(val & 0x80)) {
if (midi->midi_pos < (SYSEX_SIZE-1))
midi->midi_sysex_data[midi->midi_pos++] = val;
return;
} else {
midi->midi_sysex_data[midi->midi_pos++] = 0xf7;
if (!(val & 0x80)) {
if (midi->midi_pos < (SYSEX_SIZE - 1))
midi->midi_sysex_data[midi->midi_pos++] = val;
return;
} else {
midi->midi_sysex_data[midi->midi_pos++] = 0xf7;
if ((midi->midi_sysex_start) && (midi->midi_pos >= 4) && (midi->midi_pos <= 9) &&
(midi->midi_sysex_data[1] == 0x41) && (midi->midi_sysex_data[3] == 0x16)) {
/* pclog("MIDI: Skipping invalid MT-32 SysEx MIDI message\n"); */
} else {
play_sysex(midi->midi_sysex_data, midi->midi_pos);
if (midi->midi_sysex_start) {
if (midi-> midi_sysex_data[5] == 0x7f)
midi->midi_sysex_delay = 290; /* All parameters reset */
else if ((midi->midi_sysex_data[5] == 0x10) && (midi->midi_sysex_data[6] == 0x00) &&
(midi->midi_sysex_data[7] == 0x04))
midi->midi_sysex_delay = 145; /* Viking Child */
else if ((midi->midi_sysex_data[5] == 0x10) && (midi->midi_sysex_data[6] == 0x00) &&
(midi->midi_sysex_data[7] == 0x01))
midi->midi_sysex_delay = 30; /* Dark Sun 1 */
else
midi->midi_sysex_delay = (unsigned int) (((float) (midi->midi_pos) * 1.25f) * 1000.0f / 3125.0f) + 2;
if ((midi->midi_sysex_start) && (midi->midi_pos >= 4) && (midi->midi_pos <= 9) && (midi->midi_sysex_data[1] == 0x41) && (midi->midi_sysex_data[3] == 0x16)) {
/* pclog("MIDI: Skipping invalid MT-32 SysEx MIDI message\n"); */
} else {
play_sysex(midi->midi_sysex_data, midi->midi_pos);
if (midi->midi_sysex_start) {
if (midi->midi_sysex_data[5] == 0x7f)
midi->midi_sysex_delay = 290; /* All parameters reset */
else if ((midi->midi_sysex_data[5] == 0x10) && (midi->midi_sysex_data[6] == 0x00) && (midi->midi_sysex_data[7] == 0x04))
midi->midi_sysex_delay = 145; /* Viking Child */
else if ((midi->midi_sysex_data[5] == 0x10) && (midi->midi_sysex_data[6] == 0x00) && (midi->midi_sysex_data[7] == 0x01))
midi->midi_sysex_delay = 30; /* Dark Sun 1 */
else
midi->midi_sysex_delay = (unsigned int) (((float) (midi->midi_pos) * 1.25f) * 1000.0f / 3125.0f) + 2;
midi->midi_sysex_start = plat_get_ticks();
}
}
}
midi->midi_sysex_start = plat_get_ticks();
}
}
}
}
if (val & 0x80) {
midi->midi_status = val;
midi->midi_cmd_pos = 0;
midi->midi_cmd_len = MIDI_evt_len[val];
if (midi->midi_status == 0xf0) {
midi->midi_sysex_data[0] = 0xf0;
midi->midi_pos = 1;
}
midi->midi_status = val;
midi->midi_cmd_pos = 0;
midi->midi_cmd_len = MIDI_evt_len[val];
if (midi->midi_status == 0xf0) {
midi->midi_sysex_data[0] = 0xf0;
midi->midi_pos = 1;
}
}
if (midi->midi_cmd_len) {
midi->midi_cmd_buf[midi->midi_cmd_pos++] = val;
if (midi->midi_cmd_pos >= midi->midi_cmd_len) {
play_msg(midi->midi_cmd_buf);
midi->midi_cmd_pos = 1;
}
midi->midi_cmd_buf[midi->midi_cmd_pos++] = val;
if (midi->midi_cmd_pos >= midi->midi_cmd_len) {
play_msg(midi->midi_cmd_buf);
midi->midi_cmd_pos = 1;
}
}
}
void
midi_clear_buffer(void)
{
if (!midi)
return;
return;
midi->midi_pos = 0;
midi->midi_status = 0x00;
midi->midi_pos = 0;
midi->midi_status = 0x00;
midi->midi_cmd_pos = 0;
midi->midi_cmd_len = 0;
}
void
midi_in_handler(int set, void (*msg)(void *p, uint8_t *msg, uint32_t len), int (*sysex)(void *p, uint8_t *buffer, uint32_t len, int abort), void *p)
{
midi_in_handler_t *temp = NULL, *next;
if (set) {
/* Add MIDI IN handler. */
if ((mih_first == NULL) && (mih_last != NULL))
fatal("Last MIDI IN handler present with no first MIDI IN handler\n");
/* Add MIDI IN handler. */
if ((mih_first == NULL) && (mih_last != NULL))
fatal("Last MIDI IN handler present with no first MIDI IN handler\n");
if ((mih_first != NULL) && (mih_last == NULL))
fatal("First MIDI IN handler present with no last MIDI IN handler\n");
if ((mih_first != NULL) && (mih_last == NULL))
fatal("First MIDI IN handler present with no last MIDI IN handler\n");
temp = (midi_in_handler_t *) malloc(sizeof(midi_in_handler_t));
memset(temp, 0, sizeof(midi_in_handler_t));
temp->msg = msg;
temp->sysex = sysex;
temp->p = p;
temp = (midi_in_handler_t *) malloc(sizeof(midi_in_handler_t));
memset(temp, 0, sizeof(midi_in_handler_t));
temp->msg = msg;
temp->sysex = sysex;
temp->p = p;
if (mih_last == NULL)
mih_first = mih_last = temp;
else {
temp->prev = mih_last;
mih_last = temp;
}
if (mih_last == NULL)
mih_first = mih_last = temp;
else {
temp->prev = mih_last;
mih_last = temp;
}
} else if ((mih_first != NULL) && (mih_last != NULL)) {
temp = mih_first;
temp = mih_first;
while(1) {
if (temp == NULL)
break;
while (1) {
if (temp == NULL)
break;
if ((temp->msg == msg) && (temp->sysex == sysex) && (temp->p == p)) {
if (temp->prev != NULL)
temp->prev->next = temp->next;
if ((temp->msg == msg) && (temp->sysex == sysex) && (temp->p == p)) {
if (temp->prev != NULL)
temp->prev->next = temp->next;
if (temp->next != NULL)
temp->next->prev = temp->prev;
if (temp->next != NULL)
temp->next->prev = temp->prev;
next = temp->next;
next = temp->next;
if (temp == mih_first) {
mih_first = NULL;
if (next == NULL)
mih_last = NULL;
}
if (temp == mih_first) {
mih_first = NULL;
if (next == NULL)
mih_last = NULL;
}
if (temp == mih_last)
mih_last = NULL;
if (temp == mih_last)
mih_last = NULL;
free(temp);
temp = next;
free(temp);
temp = next;
if (next == NULL)
break;
}
}
if (next == NULL)
break;
}
}
}
}
void
midi_in_handlers_clear(void)
{
midi_in_handler_t *temp = mih_first, *next;
while(1) {
if (temp == NULL)
break;
while (1) {
if (temp == NULL)
break;
next = temp->next;
free(temp);
next = temp->next;
free(temp);
temp = next;
temp = next;
if (next == NULL)
break;
if (next == NULL)
break;
}
mih_first = mih_last = NULL;
}
void
midi_in_msg(uint8_t *msg, uint32_t len)
{
midi_in_handler_t *temp = mih_first;
while(1) {
if (temp == NULL)
break;
while (1) {
if (temp == NULL)
break;
if (temp->msg)
temp->msg(temp->p, msg, len);
if (temp->msg)
temp->msg(temp->p, msg, len);
temp = temp->next;
temp = temp->next;
if (temp == NULL)
break;
if (temp == NULL)
break;
}
}
static void
midi_start_sysex(uint8_t *buffer, uint32_t len)
{
midi_in_handler_t *temp = mih_first;
while(1) {
if (temp == NULL)
break;
while (1) {
if (temp == NULL)
break;
temp->cnt = 5;
temp->buf = buffer;
temp->len = len;
temp->cnt = 5;
temp->buf = buffer;
temp->len = len;
temp = temp->next;
temp = temp->next;
if (temp == NULL)
break;
if (temp == NULL)
break;
}
}
/* Returns:
0 = All handlers have returnd 0;
1 = There are still handlers to go. */
0 = All handlers have returnd 0;
1 = There are still handlers to go. */
static int
midi_do_sysex(void)
{
midi_in_handler_t *temp = mih_first;
int ret, cnt_acc = 0;
int ret, cnt_acc = 0;
while(1) {
if (temp == NULL)
break;
while (1) {
if (temp == NULL)
break;
/* Do nothing if the handler has a zero count. */
if ((temp->cnt > 0) || (temp->len > 0)) {
ret = 0;
if (temp->sysex) {
if (temp->cnt == 0)
ret = temp->sysex(temp->p, temp->buf, 0, 0);
else
ret = temp->sysex(temp->p, temp->buf, temp->len, 0);
}
/* Do nothing if the handler has a zero count. */
if ((temp->cnt > 0) || (temp->len > 0)) {
ret = 0;
if (temp->sysex) {
if (temp->cnt == 0)
ret = temp->sysex(temp->p, temp->buf, 0, 0);
else
ret = temp->sysex(temp->p, temp->buf, temp->len, 0);
}
/* If count is 0 and length is 0, then this is just a finishing
call to temp->sysex(), so skip this entire block. */
if (temp->cnt > 0) {
if (ret) {
/* Decrease or reset the counter. */
if (temp->len == ret)
temp->cnt--;
else
temp->cnt = 5;
/* If count is 0 and length is 0, then this is just a finishing
call to temp->sysex(), so skip this entire block. */
if (temp->cnt > 0) {
if (ret) {
/* Decrease or reset the counter. */
if (temp->len == ret)
temp->cnt--;
else
temp->cnt = 5;
/* Advance the buffer pointer and remember the
remaining length. */
temp->buf += (temp->len - ret);
temp->len = ret;
} else {
/* Set count to 0 so that this handler will be
ignored on the next interation. */
temp->cnt = 0;
/* Advance the buffer pointer and remember the
remaining length. */
temp->buf += (temp->len - ret);
temp->len = ret;
} else {
/* Set count to 0 so that this handler will be
ignored on the next interation. */
temp->cnt = 0;
/* Reset the buffer pointer and length. */
temp->buf = NULL;
temp->len = 0;
}
/* Reset the buffer pointer and length. */
temp->buf = NULL;
temp->len = 0;
}
/* If the remaining count is above zero, add it to the
accumulator. */
if (temp->cnt > 0)
cnt_acc |= temp->cnt;
}
}
/* If the remaining count is above zero, add it to the
accumulator. */
if (temp->cnt > 0)
cnt_acc |= temp->cnt;
}
}
temp = temp->next;
temp = temp->next;
if (temp == NULL)
break;
if (temp == NULL)
break;
}
/* Return 0 if all handlers have returned 0 or all the counts are otherwise 0. */
if (cnt_acc == 0)
return 0;
return 0;
else
return 1;
return 1;
}
void
midi_in_sysex(uint8_t *buffer, uint32_t len)
{
midi_start_sysex(buffer, len);
while (1) {
/* This will return 0 if all theh handlers have either
timed out or otherwise indicated it is time to stop. */
if (midi_do_sysex())
plat_delay_ms(5); /* msec */
else
break;
/* This will return 0 if all theh handlers have either
timed out or otherwise indicated it is time to stop. */
if (midi_do_sysex())
plat_delay_ms(5); /* msec */
else
break;
}
}

File diff suppressed because it is too large Load Diff

View File

@@ -1,18 +1,18 @@
#include <stdio.h>
#include <stdint.h>
#include <string.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <wchar.h>
#include <mt32emu/c_interface/c_interface.h>
#include <86box/86box.h>
#include <86box/device.h>
#include <86box/mem.h>
#include <86box/rom.h>
#include <86box/plat.h>
#include <86box/ui.h>
#include <86box/sound.h>
#include <86box/midi.h>
#include <86box/plat.h>
#include <86box/rom.h>
#include <86box/sound.h>
#include <86box/ui.h>
#include <mt32emu/c_interface/c_interface.h>
extern void givealbuffer_midi(void *buf, uint32_t size);
extern void al_set_midi(int freq, int buf_size);
@@ -20,375 +20,384 @@ extern void al_set_midi(int freq, int buf_size);
static void display_mt32_message(void *instance_data, const char *message);
static const mt32emu_report_handler_i_v0 handler_mt32_v0 = {
/** Returns the actual interface version ID */
NULL, //mt32emu_report_handler_version (*getVersionID)(mt32emu_report_handler_i i);
/** Returns the actual interface version ID */
NULL, // mt32emu_report_handler_version (*getVersionID)(mt32emu_report_handler_i i);
/** Callback for debug messages, in vprintf() format */
NULL, //void (*printDebug)(void *instance_data, const char *fmt, va_list list);
/** Callbacks for reporting errors */
NULL, //void (*onErrorControlROM)(void *instance_data);
NULL, //void (*onErrorPCMROM)(void *instance_data);
/** Callback for reporting about displaying a new custom message on LCD */
display_mt32_message, //void (*showLCDMessage)(void *instance_data, const char *message);
/** Callback for reporting actual processing of a MIDI message */
NULL, //void (*onMIDIMessagePlayed)(void *instance_data);
/**
* Callback for reporting an overflow of the input MIDI queue.
* Returns MT32EMU_BOOL_TRUE if a recovery action was taken
* and yet another attempt to enqueue the MIDI event is desired.
*/
NULL, //mt32emu_boolean (*onMIDIQueueOverflow)(void *instance_data);
/**
* Callback invoked when a System Realtime MIDI message is detected in functions
* mt32emu_parse_stream and mt32emu_play_short_message and the likes.
*/
NULL, //void (*onMIDISystemRealtime)(void *instance_data, mt32emu_bit8u system_realtime);
/** Callbacks for reporting system events */
NULL, //void (*onDeviceReset)(void *instance_data);
NULL, //void (*onDeviceReconfig)(void *instance_data);
/** Callbacks for reporting changes of reverb settings */
NULL, //void (*onNewReverbMode)(void *instance_data, mt32emu_bit8u mode);
NULL, //void (*onNewReverbTime)(void *instance_data, mt32emu_bit8u time);
NULL, //void (*onNewReverbLevel)(void *instance_data, mt32emu_bit8u level);
/** Callbacks for reporting various information */
NULL, //void (*onPolyStateChanged)(void *instance_data, mt32emu_bit8u part_num);
NULL, //void (*onProgramChanged)(void *instance_data, mt32emu_bit8u part_num, const char *sound_group_name, const char *patch_name);
/** Callback for debug messages, in vprintf() format */
NULL, // void (*printDebug)(void *instance_data, const char *fmt, va_list list);
/** Callbacks for reporting errors */
NULL, // void (*onErrorControlROM)(void *instance_data);
NULL, // void (*onErrorPCMROM)(void *instance_data);
/** Callback for reporting about displaying a new custom message on LCD */
display_mt32_message, // void (*showLCDMessage)(void *instance_data, const char *message);
/** Callback for reporting actual processing of a MIDI message */
NULL, // void (*onMIDIMessagePlayed)(void *instance_data);
/**
* Callback for reporting an overflow of the input MIDI queue.
* Returns MT32EMU_BOOL_TRUE if a recovery action was taken
* and yet another attempt to enqueue the MIDI event is desired.
*/
NULL, // mt32emu_boolean (*onMIDIQueueOverflow)(void *instance_data);
/**
* Callback invoked when a System Realtime MIDI message is detected in functions
* mt32emu_parse_stream and mt32emu_play_short_message and the likes.
*/
NULL, // void (*onMIDISystemRealtime)(void *instance_data, mt32emu_bit8u system_realtime);
/** Callbacks for reporting system events */
NULL, // void (*onDeviceReset)(void *instance_data);
NULL, // void (*onDeviceReconfig)(void *instance_data);
/** Callbacks for reporting changes of reverb settings */
NULL, // void (*onNewReverbMode)(void *instance_data, mt32emu_bit8u mode);
NULL, // void (*onNewReverbTime)(void *instance_data, mt32emu_bit8u time);
NULL, // void (*onNewReverbLevel)(void *instance_data, mt32emu_bit8u level);
/** Callbacks for reporting various information */
NULL, // void (*onPolyStateChanged)(void *instance_data, mt32emu_bit8u part_num);
NULL, // void (*onProgramChanged)(void *instance_data, mt32emu_bit8u part_num, const char *sound_group_name, const char *patch_name);
};
/** Alternate report handler for Roland CM-32L */
static const mt32emu_report_handler_i_v0 handler_cm32l_v0 = {
/** Returns the actual interface version ID */
NULL, //mt32emu_report_handler_version (*getVersionID)(mt32emu_report_handler_i i);
/** Returns the actual interface version ID */
NULL, // mt32emu_report_handler_version (*getVersionID)(mt32emu_report_handler_i i);
/** Callback for debug messages, in vprintf() format */
NULL, //void (*printDebug)(void *instance_data, const char *fmt, va_list list);
/** Callbacks for reporting errors */
NULL, //void (*onErrorControlROM)(void *instance_data);
NULL, //void (*onErrorPCMROM)(void *instance_data);
/** Callback for reporting about displaying a new custom message on LCD */
NULL, //void (*showLCDMessage)(void *instance_data, const char *message);
/** Callback for reporting actual processing of a MIDI message */
NULL, //void (*onMIDIMessagePlayed)(void *instance_data);
/**
* Callback for reporting an overflow of the input MIDI queue.
* Returns MT32EMU_BOOL_TRUE if a recovery action was taken
* and yet another attempt to enqueue the MIDI event is desired.
*/
NULL, //mt32emu_boolean (*onMIDIQueueOverflow)(void *instance_data);
/**
* Callback invoked when a System Realtime MIDI message is detected in functions
* mt32emu_parse_stream and mt32emu_play_short_message and the likes.
*/
NULL, //void (*onMIDISystemRealtime)(void *instance_data, mt32emu_bit8u system_realtime);
/** Callbacks for reporting system events */
NULL, //void (*onDeviceReset)(void *instance_data);
NULL, //void (*onDeviceReconfig)(void *instance_data);
/** Callbacks for reporting changes of reverb settings */
NULL, //void (*onNewReverbMode)(void *instance_data, mt32emu_bit8u mode);
NULL, //void (*onNewReverbTime)(void *instance_data, mt32emu_bit8u time);
NULL, //void (*onNewReverbLevel)(void *instance_data, mt32emu_bit8u level);
/** Callbacks for reporting various information */
NULL, //void (*onPolyStateChanged)(void *instance_data, mt32emu_bit8u part_num);
NULL, //void (*onProgramChanged)(void *instance_data, mt32emu_bit8u part_num, const char *sound_group_name, const char *patch_name);
/** Callback for debug messages, in vprintf() format */
NULL, // void (*printDebug)(void *instance_data, const char *fmt, va_list list);
/** Callbacks for reporting errors */
NULL, // void (*onErrorControlROM)(void *instance_data);
NULL, // void (*onErrorPCMROM)(void *instance_data);
/** Callback for reporting about displaying a new custom message on LCD */
NULL, // void (*showLCDMessage)(void *instance_data, const char *message);
/** Callback for reporting actual processing of a MIDI message */
NULL, // void (*onMIDIMessagePlayed)(void *instance_data);
/**
* Callback for reporting an overflow of the input MIDI queue.
* Returns MT32EMU_BOOL_TRUE if a recovery action was taken
* and yet another attempt to enqueue the MIDI event is desired.
*/
NULL, // mt32emu_boolean (*onMIDIQueueOverflow)(void *instance_data);
/**
* Callback invoked when a System Realtime MIDI message is detected in functions
* mt32emu_parse_stream and mt32emu_play_short_message and the likes.
*/
NULL, // void (*onMIDISystemRealtime)(void *instance_data, mt32emu_bit8u system_realtime);
/** Callbacks for reporting system events */
NULL, // void (*onDeviceReset)(void *instance_data);
NULL, // void (*onDeviceReconfig)(void *instance_data);
/** Callbacks for reporting changes of reverb settings */
NULL, // void (*onNewReverbMode)(void *instance_data, mt32emu_bit8u mode);
NULL, // void (*onNewReverbTime)(void *instance_data, mt32emu_bit8u time);
NULL, // void (*onNewReverbLevel)(void *instance_data, mt32emu_bit8u level);
/** Callbacks for reporting various information */
NULL, // void (*onPolyStateChanged)(void *instance_data, mt32emu_bit8u part_num);
NULL, // void (*onProgramChanged)(void *instance_data, mt32emu_bit8u part_num, const char *sound_group_name, const char *patch_name);
};
static const mt32emu_report_handler_i handler_mt32 = { &handler_mt32_v0 };
static const mt32emu_report_handler_i handler_mt32 = { &handler_mt32_v0 };
static const mt32emu_report_handler_i handler_cm32l = { &handler_cm32l_v0 };
static mt32emu_context context = NULL;
static int roms_present[2] = {-1, -1};
static mt32emu_context context = NULL;
static int roms_present[2] = { -1, -1 };
mt32emu_return_code mt32_check(const char* func, mt32emu_return_code ret, mt32emu_return_code expected)
mt32emu_return_code
mt32_check(const char *func, mt32emu_return_code ret, mt32emu_return_code expected)
{
if (ret != expected)
{
return 0;
}
return 1;
if (ret != expected) {
return 0;
}
return 1;
}
int mt32_available()
int
mt32_available()
{
if (roms_present[0] < 0)
roms_present[0] = (rom_present("roms/sound/mt32/MT32_CONTROL.ROM") && rom_present("roms/sound/mt32/MT32_PCM.ROM"));
return roms_present[0];
if (roms_present[0] < 0)
roms_present[0] = (rom_present("roms/sound/mt32/MT32_CONTROL.ROM") && rom_present("roms/sound/mt32/MT32_PCM.ROM"));
return roms_present[0];
}
int cm32l_available()
int
cm32l_available()
{
if (roms_present[1] < 0)
roms_present[1] = (rom_present("roms/sound/cm32l/CM32L_CONTROL.ROM") && rom_present("roms/sound/cm32l/CM32L_PCM.ROM"));
return roms_present[1];
if (roms_present[1] < 0)
roms_present[1] = (rom_present("roms/sound/cm32l/CM32L_CONTROL.ROM") && rom_present("roms/sound/cm32l/CM32L_PCM.ROM"));
return roms_present[1];
}
static thread_t *thread_h = NULL;
static event_t *event = NULL;
static event_t *start_event = NULL;
static int mt32_on = 0;
static thread_t *thread_h = NULL;
static event_t *event = NULL;
static event_t *start_event = NULL;
static int mt32_on = 0;
#define RENDER_RATE 100
#define RENDER_RATE 100
#define BUFFER_SEGMENTS 10
static uint32_t samplerate = 44100;
static int buf_size = 0;
static float* buffer = NULL;
static int16_t* buffer_int16 = NULL;
static int midi_pos = 0;
static uint32_t samplerate = 44100;
static int buf_size = 0;
static float *buffer = NULL;
static int16_t *buffer_int16 = NULL;
static int midi_pos = 0;
static void display_mt32_message(void *instance_data, const char *message)
static void
display_mt32_message(void *instance_data, const char *message)
{
int sz = 0;
char* ui_msg = NULL;
int sz = 0;
char *ui_msg = NULL;
sz = snprintf(NULL, 0, "MT-32: %s", message);
sz = snprintf(NULL, 0, "MT-32: %s", message);
ui_msg = calloc(sz + 1, 1);
if (ui_msg)
{
if (ui_msg) {
snprintf(ui_msg, sz, "MT-32: %s", message);
ui_sb_mt32lcd(ui_msg);
}
}
void mt32_stream(float* stream, int len)
void
mt32_stream(float *stream, int len)
{
if (context) mt32emu_render_float(context, stream, len);
if (context)
mt32emu_render_float(context, stream, len);
}
void mt32_stream_int16(int16_t* stream, int len)
void
mt32_stream_int16(int16_t *stream, int len)
{
if (context) mt32emu_render_bit16s(context, stream, len);
if (context)
mt32emu_render_bit16s(context, stream, len);
}
void mt32_poll()
void
mt32_poll()
{
midi_pos++;
if (midi_pos == 48000/RENDER_RATE)
{
midi_pos = 0;
thread_set_event(event);
midi_pos++;
if (midi_pos == 48000 / RENDER_RATE) {
midi_pos = 0;
thread_set_event(event);
}
}
static void
mt32_thread(void *param)
{
int buf_pos = 0;
int bsize = buf_size / BUFFER_SEGMENTS;
float *buf;
int16_t *buf16;
thread_set_event(start_event);
while (mt32_on) {
thread_wait_event(event, -1);
thread_reset_event(event);
if (sound_is_float) {
buf = (float *) ((uint8_t *) buffer + buf_pos);
memset(buf, 0, bsize);
mt32_stream(buf, bsize / (2 * sizeof(float)));
buf_pos += bsize;
if (buf_pos >= buf_size) {
givealbuffer_midi(buffer, buf_size / sizeof(float));
buf_pos = 0;
}
} else {
buf16 = (int16_t *) ((uint8_t *) buffer_int16 + buf_pos);
memset(buf16, 0, bsize);
mt32_stream_int16(buf16, bsize / (2 * sizeof(int16_t)));
buf_pos += bsize;
if (buf_pos >= buf_size) {
givealbuffer_midi(buffer_int16, buf_size / sizeof(int16_t));
buf_pos = 0;
}
}
}
}
static void mt32_thread(void *param)
void
mt32_msg(uint8_t *val)
{
int buf_pos = 0;
int bsize = buf_size / BUFFER_SEGMENTS;
float *buf;
int16_t *buf16;
thread_set_event(start_event);
while (mt32_on)
{
thread_wait_event(event, -1);
thread_reset_event(event);
if (sound_is_float)
{
buf = (float *) ((uint8_t*)buffer + buf_pos);
memset(buf, 0, bsize);
mt32_stream(buf, bsize / (2 * sizeof(float)));
buf_pos += bsize;
if (buf_pos >= buf_size)
{
givealbuffer_midi(buffer, buf_size / sizeof(float));
buf_pos = 0;
}
}
else
{
buf16 = (int16_t *) ((uint8_t*)buffer_int16 + buf_pos);
memset(buf16, 0, bsize);
mt32_stream_int16(buf16, bsize / (2 * sizeof(int16_t)));
buf_pos += bsize;
if (buf_pos >= buf_size)
{
givealbuffer_midi(buffer_int16, buf_size / sizeof(int16_t));
buf_pos = 0;
}
}
}
if (context)
mt32_check("mt32emu_play_msg", mt32emu_play_msg(context, *(uint32_t *) val), MT32EMU_RC_OK);
}
void mt32_msg(uint8_t* val)
void
mt32_sysex(uint8_t *data, unsigned int len)
{
if (context) mt32_check("mt32emu_play_msg", mt32emu_play_msg(context, *(uint32_t*)val), MT32EMU_RC_OK);
if (context)
mt32_check("mt32emu_play_sysex", mt32emu_play_sysex(context, data, len), MT32EMU_RC_OK);
}
void mt32_sysex(uint8_t* data, unsigned int len)
void *
mt32emu_init(char *control_rom, char *pcm_rom)
{
if (context) mt32_check("mt32emu_play_sysex", mt32emu_play_sysex(context, data, len), MT32EMU_RC_OK);
}
midi_device_t *dev;
char fn[512];
void* mt32emu_init(char *control_rom, char *pcm_rom)
{
midi_device_t* dev;
char fn[512];
context = mt32emu_create_context(strstr(control_rom, "CM32L_CONTROL.ROM") ? handler_cm32l : handler_mt32, NULL);
context = mt32emu_create_context(strstr(control_rom, "CM32L_CONTROL.ROM") ? handler_cm32l : handler_mt32, NULL);
if (!rom_getfile(control_rom, fn, 512))
return 0;
if (!mt32_check("mt32emu_add_rom_file", mt32emu_add_rom_file(context, fn), MT32EMU_RC_ADDED_CONTROL_ROM))
return 0;
if (!rom_getfile(pcm_rom, fn, 512))
return 0;
if (!mt32_check("mt32emu_add_rom_file", mt32emu_add_rom_file(context, fn), MT32EMU_RC_ADDED_PCM_ROM))
return 0;
if (!rom_getfile(control_rom, fn, 512)) return 0;
if (!mt32_check("mt32emu_add_rom_file", mt32emu_add_rom_file(context, fn), MT32EMU_RC_ADDED_CONTROL_ROM)) return 0;
if (!rom_getfile(pcm_rom, fn, 512)) return 0;
if (!mt32_check("mt32emu_add_rom_file", mt32emu_add_rom_file(context, fn), MT32EMU_RC_ADDED_PCM_ROM)) return 0;
if (!mt32_check("mt32emu_open_synth", mt32emu_open_synth(context), MT32EMU_RC_OK))
return 0;
if (!mt32_check("mt32emu_open_synth", mt32emu_open_synth(context), MT32EMU_RC_OK)) return 0;
samplerate = mt32emu_get_actual_stereo_output_samplerate(context);
/* buf_size = samplerate/RENDER_RATE*2; */
if (sound_is_float)
{
buf_size = (samplerate/RENDER_RATE)*2*BUFFER_SEGMENTS*sizeof(float);
buffer = malloc(buf_size);
buffer_int16 = NULL;
}
else
{
buf_size = (samplerate/RENDER_RATE)*2*BUFFER_SEGMENTS*sizeof(int16_t);
buffer = NULL;
buffer_int16 = malloc(buf_size);
}
mt32emu_set_output_gain(context, device_get_config_int("output_gain")/100.0f);
mt32emu_set_reverb_enabled(context, device_get_config_int("reverb"));
mt32emu_set_reverb_output_gain(context, device_get_config_int("reverb_output_gain")/100.0f);
mt32emu_set_reversed_stereo_enabled(context, device_get_config_int("reversed_stereo"));
mt32emu_set_nice_amp_ramp_enabled(context, device_get_config_int("nice_ramp"));
al_set_midi(samplerate, buf_size);
dev = malloc(sizeof(midi_device_t));
memset(dev, 0, sizeof(midi_device_t));
dev->play_msg = mt32_msg;
dev->play_sysex = mt32_sysex;
dev->poll = mt32_poll;
midi_init(dev);
mt32_on = 1;
start_event = thread_create_event();
event = thread_create_event();
thread_h = thread_create(mt32_thread, 0);
thread_wait_event(start_event, -1);
thread_reset_event(start_event);
return dev;
}
void *mt32_init(const device_t *info)
{
return mt32emu_init("roms/sound/mt32/MT32_CONTROL.ROM", "roms/sound/mt32/MT32_PCM.ROM");
}
void *cm32l_init(const device_t *info)
{
return mt32emu_init("roms/sound/cm32l/CM32L_CONTROL.ROM", "roms/sound/cm32l/CM32L_PCM.ROM");
}
void mt32_close(void* p)
{
if (!p) return;
mt32_on = 0;
thread_set_event(event);
thread_wait(thread_h);
event = NULL;
start_event = NULL;
thread_h = NULL;
if (context) {
mt32emu_close_synth(context);
mt32emu_free_context(context);
}
context = NULL;
if (buffer)
free(buffer);
buffer = NULL;
if (buffer_int16)
free(buffer_int16);
samplerate = mt32emu_get_actual_stereo_output_samplerate(context);
/* buf_size = samplerate/RENDER_RATE*2; */
if (sound_is_float) {
buf_size = (samplerate / RENDER_RATE) * 2 * BUFFER_SEGMENTS * sizeof(float);
buffer = malloc(buf_size);
buffer_int16 = NULL;
} else {
buf_size = (samplerate / RENDER_RATE) * 2 * BUFFER_SEGMENTS * sizeof(int16_t);
buffer = NULL;
buffer_int16 = malloc(buf_size);
}
mt32emu_set_output_gain(context, device_get_config_int("output_gain") / 100.0f);
mt32emu_set_reverb_enabled(context, device_get_config_int("reverb"));
mt32emu_set_reverb_output_gain(context, device_get_config_int("reverb_output_gain") / 100.0f);
mt32emu_set_reversed_stereo_enabled(context, device_get_config_int("reversed_stereo"));
mt32emu_set_nice_amp_ramp_enabled(context, device_get_config_int("nice_ramp"));
al_set_midi(samplerate, buf_size);
dev = malloc(sizeof(midi_device_t));
memset(dev, 0, sizeof(midi_device_t));
dev->play_msg = mt32_msg;
dev->play_sysex = mt32_sysex;
dev->poll = mt32_poll;
midi_init(dev);
mt32_on = 1;
start_event = thread_create_event();
event = thread_create_event();
thread_h = thread_create(mt32_thread, 0);
thread_wait_event(start_event, -1);
thread_reset_event(start_event);
return dev;
}
static const device_config_t mt32_config[] =
void *
mt32_init(const device_t *info)
{
{
.name = "output_gain",
.description = "Output Gain",
.type = CONFIG_SPINNER,
.spinner =
{
.min = 0,
.max = 100
},
.default_int = 100
return mt32emu_init("roms/sound/mt32/MT32_CONTROL.ROM", "roms/sound/mt32/MT32_PCM.ROM");
}
void *
cm32l_init(const device_t *info)
{
return mt32emu_init("roms/sound/cm32l/CM32L_CONTROL.ROM", "roms/sound/cm32l/CM32L_PCM.ROM");
}
void
mt32_close(void *p)
{
if (!p)
return;
mt32_on = 0;
thread_set_event(event);
thread_wait(thread_h);
event = NULL;
start_event = NULL;
thread_h = NULL;
if (context) {
mt32emu_close_synth(context);
mt32emu_free_context(context);
}
context = NULL;
if (buffer)
free(buffer);
buffer = NULL;
if (buffer_int16)
free(buffer_int16);
buffer_int16 = NULL;
}
static const device_config_t mt32_config[] = {
// clang-format off
{
.name = "output_gain",
.description = "Output Gain",
.type = CONFIG_SPINNER,
.spinner = {
.min = 0,
.max = 100
},
{
.name = "reverb",
.description = "Reverb",
.type = CONFIG_BINARY,
.default_int = 1
.default_int = 100
},
{
.name = "reverb",
.description = "Reverb",
.type = CONFIG_BINARY,
.default_int = 1
},
{
.name = "reverb_output_gain",
.description = "Reverb Output Gain",
.type = CONFIG_SPINNER,
.spinner = {
.min = 0,
.max = 100
},
{
.name = "reverb_output_gain",
.description = "Reverb Output Gain",
.type = CONFIG_SPINNER,
.spinner =
{
.min = 0,
.max = 100
},
.default_int = 100
},
{
.name = "reversed_stereo",
.description = "Reversed stereo",
.type = CONFIG_BINARY,
.default_int = 0
},
{
.name = "nice_ramp",
.description = "Nice ramp",
.type = CONFIG_BINARY,
.default_int = 1
},
{
.type = -1
}
.default_int = 100
},
{
.name = "reversed_stereo",
.description = "Reversed stereo",
.type = CONFIG_BINARY,
.default_int = 0
},
{
.name = "nice_ramp",
.description = "Nice ramp",
.type = CONFIG_BINARY,
.default_int = 1
},
{
.type = -1
}
// clang-format on
};
const device_t mt32_device =
{
"Roland MT-32 Emulation",
"mt32",
0,
0,
mt32_init,
mt32_close,
NULL,
{ mt32_available },
NULL,
NULL,
mt32_config
const device_t mt32_device = {
"Roland MT-32 Emulation",
"mt32",
0,
0,
mt32_init,
mt32_close,
NULL,
{ mt32_available },
NULL,
NULL,
mt32_config
};
const device_t cm32l_device =
{
"Roland CM-32L Emulation",
"cm32l",
0,
0,
cm32l_init,
mt32_close,
NULL,
{ cm32l_available },
NULL,
NULL,
mt32_config
const device_t cm32l_device = {
"Roland CM-32L Emulation",
"cm32l",
0,
0,
cm32l_init,
mt32_close,
NULL,
{ cm32l_available },
NULL,
NULL,
mt32_config
};

View File

@@ -1,17 +1,17 @@
/*
* 86Box A hypervisor and IBM PC system emulator that specializes in
* running old operating systems and software designed for IBM
* PC systems and compatibles from 1981 through fairly recent
* system designs based on the PCI bus.
* 86Box A hypervisor and IBM PC system emulator that specializes in
* running old operating systems and software designed for IBM
* PC systems and compatibles from 1981 through fairly recent
* system designs based on the PCI bus.
*
* This file is part of the 86Box distribution.
* This file is part of the 86Box distribution.
*
* MIDI backend implemented using the RtMidi library.
* MIDI backend implemented using the RtMidi library.
*
* Author: Cacodemon345,
* Miran Grca, <mgrca8@gmail.com>
* Copyright 2021 Cacodemon345.
* Copyright 2021 Miran Grca.
* Author: Cacodemon345,
* Miran Grca, <mgrca8@gmail.com>
* Copyright 2021 Cacodemon345.
* Copyright 2021 Miran Grca.
*/
#if defined __has_include
# if __has_include (<RtMidi.h>)
@@ -36,10 +36,10 @@ extern "C"
#include <86box/config.h>
static RtMidiOut * midiout = nullptr;
static RtMidiIn * midiin = nullptr;
static int midi_out_id = 0, midi_in_id = 0;
static const int midi_lengths[8] = {3, 3, 3, 3, 2, 2, 3, 1};
static RtMidiOut * midiout = nullptr;
static RtMidiIn * midiin = nullptr;
static int midi_out_id = 0, midi_in_id = 0;
static const int midi_lengths[8] = {3, 3, 3, 3, 2, 2, 3, 1};
int
@@ -53,7 +53,7 @@ void
rtmidi_play_msg(uint8_t *msg)
{
if (midiout)
midiout->sendMessage(msg, midi_lengths[(msg[0] >> 4) & 7]);
midiout->sendMessage(msg, midi_lengths[(msg[0] >> 4) & 7]);
}
@@ -61,7 +61,7 @@ void
rtmidi_play_sysex(uint8_t *sysex, unsigned int len)
{
if (midiout)
midiout->sendMessage(sysex, len);
midiout->sendMessage(sysex, len);
}
@@ -76,27 +76,27 @@ rtmidi_init(const device_t *info)
dev->write = rtmidi_write;
try {
if (!midiout) midiout = new RtMidiOut;
if (!midiout) midiout = new RtMidiOut;
} catch (RtMidiError& error) {
pclog("Failed to initialize MIDI output: %s\n", error.getMessage().c_str());
return nullptr;
pclog("Failed to initialize MIDI output: %s\n", error.getMessage().c_str());
return nullptr;
}
midi_out_id = config_get_int((char*)SYSTEM_MIDI_NAME, (char*)"midi", 0);
try {
midiout->openPort(midi_out_id);
midiout->openPort(midi_out_id);
} catch (RtMidiError& error) {
pclog("Fallback to default MIDI output port: %s\n", error.getMessage().c_str());
pclog("Fallback to default MIDI output port: %s\n", error.getMessage().c_str());
try {
midiout->openPort(0);
} catch (RtMidiError& error) {
pclog("Failed to initialize MIDI output: %s\n", error.getMessage().c_str());
delete midiout;
midiout = nullptr;
return nullptr;
}
try {
midiout->openPort(0);
} catch (RtMidiError& error) {
pclog("Failed to initialize MIDI output: %s\n", error.getMessage().c_str());
delete midiout;
midiout = nullptr;
return nullptr;
}
}
midi_init(dev);
@@ -109,7 +109,7 @@ void
rtmidi_close(void *p)
{
if (!midiout)
return;
return;
midiout->closePort();
@@ -124,11 +124,11 @@ int
rtmidi_get_num_devs(void)
{
if (!midiout) {
try {
midiout = new RtMidiOut;
} catch (RtMidiError& error) {
pclog("Failed to initialize MIDI output: %s\n", error.getMessage().c_str());
}
try {
midiout = new RtMidiOut;
} catch (RtMidiError& error) {
pclog("Failed to initialize MIDI output: %s\n", error.getMessage().c_str());
}
}
return midiout ? midiout->getPortCount() : 0;
@@ -148,7 +148,7 @@ rtmidi_input_callback(double timeStamp, std::vector<unsigned char> *message, voi
if (message->front() == 0xF0)
midi_in_sysex(message->data(), message->size());
else
midi_in_msg(message->data(), message->size());
midi_in_msg(message->data(), message->size());
}
@@ -159,28 +159,28 @@ rtmidi_input_init(const device_t *info)
memset(dev, 0, sizeof(midi_device_t));
try {
if (!midiin)
midiin = new RtMidiIn;
if (!midiin)
midiin = new RtMidiIn;
} catch (RtMidiError& error) {
pclog("Failed to initialize MIDI input: %s\n", error.getMessage().c_str());
return nullptr;
pclog("Failed to initialize MIDI input: %s\n", error.getMessage().c_str());
return nullptr;
}
midi_in_id = config_get_int((char*)MIDI_INPUT_NAME, (char*)"midi_input", 0);
try {
midiin->openPort(midi_in_id);
midiin->openPort(midi_in_id);
} catch (RtMidiError& error) {
pclog("Fallback to default MIDI input port: %s\n", error.getMessage().c_str());
pclog("Fallback to default MIDI input port: %s\n", error.getMessage().c_str());
try {
midiin->openPort(0);
} catch (RtMidiError& error) {
pclog("Failed to initialize MIDI input: %s\n", error.getMessage().c_str());
delete midiin;
midiin = nullptr;
return nullptr;
}
try {
midiin->openPort(0);
} catch (RtMidiError& error) {
pclog("Failed to initialize MIDI input: %s\n", error.getMessage().c_str());
delete midiin;
midiin = nullptr;
return nullptr;
}
}
midiin->setCallback(&rtmidi_input_callback);
@@ -215,11 +215,11 @@ int
rtmidi_in_get_num_devs(void)
{
if (!midiin) {
try {
midiin = new RtMidiIn;
} catch (RtMidiError& error) {
pclog("Failed to initialize MIDI input: %s\n", error.getMessage().c_str());
}
try {
midiin = new RtMidiIn;
} catch (RtMidiError& error) {
pclog("Failed to initialize MIDI input: %s\n", error.getMessage().c_str());
}
}
return midiin ? midiin->getPortCount() : 0;
@@ -235,29 +235,29 @@ rtmidi_in_get_dev_name(int num, char *s)
static const device_config_t system_midi_config[] =
{
{
"midi", "MIDI out device", CONFIG_MIDI_OUT, "", 0
"midi", "MIDI out device", CONFIG_MIDI_OUT, "", 0
},
{
"", "", -1
"", "", -1
}
};
static const device_config_t midi_input_config[] =
{
{
"midi_input", "MIDI in device", CONFIG_MIDI_IN, "", 0
"midi_input", "MIDI in device", CONFIG_MIDI_IN, "", 0
},
{
"realtime", "MIDI Real time", CONFIG_BINARY, "", 0
"realtime", "MIDI Real time", CONFIG_BINARY, "", 0
},
{
"thruchan", "MIDI Thru", CONFIG_BINARY, "", 1
"thruchan", "MIDI Thru", CONFIG_BINARY, "", 1
},
{
"clockout", "MIDI Clockout", CONFIG_BINARY, "", 1
"clockout", "MIDI Clockout", CONFIG_BINARY, "", 1
},
{
"", "", -1
"", "", -1
}
};

View File

@@ -1,109 +1,105 @@
/*
* 86Box A hypervisor and IBM PC system emulator that specializes in
* running old operating systems and software designed for IBM
* PC systems and compatibles from 1981 through fairly recent
* system designs based on the PCI bus.
* 86Box A hypervisor and IBM PC system emulator that specializes in
* running old operating systems and software designed for IBM
* PC systems and compatibles from 1981 through fairly recent
* system designs based on the PCI bus.
*
* This file is part of the 86Box distribution.
* This file is part of the 86Box distribution.
*
* Interface to the OpenAL sound processing library.
* Interface to the OpenAL sound processing library.
*
*
*
* Authors: Sarah Walker, <http://pcem-emulator.co.uk/>
* Miran Grca, <mgrca8@gmail.com>
* Authors: Sarah Walker, <http://pcem-emulator.co.uk/>
* Miran Grca, <mgrca8@gmail.com>
*
* Copyright 2008-2019 Sarah Walker.
* Copyright 2016-2019 Miran Grca.
* Copyright 2008-2019 Sarah Walker.
* Copyright 2016-2019 Miran Grca.
*/
#include <math.h>
#include <stdio.h>
#include <stdint.h>
#include <string.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <wchar.h>
# undef AL_API
# undef ALC_API
# define AL_LIBTYPE_STATIC
# define ALC_LIBTYPE_STATIC
# include "AL/al.h"
# include "AL/alc.h"
# include "AL/alext.h"
#undef AL_API
#undef ALC_API
#define AL_LIBTYPE_STATIC
#define ALC_LIBTYPE_STATIC
#include "AL/al.h"
#include "AL/alc.h"
#include "AL/alext.h"
#include <86box/86box.h>
#include <86box/sound.h>
#include <86box/midi.h>
#include <86box/sound.h>
#define FREQ 48000
#define BUFLEN SOUNDBUFLEN
#define FREQ 48000
#define BUFLEN SOUNDBUFLEN
ALuint buffers[4]; /* front and back buffers */
ALuint buffers_cd[4]; /* front and back buffers */
ALuint buffers_midi[4]; /* front and back buffers */
static ALuint source[3]; /* audio source */
ALuint buffers[4]; /* front and back buffers */
ALuint buffers_cd[4]; /* front and back buffers */
ALuint buffers_midi[4]; /* front and back buffers */
static ALuint source[3]; /* audio source */
static int midi_freq = 44100;
static int midi_buf_size = 4410;
static int initialized = 0;
static int sources = 2;
static int midi_freq = 44100;
static int midi_buf_size = 4410;
static int initialized = 0;
static int sources = 2;
static ALCcontext *Context;
static ALCdevice *Device;
static ALCdevice *Device;
void
al_set_midi(int freq, int buf_size)
{
midi_freq = freq;
midi_freq = freq;
midi_buf_size = buf_size;
}
void closeal(void);
ALvoid alutInit(ALint *argc,ALbyte **argv)
ALvoid
alutInit(ALint *argc, ALbyte **argv)
{
/* Open device */
Device = alcOpenDevice((ALCchar *)"");
Device = alcOpenDevice((ALCchar *) "");
if (Device != NULL) {
/* Create context(s) */
Context = alcCreateContext(Device, NULL);
if (Context != NULL) {
/* Set active context */
alcMakeContextCurrent(Context);
}
/* Create context(s) */
Context = alcCreateContext(Device, NULL);
if (Context != NULL) {
/* Set active context */
alcMakeContextCurrent(Context);
}
}
}
ALvoid
alutExit(ALvoid)
{
if (Context != NULL) {
/* Disable context */
alcMakeContextCurrent(NULL);
/* Disable context */
alcMakeContextCurrent(NULL);
/* Release context(s) */
alcDestroyContext(Context);
/* Release context(s) */
alcDestroyContext(Context);
if (Device != NULL) {
/* Close device */
alcCloseDevice(Device);
}
if (Device != NULL) {
/* Close device */
alcCloseDevice(Device);
}
}
}
void
closeal(void)
{
if (!initialized)
return;
return;
alSourceStopv(sources, source);
alDeleteSources(sources, source);
if (sources == 3)
alDeleteBuffers(4, buffers_midi);
alDeleteBuffers(4, buffers_midi);
alDeleteBuffers(4, buffers_cd);
alDeleteBuffers(4, buffers);
@@ -112,168 +108,163 @@ closeal(void)
initialized = 0;
}
void
inital(void)
{
float *buf = NULL, *cd_buf = NULL, *midi_buf = NULL;
float *buf = NULL, *cd_buf = NULL, *midi_buf = NULL;
int16_t *buf_int16 = NULL, *cd_buf_int16 = NULL, *midi_buf_int16 = NULL;
int c;
int c;
char *mdn;
int init_midi = 0;
int init_midi = 0;
if (initialized)
return;
return;
alutInit(0, 0);
atexit(closeal);
mdn = midi_device_get_internal_name(midi_device_current);
if (strcmp(mdn, "none") && strcmp(mdn, SYSTEM_MIDI_INTERNAL_NAME))
init_midi = 1; /* If the device is neither none, nor system MIDI, initialize the
MIDI buffer and source, otherwise, do not. */
init_midi = 1; /* If the device is neither none, nor system MIDI, initialize the
MIDI buffer and source, otherwise, do not. */
sources = 2 + !!init_midi;
if (sound_is_float) {
buf = (float *) malloc((BUFLEN << 1) * sizeof(float));
cd_buf = (float *) malloc((CD_BUFLEN << 1) * sizeof(float));
if (init_midi)
midi_buf = (float *) malloc(midi_buf_size * sizeof(float));
buf = (float *) malloc((BUFLEN << 1) * sizeof(float));
cd_buf = (float *) malloc((CD_BUFLEN << 1) * sizeof(float));
if (init_midi)
midi_buf = (float *) malloc(midi_buf_size * sizeof(float));
} else {
buf_int16 = (int16_t *) malloc((BUFLEN << 1) * sizeof(int16_t));
cd_buf_int16 = (int16_t *) malloc((CD_BUFLEN << 1) * sizeof(int16_t));
if (init_midi)
midi_buf_int16 = (int16_t *) malloc(midi_buf_size * sizeof(int16_t));
buf_int16 = (int16_t *) malloc((BUFLEN << 1) * sizeof(int16_t));
cd_buf_int16 = (int16_t *) malloc((CD_BUFLEN << 1) * sizeof(int16_t));
if (init_midi)
midi_buf_int16 = (int16_t *) malloc(midi_buf_size * sizeof(int16_t));
}
alGenBuffers(4, buffers);
alGenBuffers(4, buffers_cd);
if (init_midi)
alGenBuffers(4, buffers_midi);
alGenBuffers(4, buffers_midi);
if (init_midi)
alGenSources(3, source);
alGenSources(3, source);
else
alGenSources(2, source);
alGenSources(2, source);
alSource3f(source[0], AL_POSITION, 0.0, 0.0, 0.0);
alSource3f(source[0], AL_VELOCITY, 0.0, 0.0, 0.0);
alSource3f(source[0], AL_DIRECTION, 0.0, 0.0, 0.0);
alSourcef (source[0], AL_ROLLOFF_FACTOR, 0.0 );
alSourcei (source[0], AL_SOURCE_RELATIVE, AL_TRUE );
alSource3f(source[1], AL_POSITION, 0.0, 0.0, 0.0);
alSource3f(source[1], AL_VELOCITY, 0.0, 0.0, 0.0);
alSource3f(source[1], AL_DIRECTION, 0.0, 0.0, 0.0);
alSourcef (source[1], AL_ROLLOFF_FACTOR, 0.0 );
alSourcei (source[1], AL_SOURCE_RELATIVE, AL_TRUE );
alSource3f(source[0], AL_POSITION, 0.0, 0.0, 0.0);
alSource3f(source[0], AL_VELOCITY, 0.0, 0.0, 0.0);
alSource3f(source[0], AL_DIRECTION, 0.0, 0.0, 0.0);
alSourcef(source[0], AL_ROLLOFF_FACTOR, 0.0);
alSourcei(source[0], AL_SOURCE_RELATIVE, AL_TRUE);
alSource3f(source[1], AL_POSITION, 0.0, 0.0, 0.0);
alSource3f(source[1], AL_VELOCITY, 0.0, 0.0, 0.0);
alSource3f(source[1], AL_DIRECTION, 0.0, 0.0, 0.0);
alSourcef(source[1], AL_ROLLOFF_FACTOR, 0.0);
alSourcei(source[1], AL_SOURCE_RELATIVE, AL_TRUE);
if (init_midi) {
alSource3f(source[2], AL_POSITION, 0.0, 0.0, 0.0);
alSource3f(source[2], AL_VELOCITY, 0.0, 0.0, 0.0);
alSource3f(source[2], AL_DIRECTION, 0.0, 0.0, 0.0);
alSourcef (source[2], AL_ROLLOFF_FACTOR, 0.0 );
alSourcei (source[2], AL_SOURCE_RELATIVE, AL_TRUE );
alSource3f(source[2], AL_POSITION, 0.0, 0.0, 0.0);
alSource3f(source[2], AL_VELOCITY, 0.0, 0.0, 0.0);
alSource3f(source[2], AL_DIRECTION, 0.0, 0.0, 0.0);
alSourcef(source[2], AL_ROLLOFF_FACTOR, 0.0);
alSourcei(source[2], AL_SOURCE_RELATIVE, AL_TRUE);
}
if (sound_is_float) {
memset(buf,0,BUFLEN*2*sizeof(float));
memset(cd_buf,0,BUFLEN*2*sizeof(float));
if (init_midi)
memset(midi_buf,0,midi_buf_size*sizeof(float));
memset(buf, 0, BUFLEN * 2 * sizeof(float));
memset(cd_buf, 0, BUFLEN * 2 * sizeof(float));
if (init_midi)
memset(midi_buf, 0, midi_buf_size * sizeof(float));
} else {
memset(buf_int16,0,BUFLEN*2*sizeof(int16_t));
memset(cd_buf_int16,0,BUFLEN*2*sizeof(int16_t));
if (init_midi)
memset(midi_buf_int16,0,midi_buf_size*sizeof(int16_t));
memset(buf_int16, 0, BUFLEN * 2 * sizeof(int16_t));
memset(cd_buf_int16, 0, BUFLEN * 2 * sizeof(int16_t));
if (init_midi)
memset(midi_buf_int16, 0, midi_buf_size * sizeof(int16_t));
}
for (c=0; c<4; c++) {
if (sound_is_float) {
alBufferData(buffers[c], AL_FORMAT_STEREO_FLOAT32, buf, BUFLEN*2*sizeof(float), FREQ);
alBufferData(buffers_cd[c], AL_FORMAT_STEREO_FLOAT32, cd_buf, CD_BUFLEN*2*sizeof(float), CD_FREQ);
if (init_midi)
alBufferData(buffers_midi[c], AL_FORMAT_STEREO_FLOAT32, midi_buf, midi_buf_size*sizeof(float), midi_freq);
} else {
alBufferData(buffers[c], AL_FORMAT_STEREO16, buf_int16, BUFLEN*2*sizeof(int16_t), FREQ);
alBufferData(buffers_cd[c], AL_FORMAT_STEREO16, cd_buf_int16, CD_BUFLEN*2*sizeof(int16_t), CD_FREQ);
if (init_midi)
alBufferData(buffers_midi[c], AL_FORMAT_STEREO16, midi_buf_int16, midi_buf_size*sizeof(int16_t), midi_freq);
}
for (c = 0; c < 4; c++) {
if (sound_is_float) {
alBufferData(buffers[c], AL_FORMAT_STEREO_FLOAT32, buf, BUFLEN * 2 * sizeof(float), FREQ);
alBufferData(buffers_cd[c], AL_FORMAT_STEREO_FLOAT32, cd_buf, CD_BUFLEN * 2 * sizeof(float), CD_FREQ);
if (init_midi)
alBufferData(buffers_midi[c], AL_FORMAT_STEREO_FLOAT32, midi_buf, midi_buf_size * sizeof(float), midi_freq);
} else {
alBufferData(buffers[c], AL_FORMAT_STEREO16, buf_int16, BUFLEN * 2 * sizeof(int16_t), FREQ);
alBufferData(buffers_cd[c], AL_FORMAT_STEREO16, cd_buf_int16, CD_BUFLEN * 2 * sizeof(int16_t), CD_FREQ);
if (init_midi)
alBufferData(buffers_midi[c], AL_FORMAT_STEREO16, midi_buf_int16, midi_buf_size * sizeof(int16_t), midi_freq);
}
}
alSourceQueueBuffers(source[0], 4, buffers);
alSourceQueueBuffers(source[1], 4, buffers_cd);
if (init_midi)
alSourceQueueBuffers(source[2], 4, buffers_midi);
alSourceQueueBuffers(source[2], 4, buffers_midi);
alSourcePlay(source[0]);
alSourcePlay(source[1]);
if (init_midi)
alSourcePlay(source[2]);
alSourcePlay(source[2]);
if (sound_is_float) {
if (init_midi)
free(midi_buf);
free(cd_buf);
free(buf);
if (init_midi)
free(midi_buf);
free(cd_buf);
free(buf);
} else {
if (init_midi)
free(midi_buf_int16);
free(cd_buf_int16);
free(buf_int16);
if (init_midi)
free(midi_buf_int16);
free(cd_buf_int16);
free(buf_int16);
}
initialized = 1;
}
void
givealbuffer_common(void *buf, uint8_t src, int size, int freq)
{
int processed;
int state;
int processed;
int state;
ALuint buffer;
double gain;
if (!initialized)
return;
return;
alGetSourcei(source[src], AL_SOURCE_STATE, &state);
if (state == 0x1014) {
alSourcePlay(source[src]);
alSourcePlay(source[src]);
}
alGetSourcei(source[src], AL_BUFFERS_PROCESSED, &processed);
if (processed >= 1) {
gain = pow(10.0, (double)sound_gain / 20.0);
alListenerf(AL_GAIN, gain);
gain = pow(10.0, (double) sound_gain / 20.0);
alListenerf(AL_GAIN, gain);
alSourceUnqueueBuffers(source[src], 1, &buffer);
alSourceUnqueueBuffers(source[src], 1, &buffer);
if (sound_is_float)
alBufferData(buffer, AL_FORMAT_STEREO_FLOAT32, buf, size * sizeof(float), freq);
else
alBufferData(buffer, AL_FORMAT_STEREO16, buf, size * sizeof(int16_t), freq);
if (sound_is_float)
alBufferData(buffer, AL_FORMAT_STEREO_FLOAT32, buf, size * sizeof(float), freq);
else
alBufferData(buffer, AL_FORMAT_STEREO16, buf, size * sizeof(int16_t), freq);
alSourceQueueBuffers(source[src], 1, &buffer);
alSourceQueueBuffers(source[src], 1, &buffer);
}
}
void
givealbuffer(void *buf)
{
givealbuffer_common(buf, 0, BUFLEN << 1, FREQ);
}
void
givealbuffer_cd(void *buf)
{
givealbuffer_common(buf, 1, CD_BUFLEN << 1, CD_FREQ);
}
void
givealbuffer_midi(void *buf, uint32_t size)
{

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@@ -1,28 +1,29 @@
/*
* 86Box A hypervisor and IBM PC system emulator that specializes in
* running old operating systems and software designed for IBM
* PC systems and compatibles from 1981 through fairly recent
* system designs based on the PCI bus.
* 86Box A hypervisor and IBM PC system emulator that specializes in
* running old operating systems and software designed for IBM
* PC systems and compatibles from 1981 through fairly recent
* system designs based on the PCI bus.
*
* This file is part of the 86Box distribution.
* This file is part of the 86Box distribution.
*
* AD1848 / CS4248 / CS4231 (Windows Sound System) codec emulation.
* AD1848 / CS4248 / CS4231 (Windows Sound System) codec emulation.
*
*
*
* Authors: Sarah Walker, <http://pcem-emulator.co.uk/>
* TheCollector1995, <mariogplayer@gmail.com>
* RichardG, <richardg867@gmail.com>
* Authors: Sarah Walker, <http://pcem-emulator.co.uk/>
* TheCollector1995, <mariogplayer@gmail.com>
* RichardG, <richardg867@gmail.com>
*
* Copyright 2008-2020 Sarah Walker.
* Copyright 2018-2020 TheCollector1995.
* Copyright 2021-2022 RichardG.
* Copyright 2008-2020 Sarah Walker.
* Copyright 2018-2020 TheCollector1995.
* Copyright 2021-2022 RichardG.
*/
#include <stdio.h>
#include <math.h>
#include <stdint.h>
#include <stdio.h>
#include <string.h>
#include <wchar.h>
#include <math.h>
#include <86box/86box.h>
#include <86box/dma.h>
#include <86box/pic.h>
@@ -30,14 +31,11 @@
#include <86box/sound.h>
#include <86box/snd_ad1848.h>
#define CS4231 0x80
#define CS4236 0x03
#define CS4231 0x80
#define CS4236 0x03
static int ad1848_vols_7bits[128];
static double ad1848_vols_5bits_aux_gain[32];
static int ad1848_vols_7bits[128];
static double ad1848_vols_5bits_aux_gain[32];
void
ad1848_setirq(ad1848_t *ad1848, int irq)
@@ -45,485 +43,519 @@ ad1848_setirq(ad1848_t *ad1848, int irq)
ad1848->irq = irq;
}
void
ad1848_setdma(ad1848_t *ad1848, int dma)
{
ad1848->dma = dma;
}
void
ad1848_updatevolmask(ad1848_t *ad1848)
{
if ((ad1848->type >= AD1848_TYPE_CS4235) && ((ad1848->xregs[4] & 0x10) || ad1848->wten))
ad1848->wave_vol_mask = 0x3f;
ad1848->wave_vol_mask = 0x3f;
else
ad1848->wave_vol_mask = 0x7f;
ad1848->wave_vol_mask = 0x7f;
}
static void
ad1848_updatefreq(ad1848_t *ad1848)
{
double freq;
double freq;
uint8_t set = 0;
if (ad1848->type >= AD1848_TYPE_CS4235) {
if (ad1848->xregs[11] & 0x20) {
freq = 16934400LL;
switch (ad1848->xregs[13]) {
case 1: freq /= 353; break;
case 2: freq /= 529; break;
case 3: freq /= 617; break;
case 4: freq /= 1058; break;
case 5: freq /= 1764; break;
case 6: freq /= 2117; break;
case 7: freq /= 2558; break;
default: freq /= 16 * MAX(ad1848->xregs[13], 21); break;
}
set = 1;
} else if (ad1848->regs[22] & 0x80) {
freq = (ad1848->regs[22] & 1) ? 33868800LL : 49152000LL;
set = (ad1848->regs[22] >> 1) & 0x3f;
switch (ad1848->regs[10] & 0x30) {
case 0x00: freq /= 128 * set; break;
case 0x10: freq /= 64 * set; break;
case 0x20: freq /= 256 * set; break;
}
set = 1;
}
if (ad1848->xregs[11] & 0x20) {
freq = 16934400LL;
switch (ad1848->xregs[13]) {
case 1:
freq /= 353;
break;
case 2:
freq /= 529;
break;
case 3:
freq /= 617;
break;
case 4:
freq /= 1058;
break;
case 5:
freq /= 1764;
break;
case 6:
freq /= 2117;
break;
case 7:
freq /= 2558;
break;
default:
freq /= 16 * MAX(ad1848->xregs[13], 21);
break;
}
set = 1;
} else if (ad1848->regs[22] & 0x80) {
freq = (ad1848->regs[22] & 1) ? 33868800LL : 49152000LL;
set = (ad1848->regs[22] >> 1) & 0x3f;
switch (ad1848->regs[10] & 0x30) {
case 0x00:
freq /= 128 * set;
break;
case 0x10:
freq /= 64 * set;
break;
case 0x20:
freq /= 256 * set;
break;
}
set = 1;
}
}
if (!set) {
freq = (ad1848->regs[8] & 1) ? 16934400LL : 24576000LL;
switch ((ad1848->regs[8] >> 1) & 7) {
case 0: freq /= 3072; break;
case 1: freq /= 1536; break;
case 2: freq /= 896; break;
case 3: freq /= 768; break;
case 4: freq /= 448; break;
case 5: freq /= 384; break;
case 6: freq /= 512; break;
case 7: freq /= 2560; break;
}
freq = (ad1848->regs[8] & 1) ? 16934400LL : 24576000LL;
switch ((ad1848->regs[8] >> 1) & 7) {
case 0:
freq /= 3072;
break;
case 1:
freq /= 1536;
break;
case 2:
freq /= 896;
break;
case 3:
freq /= 768;
break;
case 4:
freq /= 448;
break;
case 5:
freq /= 384;
break;
case 6:
freq /= 512;
break;
case 7:
freq /= 2560;
break;
}
}
ad1848->freq = freq;
ad1848->freq = freq;
ad1848->timer_latch = (uint64_t) ((double) TIMER_USEC * (1000000.0 / (double) ad1848->freq));
}
uint8_t
ad1848_read(uint16_t addr, void *priv)
{
ad1848_t *ad1848 = (ad1848_t *) priv;
uint8_t ret = 0xff;
uint8_t ret = 0xff;
switch (addr & 3) {
case 0: /* Index */
ret = ad1848->index | ad1848->trd | ad1848->mce;
break;
case 0: /* Index */
ret = ad1848->index | ad1848->trd | ad1848->mce;
break;
case 1:
ret = ad1848->regs[ad1848->index];
switch (ad1848->index) {
case 11:
ret ^= 0x20;
ad1848->regs[ad1848->index] = ret;
break;
case 1:
ret = ad1848->regs[ad1848->index];
switch (ad1848->index) {
case 11:
ret ^= 0x20;
ad1848->regs[ad1848->index] = ret;
break;
case 18: case 19:
if (ad1848->type >= AD1848_TYPE_CS4235) {
if ((ad1848->xregs[4] & 0x14) == 0x14) /* FM remapping */
ret = ad1848->xregs[ad1848->index - 12]; /* real FM volume on registers 6 and 7 */
else if (ad1848->wten && !(ad1848->xregs[4] & 0x08)) /* wavetable remapping */
ret = ad1848->xregs[ad1848->index - 2]; /* real wavetable volume on registers 16 and 17 */
}
break;
case 18:
case 19:
if (ad1848->type >= AD1848_TYPE_CS4235) {
if ((ad1848->xregs[4] & 0x14) == 0x14) /* FM remapping */
ret = ad1848->xregs[ad1848->index - 12]; /* real FM volume on registers 6 and 7 */
else if (ad1848->wten && !(ad1848->xregs[4] & 0x08)) /* wavetable remapping */
ret = ad1848->xregs[ad1848->index - 2]; /* real wavetable volume on registers 16 and 17 */
}
break;
case 20: case 21:
/* Backdoor to the Control/RAM registers on CS4235. */
if ((ad1848->type == AD1848_TYPE_CS4235) && (ad1848->xregs[18] & 0x80))
ret = ad1848->cram_read(ad1848->index - 15, ad1848->cram_priv);
break;
case 20:
case 21:
/* Backdoor to the Control/RAM registers on CS4235. */
if ((ad1848->type == AD1848_TYPE_CS4235) && (ad1848->xregs[18] & 0x80))
ret = ad1848->cram_read(ad1848->index - 15, ad1848->cram_priv);
break;
case 23:
if ((ad1848->type >= AD1848_TYPE_CS4235) && (ad1848->regs[23] & 0x08)) {
if ((ad1848->xindex & 0xfe) == 0x00) /* remapped line volume */
ret = ad1848->regs[18 + ad1848->xindex];
else
ret = ad1848->xregs[ad1848->xindex];
}
break;
}
break;
case 23:
if ((ad1848->type >= AD1848_TYPE_CS4235) && (ad1848->regs[23] & 0x08)) {
if ((ad1848->xindex & 0xfe) == 0x00) /* remapped line volume */
ret = ad1848->regs[18 + ad1848->xindex];
else
ret = ad1848->xregs[ad1848->xindex];
}
break;
}
break;
case 2:
ret = ad1848->status;
break;
case 2:
ret = ad1848->status;
break;
}
return ret;
}
void
ad1848_write(uint16_t addr, uint8_t val, void *priv)
{
ad1848_t *ad1848 = (ad1848_t *) priv;
uint8_t temp = 0, updatefreq = 0;
uint8_t temp = 0, updatefreq = 0;
switch (addr & 3) {
case 0: /* Index */
if ((ad1848->regs[12] & 0x40) && (ad1848->type >= AD1848_TYPE_CS4231))
ad1848->index = val & 0x1f; /* cs4231a extended mode enabled */
else
ad1848->index = val & 0x0f; /* ad1848/cs4248 mode TODO: some variants/clones DO NOT mirror, just ignore the writes? */
if (ad1848->type >= AD1848_TYPE_CS4235)
ad1848->regs[23] &= ~0x08; /* clear XRAE */
ad1848->trd = val & 0x20;
ad1848->mce = val & 0x40;
break;
case 0: /* Index */
if ((ad1848->regs[12] & 0x40) && (ad1848->type >= AD1848_TYPE_CS4231))
ad1848->index = val & 0x1f; /* cs4231a extended mode enabled */
else
ad1848->index = val & 0x0f; /* ad1848/cs4248 mode TODO: some variants/clones DO NOT mirror, just ignore the writes? */
if (ad1848->type >= AD1848_TYPE_CS4235)
ad1848->regs[23] &= ~0x08; /* clear XRAE */
ad1848->trd = val & 0x20;
ad1848->mce = val & 0x40;
break;
case 1:
switch (ad1848->index) {
case 10:
if (ad1848->type < AD1848_TYPE_CS4235)
break;
/* fall-through */
case 1:
switch (ad1848->index) {
case 10:
if (ad1848->type < AD1848_TYPE_CS4235)
break;
/* fall-through */
case 8:
updatefreq = 1;
break;
case 8:
updatefreq = 1;
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) {
timer_disable(&ad1848->timer_count);
ad1848->out_l = ad1848->out_r = 0;
}
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) {
timer_disable(&ad1848->timer_count);
ad1848->out_l = ad1848->out_r = 0;
}
break;
case 11:
return;
case 11:
return;
case 12:
if (ad1848->type != AD1848_TYPE_DEFAULT)
ad1848->regs[12] = ((ad1848->regs[12] & 0x0f) + (val & 0xf0)) | 0x80;
return;
case 12:
if (ad1848->type != AD1848_TYPE_DEFAULT)
ad1848->regs[12] = ((ad1848->regs[12] & 0x0f) + (val & 0xf0)) | 0x80;
return;
case 14:
ad1848->count = ad1848->regs[15] | (val << 8);
break;
case 14:
ad1848->count = ad1848->regs[15] | (val << 8);
break;
case 17:
if (ad1848->type >= AD1848_TYPE_CS4231) /* enable additional data formats on modes 2 and 3 */
ad1848->fmt_mask = (val & 0x40) ? 0xf0 : 0x70;
break;
case 17:
if (ad1848->type >= AD1848_TYPE_CS4231) /* enable additional data formats on modes 2 and 3 */
ad1848->fmt_mask = (val & 0x40) ? 0xf0 : 0x70;
break;
case 18: case 19:
if (ad1848->type >= AD1848_TYPE_CS4235) {
if ((ad1848->xregs[4] & 0x14) == 0x14) { /* FM remapping */
ad1848->xregs[ad1848->index - 12] = val; /* real FM volume on extended registers 6 and 7 */
temp = 1;
case 18:
case 19:
if (ad1848->type >= AD1848_TYPE_CS4235) {
if ((ad1848->xregs[4] & 0x14) == 0x14) { /* FM remapping */
ad1848->xregs[ad1848->index - 12] = val; /* real FM volume on extended registers 6 and 7 */
temp = 1;
if (ad1848->index == 18) {
if (val & 0x80)
ad1848->fm_vol_l = 0;
else
ad1848->fm_vol_l = ad1848_vols_7bits[val & 0x3f];
} else {
if (val & 0x80)
ad1848->fm_vol_r = 0;
else
ad1848->fm_vol_r = ad1848_vols_7bits[val & 0x3f];
}
}
if (ad1848->wten && !(ad1848->xregs[4] & 0x08)) { /* wavetable remapping */
ad1848->xregs[ad1848->index - 2] = val; /* real wavetable volume on extended registers 16 and 17 */
temp = 1;
}
if (ad1848->index == 18) {
if (val & 0x80)
ad1848->fm_vol_l = 0;
else
ad1848->fm_vol_l = ad1848_vols_7bits[val & 0x3f];
} else {
if (val & 0x80)
ad1848->fm_vol_r = 0;
else
ad1848->fm_vol_r = ad1848_vols_7bits[val & 0x3f];
}
}
if (ad1848->wten && !(ad1848->xregs[4] & 0x08)) { /* wavetable remapping */
ad1848->xregs[ad1848->index - 2] = val; /* real wavetable volume on extended registers 16 and 17 */
temp = 1;
}
/* Stop here if any remapping is enabled. */
if (temp)
return;
/* Stop here if any remapping is enabled. */
if (temp)
return;
/* HACK: the Windows 9x driver's "Synth" control writes to this
register with no remapping, even if internal FM is enabled. */
if (ad1848->index == 18) {
if (val & 0x80)
ad1848->fm_vol_l = 0;
else
ad1848->fm_vol_l = (int) ad1848_vols_5bits_aux_gain[val & 0x1f];
} else {
if (val & 0x80)
ad1848->fm_vol_r = 0;
else
ad1848->fm_vol_r = (int) ad1848_vols_5bits_aux_gain[val & 0x1f];
}
}
break;
/* HACK: the Windows 9x driver's "Synth" control writes to this
register with no remapping, even if internal FM is enabled. */
if (ad1848->index == 18) {
if (val & 0x80)
ad1848->fm_vol_l = 0;
else
ad1848->fm_vol_l = (int) ad1848_vols_5bits_aux_gain[val & 0x1f];
} else {
if (val & 0x80)
ad1848->fm_vol_r = 0;
else
ad1848->fm_vol_r = (int) ad1848_vols_5bits_aux_gain[val & 0x1f];
}
}
break;
case 20: case 21:
/* Backdoor to the Control/RAM registers on CS4235. */
if ((ad1848->type == AD1848_TYPE_CS4235) && (ad1848->xregs[18] & 0x80)) {
ad1848->cram_write(ad1848->index - 15, val, ad1848->cram_priv);
val = ad1848->regs[ad1848->index];
}
break;
case 20:
case 21:
/* Backdoor to the Control/RAM registers on CS4235. */
if ((ad1848->type == AD1848_TYPE_CS4235) && (ad1848->xregs[18] & 0x80)) {
ad1848->cram_write(ad1848->index - 15, val, ad1848->cram_priv);
val = ad1848->regs[ad1848->index];
}
break;
case 22:
updatefreq = 1;
break;
case 22:
updatefreq = 1;
break;
case 23:
if ((ad1848->type >= AD1848_TYPE_CS4235) && ((ad1848->regs[12] & 0x60) == 0x60)) {
if (!(ad1848->regs[23] & 0x08)) { /* existing (not new) XRAE is clear */
ad1848->xindex = ((val & 0x04) << 2) | (val >> 4);
break;
}
case 23:
if ((ad1848->type >= AD1848_TYPE_CS4235) && ((ad1848->regs[12] & 0x60) == 0x60)) {
if (!(ad1848->regs[23] & 0x08)) { /* existing (not new) XRAE is clear */
ad1848->xindex = ((val & 0x04) << 2) | (val >> 4);
break;
}
switch (ad1848->xindex) {
case 0: case 1: /* remapped line volume */
ad1848->regs[18 + ad1848->xindex] = val;
return;
switch (ad1848->xindex) {
case 0:
case 1: /* remapped line volume */
ad1848->regs[18 + ad1848->xindex] = val;
return;
case 6:
if (val & 0x80)
ad1848->fm_vol_l = 0;
else
ad1848->fm_vol_l = ad1848_vols_7bits[val & 0x3f];
break;
case 6:
if (val & 0x80)
ad1848->fm_vol_l = 0;
else
ad1848->fm_vol_l = ad1848_vols_7bits[val & 0x3f];
break;
case 7:
if (val & 0x80)
ad1848->fm_vol_r = 0;
else
ad1848->fm_vol_r = ad1848_vols_7bits[val & 0x3f];
break;
case 7:
if (val & 0x80)
ad1848->fm_vol_r = 0;
else
ad1848->fm_vol_r = ad1848_vols_7bits[val & 0x3f];
break;
case 11: case 13:
updatefreq = 1;
break;
case 11:
case 13:
updatefreq = 1;
break;
case 25:
return;
}
ad1848->xregs[ad1848->xindex] = val;
case 25:
return;
}
ad1848->xregs[ad1848->xindex] = val;
if (updatefreq)
ad1848_updatefreq(ad1848);
if (updatefreq)
ad1848_updatefreq(ad1848);
return;
}
break;
return;
}
break;
case 24:
val = ad1848->regs[24] & ((val & 0x70) | 0x0f);
if (!(val & 0x70)) {
ad1848->status &= 0xfe;
picintc(1 << ad1848->irq);
}
break;
case 24:
val = ad1848->regs[24] & ((val & 0x70) | 0x0f);
if (!(val & 0x70)) {
ad1848->status &= 0xfe;
picintc(1 << ad1848->irq);
}
break;
case 25:
return;
}
ad1848->regs[ad1848->index] = val;
case 25:
return;
}
ad1848->regs[ad1848->index] = val;
if (updatefreq)
ad1848_updatefreq(ad1848);
if (updatefreq)
ad1848_updatefreq(ad1848);
if (ad1848->type >= AD1848_TYPE_CS4231) { /* TODO: configure CD volume for CS4248/AD1848 too */
temp = (ad1848->type == AD1848_TYPE_CS4231) ? 18 : 4;
if (ad1848->regs[temp] & 0x80)
ad1848->cd_vol_l = 0;
else
ad1848->cd_vol_l = ad1848_vols_5bits_aux_gain[ad1848->regs[temp] & 0x1f];
temp++;
if (ad1848->regs[temp] & 0x80)
ad1848->cd_vol_r = 0;
else
ad1848->cd_vol_r = ad1848_vols_5bits_aux_gain[ad1848->regs[temp] & 0x1f];
}
break;
if (ad1848->type >= AD1848_TYPE_CS4231) { /* TODO: configure CD volume for CS4248/AD1848 too */
temp = (ad1848->type == AD1848_TYPE_CS4231) ? 18 : 4;
if (ad1848->regs[temp] & 0x80)
ad1848->cd_vol_l = 0;
else
ad1848->cd_vol_l = ad1848_vols_5bits_aux_gain[ad1848->regs[temp] & 0x1f];
temp++;
if (ad1848->regs[temp] & 0x80)
ad1848->cd_vol_r = 0;
else
ad1848->cd_vol_r = ad1848_vols_5bits_aux_gain[ad1848->regs[temp] & 0x1f];
}
break;
case 2:
ad1848->status &= 0xfe;
ad1848->regs[24] &= 0x0f;
break;
case 2:
ad1848->status &= 0xfe;
ad1848->regs[24] &= 0x0f;
break;
}
}
void
ad1848_speed_changed(ad1848_t *ad1848)
{
ad1848->timer_latch = (uint64_t) ((double) TIMER_USEC * (1000000.0 / (double) ad1848->freq));
}
void
ad1848_update(ad1848_t *ad1848)
{
for (; ad1848->pos < sound_pos_global; ad1848->pos++) {
ad1848->buffer[ad1848->pos*2] = ad1848->out_l;
ad1848->buffer[ad1848->pos*2 + 1] = ad1848->out_r;
ad1848->buffer[ad1848->pos * 2] = ad1848->out_l;
ad1848->buffer[ad1848->pos * 2 + 1] = ad1848->out_r;
}
}
static void
ad1848_poll(void *priv)
{
ad1848_t *ad1848 = (ad1848_t *) priv;
if (ad1848->timer_latch)
timer_advance_u64(&ad1848->timer_count, ad1848->timer_latch);
timer_advance_u64(&ad1848->timer_count, ad1848->timer_latch);
else
timer_advance_u64(&ad1848->timer_count, TIMER_USEC * 1000);
timer_advance_u64(&ad1848->timer_count, TIMER_USEC * 1000);
ad1848_update(ad1848);
if (ad1848->enable) {
int32_t temp;
int32_t temp;
switch (ad1848->regs[8] & ad1848->fmt_mask) {
case 0x00: /* Mono, 8-bit PCM */
ad1848->out_l = ad1848->out_r = (dma_channel_read(ad1848->dma) ^ 0x80) * 256;
break;
switch (ad1848->regs[8] & ad1848->fmt_mask) {
case 0x00: /* Mono, 8-bit PCM */
ad1848->out_l = ad1848->out_r = (dma_channel_read(ad1848->dma) ^ 0x80) * 256;
break;
case 0x10: /* Stereo, 8-bit PCM */
ad1848->out_l = (dma_channel_read(ad1848->dma) ^ 0x80) * 256;
ad1848->out_r = (dma_channel_read(ad1848->dma) ^ 0x80) * 256;
break;
case 0x10: /* Stereo, 8-bit PCM */
ad1848->out_l = (dma_channel_read(ad1848->dma) ^ 0x80) * 256;
ad1848->out_r = (dma_channel_read(ad1848->dma) ^ 0x80) * 256;
break;
case 0x40: /* Mono, 16-bit PCM little endian */
temp = dma_channel_read(ad1848->dma);
ad1848->out_l = ad1848->out_r = (dma_channel_read(ad1848->dma) << 8) | temp;
break;
case 0x40: /* Mono, 16-bit PCM little endian */
temp = dma_channel_read(ad1848->dma);
ad1848->out_l = ad1848->out_r = (dma_channel_read(ad1848->dma) << 8) | temp;
break;
case 0x50: /* Stereo, 16-bit PCM little endian */
temp = dma_channel_read(ad1848->dma);
ad1848->out_l = (dma_channel_read(ad1848->dma) << 8) | temp;
temp = dma_channel_read(ad1848->dma);
ad1848->out_r = (dma_channel_read(ad1848->dma) << 8) | temp;
break;
case 0x50: /* Stereo, 16-bit PCM little endian */
temp = dma_channel_read(ad1848->dma);
ad1848->out_l = (dma_channel_read(ad1848->dma) << 8) | temp;
temp = dma_channel_read(ad1848->dma);
ad1848->out_r = (dma_channel_read(ad1848->dma) << 8) | temp;
break;
case 0xc0: /* Mono, 16-bit PCM big endian */
temp = dma_channel_read(ad1848->dma);
ad1848->out_l = ad1848->out_r = dma_channel_read(ad1848->dma) | (temp << 8);
break;
case 0xc0: /* Mono, 16-bit PCM big endian */
temp = dma_channel_read(ad1848->dma);
ad1848->out_l = ad1848->out_r = dma_channel_read(ad1848->dma) | (temp << 8);
break;
case 0xd0: /* Stereo, 16-bit PCM big endian */
temp = dma_channel_read(ad1848->dma);
ad1848->out_l = dma_channel_read(ad1848->dma) | (temp << 8);
temp = dma_channel_read(ad1848->dma);
ad1848->out_r = dma_channel_read(ad1848->dma) | (temp << 8);
break;
}
case 0xd0: /* Stereo, 16-bit PCM big endian */
temp = dma_channel_read(ad1848->dma);
ad1848->out_l = dma_channel_read(ad1848->dma) | (temp << 8);
temp = dma_channel_read(ad1848->dma);
ad1848->out_r = dma_channel_read(ad1848->dma) | (temp << 8);
break;
}
if (ad1848->regs[6] & 0x80)
ad1848->out_l = 0;
else
ad1848->out_l = (ad1848->out_l * ad1848_vols_7bits[ad1848->regs[6] & ad1848->wave_vol_mask]) >> 16;
if (ad1848->regs[6] & 0x80)
ad1848->out_l = 0;
else
ad1848->out_l = (ad1848->out_l * ad1848_vols_7bits[ad1848->regs[6] & ad1848->wave_vol_mask]) >> 16;
if (ad1848->regs[7] & 0x80)
ad1848->out_r = 0;
else
ad1848->out_r = (ad1848->out_r * ad1848_vols_7bits[ad1848->regs[7] & ad1848->wave_vol_mask]) >> 16;
if (ad1848->regs[7] & 0x80)
ad1848->out_r = 0;
else
ad1848->out_r = (ad1848->out_r * ad1848_vols_7bits[ad1848->regs[7] & ad1848->wave_vol_mask]) >> 16;
if (ad1848->count < 0) {
ad1848->count = ad1848->regs[15] | (ad1848->regs[14] << 8);
if (!(ad1848->status & 0x01)) {
ad1848->status |= 0x01;
ad1848->regs[24] |= 0x10;
if (ad1848->regs[10] & 2)
picint(1 << ad1848->irq);
}
}
if (ad1848->count < 0) {
ad1848->count = ad1848->regs[15] | (ad1848->regs[14] << 8);
if (!(ad1848->status & 0x01)) {
ad1848->status |= 0x01;
ad1848->regs[24] |= 0x10;
if (ad1848->regs[10] & 2)
picint(1 << ad1848->irq);
}
}
ad1848->count--;
ad1848->count--;
} else {
ad1848->out_l = ad1848->out_r = 0;
ad1848->cd_vol_l = ad1848->cd_vol_r = 0;
ad1848->out_l = ad1848->out_r = 0;
ad1848->cd_vol_l = ad1848->cd_vol_r = 0;
}
}
void
ad1848_filter_cd_audio(int channel, double *buffer, void *priv)
{
ad1848_t *ad1848 = (ad1848_t *) priv;
double c;
double volume = channel ? ad1848->cd_vol_r : ad1848->cd_vol_l;
double c;
double volume = channel ? ad1848->cd_vol_r : ad1848->cd_vol_l;
c = ((*buffer) * volume) / 65536.0;
c = ((*buffer) * volume) / 65536.0;
*buffer = c;
}
void
ad1848_init(ad1848_t *ad1848, uint8_t type)
{
uint8_t c;
double attenuation;
double attenuation;
ad1848->status = 0xcc;
ad1848->index = ad1848->trd = 0;
ad1848->mce = 0x40;
ad1848->wten = 0;
ad1848->mce = 0x40;
ad1848->wten = 0;
ad1848->regs[0] = ad1848->regs[1] = 0;
ad1848->regs[2] = ad1848->regs[3] = 0x80; /* Line-in */
ad1848->regs[4] = ad1848->regs[5] = 0x80;
ad1848->regs[6] = ad1848->regs[7] = 0x80; /* Left/right Output */
ad1848->regs[8] = 0;
ad1848->regs[9] = 0x08;
ad1848->regs[8] = 0;
ad1848->regs[9] = 0x08;
ad1848->regs[10] = ad1848->regs[11] = 0;
if ((type == AD1848_TYPE_CS4248) || (type == AD1848_TYPE_CS4231) || (type >= AD1848_TYPE_CS4235))
ad1848->regs[12] = 0x8a;
ad1848->regs[12] = 0x8a;
else
ad1848->regs[12] = 0xa;
ad1848->regs[12] = 0xa;
ad1848->regs[13] = 0;
ad1848->regs[14] = ad1848->regs[15] = 0;
if (type == AD1848_TYPE_CS4231) {
ad1848->regs[16] = ad1848->regs[17] = 0;
ad1848->regs[18] = ad1848->regs[19] = 0x88;
ad1848->regs[22] = 0x80;
ad1848->regs[24] = 0;
ad1848->regs[25] = CS4231;
ad1848->regs[26] = 0x80;
ad1848->regs[29] = 0x80;
ad1848->regs[16] = ad1848->regs[17] = 0;
ad1848->regs[18] = ad1848->regs[19] = 0x88;
ad1848->regs[22] = 0x80;
ad1848->regs[24] = 0;
ad1848->regs[25] = CS4231;
ad1848->regs[26] = 0x80;
ad1848->regs[29] = 0x80;
} else if (type >= AD1848_TYPE_CS4235) {
ad1848->regs[16] = ad1848->regs[17] = 0;
ad1848->regs[18] = ad1848->regs[19] = 0;
ad1848->regs[20] = ad1848->regs[21] = 0;
ad1848->regs[22] = ad1848->regs[23] = 0;
ad1848->regs[24] = 0;
ad1848->regs[25] = CS4236;
ad1848->regs[26] = 0xa0;
ad1848->regs[27] = ad1848->regs[29] = 0;
ad1848->regs[30] = ad1848->regs[31] = 0;
ad1848->regs[16] = ad1848->regs[17] = 0;
ad1848->regs[18] = ad1848->regs[19] = 0;
ad1848->regs[20] = ad1848->regs[21] = 0;
ad1848->regs[22] = ad1848->regs[23] = 0;
ad1848->regs[24] = 0;
ad1848->regs[25] = CS4236;
ad1848->regs[26] = 0xa0;
ad1848->regs[27] = ad1848->regs[29] = 0;
ad1848->regs[30] = ad1848->regs[31] = 0;
ad1848->xregs[0] = ad1848->xregs[1] = 0xe8;
ad1848->xregs[2] = ad1848->xregs[3] = 0xcf;
ad1848->xregs[4] = 0x84;
ad1848->xregs[5] = 0;
ad1848->xregs[6] = ad1848->xregs[7] = 0x80;
ad1848->xregs[8] = ad1848->xregs[9] = 0;
ad1848->xregs[10] = 0x3f;
ad1848->xregs[11] = 0xc0;
ad1848->xregs[14] = ad1848->xregs[15] = 0;
ad1848->xregs[16] = ad1848->xregs[17] = 0;
ad1848->xregs[0] = ad1848->xregs[1] = 0xe8;
ad1848->xregs[2] = ad1848->xregs[3] = 0xcf;
ad1848->xregs[4] = 0x84;
ad1848->xregs[5] = 0;
ad1848->xregs[6] = ad1848->xregs[7] = 0x80;
ad1848->xregs[8] = ad1848->xregs[9] = 0;
ad1848->xregs[10] = 0x3f;
ad1848->xregs[11] = 0xc0;
ad1848->xregs[14] = ad1848->xregs[15] = 0;
ad1848->xregs[16] = ad1848->xregs[17] = 0;
}
ad1848_updatefreq(ad1848);
@@ -534,34 +566,46 @@ ad1848_init(ad1848_t *ad1848, uint8_t type)
ad1848->fmt_mask = 0x70;
for (c = 0; c < 128; c++) {
attenuation = 0.0;
if (c & 0x40) {
if (c < 72) attenuation = (c - 72) * -1.5;
} else {
if (c & 0x01) attenuation -= 1.5;
if (c & 0x02) attenuation -= 3.0;
if (c & 0x04) attenuation -= 6.0;
if (c & 0x08) attenuation -= 12.0;
if (c & 0x10) attenuation -= 24.0;
if (c & 0x20) attenuation -= 48.0;
}
attenuation = 0.0;
if (c & 0x40) {
if (c < 72)
attenuation = (c - 72) * -1.5;
} else {
if (c & 0x01)
attenuation -= 1.5;
if (c & 0x02)
attenuation -= 3.0;
if (c & 0x04)
attenuation -= 6.0;
if (c & 0x08)
attenuation -= 12.0;
if (c & 0x10)
attenuation -= 24.0;
if (c & 0x20)
attenuation -= 48.0;
}
attenuation = pow(10, attenuation / 10);
attenuation = pow(10, attenuation / 10);
ad1848_vols_7bits[c] = (int) (attenuation * 65536);
ad1848_vols_7bits[c] = (int) (attenuation * 65536);
}
for (c = 0; c < 32; c++) {
attenuation = 12.0;
if (c & 0x01) attenuation -= 1.5;
if (c & 0x02) attenuation -= 3.0;
if (c & 0x04) attenuation -= 6.0;
if (c & 0x08) attenuation -= 12.0;
if (c & 0x10) attenuation -= 24.0;
attenuation = 12.0;
if (c & 0x01)
attenuation -= 1.5;
if (c & 0x02)
attenuation -= 3.0;
if (c & 0x04)
attenuation -= 6.0;
if (c & 0x08)
attenuation -= 12.0;
if (c & 0x10)
attenuation -= 24.0;
attenuation = pow(10, attenuation / 10);
attenuation = pow(10, attenuation / 10);
ad1848_vols_5bits_aux_gain[c] = (attenuation * 65536);
ad1848_vols_5bits_aux_gain[c] = (attenuation * 65536);
}
ad1848->type = type;
@@ -569,5 +613,5 @@ ad1848_init(ad1848_t *ad1848, uint8_t type)
timer_add(&ad1848->timer_count, ad1848_poll, ad1848, 0);
if ((ad1848->type != AD1848_TYPE_DEFAULT) && (ad1848->type != AD1848_TYPE_CS4248))
sound_set_cd_audio_filter(ad1848_filter_cd_audio, ad1848);
sound_set_cd_audio_filter(ad1848_filter_cd_audio, ad1848);
}

View File

@@ -1,147 +1,170 @@
#include <stdarg.h>
#include <stdint.h>
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <string.h>
#include <wchar.h>
#define HAVE_STDARG_H
#include <86box/86box.h>
#include <86box/io.h>
#include <86box/timer.h>
#include <86box/mca.h>
#include <86box/device.h>
#include <86box/sound.h>
#include <86box/snd_opl.h>
#include <86box/86box.h>
#include <86box/device.h>
#include <86box/io.h>
#include <86box/mca.h>
#include <86box/sound.h>
#include <86box/timer.h>
#include <86box/snd_opl.h>
#ifdef ENABLE_ADLIB_LOG
int adlib_do_log = ENABLE_ADLIB_LOG;
static void
adlib_log(const char *fmt, ...)
{
va_list ap;
if (adlib_do_log) {
va_start(ap, fmt);
pclog_ex(fmt, ap);
va_end(ap);
va_start(ap, fmt);
pclog_ex(fmt, ap);
va_end(ap);
}
}
#else
#define adlib_log(fmt, ...)
# define adlib_log(fmt, ...)
#endif
typedef struct adlib_t {
opl_t opl;
typedef struct adlib_t
{
opl_t opl;
uint8_t pos_regs[8];
uint8_t pos_regs[8];
} adlib_t;
static void adlib_get_buffer(int32_t *buffer, int len, void *p)
static void
adlib_get_buffer(int32_t *buffer, int len, void *p)
{
adlib_t *adlib = (adlib_t *)p;
int c;
adlib_t *adlib = (adlib_t *) p;
int c;
opl2_update(&adlib->opl);
opl2_update(&adlib->opl);
for (c = 0; c < len * 2; c++)
buffer[c] += (int32_t)adlib->opl.buffer[c];
for (c = 0; c < len * 2; c++)
buffer[c] += (int32_t) adlib->opl.buffer[c];
adlib->opl.pos = 0;
adlib->opl.pos = 0;
}
uint8_t adlib_mca_read(int port, void *p)
uint8_t
adlib_mca_read(int port, void *p)
{
adlib_t *adlib = (adlib_t *)p;
adlib_t *adlib = (adlib_t *) p;
adlib_log("adlib_mca_read: port=%04x\n", port);
adlib_log("adlib_mca_read: port=%04x\n", port);
return adlib->pos_regs[port & 7];
return adlib->pos_regs[port & 7];
}
void adlib_mca_write(int port, uint8_t val, void *p)
void
adlib_mca_write(int port, uint8_t val, void *p)
{
adlib_t *adlib = (adlib_t *)p;
adlib_t *adlib = (adlib_t *) p;
if (port < 0x102)
return;
if (port < 0x102)
return;
adlib_log("adlib_mca_write: port=%04x val=%02x\n", port, val);
adlib_log("adlib_mca_write: port=%04x val=%02x\n", port, val);
switch (port)
{
case 0x102:
if ((adlib->pos_regs[2] & 1) && !(val & 1))
io_removehandler(0x0388, 0x0002, opl2_read, NULL, NULL, opl2_write, NULL, NULL, &adlib->opl);
if (!(adlib->pos_regs[2] & 1) && (val & 1))
io_sethandler(0x0388, 0x0002, opl2_read, NULL, NULL, opl2_write, NULL, NULL, &adlib->opl);
break;
}
adlib->pos_regs[port & 7] = val;
switch (port) {
case 0x102:
if ((adlib->pos_regs[2] & 1) && !(val & 1))
io_removehandler(0x0388, 0x0002,
opl2_read, NULL, NULL,
opl2_write, NULL, NULL,
&adlib->opl);
if (!(adlib->pos_regs[2] & 1) && (val & 1))
io_sethandler(0x0388, 0x0002,
opl2_read, NULL, NULL,
opl2_write, NULL, NULL,
&adlib->opl);
break;
}
adlib->pos_regs[port & 7] = val;
}
uint8_t adlib_mca_feedb(void *p)
uint8_t
adlib_mca_feedb(void *p)
{
adlib_t *adlib = (adlib_t *)p;
adlib_t *adlib = (adlib_t *) p;
return (adlib->pos_regs[2] & 1);
return (adlib->pos_regs[2] & 1);
}
void *adlib_init(const device_t *info)
void *
adlib_init(const device_t *info)
{
adlib_t *adlib = malloc(sizeof(adlib_t));
memset(adlib, 0, sizeof(adlib_t));
adlib_t *adlib = malloc(sizeof(adlib_t));
memset(adlib, 0, sizeof(adlib_t));
adlib_log("adlib_init\n");
opl2_init(&adlib->opl);
io_sethandler(0x0388, 0x0002, opl2_read, NULL, NULL, opl2_write, NULL, NULL, &adlib->opl);
sound_add_handler(adlib_get_buffer, adlib);
return adlib;
adlib_log("adlib_init\n");
opl2_init(&adlib->opl);
io_sethandler(0x0388, 0x0002,
opl2_read, NULL, NULL,
opl2_write, NULL, NULL,
&adlib->opl);
sound_add_handler(adlib_get_buffer, adlib);
return adlib;
}
void *adlib_mca_init(const device_t *info)
void *
adlib_mca_init(const device_t *info)
{
adlib_t *adlib = adlib_init(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_feedb, NULL, adlib);
adlib->pos_regs[0] = 0xd7;
adlib->pos_regs[1] = 0x70;
io_removehandler(0x0388, 0x0002,
opl2_read, NULL, NULL,
opl2_write, NULL, NULL,
&adlib->opl);
mca_add(adlib_mca_read,
adlib_mca_write,
adlib_mca_feedb,
NULL,
adlib);
adlib->pos_regs[0] = 0xd7;
adlib->pos_regs[1] = 0x70;
return adlib;
return adlib;
}
void adlib_close(void *p)
void
adlib_close(void *p)
{
adlib_t *adlib = (adlib_t *)p;
adlib_t *adlib = (adlib_t *) p;
free(adlib);
free(adlib);
}
const device_t adlib_device =
{
"AdLib",
"adlib",
DEVICE_ISA,
0,
adlib_init, adlib_close, NULL,
{ NULL }, NULL, NULL,
NULL
const device_t adlib_device = {
"AdLib",
"adlib",
DEVICE_ISA,
0,
adlib_init,
adlib_close,
NULL,
{ NULL },
NULL,
NULL,
NULL
};
const device_t adlib_mca_device =
{
"AdLib (MCA)",
"adlib_mca",
DEVICE_MCA,
0,
adlib_init, adlib_close, NULL,
{ NULL }, NULL, NULL,
NULL
const device_t adlib_mca_device = {
"AdLib (MCA)",
"adlib_mca",
DEVICE_MCA,
0,
adlib_init,
adlib_close,
NULL,
{ NULL },
NULL,
NULL,
NULL
};

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@@ -1,215 +1,221 @@
#include <stdarg.h>
#include <stdint.h>
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <string.h>
#include <wchar.h>
#define HAVE_STDARG_H
#include <86box/86box.h>
#include <86box/io.h>
#include <86box/device.h>
#include <86box/sound.h>
#include <86box/io.h>
#include <86box/snd_cms.h>
#include <86box/sound.h>
void cms_update(cms_t *cms)
void
cms_update(cms_t *cms)
{
for (; cms->pos < sound_pos_global; cms->pos++)
{
int c, d;
int16_t out_l = 0, out_r = 0;
for (; cms->pos < sound_pos_global; cms->pos++) {
int c, d;
int16_t out_l = 0, out_r = 0;
for (c = 0; c < 4; c++)
{
switch (cms->noisetype[c >> 1][c & 1])
{
case 0: cms->noisefreq[c >> 1][c & 1] = MASTER_CLOCK/256; break;
case 1: cms->noisefreq[c >> 1][c & 1] = MASTER_CLOCK/512; break;
case 2: cms->noisefreq[c >> 1][c & 1] = MASTER_CLOCK/1024; break;
case 3: cms->noisefreq[c >> 1][c & 1] = cms->freq[c >> 1][(c & 1) * 3]; break;
}
}
for (c = 0; c < 2; c ++)
{
if (cms->regs[c][0x1C] & 1)
{
for (d = 0; d < 6; d++)
{
if (cms->regs[c][0x14] & (1 << d))
{
if (cms->stat[c][d]) out_l += (cms->vol[c][d][0] * 90);
if (cms->stat[c][d]) out_r += (cms->vol[c][d][1] * 90);
cms->count[c][d] += cms->freq[c][d];
if (cms->count[c][d] >= 24000)
{
cms->count[c][d] -= 24000;
cms->stat[c][d] ^= 1;
}
}
else if (cms->regs[c][0x15] & (1 << d))
{
if (cms->noise[c][d / 3] & 1) out_l += (cms->vol[c][d][0] * 90);
if (cms->noise[c][d / 3] & 1) out_r += (cms->vol[c][d][0] * 90);
}
}
for (d = 0; d < 2; d++)
{
cms->noisecount[c][d] += cms->noisefreq[c][d];
while (cms->noisecount[c][d] >= 24000)
{
cms->noisecount[c][d] -= 24000;
cms->noise[c][d] <<= 1;
if (!(((cms->noise[c][d] & 0x4000) >> 8) ^ (cms->noise[c][d] & 0x40)))
cms->noise[c][d] |= 1;
}
}
}
}
cms->buffer[(cms->pos << 1)] = out_l;
cms->buffer[(cms->pos << 1) + 1] = out_r;
}
}
void cms_get_buffer(int32_t *buffer, int len, void *p)
{
cms_t *cms = (cms_t *)p;
int c;
cms_update(cms);
for (c = 0; c < len * 2; c++)
buffer[c] += cms->buffer[c];
cms->pos = 0;
}
void cms_write(uint16_t addr, uint8_t val, void *p)
{
cms_t *cms = (cms_t *)p;
int voice;
int chip = (addr & 2) >> 1;
switch (addr & 0xf)
{
for (c = 0; c < 4; c++) {
switch (cms->noisetype[c >> 1][c & 1]) {
case 0:
cms->noisefreq[c >> 1][c & 1] = MASTER_CLOCK / 256;
break;
case 1:
cms->addrs[0] = val & 31;
break;
cms->noisefreq[c >> 1][c & 1] = MASTER_CLOCK / 512;
break;
case 2:
cms->noisefreq[c >> 1][c & 1] = MASTER_CLOCK / 1024;
break;
case 3:
cms->addrs[1] = val & 31;
break;
case 0: case 2:
cms_update(cms);
cms->regs[chip][cms->addrs[chip] & 31] = val;
switch (cms->addrs[chip] & 31)
{
case 0x00: case 0x01: case 0x02: /*Volume*/
case 0x03: case 0x04: case 0x05:
voice = cms->addrs[chip] & 7;
cms->vol[chip][voice][0] = val & 0xf;
cms->vol[chip][voice][1] = val >> 4;
break;
case 0x08: case 0x09: case 0x0A: /*Frequency*/
case 0x0B: case 0x0C: case 0x0D:
voice = cms->addrs[chip] & 7;
cms->latch[chip][voice] = (cms->latch[chip][voice] & 0x700) | val;
cms->freq[chip][voice] = (MASTER_CLOCK/512 << (cms->latch[chip][voice] >> 8)) / (511 - (cms->latch[chip][voice] & 255));
break;
case 0x10: case 0x11: case 0x12: /*Octave*/
voice = (cms->addrs[chip] & 3) << 1;
cms->latch[chip][voice] = (cms->latch[chip][voice] & 0xFF) | ((val & 7) << 8);
cms->latch[chip][voice + 1] = (cms->latch[chip][voice + 1] & 0xFF) | ((val & 0x70) << 4);
cms->freq[chip][voice] = (MASTER_CLOCK/512 << (cms->latch[chip][voice] >> 8)) / (511 - (cms->latch[chip][voice] & 255));
cms->freq[chip][voice + 1] = (MASTER_CLOCK/512 << (cms->latch[chip][voice + 1] >> 8)) / (511 - (cms->latch[chip][voice + 1] & 255));
break;
case 0x16: /*Noise*/
cms->noisetype[chip][0] = val & 3;
cms->noisetype[chip][1] = (val >> 4) & 3;
break;
}
break;
case 0x6: case 0x7:
cms->latched_data = val;
break;
cms->noisefreq[c >> 1][c & 1] = cms->freq[c >> 1][(c & 1) * 3];
break;
}
}
}
uint8_t cms_read(uint16_t addr, void *p)
{
cms_t *cms = (cms_t *)p;
switch (addr & 0xf)
{
case 0x1:
return cms->addrs[0];
case 0x3:
return cms->addrs[1];
case 0x4:
return 0x7f;
case 0xa: case 0xb:
return cms->latched_data;
}
return 0xff;
}
void *cms_init(const device_t *info)
{
cms_t *cms = malloc(sizeof(cms_t));
memset(cms, 0, sizeof(cms_t));
uint16_t addr = device_get_config_hex16("base");
io_sethandler(addr, 0x0010, cms_read, NULL, NULL, cms_write, NULL, NULL, cms);
sound_add_handler(cms_get_buffer, cms);
return cms;
}
void cms_close(void *p)
{
cms_t *cms = (cms_t *)p;
free(cms);
}
static const device_config_t cms_config[] =
{
{
"base", "Address", CONFIG_HEX16, "", 0x220, "", { 0 },
{
{
"0x210", 0x210
},
{
"0x220", 0x220
},
{
"0x230", 0x230
},
{
"0x240", 0x240
},
{
"0x250", 0x250
},
{
"0x260", 0x260
},
{
""
for (c = 0; c < 2; c++) {
if (cms->regs[c][0x1C] & 1) {
for (d = 0; d < 6; d++) {
if (cms->regs[c][0x14] & (1 << d)) {
if (cms->stat[c][d])
out_l += (cms->vol[c][d][0] * 90);
if (cms->stat[c][d])
out_r += (cms->vol[c][d][1] * 90);
cms->count[c][d] += cms->freq[c][d];
if (cms->count[c][d] >= 24000) {
cms->count[c][d] -= 24000;
cms->stat[c][d] ^= 1;
}
} else if (cms->regs[c][0x15] & (1 << d)) {
if (cms->noise[c][d / 3] & 1)
out_l += (cms->vol[c][d][0] * 90);
if (cms->noise[c][d / 3] & 1)
out_r += (cms->vol[c][d][0] * 90);
}
}
},
{
"", "", -1
for (d = 0; d < 2; d++) {
cms->noisecount[c][d] += cms->noisefreq[c][d];
while (cms->noisecount[c][d] >= 24000) {
cms->noisecount[c][d] -= 24000;
cms->noise[c][d] <<= 1;
if (!(((cms->noise[c][d] & 0x4000) >> 8) ^ (cms->noise[c][d] & 0x40)))
cms->noise[c][d] |= 1;
}
}
}
}
cms->buffer[(cms->pos << 1)] = out_l;
cms->buffer[(cms->pos << 1) + 1] = out_r;
}
}
void
cms_get_buffer(int32_t *buffer, int len, void *p)
{
cms_t *cms = (cms_t *) p;
int c;
cms_update(cms);
for (c = 0; c < len * 2; c++)
buffer[c] += cms->buffer[c];
cms->pos = 0;
}
void
cms_write(uint16_t addr, uint8_t val, void *p)
{
cms_t *cms = (cms_t *) p;
int voice;
int chip = (addr & 2) >> 1;
switch (addr & 0xf) {
case 1:
cms->addrs[0] = val & 31;
break;
case 3:
cms->addrs[1] = val & 31;
break;
case 0:
case 2:
cms_update(cms);
cms->regs[chip][cms->addrs[chip] & 31] = val;
switch (cms->addrs[chip] & 31) {
case 0x00:
case 0x01:
case 0x02: /*Volume*/
case 0x03:
case 0x04:
case 0x05:
voice = cms->addrs[chip] & 7;
cms->vol[chip][voice][0] = val & 0xf;
cms->vol[chip][voice][1] = val >> 4;
break;
case 0x08:
case 0x09:
case 0x0A: /*Frequency*/
case 0x0B:
case 0x0C:
case 0x0D:
voice = cms->addrs[chip] & 7;
cms->latch[chip][voice] = (cms->latch[chip][voice] & 0x700) | val;
cms->freq[chip][voice] = (MASTER_CLOCK / 512 << (cms->latch[chip][voice] >> 8)) / (511 - (cms->latch[chip][voice] & 255));
break;
case 0x10:
case 0x11:
case 0x12: /*Octave*/
voice = (cms->addrs[chip] & 3) << 1;
cms->latch[chip][voice] = (cms->latch[chip][voice] & 0xFF) | ((val & 7) << 8);
cms->latch[chip][voice + 1] = (cms->latch[chip][voice + 1] & 0xFF) | ((val & 0x70) << 4);
cms->freq[chip][voice] = (MASTER_CLOCK / 512 << (cms->latch[chip][voice] >> 8)) / (511 - (cms->latch[chip][voice] & 255));
cms->freq[chip][voice + 1] = (MASTER_CLOCK / 512 << (cms->latch[chip][voice + 1] >> 8)) / (511 - (cms->latch[chip][voice + 1] & 255));
break;
case 0x16: /*Noise*/
cms->noisetype[chip][0] = val & 3;
cms->noisetype[chip][1] = (val >> 4) & 3;
break;
}
break;
case 0x6:
case 0x7:
cms->latched_data = val;
break;
}
}
uint8_t
cms_read(uint16_t addr, void *p)
{
cms_t *cms = (cms_t *) p;
switch (addr & 0xf) {
case 0x1:
return cms->addrs[0];
case 0x3:
return cms->addrs[1];
case 0x4:
return 0x7f;
case 0xa:
case 0xb:
return cms->latched_data;
}
return 0xff;
}
void *
cms_init(const device_t *info)
{
cms_t *cms = malloc(sizeof(cms_t));
memset(cms, 0, sizeof(cms_t));
uint16_t addr = device_get_config_hex16("base");
io_sethandler(addr, 0x0010, cms_read, NULL, NULL, cms_write, NULL, NULL, cms);
sound_add_handler(cms_get_buffer, cms);
return cms;
}
void
cms_close(void *p)
{
cms_t *cms = (cms_t *) p;
free(cms);
}
static const device_config_t cms_config[] = {
// clang-format off
{
"base", "Address", CONFIG_HEX16, "", 0x220, "", { 0 },
{
{ "0x210", 0x210 },
{ "0x220", 0x220 },
{ "0x230", 0x230 },
{ "0x240", 0x240 },
{ "0x250", 0x250 },
{ "0x260", 0x260 },
{ "" }
}
},
{
"", "", -1
}
// clang-format on
};
const device_t cms_device =
{
"Creative Music System / Game Blaster",
"cms",
DEVICE_ISA, 0,
cms_init, cms_close, NULL,
{ NULL }, NULL, NULL,
cms_config
const device_t cms_device = {
"Creative Music System / Game Blaster",
"cms",
DEVICE_ISA,
0,
cms_init,
cms_close,
NULL,
{ NULL },
NULL,
NULL,
cms_config
};

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@@ -1,129 +1,131 @@
#include <stdio.h>
#include <stdint.h>
#include <string.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <wchar.h>
#include <86box/86box.h>
#include "cpu.h"
#include <86box/machine.h>
#include <86box/lpt.h>
#include <86box/timer.h>
#include <86box/sound.h>
#include <86box/86box.h>
#include <86box/filters.h>
#include <86box/lpt.h>
#include <86box/machine.h>
#include <86box/sound.h>
#include <86box/timer.h>
typedef struct lpt_dac_t
{
void *lpt;
typedef struct lpt_dac_t {
void *lpt;
uint8_t dac_val_l, dac_val_r;
uint8_t dac_val_l, dac_val_r;
int is_stereo;
int channel;
int is_stereo;
int channel;
int16_t buffer[2][SOUNDBUFLEN];
int pos;
int16_t buffer[2][SOUNDBUFLEN];
int pos;
} lpt_dac_t;
static void dac_update(lpt_dac_t *lpt_dac)
static void
dac_update(lpt_dac_t *lpt_dac)
{
for (; lpt_dac->pos < sound_pos_global; lpt_dac->pos++)
{
lpt_dac->buffer[0][lpt_dac->pos] = (int8_t)(lpt_dac->dac_val_l ^ 0x80) * 0x40;
lpt_dac->buffer[1][lpt_dac->pos] = (int8_t)(lpt_dac->dac_val_r ^ 0x80) * 0x40;
}
for (; lpt_dac->pos < sound_pos_global; lpt_dac->pos++) {
lpt_dac->buffer[0][lpt_dac->pos] = (int8_t) (lpt_dac->dac_val_l ^ 0x80) * 0x40;
lpt_dac->buffer[1][lpt_dac->pos] = (int8_t) (lpt_dac->dac_val_r ^ 0x80) * 0x40;
}
}
static void dac_write_data(uint8_t val, void *p)
static void
dac_write_data(uint8_t val, void *p)
{
lpt_dac_t *lpt_dac = (lpt_dac_t *)p;
lpt_dac_t *lpt_dac = (lpt_dac_t *) p;
if (lpt_dac->is_stereo)
{
if (lpt_dac->channel)
lpt_dac->dac_val_r = val;
else
lpt_dac->dac_val_l = val;
}
if (lpt_dac->is_stereo) {
if (lpt_dac->channel)
lpt_dac->dac_val_r = val;
else
lpt_dac->dac_val_l = lpt_dac->dac_val_r = val;
dac_update(lpt_dac);
lpt_dac->dac_val_l = val;
} else
lpt_dac->dac_val_l = lpt_dac->dac_val_r = val;
dac_update(lpt_dac);
}
static void dac_write_ctrl(uint8_t val, void *p)
static void
dac_write_ctrl(uint8_t val, void *p)
{
lpt_dac_t *lpt_dac = (lpt_dac_t *)p;
lpt_dac_t *lpt_dac = (lpt_dac_t *) p;
if (lpt_dac->is_stereo)
lpt_dac->channel = val & 0x01;
if (lpt_dac->is_stereo)
lpt_dac->channel = val & 0x01;
}
static uint8_t dac_read_status(void *p)
static uint8_t
dac_read_status(void *p)
{
return 0x0f;
return 0x0f;
}
static void dac_get_buffer(int32_t *buffer, int len, void *p)
static void
dac_get_buffer(int32_t *buffer, int len, void *p)
{
lpt_dac_t *lpt_dac = (lpt_dac_t *)p;
int c;
lpt_dac_t *lpt_dac = (lpt_dac_t *) p;
int c;
dac_update(lpt_dac);
dac_update(lpt_dac);
for (c = 0; c < len; c++)
{
buffer[c*2] += dac_iir(0, lpt_dac->buffer[0][c]);
buffer[c*2 + 1] += dac_iir(1, lpt_dac->buffer[1][c]);
}
lpt_dac->pos = 0;
for (c = 0; c < len; c++) {
buffer[c * 2] += dac_iir(0, lpt_dac->buffer[0][c]);
buffer[c * 2 + 1] += dac_iir(1, lpt_dac->buffer[1][c]);
}
lpt_dac->pos = 0;
}
static void *dac_init(void *lpt)
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_t *lpt_dac = malloc(sizeof(lpt_dac_t));
memset(lpt_dac, 0, sizeof(lpt_dac_t));
lpt_dac->lpt = lpt;
lpt_dac->lpt = lpt;
sound_add_handler(dac_get_buffer, lpt_dac);
sound_add_handler(dac_get_buffer, lpt_dac);
return lpt_dac;
}
static void *dac_stereo_init(void *lpt)
{
lpt_dac_t *lpt_dac = dac_init(lpt);
lpt_dac->is_stereo = 1;
return lpt_dac;
}
static void dac_close(void *p)
{
lpt_dac_t *lpt_dac = (lpt_dac_t *)p;
free(lpt_dac);
return lpt_dac;
}
const lpt_device_t lpt_dac_device =
static void *
dac_stereo_init(void *lpt)
{
"LPT DAC / Covox Speech Thing",
dac_init,
dac_close,
dac_write_data,
dac_write_ctrl,
NULL,
dac_read_status,
NULL
lpt_dac_t *lpt_dac = dac_init(lpt);
lpt_dac->is_stereo = 1;
return lpt_dac;
}
static void
dac_close(void *p)
{
lpt_dac_t *lpt_dac = (lpt_dac_t *) p;
free(lpt_dac);
}
const lpt_device_t lpt_dac_device = {
"LPT DAC / Covox Speech Thing",
dac_init,
dac_close,
dac_write_data,
dac_write_ctrl,
NULL,
dac_read_status,
NULL
};
const lpt_device_t lpt_dac_stereo_device =
{
"Stereo LPT DAC",
dac_stereo_init,
dac_close,
dac_write_data,
dac_write_ctrl,
NULL,
dac_read_status,
NULL
const lpt_device_t lpt_dac_stereo_device = {
"Stereo LPT DAC",
dac_stereo_init,
dac_close,
dac_write_data,
dac_write_ctrl,
NULL,
dac_read_status,
NULL
};

View File

@@ -1,141 +1,143 @@
#include <stdio.h>
#include <stdint.h>
#include <string.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <wchar.h>
#include <86box/86box.h>
#include "cpu.h"
#include <86box/machine.h>
#include <86box/timer.h>
#include <86box/lpt.h>
#include <86box/sound.h>
#include <86box/86box.h>
#include <86box/filters.h>
#include <86box/lpt.h>
#include <86box/machine.h>
#include <86box/sound.h>
#include <86box/timer.h>
typedef struct dss_t
{
void *lpt;
typedef struct dss_t {
void *lpt;
uint8_t fifo[16];
int read_idx, write_idx;
uint8_t fifo[16];
int read_idx, write_idx;
uint8_t dac_val,
status;
uint8_t dac_val,
status;
pc_timer_t timer;
pc_timer_t timer;
int16_t buffer[SOUNDBUFLEN];
int pos;
int16_t buffer[SOUNDBUFLEN];
int pos;
} dss_t;
static void dss_update(dss_t *dss)
static void
dss_update(dss_t *dss)
{
for (; dss->pos < sound_pos_global; dss->pos++)
dss->buffer[dss->pos] = (int8_t)(dss->dac_val ^ 0x80) * 0x40;
for (; dss->pos < sound_pos_global; dss->pos++)
dss->buffer[dss->pos] = (int8_t) (dss->dac_val ^ 0x80) * 0x40;
}
static void dss_update_status(dss_t *dss)
static void
dss_update_status(dss_t *dss)
{
uint8_t old = dss->status;
uint8_t old = dss->status;
dss->status &= ~0x40;
dss->status &= ~0x40;
if ((dss->write_idx - dss->read_idx) >= 16)
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);
if ((old & 0x40) && !(dss->status & 0x40))
lpt_irq(dss->lpt, 1);
}
static void dss_write_data(uint8_t val, void *p)
static void
dss_write_data(uint8_t val, void *p)
{
dss_t *dss = (dss_t *)p;
dss_t *dss = (dss_t *) p;
if ((dss->write_idx - dss->read_idx) < 16)
{
dss->fifo[dss->write_idx & 15] = val;
dss->write_idx++;
dss_update_status(dss);
}
if ((dss->write_idx - dss->read_idx) < 16) {
dss->fifo[dss->write_idx & 15] = val;
dss->write_idx++;
dss_update_status(dss);
}
}
static void dss_write_ctrl(uint8_t val, void *p)
static void
dss_write_ctrl(uint8_t val, void *p)
{
}
static uint8_t dss_read_status(void *p)
static uint8_t
dss_read_status(void *p)
{
dss_t *dss = (dss_t *)p;
dss_t *dss = (dss_t *) p;
return dss->status | 0x0f;
return dss->status | 0x0f;
}
static void dss_get_buffer(int32_t *buffer, int len, void *p)
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_t *dss = (dss_t *) p;
int c;
int16_t val;
float fval;
dss_update(dss);
dss_update(dss);
for (c = 0; c < len*2; c += 2)
{
fval = dss_iir((float)dss->buffer[c >> 1]);
val = (float) fval;
for (c = 0; c < len * 2; c += 2) {
fval = dss_iir((float) dss->buffer[c >> 1]);
val = (float) fval;
buffer[c] += val;
buffer[c+1] += val;
}
buffer[c] += val;
buffer[c + 1] += val;
}
dss->pos = 0;
dss->pos = 0;
}
static void dss_callback(void *p)
static void
dss_callback(void *p)
{
dss_t *dss = (dss_t *)p;
dss_t *dss = (dss_t *) p;
dss_update(dss);
dss_update(dss);
if ((dss->write_idx - dss->read_idx) > 0)
{
dss->dac_val = dss->fifo[dss->read_idx & 15];
dss->read_idx++;
dss_update_status(dss);
}
if ((dss->write_idx - dss->read_idx) > 0) {
dss->dac_val = dss->fifo[dss->read_idx & 15];
dss->read_idx++;
dss_update_status(dss);
}
timer_advance_u64(&dss->timer, (TIMER_USEC * (1000000.0 / 7000.0)));
timer_advance_u64(&dss->timer, (TIMER_USEC * (1000000.0 / 7000.0)));
}
static void *dss_init(void *lpt)
static void *
dss_init(void *lpt)
{
dss_t *dss = malloc(sizeof(dss_t));
memset(dss, 0, sizeof(dss_t));
dss_t *dss = malloc(sizeof(dss_t));
memset(dss, 0, sizeof(dss_t));
dss->lpt = lpt;
dss->lpt = lpt;
sound_add_handler(dss_get_buffer, dss);
timer_add(&dss->timer, dss_callback, dss, 1);
sound_add_handler(dss_get_buffer, dss);
timer_add(&dss->timer, dss_callback, dss, 1);
return dss;
return dss;
}
static void dss_close(void *p)
static void
dss_close(void *p)
{
dss_t *dss = (dss_t *)p;
dss_t *dss = (dss_t *) p;
free(dss);
free(dss);
}
const lpt_device_t dss_device =
{
"Disney Sound Source",
dss_init,
dss_close,
dss_write_data,
dss_write_ctrl,
NULL,
dss_read_status,
NULL
const lpt_device_t dss_device = {
"Disney Sound Source",
dss_init,
dss_close,
dss_write_data,
dss_write_ctrl,
NULL,
dss_read_status,
NULL
};

File diff suppressed because it is too large Load Diff

View File

@@ -1,22 +1,22 @@
/*
* 86Box A hypervisor and IBM PC system emulator that specializes in
* running old operating systems and software designed for IBM
* PC systems and compatibles from 1981 through fairly recent
* system designs based on the PCI bus.
* 86Box A hypervisor and IBM PC system emulator that specializes in
* running old operating systems and software designed for IBM
* PC systems and compatibles from 1981 through fairly recent
* system designs based on the PCI bus.
*
* This file is part of the 86Box distribution.
* This file is part of the 86Box distribution.
*
* Interface to the actual OPL emulator.
* Interface to the actual OPL emulator.
*
* TODO: Finish re-working this into a device_t, which requires a
* poll-like function for "update" so the sound card can call
* that and get a buffer-full of sample data.
* TODO: Finish re-working this into a device_t, which requires a
* poll-like function for "update" so the sound card can call
* that and get a buffer-full of sample data.
*
* Authors: Fred N. van Kempen, <decwiz@yahoo.com>
* Miran Grca, <mgrca8@gmail.com>
* Authors: Fred N. van Kempen, <decwiz@yahoo.com>
* Miran Grca, <mgrca8@gmail.com>
*
* Copyright 2017-2020 Fred N. van Kempen.
* Copyright 2016-2020 Miran Grca.
* Copyright 2017-2020 Fred N. van Kempen.
* Copyright 2016-2020 Miran Grca.
*/
#include <stdarg.h>
#include <stdint.h>
@@ -25,57 +25,54 @@
#include <string.h>
#include <wchar.h>
#define HAVE_STDARG_H
#include <86box/86box.h>
#include <86box/timer.h>
#include "cpu.h"
#include <86box/86box.h>
#include <86box/io.h>
#include <86box/timer.h>
#include <86box/sound.h>
#include <86box/snd_opl.h>
#include <86box/snd_opl_nuked.h>
enum {
FLAG_CYCLES = 0x02,
FLAG_OPL3 = 0x01
FLAG_OPL3 = 0x01
};
enum {
STAT_TMR_OVER = 0x60,
STAT_TMR_OVER = 0x60,
STAT_TMR1_OVER = 0x40,
STAT_TMR2_OVER = 0x20,
STAT_TMR_ANY = 0x80
STAT_TMR_ANY = 0x80
};
enum {
CTRL_RESET = 0x80,
CTRL_TMR_MASK = 0x60,
CTRL_TMR1_MASK = 0x40,
CTRL_TMR2_MASK = 0x20,
CTRL_RESET = 0x80,
CTRL_TMR_MASK = 0x60,
CTRL_TMR1_MASK = 0x40,
CTRL_TMR2_MASK = 0x20,
CTRL_TMR2_START = 0x02,
CTRL_TMR1_START = 0x01
};
#ifdef ENABLE_OPL_LOG
int opl_do_log = ENABLE_OPL_LOG;
static void
opl_log(const char *fmt, ...)
{
va_list ap;
if (opl_do_log) {
va_start(ap, fmt);
pclog_ex(fmt, ap);
va_end(ap);
va_start(ap, fmt);
pclog_ex(fmt, ap);
va_end(ap);
}
}
#else
#define opl_log(fmt, ...)
# define opl_log(fmt, ...)
#endif
static void
timer_tick(opl_t *dev, int tmr)
{
@@ -84,121 +81,114 @@ timer_tick(opl_t *dev, int tmr)
opl_log("Ticking timer %i, count now %02X...\n", tmr, dev->timer_cur_count[tmr]);
if (dev->timer_cur_count[tmr] == 0x00) {
dev->status |= ((STAT_TMR1_OVER >> tmr) & ~dev->timer_ctrl);
dev->timer_cur_count[tmr] = dev->timer_count[tmr];
dev->status |= ((STAT_TMR1_OVER >> tmr) & ~dev->timer_ctrl);
dev->timer_cur_count[tmr] = dev->timer_count[tmr];
opl_log("Count wrapped around to zero, reloading timer %i (%02X), status = %02X...\n", tmr, (STAT_TMR1_OVER >> tmr), dev->status);
opl_log("Count wrapped around to zero, reloading timer %i (%02X), status = %02X...\n", tmr, (STAT_TMR1_OVER >> tmr), dev->status);
}
timer_on_auto(&dev->timers[tmr], (tmr == 1) ? 320.0 : 80.0);
}
static void
timer_control(opl_t *dev, int tmr, int start)
{
timer_on_auto(&dev->timers[tmr], 0.0);
if (start) {
opl_log("Loading timer %i count: %02X = %02X\n", tmr, dev->timer_cur_count[tmr], dev->timer_count[tmr]);
dev->timer_cur_count[tmr] = dev->timer_count[tmr];
if (dev->flags & FLAG_OPL3)
timer_tick(dev, tmr); /* Per the YMF 262 datasheet, OPL3 starts counting immediately, unlike OPL2. */
else
timer_on_auto(&dev->timers[tmr], (tmr == 1) ? 320.0 : 80.0);
opl_log("Loading timer %i count: %02X = %02X\n", tmr, dev->timer_cur_count[tmr], dev->timer_count[tmr]);
dev->timer_cur_count[tmr] = dev->timer_count[tmr];
if (dev->flags & FLAG_OPL3)
timer_tick(dev, tmr); /* Per the YMF 262 datasheet, OPL3 starts counting immediately, unlike OPL2. */
else
timer_on_auto(&dev->timers[tmr], (tmr == 1) ? 320.0 : 80.0);
} else {
opl_log("Timer %i stopped\n", tmr);
if (tmr == 1) {
dev->status &= ~STAT_TMR2_OVER;
} else
dev->status &= ~STAT_TMR1_OVER;
}
opl_log("Timer %i stopped\n", tmr);
if (tmr == 1) {
dev->status &= ~STAT_TMR2_OVER;
} else
dev->status &= ~STAT_TMR1_OVER;
}
}
static void
timer_1(void *priv)
{
opl_t *dev = (opl_t *)priv;
opl_t *dev = (opl_t *) priv;
timer_tick(dev, 0);
}
static void
timer_2(void *priv)
{
opl_t *dev = (opl_t *)priv;
opl_t *dev = (opl_t *) priv;
timer_tick(dev, 1);
}
static uint8_t
opl_read(opl_t *dev, uint16_t port)
{
uint8_t ret = 0xff;
if ((port & 0x0003) == 0x0000) {
ret = dev->status;
if (dev->status & STAT_TMR_OVER)
ret |= STAT_TMR_ANY;
ret = dev->status;
if (dev->status & STAT_TMR_OVER)
ret |= STAT_TMR_ANY;
}
opl_log("OPL statret = %02x, status = %02x\n", ret, dev->status);
opl_log("OPL statret = %02x, status = %02x\n", ret, dev->status);
return ret;
}
static void
opl_write(opl_t *dev, uint16_t port, uint8_t val)
{
if ((port & 0x0001) == 0x0001) {
nuked_write_reg_buffered(dev->opl, dev->port, val);
nuked_write_reg_buffered(dev->opl, dev->port, val);
switch (dev->port) {
case 0x02: /* Timer 1 */
dev->timer_count[0] = val;
opl_log("Timer 0 count now: %i\n", dev->timer_count[0]);
break;
switch (dev->port) {
case 0x02: /* Timer 1 */
dev->timer_count[0] = val;
opl_log("Timer 0 count now: %i\n", dev->timer_count[0]);
break;
case 0x03: /* Timer 2 */
dev->timer_count[1] = val;
opl_log("Timer 1 count now: %i\n", dev->timer_count[1]);
break;
case 0x03: /* Timer 2 */
dev->timer_count[1] = val;
opl_log("Timer 1 count now: %i\n", dev->timer_count[1]);
break;
case 0x04: /* Timer control */
if (val & CTRL_RESET) {
opl_log("Resetting timer status...\n");
dev->status &= ~STAT_TMR_OVER;
} else {
dev->timer_ctrl = val;
timer_control(dev, 0, val & CTRL_TMR1_START);
timer_control(dev, 1, val & CTRL_TMR2_START);
opl_log("Status mask now %02X (val = %02X)\n", (val & ~CTRL_TMR_MASK) & CTRL_TMR_MASK, val);
}
break;
}
case 0x04: /* Timer control */
if (val & CTRL_RESET) {
opl_log("Resetting timer status...\n");
dev->status &= ~STAT_TMR_OVER;
} else {
dev->timer_ctrl = val;
timer_control(dev, 0, val & CTRL_TMR1_START);
timer_control(dev, 1, val & CTRL_TMR2_START);
opl_log("Status mask now %02X (val = %02X)\n", (val & ~CTRL_TMR_MASK) & CTRL_TMR_MASK, val);
}
break;
}
} else {
dev->port = nuked_write_addr(dev->opl, port, val) & 0x01ff;
dev->port = nuked_write_addr(dev->opl, port, val) & 0x01ff;
if (!(dev->flags & FLAG_OPL3))
dev->port &= 0x00ff;
if (!(dev->flags & FLAG_OPL3))
dev->port &= 0x00ff;
}
}
void
opl_set_do_cycles(opl_t *dev, int8_t do_cycles)
{
if (do_cycles)
dev->flags |= FLAG_CYCLES;
dev->flags |= FLAG_CYCLES;
else
dev->flags &= ~FLAG_CYCLES;
dev->flags &= ~FLAG_CYCLES;
}
static void
opl_init(opl_t *dev, int is_opl3)
{
@@ -206,9 +196,9 @@ opl_init(opl_t *dev, int is_opl3)
dev->flags = FLAG_CYCLES;
if (is_opl3)
dev->flags |= FLAG_OPL3;
dev->flags |= FLAG_OPL3;
else
dev->status = 0x06;
dev->status = 0x06;
/* Create a NukedOPL object. */
dev->opl = nuked_init(48000);
@@ -217,115 +207,106 @@ opl_init(opl_t *dev, int is_opl3)
timer_add(&dev->timers[1], timer_2, dev, 0);
}
void
opl_close(opl_t *dev)
{
/* Release the NukedOPL object. */
if (dev->opl) {
nuked_close(dev->opl);
dev->opl = NULL;
nuked_close(dev->opl);
dev->opl = NULL;
}
}
uint8_t
opl2_read(uint16_t port, void *priv)
{
opl_t *dev = (opl_t *)priv;
opl_t *dev = (opl_t *) priv;
if (dev->flags & FLAG_CYCLES)
cycles -= ((int) (isa_timing * 8));
cycles -= ((int) (isa_timing * 8));
opl2_update(dev);
opl_log("OPL2 port read = %04x\n", port);
opl_log("OPL2 port read = %04x\n", port);
return(opl_read(dev, port));
return (opl_read(dev, port));
}
void
opl2_write(uint16_t port, uint8_t val, void *priv)
{
opl_t *dev = (opl_t *)priv;
opl_t *dev = (opl_t *) priv;
opl2_update(dev);
opl_log("OPL2 port write = %04x\n", port);
opl_log("OPL2 port write = %04x\n", port);
opl_write(dev, port, val);
}
void
opl2_init(opl_t *dev)
{
opl_init(dev, 0);
}
void
opl2_update(opl_t *dev)
{
if (dev->pos >= sound_pos_global) {
return;
}
return;
}
nuked_generate_stream(dev->opl,
&dev->buffer[dev->pos * 2],
sound_pos_global - dev->pos);
&dev->buffer[dev->pos * 2],
sound_pos_global - dev->pos);
for (; dev->pos < sound_pos_global; dev->pos++) {
dev->buffer[dev->pos * 2] /= 2;
dev->buffer[(dev->pos * 2) + 1] = dev->buffer[dev->pos * 2];
dev->buffer[dev->pos * 2] /= 2;
dev->buffer[(dev->pos * 2) + 1] = dev->buffer[dev->pos * 2];
}
}
uint8_t
opl3_read(uint16_t port, void *priv)
{
opl_t *dev = (opl_t *)priv;
opl_t *dev = (opl_t *) priv;
if (dev->flags & FLAG_CYCLES)
cycles -= ((int)(isa_timing * 8));
cycles -= ((int) (isa_timing * 8));
opl3_update(dev);
return(opl_read(dev, port));
return (opl_read(dev, port));
}
void
opl3_write(uint16_t port, uint8_t val, void *priv)
{
opl_t *dev = (opl_t *)priv;
opl_t *dev = (opl_t *) priv;
opl3_update(dev);
opl_write(dev, port, val);
}
void
opl3_init(opl_t *dev)
{
opl_init(dev, 1);
}
/* API to sound interface. */
void
opl3_update(opl_t *dev)
{
if (dev->pos >= sound_pos_global)
return;
return;
nuked_generate_stream(dev->opl,
&dev->buffer[dev->pos * 2],
sound_pos_global - dev->pos);
&dev->buffer[dev->pos * 2],
sound_pos_global - dev->pos);
for (; dev->pos < sound_pos_global; dev->pos++) {
dev->buffer[dev->pos * 2] /= 2;
dev->buffer[(dev->pos * 2) + 1] /= 2;
dev->buffer[dev->pos * 2] /= 2;
dev->buffer[(dev->pos * 2) + 1] /= 2;
}
}

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@@ -1,34 +1,33 @@
#include <stdarg.h>
#include <stdint.h>
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <string.h>
#include <wchar.h>
#define HAVE_STDARG_H
#include <86box/86box.h>
#include <86box/device.h>
#include <86box/io.h>
#include <86box/pic.h>
#include <86box/timer.h>
#include <86box/device.h>
#include <86box/sound.h>
#include <86box/snd_sn76489.h>
#include <86box/timer.h>
typedef struct {
sn76489_t sn76489;
uint8_t status, ctrl;
uint64_t timer_latch;
sn76489_t sn76489;
uint8_t status, ctrl;
uint64_t timer_latch;
pc_timer_t timer_count;
int timer_enable;
uint8_t fifo[2048];
int fifo_read_idx, fifo_write_idx;
int fifo_threshold;
uint8_t dac_val;
int16_t buffer[SOUNDBUFLEN];
int pos;
int timer_enable;
uint8_t fifo[2048];
int fifo_read_idx, fifo_write_idx;
int fifo_threshold;
uint8_t dac_val;
int16_t buffer[SOUNDBUFLEN];
int pos;
} ps1snd_t;
static void
ps1snd_update_irq_status(ps1snd_t *snd)
{
@@ -38,96 +37,92 @@ ps1snd_update_irq_status(ps1snd_t *snd)
picintc(1 << 7);
}
static uint8_t
ps1snd_read(uint16_t port, void *priv)
{
ps1snd_t *ps1snd = (ps1snd_t *)priv;
uint8_t ret = 0xff;
ps1snd_t *ps1snd = (ps1snd_t *) priv;
uint8_t ret = 0xff;
switch (port & 7) {
case 0: /* ADC data */
ps1snd->status &= ~0x10;
ps1snd_update_irq_status(ps1snd);
ret = 0;
break;
case 0: /* ADC data */
ps1snd->status &= ~0x10;
ps1snd_update_irq_status(ps1snd);
ret = 0;
break;
case 2: /* status */
ret = ps1snd->status;
ret |= (ps1snd->ctrl & 0x01);
if ((ps1snd->fifo_write_idx - ps1snd->fifo_read_idx) >= 2048)
ret |= 0x08; /* FIFO full */
if (ps1snd->fifo_read_idx == ps1snd->fifo_write_idx)
ret |= 0x04; /* FIFO empty */
break;
case 2: /* status */
ret = ps1snd->status;
ret |= (ps1snd->ctrl & 0x01);
if ((ps1snd->fifo_write_idx - ps1snd->fifo_read_idx) >= 2048)
ret |= 0x08; /* FIFO full */
if (ps1snd->fifo_read_idx == ps1snd->fifo_write_idx)
ret |= 0x04; /* FIFO empty */
break;
case 3: /* FIFO timer */
/*
* The PS/1 Technical Reference says this should return
* thecurrent value, but the PS/1 BIOS and Stunt Island
* expect it not to change.
*/
ret = ps1snd->timer_latch;
break;
case 3: /* FIFO timer */
/*
* The PS/1 Technical Reference says this should return
* thecurrent value, but the PS/1 BIOS and Stunt Island
* expect it not to change.
*/
ret = ps1snd->timer_latch;
break;
case 4:
case 5:
case 6:
case 7:
ret = 0;
case 4:
case 5:
case 6:
case 7:
ret = 0;
}
return(ret);
return (ret);
}
static void
ps1snd_write(uint16_t port, uint8_t val, void *priv)
{
ps1snd_t *ps1snd = (ps1snd_t *)priv;
ps1snd_t *ps1snd = (ps1snd_t *) priv;
switch (port & 7) {
case 0: /* DAC output */
if ((ps1snd->fifo_write_idx - ps1snd->fifo_read_idx) < 2048) {
ps1snd->fifo[ps1snd->fifo_write_idx & 2047] = val;
ps1snd->fifo_write_idx++;
}
break;
case 0: /* DAC output */
if ((ps1snd->fifo_write_idx - ps1snd->fifo_read_idx) < 2048) {
ps1snd->fifo[ps1snd->fifo_write_idx & 2047] = val;
ps1snd->fifo_write_idx++;
}
break;
case 2: /* control */
ps1snd->ctrl = val;
if (! (val & 0x02))
ps1snd->status &= ~0x02;
ps1snd_update_irq_status(ps1snd);
break;
case 2: /* control */
ps1snd->ctrl = val;
if (!(val & 0x02))
ps1snd->status &= ~0x02;
ps1snd_update_irq_status(ps1snd);
break;
case 3: /* timer reload value */
ps1snd->timer_latch = val;
if (val)
timer_set_delay_u64(&ps1snd->timer_count, ((0xff-val) * TIMER_USEC));
else
timer_disable(&ps1snd->timer_count);
break;
case 3: /* timer reload value */
ps1snd->timer_latch = val;
if (val)
timer_set_delay_u64(&ps1snd->timer_count, ((0xff - val) * TIMER_USEC));
else
timer_disable(&ps1snd->timer_count);
break;
case 4: /* almost empty */
ps1snd->fifo_threshold = val * 4;
break;
case 4: /* almost empty */
ps1snd->fifo_threshold = val * 4;
break;
}
}
static void
ps1snd_update(ps1snd_t *ps1snd)
{
for (; ps1snd->pos < sound_pos_global; ps1snd->pos++)
ps1snd->buffer[ps1snd->pos] = (int8_t)(ps1snd->dac_val ^ 0x80) * 0x20;
ps1snd->buffer[ps1snd->pos] = (int8_t) (ps1snd->dac_val ^ 0x80) * 0x20;
}
static void
ps1snd_callback(void *priv)
{
ps1snd_t *ps1snd = (ps1snd_t *)priv;
ps1snd_t *ps1snd = (ps1snd_t *) priv;
ps1snd_update(ps1snd);
@@ -145,12 +140,11 @@ ps1snd_callback(void *priv)
timer_advance_u64(&ps1snd->timer_count, ps1snd->timer_latch * TIMER_USEC);
}
static void
ps1snd_get_buffer(int32_t *buffer, int len, void *priv)
{
ps1snd_t *ps1snd = (ps1snd_t *)priv;
int c;
ps1snd_t *ps1snd = (ps1snd_t *) priv;
int c;
ps1snd_update(ps1snd);
@@ -160,7 +154,6 @@ ps1snd_get_buffer(int32_t *buffer, int len, void *priv)
ps1snd->pos = 0;
}
static void *
ps1snd_init(const device_t *info)
{
@@ -169,31 +162,37 @@ ps1snd_init(const device_t *info)
sn76489_init(&ps1snd->sn76489, 0x0205, 0x0001, SN76496, 4000000);
io_sethandler(0x0200, 1, ps1snd_read,NULL,NULL, ps1snd_write,NULL,NULL, ps1snd);
io_sethandler(0x0202, 6, ps1snd_read,NULL,NULL, ps1snd_write,NULL,NULL, ps1snd);
io_sethandler(0x0200, 1,
ps1snd_read, NULL, NULL,
ps1snd_write, NULL, NULL,
ps1snd);
io_sethandler(0x0202, 6,
ps1snd_read, NULL, NULL,
ps1snd_write, NULL, NULL,
ps1snd);
timer_add(&ps1snd->timer_count, ps1snd_callback, ps1snd, 0);
sound_add_handler(ps1snd_get_buffer, ps1snd);
return(ps1snd);
return (ps1snd);
}
static void
ps1snd_close(void *priv)
{
ps1snd_t *ps1snd = (ps1snd_t *)priv;
ps1snd_t *ps1snd = (ps1snd_t *) priv;
free(ps1snd);
}
const device_t ps1snd_device = {
"IBM PS/1 Audio Card",
"ps1snd",
0, 0,
ps1snd_init, ps1snd_close,
0,
0,
ps1snd_init,
ps1snd_close,
NULL,
{ NULL },
NULL,

View File

@@ -1,55 +1,55 @@
#include <stdio.h>
#include <stdint.h>
#include <string.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <wchar.h>
#include <86box/86box.h>
#include <86box/io.h>
#include <86box/dma.h>
#include <86box/pic.h>
#include <86box/timer.h>
#include <86box/device.h>
#include <86box/dma.h>
#include <86box/io.h>
#include <86box/pic.h>
#include <86box/sound.h>
#include <86box/snd_sn76489.h>
#include <86box/timer.h>
typedef struct pssj_t
{
typedef struct pssj_t {
sn76489_t sn76489;
uint8_t ctrl;
uint8_t wave;
uint8_t dac_val;
uint8_t ctrl;
uint8_t wave;
uint8_t dac_val;
uint16_t freq;
int amplitude;
int amplitude;
int irq;
int irq;
pc_timer_t timer_count;
int enable;
int enable;
int wave_pos;
int pulse_width;
int16_t buffer[SOUNDBUFLEN];
int pos;
int pos;
} pssj_t;
static void pssj_update_irq(pssj_t *pssj)
static void
pssj_update_irq(pssj_t *pssj)
{
if (pssj->irq && (pssj->ctrl & 0x10) && (pssj->ctrl & 0x08))
picint(1 << 7);
}
static void pssj_write(uint16_t port, uint8_t val, void *p)
static void
pssj_write(uint16_t port, uint8_t val, void *p)
{
pssj_t *pssj = (pssj_t *)p;
pssj_t *pssj = (pssj_t *) p;
switch (port & 3)
{
switch (port & 3) {
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)));
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);
@@ -59,10 +59,9 @@ static void pssj_write(uint16_t port, uint8_t val, void *p)
pssj_update_irq(pssj);
break;
case 1:
switch (pssj->ctrl & 3)
{
switch (pssj->ctrl & 3) {
case 1: /*Sound channel*/
pssj->wave = val;
pssj->wave = val;
pssj->pulse_width = val & 7;
break;
case 3: /*Direct DAC*/
@@ -74,22 +73,21 @@ static void pssj_write(uint16_t port, uint8_t val, void *p)
pssj->freq = (pssj->freq & 0xf00) | val;
break;
case 3:
pssj->freq = (pssj->freq & 0x0ff) | ((val & 0xf) << 8);
pssj->freq = (pssj->freq & 0x0ff) | ((val & 0xf) << 8);
pssj->amplitude = val >> 4;
break;
}
}
static uint8_t pssj_read(uint16_t port, void *p)
static uint8_t
pssj_read(uint16_t port, void *p)
{
pssj_t *pssj = (pssj_t *)p;
pssj_t *pssj = (pssj_t *) p;
switch (port & 3)
{
switch (port & 3) {
case 0:
return (pssj->ctrl & ~0x88) | (pssj->irq ? 8 : 0);
case 1:
switch (pssj->ctrl & 3)
{
switch (pssj->ctrl & 3) {
case 0: /*Joystick*/
return 0;
case 1: /*Sound channel*/
@@ -111,47 +109,39 @@ static uint8_t pssj_read(uint16_t port, void *p)
return 0xff;
}
static void pssj_update(pssj_t *pssj)
static void
pssj_update(pssj_t *pssj)
{
for (; pssj->pos < sound_pos_global; pssj->pos++)
pssj->buffer[pssj->pos] = (((int8_t)(pssj->dac_val ^ 0x80) * 0x20) * pssj->amplitude) / 15;
pssj->buffer[pssj->pos] = (((int8_t) (pssj->dac_val ^ 0x80) * 0x20) * pssj->amplitude) / 15;
}
static void pssj_callback(void *p)
static void
pssj_callback(void *p)
{
pssj_t *pssj = (pssj_t *)p;
int data;
pssj_t *pssj = (pssj_t *) p;
int data;
pssj_update(pssj);
if (pssj->ctrl & 2)
{
if ((pssj->ctrl & 3) == 3)
{
if (pssj->ctrl & 2) {
if ((pssj->ctrl & 3) == 3) {
data = dma_channel_read(1);
if (data != DMA_NODATA)
{
if (data != DMA_NODATA) {
pssj->dac_val = data & 0xff;
}
}
else
{
} else {
data = dma_channel_write(1, 0x80);
}
if ((data & DMA_OVER) && data != DMA_NODATA)
{
if (pssj->ctrl & 0x08)
{
if ((data & DMA_OVER) && data != DMA_NODATA) {
if (pssj->ctrl & 0x08) {
pssj->irq = 1;
pssj_update_irq(pssj);
}
}
}
else
{
switch (pssj->wave & 0xc0)
{
} else {
switch (pssj->wave & 0xc0) {
case 0x00: /*Pulse*/
pssj->dac_val = (pssj->wave_pos > (pssj->pulse_width << 1)) ? 0xff : 0;
break;
@@ -171,13 +161,14 @@ static void pssj_callback(void *p)
pssj->wave_pos = (pssj->wave_pos + 1) & 31;
}
timer_advance_u64(&pssj->timer_count, (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)
static void
pssj_get_buffer(int32_t *buffer, int len, void *p)
{
pssj_t *pssj = (pssj_t *)p;
int c;
pssj_t *pssj = (pssj_t *) p;
int c;
pssj_update(pssj);
@@ -187,7 +178,8 @@ static void pssj_get_buffer(int32_t *buffer, int len, void *p)
pssj->pos = 0;
}
void *pssj_init(const device_t *info)
void *
pssj_init(const device_t *info)
{
pssj_t *pssj = malloc(sizeof(pssj_t));
memset(pssj, 0, sizeof(pssj_t));
@@ -201,7 +193,8 @@ void *pssj_init(const device_t *info)
return pssj;
}
void *pssj_1e0_init(const device_t *info)
void *
pssj_1e0_init(const device_t *info)
{
pssj_t *pssj = malloc(sizeof(pssj_t));
memset(pssj, 0, sizeof(pssj_t));
@@ -216,7 +209,8 @@ void *pssj_1e0_init(const device_t *info)
}
#if defined(DEV_BRANCH) && defined(USE_TANDY_ISA)
void *pssj_isa_init(const device_t *info)
void *
pssj_isa_init(const device_t *info)
{
pssj_t *pssj = malloc(sizeof(pssj_t));
memset(pssj, 0, sizeof(pssj_t));
@@ -233,41 +227,32 @@ void *pssj_isa_init(const device_t *info)
}
#endif
void pssj_close(void *p)
void
pssj_close(void *p)
{
pssj_t *pssj = (pssj_t *)p;
pssj_t *pssj = (pssj_t *) p;
free(pssj);
}
#if defined(DEV_BRANCH) && defined(USE_TANDY_ISA)
static const device_config_t pssj_isa_config[] =
{
static const device_config_t pssj_isa_config[] = {
// clang-format off
{
"base", "Address", CONFIG_HEX16, "", 0x2C0, "", { 0 },
{
{
"0xC0", 0xC0
},
{
"0x1E0", 0x1E0
},
{
"0x2C0", 0x2C0
},
{
""
}
{ "0x0C0", 0x0C0 },
{ "0x1E0", 0x1E0 },
{ "0x2C0", 0x2C0 },
{ "" }
}
},
{
"", "", -1
}
{ "", "", -1 }
// clang-format on
};
#endif
const device_t pssj_device =
{
const device_t pssj_device = {
"Tandy PSSJ",
"pssj",
0,
@@ -280,8 +265,7 @@ const device_t pssj_device =
NULL
};
const device_t pssj_1e0_device =
{
const device_t pssj_1e0_device = {
"Tandy PSSJ (port 1e0h)",
"pssj_1e0",
0,
@@ -295,8 +279,7 @@ const device_t pssj_1e0_device =
};
#if defined(DEV_BRANCH) && defined(USE_TANDY_ISA)
const device_t pssj_isa_device =
{
const device_t pssj_isa_device = {
"Tandy PSSJ Clone",
"pssj_isa",
DEVICE_ISA,

View File

@@ -1,112 +1,114 @@
#include <stdio.h>
#include <string.h>
#include <stdint.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "resid-fp/sid.h"
#include <86box/plat.h>
#include <86box/snd_resid.h>
typedef struct psid_t
{
/* resid sid implementation */
SIDFP *sid;
int16_t last_sample;
typedef struct psid_t {
/* resid sid implementation */
SIDFP *sid;
int16_t last_sample;
} psid_t;
psid_t *psid;
void *sid_init(void)
void *
sid_init(void)
{
// psid_t *psid;
int c;
sampling_method method=SAMPLE_INTERPOLATE;
float cycles_per_sec = 14318180.0 / 16.0;
psid = new psid_t;
// psid = (psid_t *)malloc(sizeof(sound_t));
psid->sid = new SIDFP;
psid->sid->set_chip_model(MOS8580FP);
psid->sid->set_voice_nonlinearity(1.0f);
psid->sid->get_filter().set_distortion_properties(0.f, 0.f, 0.f);
psid->sid->get_filter().set_type4_properties(6.55f, 20.0f);
// psid_t *psid;
int c;
sampling_method method = SAMPLE_INTERPOLATE;
float cycles_per_sec = 14318180.0 / 16.0;
psid->sid->enable_filter(true);
psid->sid->enable_external_filter(true);
psid = new psid_t;
// psid = (psid_t *)malloc(sizeof(sound_t));
psid->sid = new SIDFP;
psid->sid->reset();
for (c=0;c<32;c++)
psid->sid->write(c,0);
if (!psid->sid->set_sampling_parameters((float)cycles_per_sec, method,
(float)48000, 0.9*48000.0/2.0))
{
// printf("reSID failed!\n");
}
psid->sid->set_chip_model(MOS8580FP);
psid->sid->set_chip_model(MOS6581FP);
psid->sid->set_voice_nonlinearity(0.96f);
psid->sid->get_filter().set_distortion_properties(3.7e-3f, 2048.f, 1.2e-4f);
psid->sid->set_voice_nonlinearity(1.0f);
psid->sid->get_filter().set_distortion_properties(0.f, 0.f, 0.f);
psid->sid->get_filter().set_type4_properties(6.55f, 20.0f);
psid->sid->input(0);
psid->sid->get_filter().set_type3_properties(1.33e6f, 2.2e9f, 1.0056f, 7e3f);
psid->sid->enable_filter(true);
psid->sid->enable_external_filter(true);
return (void *)psid;
psid->sid->reset();
for (c = 0; c < 32; c++)
psid->sid->write(c, 0);
if (!psid->sid->set_sampling_parameters((float) cycles_per_sec, method,
(float) 48000, 0.9 * 48000.0 / 2.0)) {
// printf("reSID failed!\n");
}
psid->sid->set_chip_model(MOS6581FP);
psid->sid->set_voice_nonlinearity(0.96f);
psid->sid->get_filter().set_distortion_properties(3.7e-3f, 2048.f, 1.2e-4f);
psid->sid->input(0);
psid->sid->get_filter().set_type3_properties(1.33e6f, 2.2e9f, 1.0056f, 7e3f);
return (void *) psid;
}
void sid_close(UNUSED(void *p))
void
sid_close(UNUSED(void *p))
{
// psid_t *psid = (psid_t *)p;
delete psid->sid;
// free(psid);
// psid_t *psid = (psid_t *)p;
delete psid->sid;
// free(psid);
}
void sid_reset(UNUSED(void *p))
void
sid_reset(UNUSED(void *p))
{
// psid_t *psid = (psid_t *)p;
int c;
psid->sid->reset();
// psid_t *psid = (psid_t *)p;
int c;
for (c = 0; c < 32; c++)
psid->sid->write(c, 0);
psid->sid->reset();
for (c = 0; c < 32; c++)
psid->sid->write(c, 0);
}
uint8_t sid_read(uint16_t addr, UNUSED(void *p))
uint8_t
sid_read(uint16_t addr, UNUSED(void *p))
{
// psid_t *psid = (psid_t *)p;
return psid->sid->read(addr & 0x1f);
// return 0xFF;
// psid_t *psid = (psid_t *)p;
return psid->sid->read(addr & 0x1f);
// return 0xFF;
}
void sid_write(uint16_t addr, uint8_t val, UNUSED(void *p))
void
sid_write(uint16_t addr, uint8_t val, UNUSED(void *p))
{
// psid_t *psid = (psid_t *)p;
psid->sid->write(addr & 0x1f,val);
// psid_t *psid = (psid_t *)p;
psid->sid->write(addr & 0x1f, val);
}
#define CLOCK_DELTA(n) (int)(((14318180.0 * n) / 16.0) / 48000.0)
#define CLOCK_DELTA(n) (int) (((14318180.0 * n) / 16.0) / 48000.0)
static void fillbuf2(int& count, int16_t *buf, int len)
static void
fillbuf2(int &count, int16_t *buf, int len)
{
int c;
c = psid->sid->clock(count, buf, len, 1);
if (!c)
*buf = psid->last_sample;
psid->last_sample = *buf;
int c;
c = psid->sid->clock(count, buf, len, 1);
if (!c)
*buf = psid->last_sample;
psid->last_sample = *buf;
}
void sid_fillbuf(int16_t *buf, int len, UNUSED(void *p))
void
sid_fillbuf(int16_t *buf, int len, UNUSED(void *p))
{
// psid_t *psid = (psid_t *)p;
int x = CLOCK_DELTA(len);
fillbuf2(x, buf, len);
// psid_t *psid = (psid_t *)p;
int x = CLOCK_DELTA(len);
fillbuf2(x, buf, len);
}

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@@ -1,311 +1,303 @@
#include <stdio.h>
#include <stdint.h>
#include <string.h>
#include <stdio.h>
#include <stdlib.h>
#include <wchar.h>
#include <string.h>
#include <time.h>
#include <wchar.h>
#include <86box/86box.h>
#include <86box/io.h>
#include <86box/device.h>
#include <86box/io.h>
#include <86box/sound.h>
#include <86box/snd_sn76489.h>
int sn76489_mute;
static float volslog[16]=
{
0.00000f,0.59715f,0.75180f,0.94650f,
1.19145f,1.50000f,1.88835f,2.37735f,
2.99295f,3.76785f,4.74345f,5.97165f,
7.51785f,9.46440f,11.9194f,15.0000f
static float volslog[16] = {
0.00000f, 0.59715f, 0.75180f, 0.94650f,
1.19145f, 1.50000f, 1.88835f, 2.37735f,
2.99295f, 3.76785f, 4.74345f, 5.97165f,
7.51785f, 9.46440f, 11.9194f, 15.0000f
};
void sn76489_update(sn76489_t *sn76489)
void
sn76489_update(sn76489_t *sn76489)
{
for (; sn76489->pos < sound_pos_global; sn76489->pos++)
{
int c;
int16_t result = 0;
for (; sn76489->pos < sound_pos_global; sn76489->pos++) {
int c;
int16_t result = 0;
for (c = 1; c < 4; c++)
{
if (sn76489->latch[c] > 256) result += (int16_t) (volslog[sn76489->vol[c]] * sn76489->stat[c]);
else result += (int16_t) (volslog[sn76489->vol[c]] * 127);
for (c = 1; c < 4; c++) {
if (sn76489->latch[c] > 256)
result += (int16_t) (volslog[sn76489->vol[c]] * sn76489->stat[c]);
else
result += (int16_t) (volslog[sn76489->vol[c]] * 127);
sn76489->count[c] -= (256 * sn76489->psgconst);
while ((int)sn76489->count[c] < 0)
{
sn76489->count[c] += sn76489->latch[c];
sn76489->stat[c] = -sn76489->stat[c];
}
}
result += (((sn76489->shift & 1) ^ 1) * 127 * volslog[sn76489->vol[0]] * 2);
sn76489->count[0] -= (512 * sn76489->psgconst);
while ((int)sn76489->count[0] < 0 && sn76489->latch[0])
{
sn76489->count[0] += (sn76489->latch[0] * 4);
if (!(sn76489->noise & 4))
{
if (sn76489->shift & 1)
sn76489->shift |= 0x8000;
sn76489->shift >>= 1;
}
else
{
if ((sn76489->shift & 1) ^ ((sn76489->shift >> 1) & 1))
sn76489->shift |= 0x8000;
sn76489->shift >>= 1;
}
}
sn76489->buffer[sn76489->pos] = result;
sn76489->count[c] -= (256 * sn76489->psgconst);
while ((int) sn76489->count[c] < 0) {
sn76489->count[c] += sn76489->latch[c];
sn76489->stat[c] = -sn76489->stat[c];
}
}
}
result += (((sn76489->shift & 1) ^ 1) * 127 * volslog[sn76489->vol[0]] * 2);
void sn76489_get_buffer(int32_t *buffer, int len, void *p)
{
sn76489_t *sn76489 = (sn76489_t *)p;
int c;
sn76489_update(sn76489);
if (!sn76489_mute)
{
for (c = 0; c < len * 2; c++)
buffer[c] += sn76489->buffer[c >> 1];
sn76489->count[0] -= (512 * sn76489->psgconst);
while ((int) sn76489->count[0] < 0 && sn76489->latch[0]) {
sn76489->count[0] += (sn76489->latch[0] * 4);
if (!(sn76489->noise & 4)) {
if (sn76489->shift & 1)
sn76489->shift |= 0x8000;
sn76489->shift >>= 1;
} else {
if ((sn76489->shift & 1) ^ ((sn76489->shift >> 1) & 1))
sn76489->shift |= 0x8000;
sn76489->shift >>= 1;
}
}
sn76489->pos = 0;
sn76489->buffer[sn76489->pos] = result;
}
}
void sn76489_write(uint16_t addr, uint8_t data, void *p)
void
sn76489_get_buffer(int32_t *buffer, int len, void *p)
{
sn76489_t *sn76489 = (sn76489_t *)p;
int freq;
sn76489_t *sn76489 = (sn76489_t *) p;
sn76489_update(sn76489);
int c;
if (data & 0x80)
{
sn76489->firstdat = data;
switch (data & 0x70)
{
case 0:
sn76489->freqlo[3] = data & 0xf;
sn76489->latch[3] = (sn76489->freqlo[3] | (sn76489->freqhi[3] << 4)) << 6;
if (sn76489->extra_divide)
sn76489->latch[3] &= 0x3ff;
if (!sn76489->latch[3])
sn76489->latch[3] = (sn76489->extra_divide ? 2048 : 1024) << 6;
sn76489->lasttone = 3;
break;
case 0x10:
data &= 0xf;
sn76489->vol[3] = 0xf - data;
break;
case 0x20:
sn76489->freqlo[2] = data & 0xf;
sn76489->latch[2] = (sn76489->freqlo[2] | (sn76489->freqhi[2] << 4)) << 6;
if (sn76489->extra_divide)
sn76489->latch[2] &= 0x3ff;
if (!sn76489->latch[2])
sn76489->latch[2] = (sn76489->extra_divide ? 2048 : 1024) << 6;
sn76489->lasttone = 2;
break;
case 0x30:
data &= 0xf;
sn76489->vol[2] = 0xf - data;
break;
case 0x40:
sn76489->freqlo[1] = data & 0xf;
sn76489->latch[1] = (sn76489->freqlo[1] | (sn76489->freqhi[1] << 4)) << 6;
if (sn76489->extra_divide)
sn76489->latch[1] &= 0x3ff;
if (!sn76489->latch[1])
sn76489->latch[1] = (sn76489->extra_divide ? 2048 : 1024) << 6;
sn76489->lasttone = 1;
break;
case 0x50:
data &= 0xf;
sn76489->vol[1] = 0xf - data;
break;
case 0x60:
if ((data & 4) != (sn76489->noise & 4) || sn76489->type == SN76496)
sn76489->shift = 0x4000;
sn76489->noise = data & 0xf;
if ((data & 3) == 3) sn76489->latch[0] = sn76489->latch[1];
else sn76489->latch[0] = 0x400 << (data & 3);
if (sn76489->extra_divide)
sn76489->latch[0] &= 0x3ff;
if (!sn76489->latch[0])
sn76489->latch[0] = (sn76489->extra_divide ? 2048 : 1024) << 6;
break;
case 0x70:
data &= 0xf;
sn76489->vol[0] = 0xf - data;
break;
}
sn76489_update(sn76489);
if (!sn76489_mute) {
for (c = 0; c < len * 2; c++)
buffer[c] += sn76489->buffer[c >> 1];
}
sn76489->pos = 0;
}
void
sn76489_write(uint16_t addr, uint8_t data, void *p)
{
sn76489_t *sn76489 = (sn76489_t *) p;
int freq;
sn76489_update(sn76489);
if (data & 0x80) {
sn76489->firstdat = data;
switch (data & 0x70) {
case 0:
sn76489->freqlo[3] = data & 0xf;
sn76489->latch[3] = (sn76489->freqlo[3] | (sn76489->freqhi[3] << 4)) << 6;
if (sn76489->extra_divide)
sn76489->latch[3] &= 0x3ff;
if (!sn76489->latch[3])
sn76489->latch[3] = (sn76489->extra_divide ? 2048 : 1024) << 6;
sn76489->lasttone = 3;
break;
case 0x10:
data &= 0xf;
sn76489->vol[3] = 0xf - data;
break;
case 0x20:
sn76489->freqlo[2] = data & 0xf;
sn76489->latch[2] = (sn76489->freqlo[2] | (sn76489->freqhi[2] << 4)) << 6;
if (sn76489->extra_divide)
sn76489->latch[2] &= 0x3ff;
if (!sn76489->latch[2])
sn76489->latch[2] = (sn76489->extra_divide ? 2048 : 1024) << 6;
sn76489->lasttone = 2;
break;
case 0x30:
data &= 0xf;
sn76489->vol[2] = 0xf - data;
break;
case 0x40:
sn76489->freqlo[1] = data & 0xf;
sn76489->latch[1] = (sn76489->freqlo[1] | (sn76489->freqhi[1] << 4)) << 6;
if (sn76489->extra_divide)
sn76489->latch[1] &= 0x3ff;
if (!sn76489->latch[1])
sn76489->latch[1] = (sn76489->extra_divide ? 2048 : 1024) << 6;
sn76489->lasttone = 1;
break;
case 0x50:
data &= 0xf;
sn76489->vol[1] = 0xf - data;
break;
case 0x60:
if ((data & 4) != (sn76489->noise & 4) || sn76489->type == SN76496)
sn76489->shift = 0x4000;
sn76489->noise = data & 0xf;
if ((data & 3) == 3)
sn76489->latch[0] = sn76489->latch[1];
else
sn76489->latch[0] = 0x400 << (data & 3);
if (sn76489->extra_divide)
sn76489->latch[0] &= 0x3ff;
if (!sn76489->latch[0])
sn76489->latch[0] = (sn76489->extra_divide ? 2048 : 1024) << 6;
break;
case 0x70:
data &= 0xf;
sn76489->vol[0] = 0xf - data;
break;
}
else
{
if ((sn76489->firstdat & 0x70) == 0x60 && (sn76489->type == SN76496))
{
if ((data & 4) != (sn76489->noise & 4) || sn76489->type == SN76496)
sn76489->shift = 0x4000;
sn76489->noise = data & 0xf;
if ((data & 3) == 3) sn76489->latch[0] = sn76489->latch[1];
else sn76489->latch[0] = 0x400 << (data & 3);
if (!sn76489->latch[0])
sn76489->latch[0] = 1024 << 6;
}
else if ((sn76489->firstdat & 0x70) != 0x60)
{
sn76489->freqhi[sn76489->lasttone] = data & 0x7F;
freq = sn76489->freqlo[sn76489->lasttone] | (sn76489->freqhi[sn76489->lasttone] << 4);
if (sn76489->extra_divide)
freq &= 0x3ff;
if (!freq)
freq = sn76489->extra_divide ? 2048 : 1024;
if ((sn76489->noise & 3) == 3 && sn76489->lasttone == 1)
sn76489->latch[0] = freq << 6;
sn76489->latch[sn76489->lasttone] = freq << 6;
}
} else {
if ((sn76489->firstdat & 0x70) == 0x60 && (sn76489->type == SN76496)) {
if ((data & 4) != (sn76489->noise & 4) || sn76489->type == SN76496)
sn76489->shift = 0x4000;
sn76489->noise = data & 0xf;
if ((data & 3) == 3)
sn76489->latch[0] = sn76489->latch[1];
else
sn76489->latch[0] = 0x400 << (data & 3);
if (!sn76489->latch[0])
sn76489->latch[0] = 1024 << 6;
} else if ((sn76489->firstdat & 0x70) != 0x60) {
sn76489->freqhi[sn76489->lasttone] = data & 0x7F;
freq = sn76489->freqlo[sn76489->lasttone] | (sn76489->freqhi[sn76489->lasttone] << 4);
if (sn76489->extra_divide)
freq &= 0x3ff;
if (!freq)
freq = sn76489->extra_divide ? 2048 : 1024;
if ((sn76489->noise & 3) == 3 && sn76489->lasttone == 1)
sn76489->latch[0] = freq << 6;
sn76489->latch[sn76489->lasttone] = freq << 6;
}
}
}
void sn74689_set_extra_divide(sn76489_t *sn76489, int enable)
void
sn74689_set_extra_divide(sn76489_t *sn76489, int enable)
{
sn76489->extra_divide = enable;
sn76489->extra_divide = enable;
}
void sn76489_init(sn76489_t *sn76489, uint16_t base, uint16_t size, int type, int freq)
void
sn76489_init(sn76489_t *sn76489, uint16_t base, uint16_t size, int type, int freq)
{
sound_add_handler(sn76489_get_buffer, sn76489);
sound_add_handler(sn76489_get_buffer, sn76489);
sn76489->latch[0] = sn76489->latch[1] = sn76489->latch[2] = sn76489->latch[3] = 0x3FF << 6;
sn76489->vol[0] = 0;
sn76489->vol[1] = sn76489->vol[2] = sn76489->vol[3] = 8;
sn76489->stat[0] = sn76489->stat[1] = sn76489->stat[2] = sn76489->stat[3] = 127;
srand(time(NULL));
sn76489->count[0] = 0;
sn76489->count[1] = (rand()&0x3FF)<<6;
sn76489->count[2] = (rand()&0x3FF)<<6;
sn76489->count[3] = (rand()&0x3FF)<<6;
sn76489->noise = 3;
sn76489->shift = 0x4000;
sn76489->type = type;
sn76489->psgconst = (((double)freq / 64.0) / 48000.0);
sn76489->latch[0] = sn76489->latch[1] = sn76489->latch[2] = sn76489->latch[3] = 0x3FF << 6;
sn76489->vol[0] = 0;
sn76489->vol[1] = sn76489->vol[2] = sn76489->vol[3] = 8;
sn76489->stat[0] = sn76489->stat[1] = sn76489->stat[2] = sn76489->stat[3] = 127;
srand(time(NULL));
sn76489->count[0] = 0;
sn76489->count[1] = (rand() & 0x3FF) << 6;
sn76489->count[2] = (rand() & 0x3FF) << 6;
sn76489->count[3] = (rand() & 0x3FF) << 6;
sn76489->noise = 3;
sn76489->shift = 0x4000;
sn76489->type = type;
sn76489->psgconst = (((double) freq / 64.0) / 48000.0);
sn76489_mute = 0;
sn76489_mute = 0;
io_sethandler(base, size, NULL, NULL, NULL, sn76489_write, NULL, NULL, sn76489);
io_sethandler(base, size, NULL, NULL, NULL, sn76489_write, NULL, NULL, sn76489);
}
void *sn76489_device_init(const device_t *info)
void *
sn76489_device_init(const device_t *info)
{
sn76489_t *sn76489 = malloc(sizeof(sn76489_t));
memset(sn76489, 0, sizeof(sn76489_t));
sn76489_t *sn76489 = malloc(sizeof(sn76489_t));
memset(sn76489, 0, sizeof(sn76489_t));
sn76489_init(sn76489, 0x00c0, 0x0008, SN76496, 3579545);
sn76489_init(sn76489, 0x00c0, 0x0008, SN76496, 3579545);
return sn76489;
return sn76489;
}
void *ncr8496_device_init(const device_t *info)
void *
ncr8496_device_init(const device_t *info)
{
sn76489_t *sn76489 = malloc(sizeof(sn76489_t));
memset(sn76489, 0, sizeof(sn76489_t));
sn76489_t *sn76489 = malloc(sizeof(sn76489_t));
memset(sn76489, 0, sizeof(sn76489_t));
sn76489_init(sn76489, 0x00c0, 0x0008, NCR8496, 3579545);
sn76489_init(sn76489, 0x00c0, 0x0008, NCR8496, 3579545);
return sn76489;
return sn76489;
}
#if defined(DEV_BRANCH) && defined(USE_TANDY_ISA)
void *tndy_device_init(const device_t *info)
void *
tndy_device_init(const device_t *info)
{
sn76489_t *sn76489 = malloc(sizeof(sn76489_t));
memset(sn76489, 0, sizeof(sn76489_t));
sn76489_t *sn76489 = malloc(sizeof(sn76489_t));
memset(sn76489, 0, sizeof(sn76489_t));
uint16_t addr = device_get_config_hex16("base");
uint16_t addr = device_get_config_hex16("base");
sn76489_init(sn76489, addr, 0x0008, SN76496, 3579545);
sn76489_init(sn76489, addr, 0x0008, SN76496, 3579545);
return sn76489;
return sn76489;
}
#endif
void sn76489_device_close(void *p)
void
sn76489_device_close(void *p)
{
sn76489_t *sn76489 = (sn76489_t *)p;
sn76489_t *sn76489 = (sn76489_t *) p;
free(sn76489);
free(sn76489);
}
#if defined(DEV_BRANCH) && defined(USE_TANDY_ISA)
static const device_config_t tndy_config[] =
{
static const device_config_t tndy_config[] = {
// clang-format off
{
"base", "Address", CONFIG_HEX16, "", 0x0C0, "", { 0 },
{
"base", "Address", CONFIG_HEX16, "", 0x0C0, "", { 0 },
{
{
"0x0C0", 0x0C0
},
{
"0x1E0", 0x1E0
},
{
"0x2C0", 0x2C0
},
{
""
}
}
},
{
"", "", -1
{ "0x0C0", 0x0C0 },
{ "0x1E0", 0x1E0 },
{ "0x2C0", 0x2C0 },
{ "" }
}
},
{ "", "", -1 }
// clang-format on
};
#endif
const device_t sn76489_device =
{
"TI SN74689 PSG",
"sn76489",
0,
0,
sn76489_device_init,
sn76489_device_close,
NULL, { NULL }, NULL,
NULL
const device_t sn76489_device = {
"TI SN74689 PSG",
"sn76489",
0,
0,
sn76489_device_init,
sn76489_device_close,
NULL,
{ NULL },
NULL,
NULL
};
const device_t ncr8496_device =
{
"NCR8496 PSG",
"ncr8496",
0,
0,
ncr8496_device_init,
sn76489_device_close,
NULL, { NULL }, NULL,
NULL
const device_t ncr8496_device = {
"NCR8496 PSG",
"ncr8496",
0,
0,
ncr8496_device_init,
sn76489_device_close,
NULL,
{ NULL },
NULL,
NULL
};
#if defined(DEV_BRANCH) && defined(USE_TANDY_ISA)
const device_t tndy_device =
{
"TNDY",
"tndy",
DEVICE_ISA,
0,
tndy_device_init,
sn76489_device_close,
NULL, { NULL }, NULL,
NULL,
tndy_config
const device_t tndy_device = {
"TNDY",
"tndy",
DEVICE_ISA,
0,
tndy_device_init,
sn76489_device_close,
NULL,
{ NULL },
NULL,
NULL,
tndy_config
};
#endif

View File

@@ -1,89 +1,85 @@
/*
* 86Box A hypervisor and IBM PC system emulator that specializes in
* running old operating systems and software designed for IBM
* PC systems and compatibles from 1981 through fairly recent
* system designs based on the PCI bus.
* 86Box A hypervisor and IBM PC system emulator that specializes in
* running old operating systems and software designed for IBM
* PC systems and compatibles from 1981 through fairly recent
* system designs based on the PCI bus.
*
* This file is part of the 86Box distribution.
* This file is part of the 86Box distribution.
*
* Emulation of the PC speaker.
* Emulation of the PC speaker.
*
*
*
* Authors: Sarah Walker, <http://pcem-emulator.co.uk/>
* Miran Grca, <mgrca8@gmail.com>
* Authors: Sarah Walker, <http://pcem-emulator.co.uk/>
* Miran Grca, <mgrca8@gmail.com>
*
* Copyright 2008-2019 Sarah Walker.
* Copyright 2016-2019 Miran Grca.
* Copyright 2008-2019 Sarah Walker.
* Copyright 2016-2019 Miran Grca.
*/
#include <stdio.h>
#include <stdint.h>
#include <stdio.h>
#include <string.h>
#include <wchar.h>
#include <86box/86box.h>
#include <86box/timer.h>
#include <86box/pit.h>
#include <86box/sound.h>
#include <86box/snd_speaker.h>
#include <86box/sound.h>
int speaker_mute = 0, speaker_gated = 0;
int speaker_enable = 0, was_speaker_enable = 0;
int gated, speakval, speakon;
static int32_t speaker_buffer[SOUNDBUFLEN];
static int speaker_pos = 0;
static uint8_t speaker_mode = 0;
static double speaker_count = 65535.0;
static int speaker_pos = 0;
static uint8_t speaker_mode = 0;
static double speaker_count = 65535.0;
void
speaker_set_count(uint8_t new_m, int new_count)
{
speaker_mode = new_m;
speaker_mode = new_m;
speaker_count = (double) new_count;
}
void
speaker_update(void)
{
int32_t val;
double amplitude;
double amplitude;
amplitude = ((speaker_count / 64.0) * 10240.0) - 5120.0;
if (amplitude > 5120.0)
amplitude = 5120.0;
amplitude = 5120.0;
if (speaker_pos < sound_pos_global) {
for (; speaker_pos < sound_pos_global; speaker_pos++) {
if (speaker_gated && was_speaker_enable) {
if ((speaker_mode == 0) || (speaker_mode == 4))
val = (int32_t) amplitude;
else if (speaker_count < 64.0)
val = 0xa00;
else
val = speakon ? 0x1400 : 0;
} else {
if (speaker_mode == 1)
val = was_speaker_enable ? (int32_t) amplitude : 0;
else
val = was_speaker_enable ? 0x1400 : 0;
}
for (; speaker_pos < sound_pos_global; speaker_pos++) {
if (speaker_gated && was_speaker_enable) {
if ((speaker_mode == 0) || (speaker_mode == 4))
val = (int32_t) amplitude;
else if (speaker_count < 64.0)
val = 0xa00;
else
val = speakon ? 0x1400 : 0;
} else {
if (speaker_mode == 1)
val = was_speaker_enable ? (int32_t) amplitude : 0;
else
val = was_speaker_enable ? 0x1400 : 0;
}
if (!speaker_enable)
was_speaker_enable = 0;
if (!speaker_enable)
was_speaker_enable = 0;
speaker_buffer[speaker_pos] = val;
}
speaker_buffer[speaker_pos] = val;
}
}
}
void
speaker_get_buffer(int32_t *buffer, int len, void *p)
{
@@ -92,17 +88,16 @@ speaker_get_buffer(int32_t *buffer, int len, void *p)
speaker_update();
if (!speaker_mute) {
for (c = 0; c < len * 2; c += 2) {
val = speaker_buffer[c >> 1];
buffer[c] += val;
buffer[c + 1] += val;
}
for (c = 0; c < len * 2; c += 2) {
val = speaker_buffer[c >> 1];
buffer[c] += val;
buffer[c + 1] += val;
}
}
speaker_pos = 0;
}
void
speaker_init(void)
{

View File

@@ -1,126 +1,122 @@
#include <stdarg.h>
#include <stdint.h>
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <string.h>
#include <wchar.h>
#define HAVE_STDARG_H
#include <86box/86box.h>
#include <86box/io.h>
#include <86box/device.h>
#include <86box/gameport.h>
#include <86box/sound.h>
#include <86box/io.h>
#include <86box/snd_resid.h>
#include <86box/sound.h>
typedef struct ssi2001_t
{
void *psid;
int16_t buffer[SOUNDBUFLEN * 2];
int pos;
int gameport_enabled;
typedef struct ssi2001_t {
void *psid;
int16_t buffer[SOUNDBUFLEN * 2];
int pos;
int gameport_enabled;
} ssi2001_t;
static void ssi2001_update(ssi2001_t *ssi2001)
static void
ssi2001_update(ssi2001_t *ssi2001)
{
if (ssi2001->pos >= sound_pos_global)
return;
if (ssi2001->pos >= sound_pos_global)
return;
sid_fillbuf(&ssi2001->buffer[ssi2001->pos], sound_pos_global - ssi2001->pos, ssi2001->psid);
ssi2001->pos = sound_pos_global;
sid_fillbuf(&ssi2001->buffer[ssi2001->pos], sound_pos_global - ssi2001->pos, ssi2001->psid);
ssi2001->pos = sound_pos_global;
}
static void ssi2001_get_buffer(int32_t *buffer, int len, void *p)
static void
ssi2001_get_buffer(int32_t *buffer, int len, void *p)
{
ssi2001_t *ssi2001 = (ssi2001_t *)p;
int c;
ssi2001_t *ssi2001 = (ssi2001_t *) p;
int c;
ssi2001_update(ssi2001);
ssi2001_update(ssi2001);
for (c = 0; c < len * 2; c++)
buffer[c] += ssi2001->buffer[c >> 1] / 2;
for (c = 0; c < len * 2; c++)
buffer[c] += ssi2001->buffer[c >> 1] / 2;
ssi2001->pos = 0;
ssi2001->pos = 0;
}
static uint8_t ssi2001_read(uint16_t addr, void *p)
static uint8_t
ssi2001_read(uint16_t addr, void *p)
{
ssi2001_t *ssi2001 = (ssi2001_t *)p;
ssi2001_t *ssi2001 = (ssi2001_t *) p;
ssi2001_update(ssi2001);
ssi2001_update(ssi2001);
return sid_read(addr, p);
return sid_read(addr, p);
}
static void ssi2001_write(uint16_t addr, uint8_t val, void *p)
static void
ssi2001_write(uint16_t addr, uint8_t val, void *p)
{
ssi2001_t *ssi2001 = (ssi2001_t *)p;
ssi2001_t *ssi2001 = (ssi2001_t *) p;
ssi2001_update(ssi2001);
sid_write(addr, val, p);
ssi2001_update(ssi2001);
sid_write(addr, val, p);
}
void *ssi2001_init(const device_t *info)
void *
ssi2001_init(const device_t *info)
{
ssi2001_t *ssi2001 = malloc(sizeof(ssi2001_t));
memset(ssi2001, 0, sizeof(ssi2001_t));
ssi2001_t *ssi2001 = malloc(sizeof(ssi2001_t));
memset(ssi2001, 0, sizeof(ssi2001_t));
ssi2001->psid = sid_init();
sid_reset(ssi2001->psid);
uint16_t addr = device_get_config_hex16("base");
ssi2001->gameport_enabled = device_get_config_int("gameport");
io_sethandler(addr, 0x0020, ssi2001_read, NULL, NULL, ssi2001_write, NULL, NULL, ssi2001);
if (ssi2001->gameport_enabled)
ssi2001->psid = sid_init();
sid_reset(ssi2001->psid);
uint16_t addr = device_get_config_hex16("base");
ssi2001->gameport_enabled = device_get_config_int("gameport");
io_sethandler(addr, 0x0020, ssi2001_read, NULL, NULL, ssi2001_write, NULL, NULL, ssi2001);
if (ssi2001->gameport_enabled)
gameport_remap(gameport_add(&gameport_201_device), 0x201);
sound_add_handler(ssi2001_get_buffer, ssi2001);
return ssi2001;
sound_add_handler(ssi2001_get_buffer, ssi2001);
return ssi2001;
}
void ssi2001_close(void *p)
void
ssi2001_close(void *p)
{
ssi2001_t *ssi2001 = (ssi2001_t *)p;
ssi2001_t *ssi2001 = (ssi2001_t *) p;
sid_close(ssi2001->psid);
sid_close(ssi2001->psid);
free(ssi2001);
free(ssi2001);
}
static const device_config_t ssi2001_config[] =
{
static const device_config_t ssi2001_config[] = {
// clang-format off
{ "base", "Address", CONFIG_HEX16, "", 0x280, "", { 0 },
{
"base", "Address", CONFIG_HEX16, "", 0x280, "", { 0 },
{
{
"0x280", 0x280
},
{
"0x2A0", 0x2A0
},
{
"0x2C0", 0x2C0
},
{
"0x2E0", 0x2E0
},
{
""
}
}
},
{
"gameport", "Enable Game port", CONFIG_BINARY, "", 1
},
{
"", "", -1
{ "0x280", 0x280 },
{ "0x2A0", 0x2A0 },
{ "0x2C0", 0x2C0 },
{ "0x2E0", 0x2E0 },
{ "" }
}
},
{ "gameport", "Enable Game port", CONFIG_BINARY, "", 1 },
{ "", "", -1 }
// clang-format off
};
const device_t ssi2001_device =
{
"Innovation SSI-2001",
"ssi2001",
DEVICE_ISA, 0,
ssi2001_init, ssi2001_close, NULL,
{ NULL }, NULL, NULL,
ssi2001_config
"Innovation SSI-2001",
"ssi2001",
DEVICE_ISA,
0,
ssi2001_init,
ssi2001_close,
NULL,
{ NULL },
NULL,
NULL,
ssi2001_config
};

View File

@@ -1,39 +1,39 @@
/*
* 86Box A hypervisor and IBM PC system emulator that specializes in
* running old operating systems and software designed for IBM
* PC systems and compatibles from 1981 through fairly recent
* system designs based on the PCI bus.
* 86Box A hypervisor and IBM PC system emulator that specializes in
* running old operating systems and software designed for IBM
* PC systems and compatibles from 1981 through fairly recent
* system designs based on the PCI bus.
*
* This file is part of the 86Box distribution.
* This file is part of the 86Box distribution.
*
* Windows Sound System emulation.
* Windows Sound System emulation.
*
*
*
* Authors: Sarah Walker, <http://pcem-emulator.co.uk/>
* TheCollector1995, <mariogplayer@gmail.com>
* Authors: Sarah Walker, <http://pcem-emulator.co.uk/>
* TheCollector1995, <mariogplayer@gmail.com>
*
* Copyright 2012-2018 Sarah Walker.
* Copyright 2018 TheCollector1995.
* Copyright 2012-2018 Sarah Walker.
* Copyright 2018 TheCollector1995.
*/
#include <stdio.h>
#include <stdint.h>
#include <string.h>
#include <stdlib.h>
#include <wchar.h>
#include <math.h>
#include <stdint.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <wchar.h>
#include <86box/86box.h>
#include <86box/device.h>
#include <86box/dma.h>
#include <86box/io.h>
#include <86box/timer.h>
#include <86box/mca.h>
#include <86box/pic.h>
#include <86box/dma.h>
#include <86box/device.h>
#include <86box/sound.h>
#include <86box/timer.h>
#include <86box/snd_ad1848.h>
#include <86box/snd_opl.h>
/* 530, 11, 3 - 530=23
* 530, 11, 1 - 530=22
* 530, 11, 0 - 530=21
@@ -45,29 +45,26 @@
* f40, 11, 1 - 530=22
*/
static const int wss_dma[4] = {0, 0, 1, 3};
static const int wss_irq[8] = {5, 7, 9, 10, 11, 12, 14, 15}; /* W95 only uses 7-9, others may be wrong */
static const int wss_dma[4] = { 0, 0, 1, 3 };
static const int wss_irq[8] = { 5, 7, 9, 10, 11, 12, 14, 15 }; /* W95 only uses 7-9, others may be wrong */
typedef struct wss_t {
uint8_t config;
uint8_t config;
ad1848_t ad1848;
opl_t opl;
ad1848_t ad1848;
opl_t opl;
int opl_enabled;
uint8_t pos_regs[8];
int opl_enabled;
uint8_t pos_regs[8];
} wss_t;
uint8_t
wss_read(uint16_t addr, void *priv) {
wss_read(uint16_t addr, void *priv)
{
wss_t *wss = (wss_t *) priv;
return 4 | (wss->config & 0x40);
}
void
wss_write(uint16_t addr, uint8_t val, void *priv)
{
@@ -78,36 +75,34 @@ wss_write(uint16_t addr, uint8_t val, void *priv)
ad1848_setirq(&wss->ad1848, wss_irq[(val >> 3) & 7]);
}
static void
wss_get_buffer(int32_t *buffer, int len, void *priv)
{
wss_t *wss = (wss_t *) priv;
int c;
int c;
opl3_update(&wss->opl);
ad1848_update(&wss->ad1848);
for (c = 0; c < len * 2; c++) {
buffer[c] += wss->opl.buffer[c];
buffer[c] += wss->ad1848.buffer[c] / 2;
buffer[c] += wss->opl.buffer[c];
buffer[c] += wss->ad1848.buffer[c] / 2;
}
wss->opl.pos = 0;
wss->opl.pos = 0;
wss->ad1848.pos = 0;
}
void *
wss_init(const device_t *info)
{
wss_t *wss = malloc(sizeof(wss_t));
memset(wss, 0, sizeof(wss_t));
uint16_t addr = device_get_config_hex16("base");
uint16_t addr = device_get_config_hex16("base");
wss->opl_enabled = device_get_config_int("opl");
if (wss->opl_enabled)
opl3_init(&wss->opl);
opl3_init(&wss->opl);
ad1848_init(&wss->ad1848, AD1848_TYPE_DEFAULT);
@@ -115,17 +110,25 @@ wss_init(const device_t *info)
ad1848_setdma(&wss->ad1848, 3);
if (wss->opl_enabled)
io_sethandler(0x0388, 0x0004, opl3_read, NULL, NULL, opl3_write, NULL, NULL, &wss->opl);
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);
sound_add_handler(wss_get_buffer, wss);
return wss;
}
static uint8_t
ncr_audio_mca_read(int port, void *priv)
{
@@ -133,38 +136,54 @@ ncr_audio_mca_read(int port, void *priv)
return wss->pos_regs[port & 7];
}
static void
ncr_audio_mca_write(int port, uint8_t val, void *priv)
{
wss_t *wss = (wss_t *) priv;
uint16_t ports[4] = {0x530, 0xE80, 0xF40, 0x604};
wss_t *wss = (wss_t *) priv;
uint16_t ports[4] = { 0x530, 0xE80, 0xF40, 0x604 };
uint16_t addr;
if (port < 0x102)
return;
return;
wss->opl_enabled = (wss->pos_regs[2] & 0x20) ? 1 : 0;
addr = ports[(wss->pos_regs[2] & 0x18) >> 3];
addr = ports[(wss->pos_regs[2] & 0x18) >> 3];
io_removehandler(0x0388, 0x0004, opl3_read, NULL, NULL, opl3_write, NULL, NULL, &wss->opl);
io_removehandler(addr, 0x0004, wss_read, NULL, NULL, wss_write, NULL, NULL, wss);
io_removehandler(addr+4, 0x0004, ad1848_read, NULL, NULL, ad1848_write, NULL, NULL, &wss->ad1848);
io_removehandler(0x0388, 0x0004,
opl3_read, NULL, NULL,
opl3_write, NULL, NULL,
&wss->opl);
io_removehandler(addr, 0x0004,
wss_read, NULL, NULL,
wss_write, NULL, NULL,
wss);
io_removehandler(addr + 4, 0x0004,
ad1848_read, NULL, NULL,
ad1848_write, NULL, NULL,
&wss->ad1848);
wss->pos_regs[port & 7] = val;
if (wss->pos_regs[2] & 1) {
addr = ports[(wss->pos_regs[2] & 0x18) >> 3];
addr = ports[(wss->pos_regs[2] & 0x18) >> 3];
if (wss->opl_enabled)
io_sethandler(0x0388, 0x0004, opl3_read, NULL, NULL, opl3_write, NULL, NULL, &wss->opl);
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 *priv)
{
@@ -172,7 +191,6 @@ ncr_audio_mca_feedb(void *priv)
return (wss->pos_regs[2] & 1);
}
void *
ncr_audio_init(const device_t *info)
{
@@ -194,7 +212,6 @@ ncr_audio_init(const device_t *info)
return wss;
}
void
wss_close(void *priv)
{
@@ -202,7 +219,6 @@ wss_close(void *priv)
free(wss);
}
void
wss_speed_changed(void *priv)
{
@@ -210,55 +226,44 @@ wss_speed_changed(void *priv)
ad1848_speed_changed(&wss->ad1848);
}
static const device_config_t wss_config[] = {
{
"base", "Address", CONFIG_HEX16, "", 0x530, "", { 0 },
{
{
"0x530", 0x530
},
{
"0x604", 0x604
},
{
"0xe80", 0xe80
},
{
"0xf40", 0xf40
},
{
""
}
}
// clang-format off
{ "base", "Address", CONFIG_HEX16, "", 0x530, "", { 0 },
{
{ "0x530", 0x530 },
{ "0x604", 0x604 },
{ "0xe80", 0xe80 },
{ "0xf40", 0xf40 },
{ "" }
}
},
{
"opl", "Enable OPL", CONFIG_BINARY, "", 1
},
{
"", "", -1
}
{ "opl", "Enable OPL", CONFIG_BINARY, "", 1 },
{ "", "", -1 }
// clang-format on
};
const device_t wss_device =
{
const device_t wss_device = {
"Windows Sound System",
"wss",
DEVICE_ISA | DEVICE_AT, 0,
wss_init, wss_close, NULL,
DEVICE_ISA | DEVICE_AT,
0,
wss_init,
wss_close,
NULL,
{ NULL },
wss_speed_changed,
NULL,
wss_config
};
const device_t ncr_business_audio_device =
{
const device_t ncr_business_audio_device = {
"NCR Business Audio",
"ncraudio",
DEVICE_MCA, 0,
ncr_audio_init, wss_close, NULL,
DEVICE_MCA,
0,
ncr_audio_init,
wss_close,
NULL,
{ NULL },
wss_speed_changed,
NULL,

View File

@@ -1,138 +1,153 @@
#include <stdio.h>
#include <stdint.h>
#include <stdio.h>
#include <string.h>
#include <wchar.h>
#include <86box/86box.h>
#include <86box/snd_ym7128.h>
static int attenuation[32];
static int tap_position[32];
void ym7128_init(ym7128_t *ym7128)
void
ym7128_init(ym7128_t *ym7128)
{
int c;
double out = 65536.0;
int c;
double out = 65536.0;
for (c = 0; c < 32; c++)
tap_position[c] = c * (2400 / 31);
for (c = 0; c < 32; c++)
tap_position[c] = c * (2400 / 31);
for (c = 31; c >= 1; c--)
{
attenuation[c] = (int)out;
out /= 1.25963; /*2 dB steps*/
}
attenuation[0] = 0;
for (c = 31; c >= 1; c--) {
attenuation[c] = (int) out;
out /= 1.25963; /*2 dB steps*/
}
attenuation[0] = 0;
}
#define GET_ATTENUATION(val) (val & 0x20) ? -attenuation[val & 0x1f] : attenuation[val & 0x1f]
void ym7128_write(ym7128_t *ym7128, uint8_t val)
void
ym7128_write(ym7128_t *ym7128, uint8_t val)
{
int new_dat = val & 1;
int new_sci = val & 2;
int new_a0 = val & 4;
if (!ym7128->sci && new_sci)
ym7128->dat = (ym7128->dat << 1) | new_dat;
int new_dat = val & 1;
int new_sci = val & 2;
int new_a0 = val & 4;
if (!ym7128->sci && new_sci)
ym7128->dat = (ym7128->dat << 1) | new_dat;
if (ym7128->a0 != new_a0)
{
if (!ym7128->a0)
ym7128->reg_sel = ym7128->dat & 0x1f;
else
{
switch (ym7128->reg_sel)
{
case 0x00: case 0x01: case 0x02: case 0x03:
case 0x04: case 0x05: case 0x06: case 0x07:
ym7128->gl[ym7128->reg_sel & 7] = GET_ATTENUATION(ym7128->dat);
break;
case 0x08: case 0x09: case 0x0a: case 0x0b:
case 0x0c: case 0x0d: case 0x0e: case 0x0f:
ym7128->gr[ym7128->reg_sel & 7] = GET_ATTENUATION(ym7128->dat);
break;
if (ym7128->a0 != new_a0) {
if (!ym7128->a0)
ym7128->reg_sel = ym7128->dat & 0x1f;
else {
switch (ym7128->reg_sel) {
case 0x00:
case 0x01:
case 0x02:
case 0x03:
case 0x04:
case 0x05:
case 0x06:
case 0x07:
ym7128->gl[ym7128->reg_sel & 7] = GET_ATTENUATION(ym7128->dat);
break;
case 0x08:
case 0x09:
case 0x0a:
case 0x0b:
case 0x0c:
case 0x0d:
case 0x0e:
case 0x0f:
ym7128->gr[ym7128->reg_sel & 7] = GET_ATTENUATION(ym7128->dat);
break;
case 0x10:
ym7128->vm = GET_ATTENUATION(ym7128->dat);
break;
case 0x11:
ym7128->vc = GET_ATTENUATION(ym7128->dat);
break;
case 0x12:
ym7128->vl = GET_ATTENUATION(ym7128->dat);
break;
case 0x13:
ym7128->vr = GET_ATTENUATION(ym7128->dat);
break;
case 0x10:
ym7128->vm = GET_ATTENUATION(ym7128->dat);
break;
case 0x11:
ym7128->vc = GET_ATTENUATION(ym7128->dat);
break;
case 0x12:
ym7128->vl = GET_ATTENUATION(ym7128->dat);
break;
case 0x13:
ym7128->vr = GET_ATTENUATION(ym7128->dat);
break;
case 0x14:
ym7128->c0 = (ym7128->dat & 0x3f) << 6;
if (ym7128->dat & 0x20)
ym7128->c0 |= 0xfffff000;
break;
case 0x15:
ym7128->c1 = (ym7128->dat & 0x3f) << 6;
if (ym7128->dat & 0x20)
ym7128->c1 |= 0xfffff000;
break;
case 0x14:
ym7128->c0 = (ym7128->dat & 0x3f) << 6;
if (ym7128->dat & 0x20)
ym7128->c0 |= 0xfffff000;
break;
case 0x15:
ym7128->c1 = (ym7128->dat & 0x3f) << 6;
if (ym7128->dat & 0x20)
ym7128->c1 |= 0xfffff000;
break;
case 0x16: case 0x17: case 0x18: case 0x19:
case 0x1a: case 0x1b: case 0x1c: case 0x1d: case 0x1e:
ym7128->t[ym7128->reg_sel - 0x16] = tap_position[ym7128->dat & 0x1f];
break;
}
ym7128->regs[ym7128->reg_sel] = ym7128->dat;
}
ym7128->dat = 0;
case 0x16:
case 0x17:
case 0x18:
case 0x19:
case 0x1a:
case 0x1b:
case 0x1c:
case 0x1d:
case 0x1e:
ym7128->t[ym7128->reg_sel - 0x16] = tap_position[ym7128->dat & 0x1f];
break;
}
ym7128->regs[ym7128->reg_sel] = ym7128->dat;
}
ym7128->dat = 0;
}
ym7128->sci = new_sci;
ym7128->a0 = new_a0;
ym7128->sci = new_sci;
ym7128->a0 = new_a0;
}
#define GET_DELAY_SAMPLE(ym7128, offset) (((ym7128->delay_pos - offset) < 0) ? ym7128->delay_buffer[(ym7128->delay_pos - offset) + 2400] : ym7128->delay_buffer[ym7128->delay_pos - offset])
void ym7128_apply(ym7128_t *ym7128, int16_t *buffer, int len)
void
ym7128_apply(ym7128_t *ym7128, int16_t *buffer, int len)
{
int c, d;
int c, d;
for (c = 0; c < len*2; c += 4)
{
/*YM7128 samples a mono stream at ~24 kHz, so downsample*/
int32_t samp = ((int32_t)buffer[c] + (int32_t)buffer[c+1] + (int32_t)buffer[c+2] + (int32_t)buffer[c+3]) / 4;
int32_t filter_temp, filter_out;
int32_t samp_l = 0, samp_r = 0;
for (c = 0; c < len * 2; c += 4) {
/*YM7128 samples a mono stream at ~24 kHz, so downsample*/
int32_t samp = ((int32_t) buffer[c] + (int32_t) buffer[c + 1] + (int32_t) buffer[c + 2] + (int32_t) buffer[c + 3]) / 4;
int32_t filter_temp, filter_out;
int32_t samp_l = 0, samp_r = 0;
filter_temp = GET_DELAY_SAMPLE(ym7128, ym7128->t[0]);
filter_out = ((filter_temp * ym7128->c0) >> 11) + ((ym7128->filter_dat * ym7128->c1) >> 11);
filter_out = (filter_out * ym7128->vc) >> 16;
filter_temp = GET_DELAY_SAMPLE(ym7128, ym7128->t[0]);
filter_out = ((filter_temp * ym7128->c0) >> 11) + ((ym7128->filter_dat * ym7128->c1) >> 11);
filter_out = (filter_out * ym7128->vc) >> 16;
samp = (samp * ym7128->vm) >> 16;
samp += filter_out;
samp = (samp * ym7128->vm) >> 16;
samp += filter_out;
ym7128->delay_buffer[ym7128->delay_pos] = samp;
ym7128->delay_buffer[ym7128->delay_pos] = samp;
for (d = 0; d < 8; d++)
{
samp_l += (GET_DELAY_SAMPLE(ym7128, ym7128->t[d+1]) * ym7128->gl[d]) >> 16;
samp_r += (GET_DELAY_SAMPLE(ym7128, ym7128->t[d+1]) * ym7128->gr[d]) >> 16;
}
samp_l = (samp_l * ym7128->vl*2) >> 16;
samp_r = (samp_r * ym7128->vr*2) >> 16;
buffer[c] += ((int32_t)samp_l + (int32_t)ym7128->prev_l) / 2;
buffer[c+1] += ((int32_t)samp_r + (int32_t)ym7128->prev_r) / 2;
buffer[c+2] += samp_l;
buffer[c+3] += samp_r;
ym7128->delay_pos++;
if (ym7128->delay_pos >= 2400)
ym7128->delay_pos = 0;
ym7128->filter_dat = filter_temp;
ym7128->prev_l = samp_l;
ym7128->prev_r = samp_r;
for (d = 0; d < 8; d++) {
samp_l += (GET_DELAY_SAMPLE(ym7128, ym7128->t[d + 1]) * ym7128->gl[d]) >> 16;
samp_r += (GET_DELAY_SAMPLE(ym7128, ym7128->t[d + 1]) * ym7128->gr[d]) >> 16;
}
samp_l = (samp_l * ym7128->vl * 2) >> 16;
samp_r = (samp_r * ym7128->vr * 2) >> 16;
buffer[c] += ((int32_t) samp_l + (int32_t) ym7128->prev_l) / 2;
buffer[c + 1] += ((int32_t) samp_r + (int32_t) ym7128->prev_r) / 2;
buffer[c + 2] += samp_l;
buffer[c + 3] += samp_r;
ym7128->delay_pos++;
if (ym7128->delay_pos >= 2400)
ym7128->delay_pos = 0;
ym7128->filter_dat = filter_temp;
ym7128->prev_l = samp_l;
ym7128->prev_r = samp_r;
}
}

View File

@@ -1,221 +1,219 @@
/*
* 86Box A hypervisor and IBM PC system emulator that specializes in
* running old operating systems and software designed for IBM
* PC systems and compatibles from 1981 through fairly recent
* system designs based on the PCI bus.
* 86Box A hypervisor and IBM PC system emulator that specializes in
* running old operating systems and software designed for IBM
* PC systems and compatibles from 1981 through fairly recent
* system designs based on the PCI bus.
*
* This file is part of the 86Box distribution.
* This file is part of the 86Box distribution.
*
* Sound emulation core.
* Sound emulation core.
*
*
*
* Authors: Sarah Walker, <http://pcem-emulator.co.uk/>
* Miran Grca, <mgrca8@gmail.com>
* Authors: Sarah Walker, <http://pcem-emulator.co.uk/>
* Miran Grca, <mgrca8@gmail.com>
*
* Copyright 2008-2020 Sarah Walker.
* Copyright 2016-2020 Miran Grca.
* Copyright 2008-2020 Sarah Walker.
* Copyright 2016-2020 Miran Grca.
*/
#include <math.h>
#include <stdarg.h>
#include <stdint.h>
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <string.h>
#include <wchar.h>
#define HAVE_STDARG_H
#include <86box/86box.h>
#include <86box/device.h>
#include <86box/timer.h>
#include <86box/cdrom.h>
#include <86box/hdc_ide.h>
#include <86box/plat.h>
#include <86box/machine.h>
#include <86box/sound.h>
#include <86box/midi.h>
#include <86box/snd_opl.h>
#include <86box/snd_mpu401.h>
#include <86box/snd_sb_dsp.h>
#include <86box/snd_azt2316a.h>
#include <86box/snd_ac97.h>
#include <86box/filters.h>
#include <86box/86box.h>
#include <86box/cdrom.h>
#include <86box/device.h>
#include <86box/filters.h>
#include <86box/hdc_ide.h>
#include <86box/machine.h>
#include <86box/midi.h>
#include <86box/plat.h>
#include <86box/snd_ac97.h>
#include <86box/snd_azt2316a.h>
#include <86box/timer.h>
#include <86box/snd_mpu401.h>
#include <86box/sound.h>
#include <86box/snd_opl.h>
#include <86box/snd_sb_dsp.h>
typedef struct {
const device_t *device;
const device_t *device;
} SOUND_CARD;
typedef struct {
void (*get_buffer)(int32_t *buffer, int len, void *p);
void *priv;
void (*get_buffer)(int32_t *buffer, int len, void *p);
void *priv;
} sound_handler_t;
int sound_card_current = 0;
int sound_pos_global = 0;
int sound_gain = 0;
int sound_pos_global = 0;
int sound_gain = 0;
static sound_handler_t sound_handlers[8];
static thread_t *sound_cd_thread_h;
static event_t *sound_cd_event;
static event_t *sound_cd_start_event;
static int32_t *outbuffer;
static float *outbuffer_ex;
static int16_t *outbuffer_ex_int16;
static int sound_handlers_num;
static thread_t *sound_cd_thread_h;
static event_t *sound_cd_event;
static event_t *sound_cd_start_event;
static int32_t *outbuffer;
static float *outbuffer_ex;
static int16_t *outbuffer_ex_int16;
static int sound_handlers_num;
static pc_timer_t sound_poll_timer;
static uint64_t sound_poll_latch;
static uint64_t sound_poll_latch;
static int16_t cd_buffer[CDROM_NUM][CD_BUFLEN * 2];
static float cd_out_buffer[CD_BUFLEN * 2];
static int16_t cd_out_buffer_int16[CD_BUFLEN * 2];
static int16_t cd_buffer[CDROM_NUM][CD_BUFLEN * 2];
static float cd_out_buffer[CD_BUFLEN * 2];
static int16_t cd_out_buffer_int16[CD_BUFLEN * 2];
static unsigned int cd_vol_l, cd_vol_r;
static int cd_buf_update = CD_BUFLEN / SOUNDBUFLEN;
static volatile int cdaudioon = 0;
static int cd_thread_enable = 0;
static int cd_buf_update = CD_BUFLEN / SOUNDBUFLEN;
static volatile int cdaudioon = 0;
static int cd_thread_enable = 0;
static void (*filter_cd_audio)(int channel, double *buffer, void *p) = NULL;
static void *filter_cd_audio_p = NULL;
static void *filter_cd_audio_p = NULL;
static const device_t sound_none_device = {
"None",
"none",
0, 0,
NULL, NULL, NULL,
{ NULL }, NULL, NULL,
NULL
"None",
"none",
0,
0,
NULL,
NULL,
NULL,
{ NULL },
NULL,
NULL,
NULL
};
static const device_t sound_internal_device = {
"Internal",
"internal",
0, 0,
NULL, NULL, NULL,
{ NULL }, NULL, NULL,
NULL
"Internal",
"internal",
0,
0,
NULL,
NULL,
NULL,
{ NULL },
NULL,
NULL,
NULL
};
static const SOUND_CARD sound_cards[] =
{
{ &sound_none_device },
{ &sound_internal_device },
{ &adlib_device },
{ &adgold_device },
{ &azt2316a_device },
{ &azt1605_device },
{ &cs4235_device },
{ &cs4236b_device },
{ &sb_1_device },
{ &sb_15_device },
{ &sb_2_device },
{ &sb_pro_v1_device },
{ &sb_pro_v2_device },
{ &sb_16_device },
{ &sb_16_pnp_device },
{ &sb_32_pnp_device },
{ &sb_awe32_device },
{ &sb_awe32_pnp_device },
{ &sb_awe64_value_device },
{ &sb_awe64_device },
{ &sb_awe64_gold_device },
static const SOUND_CARD sound_cards[] = {
// clang-format off
{ &sound_none_device },
{ &sound_internal_device },
{ &adlib_device },
{ &adgold_device },
{ &azt2316a_device },
{ &azt1605_device },
{ &cs4235_device },
{ &cs4236b_device },
{ &sb_1_device },
{ &sb_15_device },
{ &sb_2_device },
{ &sb_pro_v1_device },
{ &sb_pro_v2_device },
{ &sb_16_device },
{ &sb_16_pnp_device },
{ &sb_32_pnp_device },
{ &sb_awe32_device },
{ &sb_awe32_pnp_device },
{ &sb_awe64_value_device },
{ &sb_awe64_device },
{ &sb_awe64_gold_device },
#if defined(DEV_BRANCH) && defined(USE_PAS16)
{ &pas16_device },
{ &pas16_device },
#endif
#if defined(DEV_BRANCH) && defined(USE_TANDY_ISA)
{ &pssj_isa_device },
{ &tndy_device },
{ &pssj_isa_device },
{ &tndy_device },
#endif
{ &wss_device },
{ &adlib_mca_device },
{ &ncr_business_audio_device },
{ &sb_mcv_device },
{ &sb_pro_mcv_device },
{ &es1371_device },
{ &ad1881_device },
{ &cs4297a_device },
{ NULL }
{ &wss_device },
{ &adlib_mca_device },
{ &ncr_business_audio_device },
{ &sb_mcv_device },
{ &sb_pro_mcv_device },
{ &es1371_device },
{ &ad1881_device },
{ &cs4297a_device },
{ NULL }
// clang-format on
};
#ifdef ENABLE_SOUND_LOG
int sound_do_log = ENABLE_SOUND_LOG;
static void
sound_log(const char *fmt, ...)
{
va_list ap;
if (sound_do_log) {
va_start(ap, fmt);
pclog_ex(fmt, ap);
va_end(ap);
va_start(ap, fmt);
pclog_ex(fmt, ap);
va_end(ap);
}
}
#else
#define sound_log(fmt, ...)
# define sound_log(fmt, ...)
#endif
int
sound_card_available(int card)
{
if (sound_cards[card].device)
return device_available(sound_cards[card].device);
return device_available(sound_cards[card].device);
return 1;
}
const device_t *
sound_card_getdevice(int card)
{
return sound_cards[card].device;
}
int
sound_card_has_config(int card)
{
if (!sound_cards[card].device)
return 0;
return 0;
return sound_cards[card].device->config ? 1 : 0;
}
char *
sound_card_get_internal_name(int card)
{
return device_get_internal_name(sound_cards[card].device);
}
int
sound_card_get_from_internal_name(char *s)
{
int c = 0;
while (sound_cards[c].device != NULL) {
if (!strcmp((char *) sound_cards[c].device->internal_name, s))
return c;
c++;
if (!strcmp((char *) sound_cards[c].device->internal_name, s))
return c;
c++;
}
return 0;
}
void
sound_card_init(void)
{
if (sound_cards[sound_card_current].device)
device_add(sound_cards[sound_card_current].device);
device_add(sound_cards[sound_card_current].device);
}
void
sound_set_cd_volume(unsigned int vol_l, unsigned int vol_r)
{
@@ -223,168 +221,163 @@ sound_set_cd_volume(unsigned int vol_l, unsigned int vol_r)
cd_vol_r = vol_r;
}
static void
sound_cd_clean_buffers(void)
{
if (sound_is_float)
memset(cd_out_buffer, 0, (CD_BUFLEN * 2) * sizeof(float));
memset(cd_out_buffer, 0, (CD_BUFLEN * 2) * sizeof(float));
else
memset(cd_out_buffer_int16, 0, (CD_BUFLEN * 2) * sizeof(int16_t));
memset(cd_out_buffer_int16, 0, (CD_BUFLEN * 2) * sizeof(int16_t));
}
static void
sound_cd_thread(void *param)
{
uint32_t lba;
int c, r, i, pre, channel_select[2];
double audio_vol_l, audio_vol_r;
double cd_buffer_temp[2] = {0.0, 0.0};
int c, r, i, pre, channel_select[2];
double audio_vol_l, audio_vol_r;
double cd_buffer_temp[2] = { 0.0, 0.0 };
thread_set_event(sound_cd_start_event);
while (cdaudioon) {
thread_wait_event(sound_cd_event, -1);
thread_reset_event(sound_cd_event);
thread_wait_event(sound_cd_event, -1);
thread_reset_event(sound_cd_event);
if (!cdaudioon)
return;
if (!cdaudioon)
return;
sound_cd_clean_buffers();
sound_cd_clean_buffers();
for (i = 0; i < CDROM_NUM; i++) {
if ((cdrom[i].bus_type == CDROM_BUS_DISABLED) ||
(cdrom[i].cd_status == CD_STATUS_EMPTY))
continue;
lba = cdrom[i].seek_pos;
r = cdrom_audio_callback(&(cdrom[i]), cd_buffer[i], CD_BUFLEN * 2);
if (!cdrom[i].bus_type || !cdrom[i].sound_on || !r)
continue;
pre = cdrom_is_pre(&(cdrom[i]), lba);
for (i = 0; i < CDROM_NUM; i++) {
if ((cdrom[i].bus_type == CDROM_BUS_DISABLED) || (cdrom[i].cd_status == CD_STATUS_EMPTY))
continue;
lba = cdrom[i].seek_pos;
r = cdrom_audio_callback(&(cdrom[i]), cd_buffer[i], CD_BUFLEN * 2);
if (!cdrom[i].bus_type || !cdrom[i].sound_on || !r)
continue;
pre = cdrom_is_pre(&(cdrom[i]), lba);
if (cdrom[i].get_volume) {
audio_vol_l = (float) (cdrom[i].get_volume(cdrom[i].priv, 0));
audio_vol_r = (float) (cdrom[i].get_volume(cdrom[i].priv, 1));
} else {
audio_vol_l = 255.0;
audio_vol_r = 255.0;
}
if (cdrom[i].get_volume) {
audio_vol_l = (float) (cdrom[i].get_volume(cdrom[i].priv, 0));
audio_vol_r = (float) (cdrom[i].get_volume(cdrom[i].priv, 1));
} else {
audio_vol_l = 255.0;
audio_vol_r = 255.0;
}
/* Calculate attenuation per the specification. */
if (audio_vol_l >= 255.0)
audio_vol_l = 1.0;
else if (audio_vol_l > 0.0)
audio_vol_l = (48.0 + (20.0 * log(audio_vol_l / 256.0))) / 48.0;
else
audio_vol_l = 0.0;
/* Calculate attenuation per the specification. */
if (audio_vol_l >= 255.0)
audio_vol_l = 1.0;
else if (audio_vol_l > 0.0)
audio_vol_l = (48.0 + (20.0 * log(audio_vol_l / 256.0))) / 48.0;
else
audio_vol_l = 0.0;
if (audio_vol_r >= 255.0)
audio_vol_r = 1.0;
else if (audio_vol_r > 0.0)
audio_vol_r = (48.0 + (20.0 * log(audio_vol_r / 256.0))) / 48.0;
else
audio_vol_r = 0.0;
if (audio_vol_r >= 255.0)
audio_vol_r = 1.0;
else if (audio_vol_r > 0.0)
audio_vol_r = (48.0 + (20.0 * log(audio_vol_r / 256.0))) / 48.0;
else
audio_vol_r = 0.0;
if (cdrom[i].get_channel) {
channel_select[0] = cdrom[i].get_channel(cdrom[i].priv, 0);
channel_select[1] = cdrom[i].get_channel(cdrom[i].priv, 1);
} else {
channel_select[0] = 1;
channel_select[1] = 2;
}
if (cdrom[i].get_channel) {
channel_select[0] = cdrom[i].get_channel(cdrom[i].priv, 0);
channel_select[1] = cdrom[i].get_channel(cdrom[i].priv, 1);
} else {
channel_select[0] = 1;
channel_select[1] = 2;
}
for (c = 0; c < CD_BUFLEN*2; c += 2) {
/*Apply ATAPI channel select*/
cd_buffer_temp[0] = cd_buffer_temp[1] = 0.0;
for (c = 0; c < CD_BUFLEN * 2; c += 2) {
/*Apply ATAPI channel select*/
cd_buffer_temp[0] = cd_buffer_temp[1] = 0.0;
if ((audio_vol_l != 0.0) && (channel_select[0] != 0)) {
if (channel_select[0] & 1)
cd_buffer_temp[0] += ((double) cd_buffer[i][c]); /* Channel 0 => Port 0 */
if (channel_select[0] & 2)
cd_buffer_temp[0] += ((double) cd_buffer[i][c + 1]); /* Channel 1 => Port 0 */
if ((audio_vol_l != 0.0) && (channel_select[0] != 0)) {
if (channel_select[0] & 1)
cd_buffer_temp[0] += ((double) cd_buffer[i][c]); /* Channel 0 => Port 0 */
if (channel_select[0] & 2)
cd_buffer_temp[0] += ((double) cd_buffer[i][c + 1]); /* Channel 1 => Port 0 */
cd_buffer_temp[0] *= audio_vol_l; /* Multiply Port 0 by Port 0 volume */
cd_buffer_temp[0] *= audio_vol_l; /* Multiply Port 0 by Port 0 volume */
if (pre)
cd_buffer_temp[0] = deemph_iir(0, cd_buffer_temp[0]); /* De-emphasize if necessary */
}
if (pre)
cd_buffer_temp[0] = deemph_iir(0, cd_buffer_temp[0]); /* De-emphasize if necessary */
}
if ((audio_vol_r != 0.0) && (channel_select[1] != 0)) {
if (channel_select[1] & 1)
cd_buffer_temp[1] += ((double) cd_buffer[i][c]); /* Channel 0 => Port 1 */
if (channel_select[1] & 2)
cd_buffer_temp[1] += ((double) cd_buffer[i][c + 1]); /* Channel 1 => Port 1 */
if ((audio_vol_r != 0.0) && (channel_select[1] != 0)) {
if (channel_select[1] & 1)
cd_buffer_temp[1] += ((double) cd_buffer[i][c]); /* Channel 0 => Port 1 */
if (channel_select[1] & 2)
cd_buffer_temp[1] += ((double) cd_buffer[i][c + 1]); /* Channel 1 => Port 1 */
cd_buffer_temp[1] *= audio_vol_r; /* Multiply Port 1 by Port 1 volume */
cd_buffer_temp[1] *= audio_vol_r; /* Multiply Port 1 by Port 1 volume */
if (pre)
cd_buffer_temp[1] = deemph_iir(1, cd_buffer_temp[1]); /* De-emphasize if necessary */
}
if (pre)
cd_buffer_temp[1] = deemph_iir(1, cd_buffer_temp[1]); /* De-emphasize if necessary */
}
/* Apply sound card CD volume and filters */
if (filter_cd_audio != NULL) {
filter_cd_audio(0, &(cd_buffer_temp[0]), filter_cd_audio_p);
filter_cd_audio(1, &(cd_buffer_temp[1]), filter_cd_audio_p);
}
/* Apply sound card CD volume and filters */
if (filter_cd_audio != NULL) {
filter_cd_audio(0, &(cd_buffer_temp[0]), filter_cd_audio_p);
filter_cd_audio(1, &(cd_buffer_temp[1]), filter_cd_audio_p);
}
if (sound_is_float) {
cd_out_buffer[c] += (float) (cd_buffer_temp[0] / 32768.0);
cd_out_buffer[c+1] += (float) (cd_buffer_temp[1] / 32768.0);
} else {
if (cd_buffer_temp[0] > 32767)
cd_buffer_temp[0] = 32767;
if (cd_buffer_temp[0] < -32768)
cd_buffer_temp[0] = -32768;
if (cd_buffer_temp[1] > 32767)
cd_buffer_temp[1] = 32767;
if (cd_buffer_temp[1] < -32768)
cd_buffer_temp[1] = -32768;
if (sound_is_float) {
cd_out_buffer[c] += (float) (cd_buffer_temp[0] / 32768.0);
cd_out_buffer[c + 1] += (float) (cd_buffer_temp[1] / 32768.0);
} else {
if (cd_buffer_temp[0] > 32767)
cd_buffer_temp[0] = 32767;
if (cd_buffer_temp[0] < -32768)
cd_buffer_temp[0] = -32768;
if (cd_buffer_temp[1] > 32767)
cd_buffer_temp[1] = 32767;
if (cd_buffer_temp[1] < -32768)
cd_buffer_temp[1] = -32768;
cd_out_buffer_int16[c] += (int16_t) cd_buffer_temp[0];
cd_out_buffer_int16[c+1] += (int16_t) cd_buffer_temp[1];
}
}
}
cd_out_buffer_int16[c] += (int16_t) cd_buffer_temp[0];
cd_out_buffer_int16[c + 1] += (int16_t) cd_buffer_temp[1];
}
}
}
if (sound_is_float)
givealbuffer_cd(cd_out_buffer);
else
givealbuffer_cd(cd_out_buffer_int16);
if (sound_is_float)
givealbuffer_cd(cd_out_buffer);
else
givealbuffer_cd(cd_out_buffer_int16);
}
}
static void
sound_realloc_buffers(void)
{
if (outbuffer_ex != NULL) {
free(outbuffer_ex);
outbuffer_ex = NULL;
free(outbuffer_ex);
outbuffer_ex = NULL;
}
if (outbuffer_ex_int16 != NULL) {
free(outbuffer_ex_int16);
outbuffer_ex_int16 = NULL;
free(outbuffer_ex_int16);
outbuffer_ex_int16 = NULL;
}
if (sound_is_float) {
outbuffer_ex = calloc(SOUNDBUFLEN * 2, sizeof(float));
memset(outbuffer_ex, 0x00, SOUNDBUFLEN * 2 * sizeof(float));
memset(outbuffer_ex, 0x00, SOUNDBUFLEN * 2 * sizeof(float));
} else {
outbuffer_ex_int16 = calloc(SOUNDBUFLEN * 2, sizeof(int16_t));
memset(outbuffer_ex_int16, 0x00, SOUNDBUFLEN * 2 * sizeof(int16_t));
memset(outbuffer_ex_int16, 0x00, SOUNDBUFLEN * 2 * sizeof(int16_t));
}
}
void
sound_init(void)
{
int i = 0;
int i = 0;
int available_cdrom_drives = 0;
outbuffer_ex = NULL;
outbuffer_ex = NULL;
outbuffer_ex_int16 = NULL;
outbuffer = NULL;
@@ -392,48 +385,45 @@ sound_init(void)
memset(outbuffer, 0x00, SOUNDBUFLEN * 2 * sizeof(int32_t));
for (i = 0; i < CDROM_NUM; i++) {
if (cdrom[i].bus_type != CDROM_BUS_DISABLED)
available_cdrom_drives++;
if (cdrom[i].bus_type != CDROM_BUS_DISABLED)
available_cdrom_drives++;
}
if (available_cdrom_drives) {
cdaudioon = 1;
cdaudioon = 1;
sound_cd_start_event = thread_create_event();
sound_cd_start_event = thread_create_event();
sound_cd_event = thread_create_event();
sound_cd_thread_h = thread_create(sound_cd_thread, NULL);
sound_cd_event = thread_create_event();
sound_cd_thread_h = thread_create(sound_cd_thread, NULL);
sound_log("Waiting for CD start event...\n");
thread_wait_event(sound_cd_start_event, -1);
thread_reset_event(sound_cd_start_event);
sound_log("Done!\n");
sound_log("Waiting for CD start event...\n");
thread_wait_event(sound_cd_start_event, -1);
thread_reset_event(sound_cd_start_event);
sound_log("Done!\n");
} else
cdaudioon = 0;
cdaudioon = 0;
cd_thread_enable = available_cdrom_drives ? 1 : 0;
}
void
sound_add_handler(void (*get_buffer)(int32_t *buffer, int len, void *p), void *p)
{
sound_handlers[sound_handlers_num].get_buffer = get_buffer;
sound_handlers[sound_handlers_num].priv = p;
sound_handlers[sound_handlers_num].priv = p;
sound_handlers_num++;
}
void
sound_set_cd_audio_filter(void (*filter)(int channel, double *buffer, void *p), void *p)
{
if ((filter_cd_audio == NULL) || (filter == NULL)) {
filter_cd_audio = filter;
filter_cd_audio_p = p;
filter_cd_audio = filter;
filter_cd_audio_p = p;
}
}
void
sound_poll(void *priv)
{
@@ -443,51 +433,49 @@ sound_poll(void *priv)
sound_pos_global++;
if (sound_pos_global == SOUNDBUFLEN) {
int c;
int c;
memset(outbuffer, 0x00, SOUNDBUFLEN * 2 * sizeof(int32_t));
memset(outbuffer, 0x00, SOUNDBUFLEN * 2 * sizeof(int32_t));
for (c = 0; c < sound_handlers_num; c++)
sound_handlers[c].get_buffer(outbuffer, SOUNDBUFLEN, sound_handlers[c].priv);
for (c = 0; c < sound_handlers_num; c++)
sound_handlers[c].get_buffer(outbuffer, SOUNDBUFLEN, sound_handlers[c].priv);
for (c = 0; c < SOUNDBUFLEN * 2; c++) {
if (sound_is_float)
outbuffer_ex[c] = ((float) outbuffer[c]) / 32768.0;
else {
if (outbuffer[c] > 32767)
outbuffer[c] = 32767;
if (outbuffer[c] < -32768)
outbuffer[c] = -32768;
for (c = 0; c < SOUNDBUFLEN * 2; c++) {
if (sound_is_float)
outbuffer_ex[c] = ((float) outbuffer[c]) / 32768.0;
else {
if (outbuffer[c] > 32767)
outbuffer[c] = 32767;
if (outbuffer[c] < -32768)
outbuffer[c] = -32768;
outbuffer_ex_int16[c] = outbuffer[c];
}
}
outbuffer_ex_int16[c] = outbuffer[c];
}
}
if (sound_is_float)
givealbuffer(outbuffer_ex);
else
givealbuffer(outbuffer_ex_int16);
if (sound_is_float)
givealbuffer(outbuffer_ex);
else
givealbuffer(outbuffer_ex_int16);
if (cd_thread_enable) {
cd_buf_update--;
if (!cd_buf_update) {
cd_buf_update = (48000 / SOUNDBUFLEN) / (CD_FREQ / CD_BUFLEN);
thread_set_event(sound_cd_event);
}
}
if (cd_thread_enable) {
cd_buf_update--;
if (!cd_buf_update) {
cd_buf_update = (48000 / SOUNDBUFLEN) / (CD_FREQ / CD_BUFLEN);
thread_set_event(sound_cd_event);
}
}
sound_pos_global = 0;
sound_pos_global = 0;
}
}
void
sound_speed_changed(void)
{
sound_poll_latch = (uint64_t)((double)TIMER_USEC * (1000000.0 / 48000.0));
sound_poll_latch = (uint64_t) ((double) TIMER_USEC * (1000000.0 / 48000.0));
}
void
sound_reset(void)
{
@@ -503,13 +491,12 @@ sound_reset(void)
sound_handlers_num = 0;
memset(sound_handlers, 0x00, 8 * sizeof(sound_handler_t));
filter_cd_audio = NULL;
filter_cd_audio = NULL;
filter_cd_audio_p = NULL;
sound_set_cd_volume(65535, 65535);
}
void
sound_card_reset(void)
{
@@ -519,70 +506,68 @@ sound_card_reset(void)
sound_card_init();
if (mpu401_standalone_enable)
mpu401_device_add();
mpu401_device_add();
if (GUS)
device_add(&gus_device);
device_add(&gus_device);
if (GAMEBLASTER)
device_add(&cms_device);
device_add(&cms_device);
if (SSI2001)
device_add(&ssi2001_device);
device_add(&ssi2001_device);
}
void
sound_cd_thread_end(void)
{
if (cdaudioon) {
cdaudioon = 0;
cdaudioon = 0;
sound_log("Waiting for CD Audio thread to terminate...\n");
thread_set_event(sound_cd_event);
thread_wait(sound_cd_thread_h);
sound_log("CD Audio thread terminated...\n");
sound_log("Waiting for CD Audio thread to terminate...\n");
thread_set_event(sound_cd_event);
thread_wait(sound_cd_thread_h);
sound_log("CD Audio thread terminated...\n");
if (sound_cd_event) {
thread_destroy_event(sound_cd_event);
sound_cd_event = NULL;
}
if (sound_cd_event) {
thread_destroy_event(sound_cd_event);
sound_cd_event = NULL;
}
sound_cd_thread_h = NULL;
sound_cd_thread_h = NULL;
if (sound_cd_start_event) {
thread_destroy_event(sound_cd_start_event);
sound_cd_event = NULL;
}
if (sound_cd_start_event) {
thread_destroy_event(sound_cd_start_event);
sound_cd_event = NULL;
}
}
}
void
sound_cd_thread_reset(void)
{
int i = 0;
int i = 0;
int available_cdrom_drives = 0;
for (i = 0; i < CDROM_NUM; i++) {
cdrom_stop(&(cdrom[i]));
cdrom_stop(&(cdrom[i]));
if (cdrom[i].bus_type != CDROM_BUS_DISABLED)
available_cdrom_drives++;
if (cdrom[i].bus_type != CDROM_BUS_DISABLED)
available_cdrom_drives++;
}
if (available_cdrom_drives && !cd_thread_enable) {
cdaudioon = 1;
cdaudioon = 1;
sound_cd_start_event = thread_create_event();
sound_cd_start_event = thread_create_event();
sound_cd_event = thread_create_event();
sound_cd_thread_h = thread_create(sound_cd_thread, NULL);
sound_cd_event = thread_create_event();
sound_cd_thread_h = thread_create(sound_cd_thread, NULL);
thread_wait_event(sound_cd_start_event, -1);
thread_reset_event(sound_cd_start_event);
thread_wait_event(sound_cd_start_event, -1);
thread_reset_event(sound_cd_start_event);
} else if (!available_cdrom_drives && cd_thread_enable)
sound_cd_thread_end();
sound_cd_thread_end();
cd_thread_enable = available_cdrom_drives ? 1 : 0;
}

View File

@@ -1,67 +1,85 @@
/*
* 86Box A hypervisor and IBM PC system emulator that specializes in
* running old operating systems and software designed for IBM
* PC systems and compatibles from 1981 through fairly recent
* system designs based on the PCI bus.
* 86Box A hypervisor and IBM PC system emulator that specializes in
* running old operating systems and software designed for IBM
* PC systems and compatibles from 1981 through fairly recent
* system designs based on the PCI bus.
*
* This file is part of the 86Box distribution.
* This file is part of the 86Box distribution.
*
* Interface to the XAudio2 audio processing library.
* Interface to the XAudio2 audio processing library.
*
*
*
* Authors: Cacodemon345
* Authors: Cacodemon345
*
* Copyright 2022 Cacodemon345.
* Copyright 2022 Cacodemon345.
*/
#include <math.h>
#include <stdio.h>
#include <stdint.h>
#include <string.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <wchar.h>
#if defined(_WIN32) && !defined(USE_FAUDIO)
#define COBJMACROS
#include <xaudio2.h>
# define COBJMACROS
# include <xaudio2.h>
#else
#include <FAudio.h>
#include <FAudio_compat.h>
# include <FAudio.h>
# include <FAudio_compat.h>
#endif
#include <86box/86box.h>
#include <86box/sound.h>
#include <86box/midi.h>
#include <86box/plat_dynld.h>
#include <86box/sound.h>
#if defined(_WIN32) && !defined(USE_FAUDIO)
static void *xaudio2_handle = NULL;
static HRESULT (WINAPI *pXAudio2Create)(IXAudio2** ppXAudio2, uint32_t Flags, XAUDIO2_PROCESSOR XAudio2Processor);
static HRESULT(WINAPI *pXAudio2Create)(IXAudio2 **ppXAudio2, uint32_t Flags, XAUDIO2_PROCESSOR XAudio2Processor);
static dllimp_t xaudio2_imports[] = {
{ "XAudio2Create", &pXAudio2Create },
{ NULL, NULL },
{"XAudio2Create", &pXAudio2Create},
{ NULL, NULL },
};
#define XAudio2Create pXAudio2Create
# define XAudio2Create pXAudio2Create
#endif
static int midi_freq = 44100;
static int midi_buf_size = 4410;
static int initialized = 0;
static IXAudio2 *xaudio2 = NULL;
static IXAudio2MasteringVoice *mastervoice = NULL;
static IXAudio2SourceVoice *srcvoice = NULL;
static IXAudio2SourceVoice *srcvoicemidi = NULL;
static IXAudio2SourceVoice *srcvoicecd = NULL;
static int midi_freq = 44100;
static int midi_buf_size = 4410;
static int initialized = 0;
static IXAudio2 *xaudio2 = NULL;
static IXAudio2MasteringVoice *mastervoice = NULL;
static IXAudio2SourceVoice *srcvoice = NULL;
static IXAudio2SourceVoice *srcvoicemidi = NULL;
static IXAudio2SourceVoice *srcvoicecd = NULL;
#define FREQ 48000
#define BUFLEN SOUNDBUFLEN
#define FREQ 48000
#define BUFLEN SOUNDBUFLEN
static void WINAPI OnVoiceProcessingPassStart(IXAudio2VoiceCallback *callback, uint32_t bytesRequired) {}
static void WINAPI OnVoiceProcessingPassEnd(IXAudio2VoiceCallback *callback) {}
static void WINAPI OnStreamEnd(IXAudio2VoiceCallback *callback) {}
static void WINAPI OnBufferStart(IXAudio2VoiceCallback *callback, void *pBufferContext) {}
static void WINAPI OnLoopEnd(IXAudio2VoiceCallback *callback, void *pBufferContext) {}
static void WINAPI OnVoiceError(IXAudio2VoiceCallback *callback, void *pBufferContext, HRESULT error) {}
static void WINAPI
OnVoiceProcessingPassStart(IXAudio2VoiceCallback *callback, uint32_t bytesRequired)
{
}
static void WINAPI
OnVoiceProcessingPassEnd(IXAudio2VoiceCallback *callback)
{
}
static void WINAPI
OnStreamEnd(IXAudio2VoiceCallback *callback)
{
}
static void WINAPI
OnBufferStart(IXAudio2VoiceCallback *callback, void *pBufferContext)
{
}
static void WINAPI
OnLoopEnd(IXAudio2VoiceCallback *callback, void *pBufferContext)
{
}
static void WINAPI
OnVoiceError(IXAudio2VoiceCallback *callback, void *pBufferContext, HRESULT error)
{
}
static void WINAPI
OnBufferEnd(IXAudio2VoiceCallback *callback, void *pBufferContext)
@@ -74,15 +92,15 @@ static IXAudio2VoiceCallbackVtbl callbacksVtbl =
#else
static FAudioVoiceCallback callbacks =
#endif
{
.OnVoiceProcessingPassStart = OnVoiceProcessingPassStart,
.OnVoiceProcessingPassEnd = OnVoiceProcessingPassEnd,
.OnStreamEnd = OnStreamEnd,
.OnBufferStart = OnBufferStart,
.OnBufferEnd = OnBufferEnd,
.OnLoopEnd = OnLoopEnd,
.OnVoiceError = OnVoiceError
};
{
.OnVoiceProcessingPassStart = OnVoiceProcessingPassStart,
.OnVoiceProcessingPassEnd = OnVoiceProcessingPassEnd,
.OnStreamEnd = OnStreamEnd,
.OnBufferStart = OnBufferStart,
.OnBufferEnd = OnBufferEnd,
.OnLoopEnd = OnLoopEnd,
.OnVoiceError = OnVoiceError
};
#if defined(_WIN32) && !defined(USE_FAUDIO)
static IXAudio2VoiceCallback callbacks = { &callbacksVtbl };
@@ -93,25 +111,23 @@ inital()
{
#if defined(_WIN32) && !defined(USE_FAUDIO)
if (xaudio2_handle == NULL) {
xaudio2_handle = dynld_module("xaudio2_9.dll", xaudio2_imports);
xaudio2_handle = dynld_module("xaudio2_9.dll", xaudio2_imports);
}
if (xaudio2_handle == NULL) {
xaudio2_handle = dynld_module("xaudio2_9redist.dll", xaudio2_imports);
xaudio2_handle = dynld_module("xaudio2_9redist.dll", xaudio2_imports);
}
if (xaudio2_handle == NULL) {
return;
return;
}
#endif
if (XAudio2Create(&xaudio2, 0, XAUDIO2_DEFAULT_PROCESSOR))
{
if (XAudio2Create(&xaudio2, 0, XAUDIO2_DEFAULT_PROCESSOR)) {
return;
}
if (IXAudio2_CreateMasteringVoice(xaudio2, &mastervoice, 2, FREQ, 0, 0, NULL, 0))
{
if (IXAudio2_CreateMasteringVoice(xaudio2, &mastervoice, 2, FREQ, 0, 0, NULL, 0)) {
IXAudio2_Release(xaudio2);
xaudio2 = NULL;
return;
@@ -120,33 +136,29 @@ inital()
WAVEFORMATEX fmt;
fmt.nChannels = 2;
if (sound_is_float)
{
fmt.wFormatTag = WAVE_FORMAT_IEEE_FLOAT;
if (sound_is_float) {
fmt.wFormatTag = WAVE_FORMAT_IEEE_FLOAT;
fmt.wBitsPerSample = 32;
}
else
{
fmt.wFormatTag = WAVE_FORMAT_PCM;
} else {
fmt.wFormatTag = WAVE_FORMAT_PCM;
fmt.wBitsPerSample = 16;
}
fmt.nSamplesPerSec = FREQ;
fmt.nBlockAlign = fmt.nChannels * fmt.wBitsPerSample / 8;
fmt.nSamplesPerSec = FREQ;
fmt.nBlockAlign = fmt.nChannels * fmt.wBitsPerSample / 8;
fmt.nAvgBytesPerSec = fmt.nSamplesPerSec * fmt.nBlockAlign;
fmt.cbSize = 0;
fmt.cbSize = 0;
if (IXAudio2_CreateSourceVoice(xaudio2, &srcvoice, &fmt, 0, 2.0f, &callbacks, NULL, NULL))
{
if (IXAudio2_CreateSourceVoice(xaudio2, &srcvoice, &fmt, 0, 2.0f, &callbacks, NULL, NULL)) {
IXAudio2MasteringVoice_DestroyVoice(mastervoice);
IXAudio2_Release(xaudio2);
xaudio2 = NULL;
xaudio2 = NULL;
mastervoice = NULL;
return;
}
fmt.nSamplesPerSec = CD_FREQ;
fmt.nBlockAlign = fmt.nChannels * fmt.wBitsPerSample / 8;
fmt.nSamplesPerSec = CD_FREQ;
fmt.nBlockAlign = fmt.nChannels * fmt.wBitsPerSample / 8;
fmt.nAvgBytesPerSec = fmt.nSamplesPerSec * fmt.nBlockAlign;
IXAudio2_CreateSourceVoice(xaudio2, &srcvoicecd, &fmt, 0, 2.0f, &callbacks, NULL, NULL);
@@ -157,10 +169,9 @@ inital()
char *mdn = midi_device_get_internal_name(midi_device_current);
if (strcmp(mdn, "none") && strcmp(mdn, SYSTEM_MIDI_INTERNAL_NAME))
{
fmt.nSamplesPerSec = midi_freq;
fmt.nBlockAlign = fmt.nChannels * fmt.wBitsPerSample / 8;
if (strcmp(mdn, "none") && strcmp(mdn, SYSTEM_MIDI_INTERNAL_NAME)) {
fmt.nSamplesPerSec = midi_freq;
fmt.nBlockAlign = fmt.nChannels * fmt.wBitsPerSample / 8;
fmt.nAvgBytesPerSec = fmt.nSamplesPerSec * fmt.nBlockAlign;
IXAudio2_CreateSourceVoice(xaudio2, &srcvoicemidi, &fmt, 0, 2.0f, &callbacks, NULL, NULL);
IXAudio2SourceVoice_Start(srcvoicemidi, 0, XAUDIO2_COMMIT_NOW);
@@ -172,14 +183,14 @@ inital()
void
closeal()
{
if (!initialized) return;
if (!initialized)
return;
initialized = 0;
IXAudio2SourceVoice_Stop(srcvoice, 0, XAUDIO2_COMMIT_NOW);
IXAudio2SourceVoice_FlushSourceBuffers(srcvoice);
IXAudio2SourceVoice_Stop(srcvoicecd, 0, XAUDIO2_COMMIT_NOW);
IXAudio2SourceVoice_FlushSourceBuffers(srcvoicecd);
if (srcvoicemidi)
{
if (srcvoicemidi) {
IXAudio2SourceVoice_Stop(srcvoicemidi, 0, XAUDIO2_COMMIT_NOW);
IXAudio2SourceVoice_FlushSourceBuffers(srcvoicemidi);
IXAudio2SourceVoice_DestroyVoice(srcvoicemidi);
@@ -189,8 +200,8 @@ closeal()
IXAudio2MasteringVoice_DestroyVoice(mastervoice);
IXAudio2_Release(xaudio2);
srcvoice = srcvoicecd = srcvoicemidi = NULL;
mastervoice = NULL;
xaudio2 = NULL;
mastervoice = NULL;
xaudio2 = NULL;
#if defined(_WIN32) && !defined(USE_FAUDIO)
dynld_close(xaudio2_handle);
@@ -199,31 +210,28 @@ closeal()
}
void
givealbuffer_common(void *buf, IXAudio2SourceVoice* sourcevoice, size_t buflen)
givealbuffer_common(void *buf, IXAudio2SourceVoice *sourcevoice, size_t buflen)
{
if (!initialized) return;
if (!initialized)
return;
IXAudio2MasteringVoice_SetVolume(mastervoice, pow(10.0, (double)sound_gain / 20.0), XAUDIO2_COMMIT_NOW);
XAUDIO2_BUFFER buffer = {0};
buffer.Flags = 0;
if (sound_is_float)
{
IXAudio2MasteringVoice_SetVolume(mastervoice, pow(10.0, (double) sound_gain / 20.0), XAUDIO2_COMMIT_NOW);
XAUDIO2_BUFFER buffer = { 0 };
buffer.Flags = 0;
if (sound_is_float) {
buffer.pAudioData = calloc(buflen, sizeof(float));
buffer.AudioBytes = (buflen) * sizeof(float);
}
else
{
} else {
buffer.pAudioData = calloc(buflen, sizeof(int16_t));
buffer.AudioBytes = (buflen) * sizeof(int16_t);
}
if (buffer.pAudioData == NULL)
{
if (buffer.pAudioData == NULL) {
fatal("xaudio2: Out Of Memory!");
}
memcpy((void*)buffer.pAudioData, buf, buffer.AudioBytes);
memcpy((void *) buffer.pAudioData, buf, buffer.AudioBytes);
buffer.PlayBegin = buffer.PlayLength = 0;
buffer.PlayLength = buflen >> 1;
buffer.pContext = (void*)buffer.pAudioData;
buffer.PlayLength = buflen >> 1;
buffer.pContext = (void *) buffer.pAudioData;
IXAudio2SourceVoice_SubmitSourceBuffer(sourcevoice, &buffer, NULL);
}
@@ -236,37 +244,34 @@ givealbuffer(void *buf)
void
givealbuffer_cd(void *buf)
{
if (srcvoicecd) givealbuffer_common(buf, srcvoicecd, CD_BUFLEN << 1);
if (srcvoicecd)
givealbuffer_common(buf, srcvoicecd, CD_BUFLEN << 1);
}
void
al_set_midi(int freq, int buf_size)
{
midi_freq = freq;
midi_freq = freq;
midi_buf_size = buf_size;
if (initialized && srcvoicemidi)
{
if (initialized && srcvoicemidi) {
IXAudio2SourceVoice_Stop(srcvoicemidi, 0, XAUDIO2_COMMIT_NOW);
IXAudio2SourceVoice_FlushSourceBuffers(srcvoicemidi);
IXAudio2SourceVoice_DestroyVoice(srcvoicemidi);
srcvoicemidi = NULL;
WAVEFORMATEX fmt;
fmt.nChannels = 2;
if (sound_is_float)
{
fmt.wFormatTag = WAVE_FORMAT_IEEE_FLOAT;
if (sound_is_float) {
fmt.wFormatTag = WAVE_FORMAT_IEEE_FLOAT;
fmt.wBitsPerSample = 32;
}
else
{
fmt.wFormatTag = WAVE_FORMAT_PCM;
} else {
fmt.wFormatTag = WAVE_FORMAT_PCM;
fmt.wBitsPerSample = 16;
}
fmt.nSamplesPerSec = midi_freq;
fmt.nBlockAlign = fmt.nChannels * fmt.wBitsPerSample / 8;
fmt.nSamplesPerSec = midi_freq;
fmt.nBlockAlign = fmt.nChannels * fmt.wBitsPerSample / 8;
fmt.nAvgBytesPerSec = fmt.nSamplesPerSec * fmt.nBlockAlign;
fmt.cbSize = 0;
fmt.cbSize = 0;
IXAudio2_CreateSourceVoice(xaudio2, &srcvoicemidi, &fmt, 0, 2.0f, &callbacks, NULL, NULL);
IXAudio2SourceVoice_Start(srcvoicemidi, 0, XAUDIO2_COMMIT_NOW);
}