Compare commits
3 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| c5df0565e6 | |||
| c06e10d458 | |||
| 0419c81f9e |
+11
-6
@@ -197,7 +197,7 @@ static __weak GenPlusGameCore *_current;
|
||||
if([[self systemIdentifier] isEqualToString:@"openemu.system.sg"] || [[self systemIdentifier] isEqualToString:@"openemu.system.scd"])
|
||||
{
|
||||
// Set initial viewport size because the system briefly outputs 256x192 when it boots
|
||||
bitmap.viewport.w = 320;
|
||||
bitmap.viewport.w = 292;
|
||||
bitmap.viewport.h = 224;
|
||||
}
|
||||
|
||||
@@ -312,7 +312,9 @@ static __weak GenPlusGameCore *_current;
|
||||
}
|
||||
else
|
||||
{
|
||||
return OEIntSizeMake(4, 3); // TODO: Correct PAR.
|
||||
// H32 mode (256px * 8:7 PAR)
|
||||
// H40 mode (320px * 32:35 PAR)
|
||||
return OEIntSizeMake(292, 224);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -572,11 +574,11 @@ const int MasterSystemMap[] = {INPUT_UP, INPUT_DOWN, INPUT_LEFT, INPUT_RIGHT, IN
|
||||
if (bitmap.viewport.w == 320)
|
||||
{
|
||||
input.analog[4][0] = aPoint.x;
|
||||
input.analog[4][1] = aPoint.y * 0.933333;
|
||||
input.analog[4][1] = aPoint.y * 0.912500;
|
||||
}
|
||||
else // w == 256
|
||||
{
|
||||
input.analog[4][0] = aPoint.x * 0.857143;
|
||||
input.analog[4][0] = aPoint.x * 0.876712;
|
||||
input.analog[4][1] = aPoint.y;
|
||||
}
|
||||
}
|
||||
@@ -708,15 +710,18 @@ const int MasterSystemMap[] = {INPUT_UP, INPUT_DOWN, INPUT_LEFT, INPUT_RIGHT, IN
|
||||
config.hq_fm = 1; /* high-quality FM resampling (slower) */
|
||||
config.hq_psg = 1; /* high-quality PSG resampling (slower) */
|
||||
config.filter = 0; /* no filter */
|
||||
config.lp_range = 0x9999; /* 0.6 in 16.16 fixed point */
|
||||
config.lp_range = 0x7fff; /* 0.5 in 0.16 fixed point */
|
||||
config.low_freq = 880;
|
||||
config.high_freq = 5000;
|
||||
config.lg = 100;
|
||||
config.mg = 100;
|
||||
config.hg = 100;
|
||||
config.dac_bits = 14; /* MAX DEPTH */
|
||||
config.ym2612 = YM2612_DISCRETE;
|
||||
config.ym2413 = 2; /* AUTO */
|
||||
config.mono = 0; /* STEREO output */
|
||||
#ifdef HAVE_YM3438_CORE
|
||||
config.ym3438 = 0;
|
||||
#endif
|
||||
|
||||
/* system options */
|
||||
config.system = 0; /* AUTO */
|
||||
|
||||
+1
-1
@@ -19,7 +19,7 @@
|
||||
<key>CFBundleSignature</key>
|
||||
<string>????</string>
|
||||
<key>CFBundleVersion</key>
|
||||
<string>1.7.4.7</string>
|
||||
<string>1.7.4.8</string>
|
||||
<key>NSPrincipalClass</key>
|
||||
<string>OEGameCoreController</string>
|
||||
<key>OEGameCoreClass</key>
|
||||
|
||||
@@ -5,7 +5,7 @@
|
||||
* Support for SG-1000, Mark-III, Master System, Game Gear, Mega Drive & Mega CD hardware
|
||||
*
|
||||
* Copyright (C) 1998-2003 Charles Mac Donald (original code)
|
||||
* Copyright (C) 2007-2016 Eke-Eke (Genesis Plus GX)
|
||||
* Copyright (C) 2007-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:
|
||||
@@ -474,8 +474,8 @@ void gen_zbusreq_w(unsigned int data, unsigned int cycles)
|
||||
/* check if Z80 is going to be restarted */
|
||||
if (zstate == 3)
|
||||
{
|
||||
/* resynchronize with 68k */
|
||||
Z80.cycles = cycles;
|
||||
/* resynchronize with 68k (Z80 cycles should remain a multiple of 15 MClocks) */
|
||||
Z80.cycles = ((cycles + 14) / 15) * 15;
|
||||
|
||||
/* disable 68k access to Z80 bus */
|
||||
m68k.memory_map[0xa0].read8 = m68k_read_bus_8;
|
||||
@@ -496,8 +496,8 @@ void gen_zreset_w(unsigned int data, unsigned int cycles)
|
||||
/* check if Z80 is going to be restarted */
|
||||
if (zstate == 0)
|
||||
{
|
||||
/* resynchronize with 68k */
|
||||
Z80.cycles = cycles;
|
||||
/* resynchronize with 68k (Z80 cycles should remain a multiple of 15 MClocks) */
|
||||
Z80.cycles = ((cycles + 14) / 15) * 15;
|
||||
|
||||
/* reset Z80 & YM2612 */
|
||||
z80_reset();
|
||||
|
||||
@@ -5,7 +5,7 @@
|
||||
* Support for SG-1000, Mark-III, Master System, Game Gear, Mega Drive & Mega CD hardware
|
||||
*
|
||||
* Copyright (C) 1998-2003 Charles Mac Donald (original code)
|
||||
* Copyright (C) 2007-2016 Eke-Eke (Genesis Plus GX)
|
||||
* Copyright (C) 2007-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:
|
||||
|
||||
+211
-135
@@ -3,7 +3,7 @@
|
||||
* Sound Hardware
|
||||
*
|
||||
* Copyright (C) 1998-2003 Charles Mac Donald (original code)
|
||||
* Copyright (C) 2007-2016 Eke-Eke (Genesis Plus GX)
|
||||
* Copyright (C) 2007-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:
|
||||
@@ -40,6 +40,9 @@
|
||||
#include "shared.h"
|
||||
#include "blip_buf.h"
|
||||
|
||||
/* YM2612 internal clock = input clock / 6 = (master clock / 7) / 6 */
|
||||
#define YM2612_CLOCK_RATIO (7*6)
|
||||
|
||||
/* FM output buffer (large enough to hold a whole frame at original chips rate) */
|
||||
#ifdef HAVE_YM3438_CORE
|
||||
static int fm_buffer[1080 * 2 * 24];
|
||||
@@ -51,28 +54,121 @@ static int fm_last[2];
|
||||
static int *fm_ptr;
|
||||
|
||||
/* Cycle-accurate FM samples */
|
||||
static uint32 fm_cycles_ratio;
|
||||
static uint32 fm_cycles_start;
|
||||
static uint32 fm_cycles_count;
|
||||
static int fm_cycles_ratio;
|
||||
static int fm_cycles_start;
|
||||
static int fm_cycles_count;
|
||||
static int fm_cycles_busy;
|
||||
|
||||
/* YM chip function pointers */
|
||||
static void (*YM_Reset)(void);
|
||||
static void (*YM_Update)(int *buffer, int length);
|
||||
static void (*YM_Write)(unsigned int a, unsigned int v);
|
||||
static unsigned int (*YM_Read)(unsigned int a);
|
||||
void (*fm_reset)(unsigned int cycles);
|
||||
void (*fm_write)(unsigned int cycles, unsigned int address, unsigned int data);
|
||||
unsigned int (*fm_read)(unsigned int cycles, unsigned int address);
|
||||
|
||||
#ifdef HAVE_YM3438_CORE
|
||||
static ym3438_t ym3438;
|
||||
static int ym3438_accm[24][2];
|
||||
static short ym3438_accm[24][2];
|
||||
static int ym3438_sample[2];
|
||||
static unsigned int ym3438_cycles;
|
||||
static int ym3438_cycles;
|
||||
#endif
|
||||
|
||||
void YM3438_Reset(void)
|
||||
/* Run FM chip until required M-cycles */
|
||||
INLINE void fm_update(int cycles)
|
||||
{
|
||||
OPN2_Reset(&ym3438);
|
||||
if (cycles > fm_cycles_count)
|
||||
{
|
||||
/* number of samples to run */
|
||||
int samples = (cycles - fm_cycles_count + fm_cycles_ratio - 1) / fm_cycles_ratio;
|
||||
|
||||
/* run FM chip to sample buffer */
|
||||
YM_Update(fm_ptr, samples);
|
||||
|
||||
/* update FM buffer pointer */
|
||||
fm_ptr += (samples * 2);
|
||||
|
||||
/* update FM cycle counter */
|
||||
fm_cycles_count += (samples * fm_cycles_ratio);
|
||||
}
|
||||
}
|
||||
|
||||
void YM3438_Update(int *buffer, int length)
|
||||
static void YM2612_Reset(unsigned int cycles)
|
||||
{
|
||||
/* synchronize FM chip with CPU */
|
||||
fm_update(cycles);
|
||||
|
||||
/* reset FM chip */
|
||||
YM2612ResetChip();
|
||||
fm_cycles_busy = 0;
|
||||
}
|
||||
|
||||
static void YM2612_Write(unsigned int cycles, unsigned int a, unsigned int v)
|
||||
{
|
||||
/* detect DATA port write */
|
||||
if (a & 1)
|
||||
{
|
||||
/* synchronize FM chip with CPU */
|
||||
fm_update(cycles);
|
||||
|
||||
/* set FM BUSY end cycle (discrete or ASIC-integrated YM2612 chip only) */
|
||||
if (config.ym2612 < YM2612_ENHANCED)
|
||||
{
|
||||
fm_cycles_busy = (((cycles + YM2612_CLOCK_RATIO - 1) / YM2612_CLOCK_RATIO) + 32) * YM2612_CLOCK_RATIO;
|
||||
}
|
||||
}
|
||||
|
||||
/* write FM register */
|
||||
YM2612Write(a, v);
|
||||
}
|
||||
|
||||
static unsigned int YM2612_Read(unsigned int cycles, unsigned int a)
|
||||
{
|
||||
/* FM status can only be read from (A0,A1)=(0,0) on discrete YM2612 */
|
||||
if ((a == 0) || (config.ym2612 > YM2612_DISCRETE))
|
||||
{
|
||||
/* synchronize FM chip with CPU */
|
||||
fm_update(cycles - fm_cycles_ratio + 1);
|
||||
|
||||
/* read FM status */
|
||||
if (cycles >= fm_cycles_busy)
|
||||
{
|
||||
/* BUSY flag cleared */
|
||||
return YM2612Read();
|
||||
}
|
||||
else
|
||||
{
|
||||
/* BUSY flag set */
|
||||
return YM2612Read() | 0x80;
|
||||
}
|
||||
}
|
||||
|
||||
/* invalid FM status address */
|
||||
return 0x00;
|
||||
}
|
||||
|
||||
static void YM2413_Reset(unsigned int cycles)
|
||||
{
|
||||
/* synchronize FM chip with CPU */
|
||||
fm_update(cycles);
|
||||
|
||||
/* reset FM chip */
|
||||
YM2413ResetChip();
|
||||
}
|
||||
|
||||
static void YM2413_Write(unsigned int cycles, unsigned int a, unsigned int v)
|
||||
{
|
||||
/* detect DATA port write */
|
||||
if (a & 1)
|
||||
{
|
||||
/* synchronize FM chip with CPU */
|
||||
fm_update(cycles);
|
||||
}
|
||||
|
||||
/* write FM register */
|
||||
YM2413Write(a, v);
|
||||
}
|
||||
|
||||
#ifdef HAVE_YM3438_CORE
|
||||
static void YM3438_Update(int *buffer, int length)
|
||||
{
|
||||
int i, j;
|
||||
for (i = 0; i < length; i++)
|
||||
@@ -94,36 +190,34 @@ void YM3438_Update(int *buffer, int length)
|
||||
}
|
||||
}
|
||||
|
||||
void YM3438_Write(unsigned int a, unsigned int v)
|
||||
static void YM3438_Reset(unsigned int cycles)
|
||||
{
|
||||
/* synchronize FM chip with CPU */
|
||||
fm_update(cycles);
|
||||
|
||||
/* reset FM chip */
|
||||
OPN2_Reset(&ym3438);
|
||||
}
|
||||
|
||||
static void YM3438_Write(unsigned int cycles, unsigned int a, unsigned int v)
|
||||
{
|
||||
/* synchronize FM chip with CPU */
|
||||
fm_update(cycles);
|
||||
|
||||
/* write FM register */
|
||||
OPN2_Write(&ym3438, a, v);
|
||||
}
|
||||
|
||||
unsigned int YM3438_Read(unsigned int a)
|
||||
static unsigned int YM3438_Read(unsigned int cycles, unsigned int a)
|
||||
{
|
||||
/* synchronize FM chip with CPU */
|
||||
fm_update(cycles - fm_cycles_ratio + 1);
|
||||
|
||||
/* read FM status */
|
||||
return OPN2_Read(&ym3438, a);
|
||||
}
|
||||
#endif
|
||||
|
||||
/* Run FM chip until required M-cycles */
|
||||
INLINE void fm_update(unsigned int cycles)
|
||||
{
|
||||
if (cycles > fm_cycles_count)
|
||||
{
|
||||
/* number of samples to run */
|
||||
unsigned int samples = (cycles - fm_cycles_count + fm_cycles_ratio - 1) / fm_cycles_ratio;
|
||||
|
||||
/* run FM chip to sample buffer */
|
||||
YM_Update(fm_ptr, samples);
|
||||
|
||||
/* update FM buffer pointer */
|
||||
fm_ptr += (samples << 1);
|
||||
|
||||
/* update FM cycle counter */
|
||||
fm_cycles_count += samples * fm_cycles_ratio;
|
||||
}
|
||||
}
|
||||
|
||||
void sound_init( void )
|
||||
{
|
||||
/* Initialize FM chip */
|
||||
@@ -137,37 +231,37 @@ void sound_init( void )
|
||||
memset(&ym3438, 0, sizeof(ym3438));
|
||||
memset(&ym3438_sample, 0, sizeof(ym3438_sample));
|
||||
memset(&ym3438_accm, 0, sizeof(ym3438_accm));
|
||||
YM_Reset = YM3438_Reset;
|
||||
YM_Update = YM3438_Update;
|
||||
YM_Write = YM3438_Write;
|
||||
YM_Read = YM3438_Read;
|
||||
fm_reset = YM3438_Reset;
|
||||
fm_write = YM3438_Write;
|
||||
fm_read = YM3438_Read;
|
||||
|
||||
/* chip is running at VCLK / 6 = MCLK / 7 / 6 */
|
||||
fm_cycles_ratio = 6 * 7;
|
||||
/* chip is running at internal clock */
|
||||
fm_cycles_ratio = YM2612_CLOCK_RATIO;
|
||||
}
|
||||
else
|
||||
#endif
|
||||
{
|
||||
/* MAME */
|
||||
/* MAME OPN2*/
|
||||
YM2612Init();
|
||||
YM2612Config(config.dac_bits);
|
||||
YM_Reset = YM2612ResetChip;
|
||||
YM2612Config(config.ym2612);
|
||||
YM_Update = YM2612Update;
|
||||
YM_Write = YM2612Write;
|
||||
YM_Read = YM2612Read;
|
||||
fm_reset = YM2612_Reset;
|
||||
fm_write = YM2612_Write;
|
||||
fm_read = YM2612_Read;
|
||||
|
||||
/* chip is running at VCLK / 144 = MCLK / 7 / 144 */
|
||||
fm_cycles_ratio = 144 * 7;
|
||||
/* chip is running at sample clock */
|
||||
fm_cycles_ratio = YM2612_CLOCK_RATIO * 24;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
/* YM2413 */
|
||||
YM2413Init();
|
||||
YM_Reset = YM2413ResetChip;
|
||||
YM_Update = YM2413Update;
|
||||
YM_Write = YM2413Write;
|
||||
YM_Read = NULL;
|
||||
YM_Update = (config.ym2413 & 1) ? YM2413Update : NULL;
|
||||
fm_reset = YM2413_Reset;
|
||||
fm_write = YM2413_Write;
|
||||
fm_read = NULL;
|
||||
|
||||
/* chip is running at ZCLK / 72 = MCLK / 15 / 72 */
|
||||
fm_cycles_ratio = 72 * 15;
|
||||
@@ -180,7 +274,7 @@ void sound_init( void )
|
||||
void sound_reset(void)
|
||||
{
|
||||
/* reset sound chips */
|
||||
YM_Reset();
|
||||
fm_reset(0);
|
||||
psg_reset();
|
||||
psg_config(0, config.psg_preamp, 0xff);
|
||||
|
||||
@@ -196,73 +290,85 @@ void sound_reset(void)
|
||||
|
||||
int sound_update(unsigned int cycles)
|
||||
{
|
||||
int prev_l, prev_r, preamp, time, l, r, *ptr;
|
||||
|
||||
/* Run PSG chip until end of frame */
|
||||
psg_end_frame(cycles);
|
||||
|
||||
/* Run FM chip until end of frame */
|
||||
fm_update(cycles);
|
||||
|
||||
/* FM output pre-amplification */
|
||||
preamp = config.fm_preamp;
|
||||
|
||||
/* FM frame initial timestamp */
|
||||
time = fm_cycles_start;
|
||||
|
||||
/* Restore last FM outputs from previous frame */
|
||||
prev_l = fm_last[0];
|
||||
prev_r = fm_last[1];
|
||||
|
||||
/* FM buffer start pointer */
|
||||
ptr = fm_buffer;
|
||||
|
||||
/* flush FM samples */
|
||||
if (config.hq_fm)
|
||||
/* FM chip is enabled ? */
|
||||
if (YM_Update)
|
||||
{
|
||||
/* high-quality Band-Limited synthesis */
|
||||
do
|
||||
int prev_l, prev_r, preamp, time, l, r, *ptr;
|
||||
|
||||
/* Run FM chip until end of frame */
|
||||
fm_update(cycles);
|
||||
|
||||
/* FM output pre-amplification */
|
||||
preamp = config.fm_preamp;
|
||||
|
||||
/* FM frame initial timestamp */
|
||||
time = fm_cycles_start;
|
||||
|
||||
/* Restore last FM outputs from previous frame */
|
||||
prev_l = fm_last[0];
|
||||
prev_r = fm_last[1];
|
||||
|
||||
/* FM buffer start pointer */
|
||||
ptr = fm_buffer;
|
||||
|
||||
/* flush FM samples */
|
||||
if (config.hq_fm)
|
||||
{
|
||||
/* left & right channels */
|
||||
l = ((*ptr++ * preamp) / 100);
|
||||
r = ((*ptr++ * preamp) / 100);
|
||||
blip_add_delta(snd.blips[0], time, l-prev_l, r-prev_r);
|
||||
prev_l = l;
|
||||
prev_r = r;
|
||||
/* high-quality Band-Limited synthesis */
|
||||
do
|
||||
{
|
||||
/* left & right channels */
|
||||
l = ((*ptr++ * preamp) / 100);
|
||||
r = ((*ptr++ * preamp) / 100);
|
||||
blip_add_delta(snd.blips[0], time, l-prev_l, r-prev_r);
|
||||
prev_l = l;
|
||||
prev_r = r;
|
||||
|
||||
/* increment time counter */
|
||||
time += fm_cycles_ratio;
|
||||
/* increment time counter */
|
||||
time += fm_cycles_ratio;
|
||||
}
|
||||
while (time < cycles);
|
||||
}
|
||||
while (time < cycles);
|
||||
}
|
||||
else
|
||||
{
|
||||
/* faster Linear Interpolation */
|
||||
do
|
||||
else
|
||||
{
|
||||
/* left & right channels */
|
||||
l = ((*ptr++ * preamp) / 100);
|
||||
r = ((*ptr++ * preamp) / 100);
|
||||
blip_add_delta_fast(snd.blips[0], time, l-prev_l, r-prev_r);
|
||||
prev_l = l;
|
||||
prev_r = r;
|
||||
/* faster Linear Interpolation */
|
||||
do
|
||||
{
|
||||
/* left & right channels */
|
||||
l = ((*ptr++ * preamp) / 100);
|
||||
r = ((*ptr++ * preamp) / 100);
|
||||
blip_add_delta_fast(snd.blips[0], time, l-prev_l, r-prev_r);
|
||||
prev_l = l;
|
||||
prev_r = r;
|
||||
|
||||
/* increment time counter */
|
||||
time += fm_cycles_ratio;
|
||||
/* increment time counter */
|
||||
time += fm_cycles_ratio;
|
||||
}
|
||||
while (time < cycles);
|
||||
}
|
||||
|
||||
/* reset FM buffer pointer */
|
||||
fm_ptr = fm_buffer;
|
||||
|
||||
/* save last FM output for next frame */
|
||||
fm_last[0] = prev_l;
|
||||
fm_last[1] = prev_r;
|
||||
|
||||
/* adjust FM cycle counters for next frame */
|
||||
fm_cycles_count = fm_cycles_start = time - cycles;
|
||||
if (fm_cycles_busy > cycles)
|
||||
{
|
||||
fm_cycles_busy -= cycles;
|
||||
}
|
||||
else
|
||||
{
|
||||
fm_cycles_busy = 0;
|
||||
}
|
||||
while (time < cycles);
|
||||
}
|
||||
|
||||
/* reset FM buffer pointer */
|
||||
fm_ptr = fm_buffer;
|
||||
|
||||
/* save last FM output for next frame */
|
||||
fm_last[0] = prev_l;
|
||||
fm_last[1] = prev_r;
|
||||
|
||||
/* adjust FM cycle counters for next frame */
|
||||
fm_cycles_count = fm_cycles_start = time - cycles;
|
||||
|
||||
/* end of blip buffer time frame */
|
||||
blip_end_frame(snd.blips[0], cycles);
|
||||
|
||||
@@ -288,7 +394,6 @@ int sound_context_save(uint8 *state)
|
||||
else
|
||||
{
|
||||
bufferptr += YM2612SaveContext(state + sizeof(config.ym3438));
|
||||
YM2612Config(config.dac_bits);
|
||||
}
|
||||
#else
|
||||
bufferptr = YM2612SaveContext(state);
|
||||
@@ -325,11 +430,9 @@ int sound_context_load(uint8 *state)
|
||||
else
|
||||
{
|
||||
bufferptr += YM2612LoadContext(state + sizeof(config_ym3438));
|
||||
YM2612Config(config.dac_bits);
|
||||
}
|
||||
#else
|
||||
bufferptr = YM2612LoadContext(state);
|
||||
YM2612Config(config.dac_bits);
|
||||
#endif
|
||||
}
|
||||
else
|
||||
@@ -344,30 +447,3 @@ int sound_context_load(uint8 *state)
|
||||
|
||||
return bufferptr;
|
||||
}
|
||||
|
||||
void fm_reset(unsigned int cycles)
|
||||
{
|
||||
/* synchronize FM chip with CPU */
|
||||
fm_update(cycles);
|
||||
|
||||
/* reset FM chip */
|
||||
YM_Reset();
|
||||
}
|
||||
|
||||
void fm_write(unsigned int cycles, unsigned int address, unsigned int data)
|
||||
{
|
||||
/* synchronize FM chip with CPU */
|
||||
fm_update(cycles);
|
||||
|
||||
/* write FM register */
|
||||
YM_Write(address, data);
|
||||
}
|
||||
|
||||
unsigned int fm_read(unsigned int cycles, unsigned int address)
|
||||
{
|
||||
/* synchronize FM chip with CPU */
|
||||
fm_update(cycles);
|
||||
|
||||
/* read FM status (YM2612 only) */
|
||||
return YM_Read(address);
|
||||
}
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
* Sound Hardware
|
||||
*
|
||||
* Copyright (C) 1998-2003 Charles Mac Donald (original code)
|
||||
* Copyright (C) 2007-2016 Eke-Eke (Genesis Plus GX)
|
||||
* Copyright (C) 2007-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:
|
||||
@@ -46,8 +46,8 @@ extern void sound_reset(void);
|
||||
extern int sound_context_save(uint8 *state);
|
||||
extern int sound_context_load(uint8 *state);
|
||||
extern int sound_update(unsigned int cycles);
|
||||
extern void fm_reset(unsigned int cycles);
|
||||
extern void fm_write(unsigned int cycles, unsigned int address, unsigned int data);
|
||||
extern unsigned int fm_read(unsigned int cycles, unsigned int address);
|
||||
extern void (*fm_reset)(unsigned int cycles);
|
||||
extern void (*fm_write)(unsigned int cycles, unsigned int address, unsigned int data);
|
||||
extern unsigned int (*fm_read)(unsigned int cycles, unsigned int address);
|
||||
|
||||
#endif /* _SOUND_H_ */
|
||||
|
||||
+111
-47
@@ -15,15 +15,16 @@
|
||||
** Additional info from YM2612 die shot analysis by Sauraen
|
||||
** See http://gendev.spritesmind.net/forum/viewtopic.php?t=386
|
||||
**
|
||||
** TODO:
|
||||
** - better documentation
|
||||
** - BUSY flag emulation
|
||||
** - accurate DAC output
|
||||
*/
|
||||
|
||||
/*
|
||||
** CHANGELOG:
|
||||
**
|
||||
** 03-12-2017 Eke-Eke (Genesis Plus GX):
|
||||
** - improved 9-bit DAC emulation accuracy
|
||||
** - added discrete YM2612 DAC distortion emulation ("ladder effect")
|
||||
** - replaced configurable DAC depth with configurable chip types (discrete, integrated or enhanced)
|
||||
**
|
||||
** 26-09-2017 Eke-Eke (Genesis Plus GX):
|
||||
** - fixed EG counter loopback behavior (verified on YM3438 die)
|
||||
** - reverted changes to EG rates 2-7 increment values
|
||||
@@ -626,8 +627,11 @@ static YM2612 ym2612;
|
||||
/* current chip state */
|
||||
static INT32 m2,c1,c2; /* Phase Modulation input for operators 2,3,4 */
|
||||
static INT32 mem; /* one sample delay memory */
|
||||
static INT32 out_fm[8]; /* outputs of working channels */
|
||||
static UINT32 bitmask; /* working channels output bitmasking (DAC quantization) */
|
||||
static INT32 out_fm[6]; /* outputs of working channels */
|
||||
|
||||
/* chip type */
|
||||
static UINT32 op_mask[8][4]; /* operator output bitmasking (DAC quantization) */
|
||||
static int chip_type = YM2612_DISCRETE;
|
||||
|
||||
|
||||
INLINE void FM_KEYON(FM_CH *CH , int s )
|
||||
@@ -1408,22 +1412,22 @@ INLINE void refresh_fc_eg_chan(FM_CH *CH )
|
||||
|
||||
#define volume_calc(OP) ((OP)->vol_out + (AM & (OP)->AMmask))
|
||||
|
||||
INLINE signed int op_calc(UINT32 phase, unsigned int env, unsigned int pm)
|
||||
INLINE signed int op_calc(UINT32 phase, unsigned int env, unsigned int pm, unsigned int opmask)
|
||||
{
|
||||
UINT32 p = (env<<3) + sin_tab[ ( (phase >> SIN_BITS) + (pm >> 1) ) & SIN_MASK ];
|
||||
|
||||
if (p >= TL_TAB_LEN)
|
||||
return 0;
|
||||
return tl_tab[p];
|
||||
return (tl_tab[p] & opmask);
|
||||
}
|
||||
|
||||
INLINE signed int op_calc1(UINT32 phase, unsigned int env, unsigned int pm)
|
||||
INLINE signed int op_calc1(UINT32 phase, unsigned int env, unsigned int pm, unsigned int opmask)
|
||||
{
|
||||
UINT32 p = (env<<3) + sin_tab[ ( ( phase >> SIN_BITS ) + pm ) & SIN_MASK ];
|
||||
|
||||
if (p >= TL_TAB_LEN)
|
||||
return 0;
|
||||
return tl_tab[p];
|
||||
return (tl_tab[p] & opmask);
|
||||
}
|
||||
|
||||
INLINE void chan_calc(FM_CH *CH, int num)
|
||||
@@ -1433,6 +1437,7 @@ INLINE void chan_calc(FM_CH *CH, int num)
|
||||
INT32 out = 0;
|
||||
UINT32 AM = ym2612.OPN.LFO_AM >> CH->ams;
|
||||
unsigned int eg_out = volume_calc(&CH->SLOT[SLOT1]);
|
||||
UINT32 *mask = op_mask[CH->ALGO];
|
||||
|
||||
m2 = c1 = c2 = mem = 0;
|
||||
|
||||
@@ -1443,7 +1448,7 @@ INLINE void chan_calc(FM_CH *CH, int num)
|
||||
if (CH->FB < SIN_BITS)
|
||||
out = (CH->op1_out[0] + CH->op1_out[1]) >> CH->FB;
|
||||
|
||||
out = op_calc1(CH->SLOT[SLOT1].phase, eg_out, out );
|
||||
out = op_calc1(CH->SLOT[SLOT1].phase, eg_out, out, mask[0]);
|
||||
}
|
||||
|
||||
CH->op1_out[0] = CH->op1_out[1];
|
||||
@@ -1459,22 +1464,21 @@ INLINE void chan_calc(FM_CH *CH, int num)
|
||||
|
||||
eg_out = volume_calc(&CH->SLOT[SLOT3]);
|
||||
if( eg_out < ENV_QUIET ) /* SLOT 3 */
|
||||
*CH->connect3 += op_calc(CH->SLOT[SLOT3].phase, eg_out, m2);
|
||||
*CH->connect3 += op_calc(CH->SLOT[SLOT3].phase, eg_out, m2, mask[2]);
|
||||
|
||||
eg_out = volume_calc(&CH->SLOT[SLOT2]);
|
||||
if( eg_out < ENV_QUIET ) /* SLOT 2 */
|
||||
*CH->connect2 += op_calc(CH->SLOT[SLOT2].phase, eg_out, c1);
|
||||
*CH->connect2 += op_calc(CH->SLOT[SLOT2].phase, eg_out, c1, mask[1]);
|
||||
|
||||
eg_out = volume_calc(&CH->SLOT[SLOT4]);
|
||||
if( eg_out < ENV_QUIET ) /* SLOT 4 */
|
||||
*CH->connect4 += op_calc(CH->SLOT[SLOT4].phase, eg_out, c2);
|
||||
|
||||
*CH->connect4 += op_calc(CH->SLOT[SLOT4].phase, eg_out, c2, mask[3]);
|
||||
|
||||
/* store current MEM */
|
||||
CH->mem_value = mem;
|
||||
|
||||
/* update phase counters AFTER output calculations */
|
||||
if(CH->pms)
|
||||
if (CH->pms)
|
||||
{
|
||||
/* 3-slot mode */
|
||||
if ((ym2612.OPN.ST.mode & 0xC0) && (CH == &ym2612.CH[2]))
|
||||
@@ -1515,7 +1519,7 @@ INLINE void OPNWriteMode(int r, int v)
|
||||
case 0x21: /* Test */
|
||||
break;
|
||||
|
||||
case 0x22: /* LFO FREQ (YM2608/YM2610/YM2610B/ym2612) */
|
||||
case 0x22: /* LFO FREQ */
|
||||
if (v&8) /* LFO enabled ? */
|
||||
{
|
||||
ym2612.OPN.lfo_timer_overflow = lfo_samples_per_step[v&7];
|
||||
@@ -1550,7 +1554,6 @@ INLINE void OPNWriteMode(int r, int v)
|
||||
if( c == 3 ) break;
|
||||
if (v&0x04) c+=3; /* CH 4-6 */
|
||||
CH = &ym2612.CH[c];
|
||||
|
||||
if (v&0x10) FM_KEYON(CH,SLOT1); else FM_KEYOFF(CH,SLOT1);
|
||||
if (v&0x20) FM_KEYON(CH,SLOT2); else FM_KEYOFF(CH,SLOT2);
|
||||
if (v&0x40) FM_KEYON(CH,SLOT3); else FM_KEYOFF(CH,SLOT3);
|
||||
@@ -1686,8 +1689,6 @@ INLINE void OPNWriteReg(int r, int v)
|
||||
That is not necessary, but then EG will be generating Attack phase.
|
||||
|
||||
*/
|
||||
|
||||
|
||||
break;
|
||||
|
||||
case 0xa0:
|
||||
@@ -1722,7 +1723,7 @@ INLINE void OPNWriteReg(int r, int v)
|
||||
ym2612.OPN.SL3.block_fnum[c] = (blk<<11) | fn;
|
||||
ym2612.CH[2].SLOT[SLOT1].Incr=-1;
|
||||
}
|
||||
break;
|
||||
break;
|
||||
case 3: /* 0xac-0xae : 3CH FNUM2,BLK */
|
||||
if(r < 0x100)
|
||||
ym2612.OPN.SL3.fn_h = v&0x3f;
|
||||
@@ -1737,7 +1738,7 @@ INLINE void OPNWriteReg(int r, int v)
|
||||
CH->ALGO = v&7;
|
||||
CH->FB = SIN_BITS - ((v>>3)&7);
|
||||
setup_connection( CH, c );
|
||||
break;
|
||||
break;
|
||||
}
|
||||
case 1: /* 0xb4-0xb6 : L , R , AMS , PMS */
|
||||
/* b0-2 PMS */
|
||||
@@ -1747,8 +1748,8 @@ INLINE void OPNWriteReg(int r, int v)
|
||||
CH->ams = lfo_ams_depth_shift[(v>>4) & 0x03];
|
||||
|
||||
/* PAN : b7 = L, b6 = R */
|
||||
ym2612.OPN.pan[ c*2 ] = (v & 0x80) ? bitmask : 0;
|
||||
ym2612.OPN.pan[ c*2+1 ] = (v & 0x40) ? bitmask : 0;
|
||||
ym2612.OPN.pan[ c*2 ] = (v & 0x80) ? 0xffffffff : 0;
|
||||
ym2612.OPN.pan[ c*2+1 ] = (v & 0x40) ? 0xffffffff : 0;
|
||||
break;
|
||||
}
|
||||
break;
|
||||
@@ -1884,6 +1885,15 @@ static void init_tables(void)
|
||||
}
|
||||
}
|
||||
|
||||
/* build default OP mask table */
|
||||
for (i = 0;i < 8;i++)
|
||||
{
|
||||
for (d = 0;d < 4;d++)
|
||||
{
|
||||
op_mask[i][d] = 0xffffffff;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
@@ -1984,9 +1994,9 @@ void YM2612Write(unsigned int a, unsigned int v)
|
||||
}
|
||||
}
|
||||
|
||||
unsigned int YM2612Read(unsigned int a)
|
||||
unsigned int YM2612Read(void)
|
||||
{
|
||||
return ym2612.OPN.ST.status & 0xff;
|
||||
return ym2612.OPN.ST.status;
|
||||
}
|
||||
|
||||
/* Generate samples for ym2612 */
|
||||
@@ -2020,7 +2030,7 @@ void YM2612Update(int *buffer, int length)
|
||||
refresh_fc_eg_chan(&ym2612.CH[5]);
|
||||
|
||||
/* buffering */
|
||||
for(i=0; i<length ; i++)
|
||||
for(i=0; i<length; i++)
|
||||
{
|
||||
/* clear outputs */
|
||||
out_fm[0] = 0;
|
||||
@@ -2066,21 +2076,21 @@ void YM2612Update(int *buffer, int length)
|
||||
advance_eg_channels(&ym2612.CH[0], ym2612.OPN.eg_cnt);
|
||||
}
|
||||
|
||||
/* 14-bit accumulator channels outputs (range is -8192;+8192) */
|
||||
if (out_fm[0] > 8192) out_fm[0] = 8192;
|
||||
/* channels accumulator output clipping (14-bit max) */
|
||||
if (out_fm[0] > 8191) out_fm[0] = 8191;
|
||||
else if (out_fm[0] < -8192) out_fm[0] = -8192;
|
||||
if (out_fm[1] > 8192) out_fm[1] = 8192;
|
||||
if (out_fm[1] > 8191) out_fm[1] = 8191;
|
||||
else if (out_fm[1] < -8192) out_fm[1] = -8192;
|
||||
if (out_fm[2] > 8192) out_fm[2] = 8192;
|
||||
if (out_fm[2] > 8191) out_fm[2] = 8191;
|
||||
else if (out_fm[2] < -8192) out_fm[2] = -8192;
|
||||
if (out_fm[3] > 8192) out_fm[3] = 8192;
|
||||
if (out_fm[3] > 8191) out_fm[3] = 8191;
|
||||
else if (out_fm[3] < -8192) out_fm[3] = -8192;
|
||||
if (out_fm[4] > 8192) out_fm[4] = 8192;
|
||||
if (out_fm[4] > 8191) out_fm[4] = 8191;
|
||||
else if (out_fm[4] < -8192) out_fm[4] = -8192;
|
||||
if (out_fm[5] > 8192) out_fm[5] = 8192;
|
||||
if (out_fm[5] > 8191) out_fm[5] = 8191;
|
||||
else if (out_fm[5] < -8192) out_fm[5] = -8192;
|
||||
|
||||
/* stereo DAC channels outputs mixing */
|
||||
/* stereo DAC output panning & mixing */
|
||||
lt = ((out_fm[0]) & ym2612.OPN.pan[0]);
|
||||
rt = ((out_fm[0]) & ym2612.OPN.pan[1]);
|
||||
lt += ((out_fm[1]) & ym2612.OPN.pan[2]);
|
||||
@@ -2094,11 +2104,34 @@ void YM2612Update(int *buffer, int length)
|
||||
lt += ((out_fm[5]) & ym2612.OPN.pan[10]);
|
||||
rt += ((out_fm[5]) & ym2612.OPN.pan[11]);
|
||||
|
||||
/* discrete YM2612 DAC */
|
||||
if (chip_type == YM2612_DISCRETE)
|
||||
{
|
||||
int i;
|
||||
|
||||
/* DAC 'ladder effect' */
|
||||
for (i=0; i<6; i++)
|
||||
{
|
||||
if (out_fm[i] < 0)
|
||||
{
|
||||
/* -4 offset (-3 when not muted) on negative channel output (9-bit) */
|
||||
lt -= ((4 - (ym2612.OPN.pan[(2*i)+0] & 1)) << 5);
|
||||
rt -= ((4 - (ym2612.OPN.pan[(2*i)+1] & 1)) << 5);
|
||||
}
|
||||
else
|
||||
{
|
||||
/* +4 offset (when muted or not) on positive channel output (9-bit) */
|
||||
lt += (4 << 5);
|
||||
rt += (4 << 5);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* buffering */
|
||||
*buffer++ = lt;
|
||||
*buffer++ = rt;
|
||||
|
||||
/* CSM mode: if CSM Key ON has occured, CSM Key OFF need to be sent */
|
||||
/* CSM mode: if CSM Key ON has occurred, CSM Key OFF need to be sent */
|
||||
/* only if Timer A does not overflow again (i.e CSM Key ON not set again) */
|
||||
ym2612.OPN.SL3.key_csm <<= 1;
|
||||
|
||||
@@ -2121,20 +2154,51 @@ void YM2612Update(int *buffer, int length)
|
||||
INTERNAL_TIMER_B(length);
|
||||
}
|
||||
|
||||
void YM2612Config(unsigned char dac_bits)
|
||||
void YM2612Config(int type)
|
||||
{
|
||||
int i;
|
||||
/* YM2612 chip type */
|
||||
chip_type = type;
|
||||
|
||||
/* DAC precision (normally 9-bit on real hardware, implemented through simple 14-bit channel output bitmasking) */
|
||||
bitmask = ~((1 << (TL_BITS - dac_bits)) - 1);
|
||||
|
||||
/* update L/R panning bitmasks */
|
||||
for (i=0; i<2*6; i++)
|
||||
/* carrier operator outputs bitmask */
|
||||
if (chip_type < YM2612_ENHANCED)
|
||||
{
|
||||
if (ym2612.OPN.pan[i])
|
||||
{
|
||||
ym2612.OPN.pan[i] = bitmask;
|
||||
}
|
||||
/* 9-bit DAC */
|
||||
op_mask[0][3] = 0xffffffe0;
|
||||
op_mask[1][3] = 0xffffffe0;
|
||||
op_mask[2][3] = 0xffffffe0;
|
||||
op_mask[3][3] = 0xffffffe0;
|
||||
op_mask[4][1] = 0xffffffe0;
|
||||
op_mask[4][3] = 0xffffffe0;
|
||||
op_mask[5][1] = 0xffffffe0;
|
||||
op_mask[5][2] = 0xffffffe0;
|
||||
op_mask[5][3] = 0xffffffe0;
|
||||
op_mask[6][1] = 0xffffffe0;
|
||||
op_mask[6][2] = 0xffffffe0;
|
||||
op_mask[6][3] = 0xffffffe0;
|
||||
op_mask[7][0] = 0xffffffe0;
|
||||
op_mask[7][1] = 0xffffffe0;
|
||||
op_mask[7][2] = 0xffffffe0;
|
||||
op_mask[7][3] = 0xffffffe0;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* 14-bit DAC */
|
||||
op_mask[0][3] = 0xffffffff;
|
||||
op_mask[1][3] = 0xffffffff;
|
||||
op_mask[2][3] = 0xffffffff;
|
||||
op_mask[3][3] = 0xffffffff;
|
||||
op_mask[4][1] = 0xffffffff;
|
||||
op_mask[4][3] = 0xffffffff;
|
||||
op_mask[5][1] = 0xffffffff;
|
||||
op_mask[5][2] = 0xffffffff;
|
||||
op_mask[5][3] = 0xffffffff;
|
||||
op_mask[6][1] = 0xffffffff;
|
||||
op_mask[6][2] = 0xffffffff;
|
||||
op_mask[6][3] = 0xffffffff;
|
||||
op_mask[7][0] = 0xffffffff;
|
||||
op_mask[7][1] = 0xffffffff;
|
||||
op_mask[7][2] = 0xffffffff;
|
||||
op_mask[7][3] = 0xffffffff;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -16,12 +16,18 @@
|
||||
#ifndef _H_YM2612_
|
||||
#define _H_YM2612_
|
||||
|
||||
enum {
|
||||
YM2612_DISCRETE = 0,
|
||||
YM2612_INTEGRATED,
|
||||
YM2612_ENHANCED
|
||||
};
|
||||
|
||||
extern void YM2612Init(void);
|
||||
extern void YM2612Config(unsigned char dac_bits);
|
||||
extern void YM2612Config(int type);
|
||||
extern void YM2612ResetChip(void);
|
||||
extern void YM2612Update(int *buffer, int length);
|
||||
extern void YM2612Write(unsigned int a, unsigned int v);
|
||||
extern unsigned int YM2612Read(unsigned int a);
|
||||
extern unsigned int YM2612Read(void);
|
||||
extern int YM2612LoadContext(unsigned char *state);
|
||||
extern int YM2612SaveContext(unsigned char *state);
|
||||
|
||||
|
||||
@@ -40,7 +40,7 @@
|
||||
* OPLx decapsulated(Matthew Gambrell, Olli Niemitalo):
|
||||
* OPL2 ROMs.
|
||||
*
|
||||
* version: 1.0.7
|
||||
* version: 1.0.8
|
||||
*/
|
||||
|
||||
#include <string.h>
|
||||
@@ -233,7 +233,7 @@ static const Bit32u fm_algorithm[4][6][8] = {
|
||||
}
|
||||
};
|
||||
|
||||
static Bit32u chip_type = ym3438_type_discrete;
|
||||
static Bit32u chip_type = ym3438_mode_readmode;
|
||||
|
||||
void OPN2_DoIO(ym3438_t *chip)
|
||||
{
|
||||
@@ -995,7 +995,7 @@ void OPN2_ChOutput(ym3438_t *chip)
|
||||
chip->mol = 0;
|
||||
chip->mor = 0;
|
||||
|
||||
if (chip_type == ym3438_type_ym2612)
|
||||
if (chip_type & ym3438_mode_ym2612)
|
||||
{
|
||||
out_en = ((cycles & 3) == 3) || test_dac;
|
||||
/* YM2612 DAC emulation(not verified) */
|
||||
@@ -1028,11 +1028,6 @@ void OPN2_ChOutput(ym3438_t *chip)
|
||||
else
|
||||
{
|
||||
out_en = ((cycles & 3) != 0) || test_dac;
|
||||
/* Discrete YM3438 seems has the ladder effect too */
|
||||
if (out >= 0 && chip_type == ym3438_type_discrete)
|
||||
{
|
||||
out++;
|
||||
}
|
||||
if (chip->ch_lock_l && out_en)
|
||||
{
|
||||
chip->mol = out;
|
||||
@@ -1223,7 +1218,7 @@ void OPN2_SetChipType(Bit32u type)
|
||||
chip_type = type;
|
||||
}
|
||||
|
||||
void OPN2_Clock(ym3438_t *chip, Bit32u *buffer)
|
||||
void OPN2_Clock(ym3438_t *chip, Bit16s *buffer)
|
||||
{
|
||||
chip->lfo_inc = chip->mode_test_21[1];
|
||||
chip->pg_read >>= 1;
|
||||
@@ -1355,6 +1350,9 @@ void OPN2_Clock(ym3438_t *chip, Bit32u *buffer)
|
||||
|
||||
buffer[0] = chip->mol;
|
||||
buffer[1] = chip->mor;
|
||||
|
||||
if (chip->status_time)
|
||||
chip->status_time--;
|
||||
}
|
||||
|
||||
void OPN2_Write(ym3438_t *chip, Bit32u port, Bit8u data)
|
||||
@@ -1394,7 +1392,7 @@ Bit32u OPN2_ReadIRQPin(ym3438_t *chip)
|
||||
|
||||
Bit8u OPN2_Read(ym3438_t *chip, Bit32u port)
|
||||
{
|
||||
if ((port & 3) == 0 || chip_type == ym3438_type_asic)
|
||||
if ((port & 3) == 0 || (chip_type & ym3438_mode_readmode))
|
||||
{
|
||||
if (chip->mode_test_21[6])
|
||||
{
|
||||
@@ -1411,18 +1409,30 @@ Bit8u OPN2_Read(ym3438_t *chip, Bit32u port)
|
||||
}
|
||||
if (chip->mode_test_21[7])
|
||||
{
|
||||
return testdata & 0xff;
|
||||
chip->status = testdata & 0xff;
|
||||
}
|
||||
else
|
||||
{
|
||||
return testdata >> 8;
|
||||
chip->status = testdata >> 8;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
return (chip->busy << 7) | (chip->timer_b_overflow_flag << 1)
|
||||
chip->status = (chip->busy << 7) | (chip->timer_b_overflow_flag << 1)
|
||||
| chip->timer_a_overflow_flag;
|
||||
}
|
||||
if (chip_type & ym3438_mode_ym2612)
|
||||
{
|
||||
chip->status_time = 300000;
|
||||
}
|
||||
else
|
||||
{
|
||||
chip->status_time = 40000000;
|
||||
}
|
||||
}
|
||||
if (chip->status_time)
|
||||
{
|
||||
return chip->status;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -39,16 +39,15 @@
|
||||
* OPLx decapsulated(Matthew Gambrell, Olli Niemitalo):
|
||||
* OPL2 ROMs.
|
||||
*
|
||||
* version: 1.0.7
|
||||
* version: 1.0.8
|
||||
*/
|
||||
|
||||
#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) */
|
||||
ym3438_mode_ym2612 = 0x01, /* Enables YM2612 emulation (MD1, MD2 VA2) */
|
||||
ym3438_mode_readmode = 0x02, /* Enables status read on any port (TeraDrive, MD1 VA7, MD2, etc) */
|
||||
};
|
||||
|
||||
#include <stdint.h>
|
||||
@@ -205,11 +204,13 @@ typedef struct
|
||||
Bit8u pan_l[6], pan_r[6];
|
||||
Bit8u ams[6];
|
||||
Bit8u pms[6];
|
||||
Bit8u status;
|
||||
Bit32u status_time;
|
||||
} ym3438_t;
|
||||
|
||||
void OPN2_Reset(ym3438_t *chip);
|
||||
void OPN2_SetChipType(Bit32u type);
|
||||
void OPN2_Clock(ym3438_t *chip, Bit32u *buffer);
|
||||
void OPN2_Clock(ym3438_t *chip, Bit16s *buffer);
|
||||
void OPN2_Write(ym3438_t *chip, Bit32u port, Bit8u data);
|
||||
void OPN2_SetTestPin(ym3438_t *chip, Bit32u value);
|
||||
Bit32u OPN2_ReadTestPin(ym3438_t *chip);
|
||||
|
||||
@@ -5,7 +5,7 @@
|
||||
* Support for 16-bit & 8-bit hardware modes
|
||||
*
|
||||
* Copyright (C) 1998-2003 Charles Mac Donald (original code)
|
||||
* Copyright (C) 2007-2017 Eke-Eke (Genesis Plus GX)
|
||||
* Copyright (C) 2007-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:
|
||||
@@ -467,10 +467,6 @@ void system_frame_gen(int do_skip)
|
||||
{
|
||||
z80_run(788);
|
||||
}
|
||||
else
|
||||
{
|
||||
Z80.cycles = 788;
|
||||
}
|
||||
|
||||
/* set VINT flag */
|
||||
status |= 0x80;
|
||||
@@ -493,10 +489,6 @@ void system_frame_gen(int do_skip)
|
||||
{
|
||||
z80_run(MCYCLES_PER_LINE);
|
||||
}
|
||||
else
|
||||
{
|
||||
Z80.cycles = MCYCLES_PER_LINE;
|
||||
}
|
||||
|
||||
/* Z80 interrupt is cleared at the end of the line */
|
||||
Z80.irq_state = CLEAR_LINE;
|
||||
@@ -538,10 +530,6 @@ void system_frame_gen(int do_skip)
|
||||
{
|
||||
z80_run(mcycles_vdp + MCYCLES_PER_LINE);
|
||||
}
|
||||
else
|
||||
{
|
||||
Z80.cycles = mcycles_vdp + MCYCLES_PER_LINE;
|
||||
}
|
||||
|
||||
/* run SVP chip */
|
||||
if (svp)
|
||||
@@ -590,10 +578,6 @@ void system_frame_gen(int do_skip)
|
||||
{
|
||||
z80_run(mcycles_vdp + MCYCLES_PER_LINE);
|
||||
}
|
||||
else
|
||||
{
|
||||
Z80.cycles = mcycles_vdp + MCYCLES_PER_LINE;
|
||||
}
|
||||
|
||||
/* run SVP chip */
|
||||
if (svp)
|
||||
@@ -654,10 +638,6 @@ void system_frame_gen(int do_skip)
|
||||
{
|
||||
z80_run(mcycles_vdp + MCYCLES_PER_LINE);
|
||||
}
|
||||
else
|
||||
{
|
||||
Z80.cycles = mcycles_vdp + MCYCLES_PER_LINE;
|
||||
}
|
||||
|
||||
/* run SVP chip */
|
||||
if (svp)
|
||||
@@ -826,10 +806,6 @@ void system_frame_scd(int do_skip)
|
||||
{
|
||||
z80_run(788);
|
||||
}
|
||||
else
|
||||
{
|
||||
Z80.cycles = 788;
|
||||
}
|
||||
|
||||
/* set VINT flag */
|
||||
status |= 0x80;
|
||||
@@ -854,10 +830,6 @@ void system_frame_scd(int do_skip)
|
||||
{
|
||||
z80_run(MCYCLES_PER_LINE);
|
||||
}
|
||||
else
|
||||
{
|
||||
Z80.cycles = MCYCLES_PER_LINE;
|
||||
}
|
||||
|
||||
/* Z80 interrupt is cleared at the end of the line */
|
||||
Z80.irq_state = CLEAR_LINE;
|
||||
@@ -895,10 +867,6 @@ void system_frame_scd(int do_skip)
|
||||
{
|
||||
z80_run(mcycles_vdp + MCYCLES_PER_LINE);
|
||||
}
|
||||
else
|
||||
{
|
||||
Z80.cycles = mcycles_vdp + MCYCLES_PER_LINE;
|
||||
}
|
||||
|
||||
/* update VDP cycle count */
|
||||
mcycles_vdp += MCYCLES_PER_LINE;
|
||||
@@ -943,10 +911,6 @@ void system_frame_scd(int do_skip)
|
||||
{
|
||||
z80_run(mcycles_vdp + MCYCLES_PER_LINE);
|
||||
}
|
||||
else
|
||||
{
|
||||
Z80.cycles = mcycles_vdp + MCYCLES_PER_LINE;
|
||||
}
|
||||
|
||||
/* update VDP cycle count */
|
||||
mcycles_vdp += MCYCLES_PER_LINE;
|
||||
@@ -1003,10 +967,6 @@ void system_frame_scd(int do_skip)
|
||||
{
|
||||
z80_run(mcycles_vdp + MCYCLES_PER_LINE);
|
||||
}
|
||||
else
|
||||
{
|
||||
Z80.cycles = mcycles_vdp + MCYCLES_PER_LINE;
|
||||
}
|
||||
|
||||
/* update VDP cycle count */
|
||||
mcycles_vdp += MCYCLES_PER_LINE;
|
||||
|
||||
@@ -5,7 +5,7 @@
|
||||
* Support for 16-bit & 8-bit hardware modes
|
||||
*
|
||||
* Copyright (C) 1998-2003 Charles Mac Donald (original code)
|
||||
* Copyright (C) 2007-2017 Eke-Eke (Genesis Plus GX)
|
||||
* Copyright (C) 2007-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:
|
||||
|
||||
Reference in New Issue
Block a user