mirror of
https://github.com/ekeeke/Genesis-Plus-GX.git
synced 2024-12-27 03:31:49 +01:00
Nuked OPN2: ASIC YM3438 & YM2612 emulation
This commit is contained in:
parent
27a77147aa
commit
51f802b2cc
@ -67,9 +67,14 @@ static int ym3438_accm[24][2];
|
||||
static int ym3438_sample[2];
|
||||
static unsigned int ym3438_cycles;
|
||||
|
||||
void sound_ym3438_set_type(uint8 type)
|
||||
{
|
||||
OPN2_SetChipType(&ym3438, type);
|
||||
}
|
||||
|
||||
void YM3438_Reset(void)
|
||||
{
|
||||
OPN2_Reset(&ym3438);
|
||||
OPN2_Reset(&ym3438, config.ym3438_type);
|
||||
}
|
||||
|
||||
void YM3438_Update(int *buffer, int length)
|
||||
@ -89,8 +94,8 @@ void YM3438_Update(int *buffer, int length)
|
||||
ym3438_sample[1] += ym3438_accm[j][1];
|
||||
}
|
||||
}
|
||||
*buffer++ = ym3438_sample[0] * 8;
|
||||
*buffer++ = ym3438_sample[1] * 8;
|
||||
*buffer++ = ym3438_sample[0] * 11;
|
||||
*buffer++ = ym3438_sample[1] * 11;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -41,6 +41,9 @@
|
||||
#define _SOUND_H_
|
||||
|
||||
/* Function prototypes */
|
||||
#ifdef HAVE_YM3438_CORE
|
||||
extern void sound_ym3438_set_type(uint8 type);
|
||||
#endif
|
||||
extern void sound_init(void);
|
||||
extern void sound_reset(void);
|
||||
extern int sound_context_save(uint8 *state);
|
||||
|
@ -39,7 +39,7 @@
|
||||
* OPLx decapsulated(Matthew Gambrell, Olli Niemitalo):
|
||||
* OPL2 ROMs.
|
||||
*
|
||||
* version: 1.0.5
|
||||
* version: 1.0.6
|
||||
*/
|
||||
|
||||
#include <string.h>
|
||||
@ -966,6 +966,8 @@ void OPN2_ChOutput(ym3438_t *chip)
|
||||
Bit32u channel = chip->channel;
|
||||
Bit32u test_dac = chip->mode_test_2c[5];
|
||||
Bit16s out;
|
||||
Bit16s sign;
|
||||
Bit32u out_en;
|
||||
chip->ch_read = chip->ch_lock;
|
||||
if (chip->slot < 12)
|
||||
{
|
||||
@ -995,14 +997,54 @@ void OPN2_ChOutput(ym3438_t *chip)
|
||||
}
|
||||
chip->mol = 0;
|
||||
chip->mor = 0;
|
||||
if (chip->ch_lock_l)
|
||||
|
||||
if (chip->chip_type == ym3438_type_ym2612)
|
||||
{
|
||||
out_en = ((chip->cycles & 3) == 3) || test_dac;
|
||||
/* YM2612 DAC emulation(not verified) */
|
||||
sign = out >> 8;
|
||||
if (out >= 0)
|
||||
{
|
||||
out++;
|
||||
sign++;
|
||||
}
|
||||
if (chip->ch_lock_l && out_en)
|
||||
{
|
||||
chip->mol = out;
|
||||
}
|
||||
if (chip->ch_lock_r)
|
||||
else
|
||||
{
|
||||
chip->mol = sign;
|
||||
}
|
||||
if (chip->ch_lock_r && out_en)
|
||||
{
|
||||
chip->mor = out;
|
||||
}
|
||||
else
|
||||
{
|
||||
chip->mor = sign;
|
||||
}
|
||||
/* Amplify signal */
|
||||
chip->mol *= 3;
|
||||
chip->mor *= 3;
|
||||
}
|
||||
else
|
||||
{
|
||||
out_en = ((chip->cycles & 3) != 0) || test_dac;
|
||||
/* Discrete YM3438 seems has the ladder effect too */
|
||||
if (out >= 0 && chip->chip_type == ym3438_type_discrete)
|
||||
{
|
||||
out++;
|
||||
}
|
||||
if (chip->ch_lock_l && out_en)
|
||||
{
|
||||
chip->mol = out;
|
||||
}
|
||||
if (chip->ch_lock_r && out_en)
|
||||
{
|
||||
chip->mor = out;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void OPN2_FMGenerate(ym3438_t *chip)
|
||||
@ -1161,7 +1203,7 @@ void OPN2_KeyOn(ym3438_t*chip)
|
||||
}
|
||||
}
|
||||
|
||||
void OPN2_Reset(ym3438_t *chip)
|
||||
void OPN2_Reset(ym3438_t *chip, Bit32u type)
|
||||
{
|
||||
Bit32u i;
|
||||
memset(chip, 0, sizeof(ym3438_t));
|
||||
@ -1177,6 +1219,12 @@ void OPN2_Reset(ym3438_t *chip)
|
||||
chip->pan_l[i] = 1;
|
||||
chip->pan_r[i] = 1;
|
||||
}
|
||||
chip->chip_type = type;
|
||||
}
|
||||
|
||||
void OPN2_SetChipType(ym3438_t *chip, Bit32u type)
|
||||
{
|
||||
chip->chip_type = type;
|
||||
}
|
||||
|
||||
void OPN2_Clock(ym3438_t *chip, Bit32u *buffer)
|
||||
@ -1350,7 +1398,7 @@ Bit32u OPN2_ReadIRQPin(ym3438_t *chip)
|
||||
|
||||
Bit8u OPN2_Read(ym3438_t *chip, Bit32u port)
|
||||
{
|
||||
if ((port & 3) == 0)
|
||||
if ((port & 3) == 0 || chip->chip_type == ym3438_type_asic)
|
||||
{
|
||||
if (chip->mode_test_21[6])
|
||||
{
|
||||
|
@ -45,6 +45,12 @@
|
||||
#ifndef YM3438_H
|
||||
#define YM3438_H
|
||||
|
||||
enum {
|
||||
ym3438_type_discrete = 0, /* Discrete YM3438 (Teradrive) */
|
||||
ym3438_type_asic = 1, /* ASIC YM3438 (MD1 VA7, MD2, MD3, etc) */
|
||||
ym3438_type_ym2612 = 2 /* YM2612 (MD1, MD2 VA2) */
|
||||
};
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
typedef uintptr_t Bitu;
|
||||
@ -60,6 +66,7 @@ typedef int8_t Bit8s;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
Bit32u chip_type;
|
||||
Bit32u cycles;
|
||||
Bit32u slot;
|
||||
Bit32u channel;
|
||||
@ -201,7 +208,8 @@ typedef struct
|
||||
Bit8u pms[6];
|
||||
} ym3438_t;
|
||||
|
||||
void OPN2_Reset(ym3438_t *chip);
|
||||
void OPN2_Reset(ym3438_t *chip, Bit32u type);
|
||||
void OPN2_SetChipType(ym3438_t *chip, Bit32u type);
|
||||
void OPN2_Clock(ym3438_t *chip, Bit32u *buffer);
|
||||
void OPN2_Write(ym3438_t *chip, Bit32u port, Bit8u data);
|
||||
void OPN2_SetTestPin(ym3438_t *chip, Bit32u value);
|
||||
|
@ -1117,6 +1117,18 @@ static void check_variables(void)
|
||||
sound_reset();
|
||||
}
|
||||
}
|
||||
var.key = "genesis_plus_gx_ym3438_type";
|
||||
environ_cb(RETRO_ENVIRONMENT_GET_VARIABLE, &var);
|
||||
{
|
||||
if (!strcmp(var.value, "ym2612"))
|
||||
config.ym3438_type = ym3438_type_ym2612;
|
||||
else if (!strcmp(var.value, "ym3438 asic"))
|
||||
config.ym3438_type = ym3438_type_asic;
|
||||
else
|
||||
config.ym3438_type = ym3438_type_discrete;
|
||||
|
||||
sound_ym3438_set_type(config.ym3438_type);
|
||||
}
|
||||
#endif
|
||||
|
||||
var.key = "genesis_plus_gx_blargg_ntsc_filter";
|
||||
@ -1657,6 +1669,7 @@ void retro_set_environment(retro_environment_t cb)
|
||||
{ "genesis_plus_gx_dac_bits", "YM2612 DAC quantization; disabled|enabled" },
|
||||
#ifdef HAVE_YM3438_CORE
|
||||
{ "genesis_plus_gx_ym3438", "YM2612/YM3438 core; mame|nuked opn2" },
|
||||
{ "genesis_plus_gx_ym3438_type", "YM2612/YM3438 type(Nuked OPN2); ym2612|ym3438 asic|ym3438 discrete" },
|
||||
#endif
|
||||
|
||||
{ "genesis_plus_gx_audio_filter", "Audio filter; disabled|low-pass" },
|
||||
|
@ -93,6 +93,7 @@ struct
|
||||
uint8 ym2413;
|
||||
#ifdef HAVE_YM3438_CORE
|
||||
uint8 ym3438;
|
||||
uint8 ym3438_type;
|
||||
#endif
|
||||
uint8 mono;
|
||||
int16 psg_preamp;
|
||||
|
Loading…
Reference in New Issue
Block a user