mirror of
https://github.com/86Box/86Box.git
synced 2026-02-25 04:45:31 -07:00
Merge pull request #2167 from jriwanek-forks/formatting
Formatting in src/sound
This commit is contained in:
18
.clang-format
Normal file
18
.clang-format
Normal 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
|
||||
@@ -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
|
||||
|
||||
@@ -143,7 +143,7 @@ cmake_dependent_option(MGA "Matrox Mystique graphics adapters"
|
||||
cmake_dependent_option(NO_SIO "Machines without emulated Super I/O chips" ON "DEV_BRANCH" OFF)
|
||||
cmake_dependent_option(OLIVETTI "Olivetti M290" ON "DEV_BRANCH" OFF)
|
||||
cmake_dependent_option(OPEN_AT "OpenAT" ON "DEV_BRANCH" OFF)
|
||||
cmake_dependent_option(PAS16 "Pro Audio Spectrum 16" OFF "DEV_BRANCH" OFF)
|
||||
cmake_dependent_option(PAS16 "Pro Audio Spectrum 16" ON "DEV_BRANCH" OFF)
|
||||
cmake_dependent_option(SIO_DETECT "Super I/O Detection Helper" ON "DEV_BRANCH" OFF)
|
||||
cmake_dependent_option(TANDY_ISA "Tandy PSG ISA clone boards" ON "DEV_BRANCH" OFF)
|
||||
cmake_dependent_option(VGAWONDER "ATI VGA Wonder (ATI-18800)" ON "DEV_BRANCH" OFF)
|
||||
|
||||
@@ -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*/
|
||||
|
||||
@@ -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
|
||||
}
|
||||
|
||||
@@ -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*/
|
||||
|
||||
@@ -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*/
|
||||
|
||||
@@ -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);
|
||||
|
||||
|
||||
@@ -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*/
|
||||
|
||||
@@ -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):
|
||||
|
||||
@@ -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*/
|
||||
|
||||
@@ -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*/
|
||||
|
||||
@@ -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*/
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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*/
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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*/
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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*/
|
||||
|
||||
558
src/sound/midi.c
558
src/sound/midi.c
@@ -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
@@ -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
|
||||
};
|
||||
|
||||
@@ -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
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
@@ -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
@@ -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);
|
||||
}
|
||||
|
||||
@@ -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
@@ -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
2431
src/sound/snd_gus.c
2431
src/sound/snd_gus.c
File diff suppressed because it is too large
Load Diff
@@ -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
|
||||
};
|
||||
|
||||
@@ -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
@@ -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
@@ -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,
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
3524
src/sound/snd_sb.c
3524
src/sound/snd_sb.c
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
@@ -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
|
||||
|
||||
@@ -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)
|
||||
{
|
||||
|
||||
@@ -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
|
||||
};
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user