make the flags option actually work

This commit is contained in:
tildearrow 2022-01-29 00:20:27 -05:00
parent 44649e3ce4
commit b6da7871d4
19 changed files with 208 additions and 68 deletions

View File

@ -242,7 +242,7 @@ void DivPlatformAmiga::notifyInsDeletion(void* ins) {
}
void DivPlatformAmiga::setFlags(unsigned int flags) {
if (flags) {
if (flags&1) {
chipClock=COLOR_PAL*4.0/5.0;
} else {
chipClock=COLOR_NTSC;

View File

@ -202,15 +202,15 @@ void DivPlatformArcade::tick() {
if (chan[i].std.hadArp) {
if (!chan[i].inPorta) {
if (chan[i].std.arpMode) {
chan[i].baseFreq=chan[i].std.arp<<6;
chan[i].baseFreq=(chan[i].std.arp<<6)+baseFreqOff;
} else {
chan[i].baseFreq=(chan[i].note+(signed char)chan[i].std.arp)<<6;
chan[i].baseFreq=((chan[i].note+(signed char)chan[i].std.arp)<<6)+baseFreqOff;
}
}
chan[i].freqChanged=true;
} else {
if (chan[i].std.arpMode && chan[i].std.finishedArp) {
chan[i].baseFreq=chan[i].note<<6;
chan[i].baseFreq=(chan[i].note<<6)+baseFreqOff;
chan[i].freqChanged=true;
}
}
@ -368,7 +368,7 @@ int DivPlatformArcade::dispatch(DivCommand c) {
break;
}
chan[c.chan].pcm.pos=0;
chan[c.chan].baseFreq=c.value<<6;
chan[c.chan].baseFreq=(c.value<<6)+baseFreqOff;
chan[c.chan].freqChanged=true;
chan[c.chan].furnacePCM=true;
if (dumpWrites) { // Sega PCM writes
@ -458,7 +458,7 @@ int DivPlatformArcade::dispatch(DivCommand c) {
chan[c.chan].insChanged=false;
if (c.value!=DIV_NOTE_NULL) {
chan[c.chan].baseFreq=c.value<<6;
chan[c.chan].baseFreq=(c.value<<6)+baseFreqOff;
chan[c.chan].note=c.value;
chan[c.chan].freqChanged=true;
}
@ -537,7 +537,7 @@ int DivPlatformArcade::dispatch(DivCommand c) {
break;
}
case DIV_CMD_NOTE_PORTA: {
int destFreq=c.value2<<6;
int destFreq=(c.value2<<6)+baseFreqOff;
int newFreq;
bool return2=false;
if (destFreq>chan[c.chan].baseFreq) {
@ -562,7 +562,7 @@ int DivPlatformArcade::dispatch(DivCommand c) {
break;
}
case DIV_CMD_LEGATO: {
chan[c.chan].baseFreq=c.value<<6;
chan[c.chan].baseFreq=(c.value<<6)+baseFreqOff;
chan[c.chan].freqChanged=true;
break;
}
@ -754,6 +754,24 @@ void DivPlatformArcade::reset() {
extMode=false;
}
void DivPlatformArcade::setFlags(unsigned int flags) {
if (flags==2) {
chipClock=4000000.0;
baseFreqOff=-122;
} else if (flags==1) {
chipClock=COLOR_PAL*4.0/5.0;
baseFreqOff=12;
} else {
chipClock=COLOR_NTSC;
baseFreqOff=0;
}
if (useYMFM) {
rate=chipClock/64;
} else {
rate=chipClock/8;
}
}
bool DivPlatformArcade::isStereo() {
return true;
}
@ -769,12 +787,8 @@ int DivPlatformArcade::init(DivEngine* p, int channels, int sugRate, unsigned in
for (int i=0; i<13; i++) {
isMuted[i]=false;
}
if (useYMFM) {
rate=447443/8;
fm_ymfm=new ymfm::ym2151(iface);
} else {
rate=447443;
}
setFlags(flags);
if (useYMFM) fm_ymfm=new ymfm::ym2151(iface);
reset();
return 13;

View File

@ -42,7 +42,7 @@ class DivPlatformArcade: public DivDispatch {
};
std::queue<QueuedWrite> writes;
opm_t fm;
int delay;
int delay, baseFreqOff;
int pcmL, pcmR, pcmCycles;
unsigned char sampleBank;
unsigned char lastBusy;
@ -76,6 +76,7 @@ class DivPlatformArcade: public DivDispatch {
void tick();
void muteChannel(int ch, bool mute);
void notifyInsChange(int ins);
void setFlags(unsigned int flags);
bool isStereo();
void setYMFM(bool use);
int init(DivEngine* parent, int channels, int sugRate, unsigned int flags);

View File

@ -24,8 +24,21 @@ void DivPlatformAY8910::acquire(short* bufL, short* bufR, size_t start, size_t l
writes.pop();
}
ay->sound_stream_update(ayBuf,len);
for (size_t i=0; i<len; i++) {
bufL[i+start]=ayBuf[0][i]+ayBuf[1][i]+ayBuf[2][i];
if (sunsoft) {
for (size_t i=0; i<len; i++) {
bufL[i+start]=ayBuf[0][i];
bufR[i+start]=bufL[i+start];
}
} else if (stereo) {
for (size_t i=0; i<len; i++) {
bufL[i+start]=ayBuf[0][i]+ayBuf[1][i];
bufR[i+start]=ayBuf[1][i]+ayBuf[2][i];
}
} else {
for (size_t i=0; i<len; i++) {
bufL[i+start]=ayBuf[0][i]+ayBuf[1][i]+ayBuf[2][i];
bufR[i+start]=bufL[i+start];
}
}
}
@ -342,7 +355,7 @@ void DivPlatformAY8910::reset() {
}
bool DivPlatformAY8910::isStereo() {
return false;
return true;
}
bool DivPlatformAY8910::keyOffAffectsArp(int ch) {
@ -356,12 +369,55 @@ void DivPlatformAY8910::notifyInsDeletion(void* ins) {
}
void DivPlatformAY8910::setFlags(unsigned int flags) {
if (flags) {
chipClock=COLOR_PAL*2.0/5.0;
} else {
chipClock=COLOR_NTSC/2.0;
switch (flags&15) {
case 1:
chipClock=COLOR_PAL*2.0/5.0;
break;
case 2:
chipClock=1750000;
break;
case 3:
chipClock=2000000;
break;
case 4:
chipClock=1500000;
break;
case 5:
chipClock=1000000;
break;
case 6:
chipClock=COLOR_NTSC/4.0;
break;
case 7:
chipClock=COLOR_PAL*3.0/8.0;
break;
case 8:
chipClock=COLOR_PAL*3.0/16.0;
break;
default:
chipClock=COLOR_NTSC/2.0;
break;
}
rate=chipClock/8;
if (ay!=NULL) delete ay;
switch ((flags>>4)&3) {
case 1:
ay=new ym2149_device(rate);
sunsoft=false;
break;
case 2:
ay=new sunsoft_5b_sound_device(rate);
sunsoft=true;
break;
default:
ay=new ay8910_device(rate);
sunsoft=false;
break;
}
ay->device_start();
stereo=flags>>6;
}
int DivPlatformAY8910::init(DivEngine* p, int channels, int sugRate, unsigned int flags) {
@ -371,10 +427,8 @@ int DivPlatformAY8910::init(DivEngine* p, int channels, int sugRate, unsigned in
for (int i=0; i<3; i++) {
isMuted[i]=false;
}
ay=NULL;
setFlags(flags);
ay=new ay8910_device(rate);
ay->set_psg_type(ay8910_device::PSG_TYPE_AY);
ay->device_start();
ayBufLen=65536;
for (int i=0; i<3; i++) ayBuf[i]=new short[ayBufLen];
reset();
@ -383,5 +437,5 @@ int DivPlatformAY8910::init(DivEngine* p, int channels, int sugRate, unsigned in
void DivPlatformAY8910::quit() {
for (int i=0; i<3; i++) delete[] ayBuf[i];
delete ay;
if (ay!=NULL) delete ay;
}

View File

@ -40,6 +40,7 @@ class DivPlatformAY8910: public DivDispatch {
int delay;
bool extMode;
bool stereo, sunsoft;
short oldWrites[16];
short pendingWrites[16];

View File

@ -33,8 +33,16 @@ void DivPlatformAY8930::acquire(short* bufL, short* bufR, size_t start, size_t l
writes.pop();
}
ay->sound_stream_update(ayBuf,len);
for (size_t i=0; i<len; i++) {
bufL[i+start]=ayBuf[0][i]+ayBuf[1][i]+ayBuf[2][i];
if (stereo) {
for (size_t i=0; i<len; i++) {
bufL[i+start]=ayBuf[0][i]+ayBuf[1][i];
bufR[i+start]=ayBuf[1][i]+ayBuf[2][i];
}
} else {
for (size_t i=0; i<len; i++) {
bufL[i+start]=ayBuf[0][i]+ayBuf[1][i]+ayBuf[2][i];
bufR[i+start]=bufL[i+start];
}
}
}
@ -377,7 +385,7 @@ void DivPlatformAY8930::reset() {
}
bool DivPlatformAY8930::isStereo() {
return false;
return true;
}
bool DivPlatformAY8930::keyOffAffectsArp(int ch) {
@ -391,12 +399,37 @@ void DivPlatformAY8930::notifyInsDeletion(void* ins) {
}
void DivPlatformAY8930::setFlags(unsigned int flags) {
if (flags) {
chipClock=COLOR_PAL*2.0/5.0;
} else {
chipClock=COLOR_NTSC/2.0;
switch (flags&15) {
case 1:
chipClock=COLOR_PAL*2.0/5.0;
break;
case 2:
chipClock=1750000;
break;
case 3:
chipClock=2000000;
break;
case 4:
chipClock=1500000;
break;
case 5:
chipClock=1000000;
break;
case 6:
chipClock=COLOR_NTSC/4.0;
break;
case 7:
chipClock=COLOR_PAL*3.0/8.0;
break;
case 8:
chipClock=COLOR_PAL*3.0/16.0;
break;
default:
chipClock=COLOR_NTSC/2.0;
break;
}
rate=chipClock/8;
stereo=flags>>6;
}
int DivPlatformAY8930::init(DivEngine* p, int channels, int sugRate, unsigned int flags) {

View File

@ -33,7 +33,7 @@ class DivPlatformAY8930: public DivDispatch {
int delay;
bool extMode;
bool extMode, stereo;
short oldWrites[32];
short pendingWrites[32];

View File

@ -356,7 +356,7 @@ void DivPlatformC64::setChipModel(bool is6581) {
}
void DivPlatformC64::setFlags(unsigned int flags) {
if (flags) {
if (flags&1) {
rate=COLOR_PAL*2.0/9.0;
} else {
rate=COLOR_NTSC*2.0/7.0;

View File

@ -639,12 +639,14 @@ void DivPlatformGenesis::notifyInsDeletion(void* ins) {
}
void DivPlatformGenesis::setFlags(unsigned int flags) {
if (flags) {
if (flags==2) {
chipClock=8000000.0;
} else if (flags==1) {
chipClock=COLOR_PAL*12.0/7.0;
} else {
chipClock=COLOR_NTSC*15.0/7.0;
}
psg.setFlags(flags);
psg.setFlags(flags==1);
rate=chipClock/36;
}
@ -655,9 +657,8 @@ int DivPlatformGenesis::init(DivEngine* p, int channels, int sugRate, unsigned i
for (int i=0; i<10; i++) {
isMuted[i]=false;
}
psg.init(p,4,sugRate,flags==1);
setFlags(flags);
// PSG
psg.init(p,4,sugRate,flags);
reset();
return 10;

View File

@ -375,11 +375,15 @@ bool DivPlatformNES::keyOffAffectsArp(int ch) {
}
void DivPlatformNES::setFlags(unsigned int flags) {
if (flags) {
if (flags==2) { // Dendy
rate=COLOR_PAL*2.0/5.0;
apuType=2;
nes->apu.type=apuType;
} else if (flags==1) { // PAL
rate=COLOR_PAL*3.0/8.0;
apuType=1;
nes->apu.type=apuType;
} else {
} else { // NTSC
rate=COLOR_NTSC/2.0;
apuType=0;
nes->apu.type=apuType;

View File

@ -397,7 +397,7 @@ void DivPlatformPCE::notifyInsDeletion(void* ins) {
}
void DivPlatformPCE::setFlags(unsigned int flags) {
if (flags) { // technically there is no PAL PC Engine but oh well...
if (flags&1) { // technically there is no PAL PC Engine but oh well...
chipClock=COLOR_PAL*4.0/5.0;
} else {
chipClock=COLOR_NTSC;

View File

@ -308,7 +308,13 @@ void DivPlatformSAA1099::notifyInsDeletion(void* ins) {
}
void DivPlatformSAA1099::setFlags(unsigned int flags) {
chipClock=8000000;
if (flags==2) {
chipClock=COLOR_PAL*8.0/5.0;
} else if (flags==1) {
chipClock=COLOR_NTSC*2.0;
} else {
chipClock=8000000;
}
rate=chipClock/32;
}

View File

@ -57,7 +57,7 @@ void DivPlatformSMS::tick() {
if (chan[3].freqChanged || updateSNMode) {
updateSNMode=false;
// seems arbitrary huh?
chan[3].freq=parent->calcFreq(chan[3].baseFreq,chan[3].pitch-1,true);
chan[3].freq=parent->calcFreq(chan[3].baseFreq,chan[3].pitch-1-(isRealSN?127:0),true);
if (chan[3].freq>1023) chan[3].freq=1023;
if (chan[3].note>0x5d) chan[3].freq=0x01;
chan[3].freqChanged=false;
@ -222,11 +222,32 @@ void DivPlatformSMS::notifyInsDeletion(void* ins) {
}
void DivPlatformSMS::setFlags(unsigned int flags) {
if (flags) {
if ((flags&3)==2) {
chipClock=4000000;
} else if ((flags&3)==1) {
chipClock=COLOR_PAL*4.0/5.0;
} else {
chipClock=COLOR_NTSC;
}
if (sn!=NULL) delete sn;
switch (flags>>2) {
case 1: // TI
sn=new sn76496_base_device(0x4000, 0x4000, 0x01, 0x02, true, 1, false, true);
isRealSN=true;
break;
case 2: // TI+Atari
sn=new sn76496_base_device(0x4000, 0x0f35, 0x01, 0x02, true, 1, false, true);
isRealSN=true;
break;
case 3: // Game Gear (not fully emulated yet!)
sn=new sn76496_base_device(0x8000, 0x8000, 0x01, 0x08, false, 1, false, false);
isRealSN=false;
break;
default: // Sega
sn=new sn76496_base_device(0x8000, 0x8000, 0x01, 0x08, false, 1, false, false);
isRealSN=false;
break;
}
rate=chipClock/16;
}
@ -237,14 +258,14 @@ int DivPlatformSMS::init(DivEngine* p, int channels, int sugRate, unsigned int f
for (int i=0; i<4; i++) {
isMuted[i]=false;
}
sn=NULL;
setFlags(flags);
sn=new sn76496_device(rate);
reset();
return 4;
}
void DivPlatformSMS::quit() {
delete sn;
if (sn!=NULL) delete sn;
}
DivPlatformSMS::~DivPlatformSMS() {

View File

@ -30,7 +30,8 @@ class DivPlatformSMS: public DivDispatch {
bool isMuted[4];
unsigned char snNoiseMode;
bool updateSNMode;
sn76496_device* sn;
bool isRealSN;
sn76496_base_device* sn;
friend void putDispatchChan(void*,int,int);
public:
int acquireOne();

View File

@ -822,12 +822,12 @@ static inline void build_3D_table(double rl, const ay8910_device::ay_ym_param *p
if (normalize)
{
for (int j = 0; j < 32*32*32*8; j++)
tab[j] = 16384 * MAX_OUTPUT * (((temp[j] - min)/(max-min))) * factor;
tab[j] = 8000 * MAX_OUTPUT * (((temp[j] - min)/(max-min))) * factor;
}
else
{
for (int j = 0; j < 32*32*32*8; j++)
tab[j] = 16384 * MAX_OUTPUT * temp[j];
tab[j] = 8000 * MAX_OUTPUT * temp[j];
}
/* for (e = 0;e<16;e++) printf("%d %d\n",e << 10, tab[e << 10]); */

View File

@ -145,19 +145,20 @@
#define MAX_OUTPUT 0x7fff
#define NOISE_START 0x8000
//#define NOISE_START 0x8000
//#define NOISE_START 0x0f35
sn76496_base_device::sn76496_base_device(
int feedbackmask,
int noise_start,
int noisetap1,
int noisetap2,
bool negate,
int clockdivider,
bool ncr,
bool sega,
uint32_t clock)
bool sega)
: m_feedback_mask(feedbackmask)
, m_noise_start(noise_start)
, m_whitenoise_tap1(noisetap1)
, m_whitenoise_tap2(noisetap2)
, m_negate(negate)
@ -167,8 +168,8 @@ sn76496_base_device::sn76496_base_device(
{
}
sn76496_device::sn76496_device(uint32_t clock)
: sn76496_base_device(0x8000, 0x01, 0x08, false, 1, false, false, clock)
sn76496_device::sn76496_device()
: sn76496_base_device(0x8000, 0x8000, 0x01, 0x08, false, 1, false, false)
{
}
@ -195,7 +196,7 @@ void sn76496_base_device::device_start()
m_count[i] = 0;
}
m_RNG = NOISE_START;
m_RNG = m_feedback_mask;
m_output[3] = m_RNG & 1;
m_current_clock = m_clock_divider-1;
@ -232,7 +233,7 @@ void sn76496_base_device::write(u8 data)
{
r = (data & 0x70) >> 4;
m_last_register = r;
if (((m_ncr_style_psg) && (r == 6)) && ((data&0x04) != (m_register[6]&0x04))) m_RNG = NOISE_START; // NCR-style PSG resets the LFSR only on a mode write which actually changes the state of bit 2 of register 6
if (((m_ncr_style_psg) && (r == 6)) && ((data&0x04) != (m_register[6]&0x04))) m_RNG = m_noise_start; // NCR-style PSG resets the LFSR only on a mode write which actually changes the state of bit 2 of register 6
m_register[r] = (m_register[r] & 0x3f0) | (data & 0x0f);
}
else
@ -271,7 +272,7 @@ void sn76496_base_device::write(u8 data)
n = m_register[6];
// N/512,N/1024,N/2048,Tone #3 output
m_period[3] = ((n&3) == 3)? (m_period[2]<<1) : (1 << (5+(n&3)));
if (!(m_ncr_style_psg)) m_RNG = NOISE_START;
if (!(m_ncr_style_psg)) m_RNG = m_noise_start;
}
break;
}

View File

@ -18,16 +18,15 @@ public:
void sound_stream_update(short* outputs, int outLen);
//DECLARE_READ_LINE_MEMBER( ready_r ) { return m_ready_state ? 1 : 0; }
protected:
sn76496_base_device(
int feedbackmask,
int noise_start,
int noisetap1,
int noisetap2,
bool negate,
int clockdivider,
bool ncr,
bool sega,
uint32_t clock);
bool sega);
private:
inline bool in_noise_mode();
@ -35,6 +34,7 @@ private:
bool m_ready_state;
const int32_t m_feedback_mask; // mask for feedback
const int32_t m_noise_start; // noise start value
const int32_t m_whitenoise_tap1; // mask for white noise tap 1 (higher one, usually bit 14)
const int32_t m_whitenoise_tap2; // mask for white noise tap 2 (lower one, usually bit 13)
bool m_negate; // output negate flag
@ -42,7 +42,6 @@ private:
const bool m_ncr_style_psg; // flag to ignore writes to regs 1,3,5,6,7 with bit 7 low
const bool m_sega_style_psg; // flag to make frequency zero acts as if it is one more than max (0x3ff+1) or if it acts like 0; the initial register is pointing to 0x3 instead of 0x0; the volume reg is preloaded with 0xF instead of 0x0
int32_t m_clock;
int32_t m_vol_table[16]; // volume table (for 4-bit to db conversion)
int32_t m_register[8]; // registers
int32_t m_last_register; // last register written
@ -58,7 +57,7 @@ private:
class sn76496_device : public sn76496_base_device
{
public:
sn76496_device(uint32_t clock);
sn76496_device();
};
#endif // MAME_SOUND_SN76496_H

View File

@ -255,11 +255,12 @@ void DivPlatformTIA::notifyInsDeletion(void* ins) {
}
void DivPlatformTIA::setFlags(unsigned int flags) {
if (flags) {
if (flags&1) {
rate=31250;
} else {
rate=31400;
rate=31468;
}
chipClock=rate;
}
int DivPlatformTIA::init(DivEngine* p, int channels, int sugRate, unsigned int flags) {

View File

@ -4580,9 +4580,9 @@ bool FurnaceGUI::loop() {
if (ImGui::RadioButton("TI SN76489 with Atari-like short noise",(flags>>2)==2)) {
e->setSysFlags(i,(flags&3)|8);
}
if (ImGui::RadioButton("Game Gear",(flags>>2)==3)) {
/*if (ImGui::RadioButton("Game Gear",(flags>>2)==3)) {
e->setSysFlags(i,(flags&3)|12);
}
}*/
break;
case DIV_SYSTEM_ARCADE:
case DIV_SYSTEM_YM2151:
@ -4650,9 +4650,11 @@ bool FurnaceGUI::loop() {
}
}
bool stereo=flags&0x40;
ImGui::BeginDisabled((flags&0x30)==32);
if (ImGui::Checkbox("Stereo##_AY_STEREO",&stereo)) {
e->setSysFlags(i,(flags&(~0x40))|(stereo?0x40:0));
}
ImGui::EndDisabled();
break;
}
case DIV_SYSTEM_SAA1099:
@ -4667,12 +4669,13 @@ bool FurnaceGUI::loop() {
}
break;
case DIV_SYSTEM_AMIGA:
/* TODO LATER: I want 0.5 out already
if (ImGui::RadioButton("Amiga 500 (OCS)",(flags&2)==0)) {
e->setSysFlags(i,flags&1);
}
if (ImGui::RadioButton("Amiga 1200 (AGA)",(flags&2)==2)) {
e->setSysFlags(i,(flags&1)|2);
}
}*/
sysPal=flags&1;
if (ImGui::Checkbox("PAL",&sysPal)) {
e->setSysFlags(i,(flags&2)|sysPal);