diff --git a/builds/genesis_plus_gx_libretro.dll b/builds/genesis_plus_gx_libretro.dll index 126af05..7ef2c3e 100644 Binary files a/builds/genesis_plus_gx_libretro.dll and b/builds/genesis_plus_gx_libretro.dll differ diff --git a/builds/genplus_cube.dol b/builds/genplus_cube.dol index 5fc77ac..9300861 100644 Binary files a/builds/genplus_cube.dol and b/builds/genplus_cube.dol differ diff --git a/builds/genplus_wii.dol b/builds/genplus_wii.dol index eb18f68..faf3ac2 100644 Binary files a/builds/genplus_wii.dol and b/builds/genplus_wii.dol differ diff --git a/core/cd_hw/cdd.c b/core/cd_hw/cdd.c index 0e37020..dff2373 100644 --- a/core/cd_hw/cdd.c +++ b/core/cd_hw/cdd.c @@ -214,7 +214,7 @@ void cdd_reset(void) cdd.status = cdd.loaded ? CD_STOP : NO_DISC; /* reset CD-DA fader (full volume) */ - cdd.volume = 0x400; + cdd.fader[0] = cdd.fader[1] = 0x400; /* clear CD-DA output */ cdd.audio[0] = cdd.audio[1] = 0; @@ -229,7 +229,7 @@ int cdd_context_save(uint8 *state) save_param(&cdd.index, sizeof(cdd.index)); save_param(&cdd.lba, sizeof(cdd.lba)); save_param(&cdd.scanOffset, sizeof(cdd.scanOffset)); - save_param(&cdd.volume, sizeof(cdd.volume)); + save_param(&cdd.fader, sizeof(cdd.fader)); save_param(&cdd.status, sizeof(cdd.status)); return bufferptr; @@ -255,7 +255,7 @@ int cdd_context_load(uint8 *state) load_param(&cdd.index, sizeof(cdd.index)); load_param(&cdd.lba, sizeof(cdd.lba)); load_param(&cdd.scanOffset, sizeof(cdd.scanOffset)); - load_param(&cdd.volume, sizeof(cdd.volume)); + load_param(&cdd.fader, sizeof(cdd.fader)); load_param(&cdd.status, sizeof(cdd.status)); /* adjust current LBA within track limit */ @@ -1287,10 +1287,10 @@ void cdd_read_audio(unsigned int samples) int i, mul, l, r; /* current CD-DA fader volume */ - int curVol = cdd.volume; + int curVol = cdd.fader[0]; /* CD-DA fader volume setup (0-1024) */ - int endVol = scd.regs[0x34>>1].w >> 4; + int endVol = cdd.fader[1]; /* read samples from current block */ #if defined(USE_LIBCHDR) @@ -1476,7 +1476,7 @@ void cdd_read_audio(unsigned int samples) } /* save current CD-DA fader volume */ - cdd.volume = curVol; + cdd.fader[0] = curVol; /* save last audio output for next frame */ cdd.audio[0] = prev_l; diff --git a/core/cd_hw/cdd.h b/core/cd_hw/cdd.h index b6d02df..00f1354 100644 --- a/core/cd_hw/cdd.h +++ b/core/cd_hw/cdd.h @@ -64,6 +64,11 @@ #define NO_DISC 0x0B #define CD_END 0x0C +/* CD-DA digital filter types */ +#define CD_TYPE_DEFAULT 0x00 +#define CD_TYPE_WONDERMEGA 0x01 +#define CD_TYPE_WONDERMEGA_M2 0x02 + /* CD track */ typedef struct { @@ -103,11 +108,12 @@ typedef struct { uint32 cycles; uint32 latency; + int type; int loaded; int index; int lba; int scanOffset; - int volume; + uint16 fader[2]; uint8 status; uint16 sectorSize; toc_t toc; diff --git a/core/cd_hw/scd.c b/core/cd_hw/scd.c index fdf49d0..0115028 100644 --- a/core/cd_hw/scd.c +++ b/core/cd_hw/scd.c @@ -2,7 +2,7 @@ * Genesis Plus * Mega CD / Sega CD hardware * - * Copyright (C) 2012-2016 Eke-Eke (Genesis Plus GX) + * Copyright (C) 2012-2018 Eke-Eke (Genesis Plus GX) * * Redistribution and use of this code or any derivative works are permitted * provided that the following conditions are met: @@ -1281,6 +1281,46 @@ static void scd_write_word(unsigned int address, unsigned int data) return; } + case 0x34: /* CD Fader */ + { + /* Wondermega hardware (CXD2554M digital filter) */ + if (cdd.type == CD_TYPE_WONDERMEGA) + { + /* only MSB is latched by CXD2554M chip, LSB is ignored (8-bit digital filter) */ + /* attenuator data is 7-bit only (bits 0-7) */ + data = (data >> 8) & 0x7f; + + /* scale CXD2554M volume (0-127) to full (LC7883KM compatible) volume range (0-1024) */ + cdd.fader[1] = (1024 * data) / 127 ; + } + + /* Wondermega M2 / X'Eye hardware (SM5841A digital filter) */ + else if (cdd.type == CD_TYPE_WONDERMEGA_M2) + { + /* only MSB is latched by SM5841A chip, LSB is ignored (8-bit digital filter) */ + data = data >> 8; + + /* attenuator data is set only when command bit (bit 0) is cleared (other commands are ignored) */ + if (data & 0x01) return; + + /* attenuator data is 7-bit only (bits 8-1) and reverted (bit 1 = msb) */ + /* bit reversing formula taken from http://graphics.stanford.edu/~seander/bithacks.html#ReverseByteWith32Bits */ + data = (((((data * 0x0802) & 0x22110) | ((data * 0x8020) & 0x88440)) * 0x10101) >> 16) & 0x7f; + + /* convert & scale SM5841A attenuation (127-0) to full (LC7883KM compatible) volume range (0-1024) */ + cdd.fader[1] = (1024 * (127 - data)) / 127 ; + } + + /* default CD hardware (LC7883KM digital filter) */ + else + { + /* get LC7883KM volume data (12-bit) */ + cdd.fader[1] = data >> 4 ; + } + + return; + } + case 0x4a: /* CDD command 9 (controlled by BIOS, word access only ?) */ { scd.regs[0x4a>>1].w = 0; diff --git a/core/cd_hw/scd.h b/core/cd_hw/scd.h index 8a29ec4..70bedeb 100644 --- a/core/cd_hw/scd.h +++ b/core/cd_hw/scd.h @@ -2,7 +2,7 @@ * Genesis Plus * Mega CD / Sega CD hardware * - * Copyright (C) 2012-2016 Eke-Eke (Genesis Plus GX) + * Copyright (C) 2012-2018 Eke-Eke (Genesis Plus GX) * * Redistribution and use of this code or any derivative works are permitted * provided that the following conditions are met: diff --git a/core/loadrom.c b/core/loadrom.c index a02d7e0..37895c0 100644 --- a/core/loadrom.c +++ b/core/loadrom.c @@ -417,6 +417,23 @@ int load_bios(int system) /* CD BOOTROM loaded ? */ if (size > 0) { + /* auto-detect CD hardware model */ + if (!memcmp (&scd.bootrom[0x120], "WONDER-MEGA BOOT", 16)) + { + /* Wondermega CD hardware */ + cdd.type = CD_TYPE_WONDERMEGA; + } + else if (!memcmp (&scd.bootrom[0x120], "WONDERMEGA2 BOOT", 16)) + { + /* Wondermega M2 / X'Eye CD hardware */ + cdd.type = CD_TYPE_WONDERMEGA_M2; + } + else + { + /* default CD hardware */ + cdd.type = CD_TYPE_DEFAULT; + } + #ifdef LSB_FIRST /* Byteswap ROM to optimize 16-bit access */ int i;