2022-02-15 03:12:20 +00:00
|
|
|
/**
|
|
|
|
* Furnace Tracker - multi-system chiptune tracker
|
|
|
|
* Copyright (C) 2021-2022 tildearrow and contributors
|
|
|
|
*
|
|
|
|
* This program is free software; you can redistribute it and/or modify
|
|
|
|
* it under the terms of the GNU General Public License as published by
|
|
|
|
* the Free Software Foundation; either version 2 of the License, or
|
|
|
|
* (at your option) any later version.
|
|
|
|
*
|
|
|
|
* This program is distributed in the hope that it will be useful,
|
|
|
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
|
|
* GNU General Public License for more details.
|
|
|
|
*
|
|
|
|
* You should have received a copy of the GNU General Public License along
|
|
|
|
* with this program; if not, write to the Free Software Foundation, Inc.,
|
|
|
|
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
|
|
|
*/
|
|
|
|
|
2022-01-17 06:42:26 +00:00
|
|
|
#include "blip_buf.h"
|
2022-01-08 21:03:32 +00:00
|
|
|
#include "engine.h"
|
|
|
|
#include "platform/genesis.h"
|
|
|
|
#include "platform/genesisext.h"
|
|
|
|
#include "platform/sms.h"
|
|
|
|
#include "platform/gb.h"
|
|
|
|
#include "platform/pce.h"
|
|
|
|
#include "platform/nes.h"
|
|
|
|
#include "platform/c64.h"
|
|
|
|
#include "platform/arcade.h"
|
|
|
|
#include "platform/ym2610.h"
|
|
|
|
#include "platform/ym2610ext.h"
|
2022-01-13 07:52:19 +00:00
|
|
|
#include "platform/ay.h"
|
2022-01-14 05:02:10 +00:00
|
|
|
#include "platform/ay8930.h"
|
2022-01-14 08:37:36 +00:00
|
|
|
#include "platform/tia.h"
|
2022-01-14 21:29:27 +00:00
|
|
|
#include "platform/saa.h"
|
2022-01-15 22:28:33 +00:00
|
|
|
#include "platform/amiga.h"
|
2022-02-23 07:52:30 +00:00
|
|
|
#include "platform/segapcm.h"
|
2022-02-22 09:01:57 +00:00
|
|
|
#include "platform/qsound.h"
|
2022-01-08 21:03:32 +00:00
|
|
|
#include "platform/dummy.h"
|
2022-02-20 17:15:15 +00:00
|
|
|
#include "platform/lynx.h"
|
2022-01-08 21:03:32 +00:00
|
|
|
#include "../ta-log.h"
|
2022-02-10 08:35:08 +00:00
|
|
|
#include "song.h"
|
2022-01-08 21:03:32 +00:00
|
|
|
|
|
|
|
void DivDispatchContainer::setRates(double gotRate) {
|
|
|
|
blip_set_rates(bb[0],dispatch->rate,gotRate);
|
|
|
|
blip_set_rates(bb[1],dispatch->rate,gotRate);
|
|
|
|
}
|
|
|
|
|
2022-01-17 06:42:26 +00:00
|
|
|
void DivDispatchContainer::setQuality(bool lowQual) {
|
|
|
|
lowQuality=lowQual;
|
|
|
|
}
|
|
|
|
|
2022-01-08 22:15:12 +00:00
|
|
|
void DivDispatchContainer::acquire(size_t offset, size_t count) {
|
|
|
|
dispatch->acquire(bbIn[0],bbIn[1],offset,count);
|
|
|
|
}
|
|
|
|
|
2022-02-08 02:31:58 +00:00
|
|
|
void DivDispatchContainer::flush(size_t count) {
|
|
|
|
blip_read_samples(bb[0],bbOut[0],count,0);
|
|
|
|
|
|
|
|
if (dispatch->isStereo()) {
|
|
|
|
blip_read_samples(bb[1],bbOut[1],count,0);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void DivDispatchContainer::fillBuf(size_t runtotal, size_t offset, size_t size) {
|
2022-01-17 06:42:26 +00:00
|
|
|
if (lowQuality) {
|
|
|
|
for (size_t i=0; i<runtotal; i++) {
|
|
|
|
temp[0]=bbIn[0][i];
|
|
|
|
blip_add_delta_fast(bb[0],i,temp[0]-prevSample[0]);
|
|
|
|
prevSample[0]=temp[0];
|
|
|
|
}
|
|
|
|
|
|
|
|
if (dispatch->isStereo()) for (size_t i=0; i<runtotal; i++) {
|
|
|
|
temp[1]=bbIn[1][i];
|
|
|
|
blip_add_delta_fast(bb[1],i,temp[1]-prevSample[1]);
|
|
|
|
prevSample[1]=temp[1];
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
for (size_t i=0; i<runtotal; i++) {
|
|
|
|
temp[0]=bbIn[0][i];
|
|
|
|
blip_add_delta(bb[0],i,temp[0]-prevSample[0]);
|
|
|
|
prevSample[0]=temp[0];
|
|
|
|
}
|
2022-01-08 22:15:12 +00:00
|
|
|
|
2022-01-17 06:42:26 +00:00
|
|
|
if (dispatch->isStereo()) for (size_t i=0; i<runtotal; i++) {
|
|
|
|
temp[1]=bbIn[1][i];
|
|
|
|
blip_add_delta(bb[1],i,temp[1]-prevSample[1]);
|
|
|
|
prevSample[1]=temp[1];
|
|
|
|
}
|
2022-01-08 22:15:12 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
blip_end_frame(bb[0],runtotal);
|
2022-02-08 02:31:58 +00:00
|
|
|
blip_read_samples(bb[0],bbOut[0]+offset,size,0);
|
|
|
|
/*if (totalRead<(int)size && totalRead>0) {
|
2022-01-18 03:15:00 +00:00
|
|
|
for (size_t i=totalRead; i<size; i++) {
|
|
|
|
bbOut[0][i]=bbOut[0][totalRead-1];//bbOut[0][totalRead];
|
|
|
|
}
|
2022-02-08 02:31:58 +00:00
|
|
|
}*/
|
2022-01-08 22:15:12 +00:00
|
|
|
|
|
|
|
if (dispatch->isStereo()) {
|
|
|
|
blip_end_frame(bb[1],runtotal);
|
2022-02-08 02:31:58 +00:00
|
|
|
blip_read_samples(bb[1],bbOut[1]+offset,size,0);
|
2022-01-08 22:15:12 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2022-01-08 21:03:32 +00:00
|
|
|
void DivDispatchContainer::clear() {
|
|
|
|
blip_clear(bb[0]);
|
|
|
|
blip_clear(bb[1]);
|
2022-01-21 04:09:04 +00:00
|
|
|
temp[0]=0;
|
|
|
|
temp[1]=0;
|
|
|
|
prevSample[0]=0;
|
|
|
|
prevSample[1]=0;
|
2022-01-20 02:04:51 +00:00
|
|
|
// run for one cycle to determine DC offset
|
2022-01-21 04:09:04 +00:00
|
|
|
// TODO: SAA1099 doesn't like that
|
|
|
|
/*dispatch->acquire(bbIn[0],bbIn[1],0,1);
|
2022-01-20 02:04:51 +00:00
|
|
|
temp[0]=bbIn[0][0];
|
|
|
|
temp[1]=bbIn[1][0];
|
|
|
|
prevSample[0]=temp[0];
|
2022-01-21 04:09:04 +00:00
|
|
|
prevSample[1]=temp[1];*/
|
2022-01-08 21:03:32 +00:00
|
|
|
}
|
|
|
|
|
2022-02-04 22:04:36 +00:00
|
|
|
void DivDispatchContainer::init(DivSystem sys, DivEngine* eng, int chanCount, double gotRate, unsigned int flags) {
|
2022-01-08 21:03:32 +00:00
|
|
|
if (dispatch!=NULL) return;
|
|
|
|
|
|
|
|
bb[0]=blip_new(32768);
|
|
|
|
if (bb[0]==NULL) {
|
|
|
|
logE("not enough memory!\n");
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
bb[1]=blip_new(32768);
|
|
|
|
if (bb[1]==NULL) {
|
|
|
|
logE("not enough memory!\n");
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
bbOut[0]=new short[32768];
|
|
|
|
bbOut[1]=new short[32768];
|
|
|
|
bbIn[0]=new short[32768];
|
|
|
|
bbIn[1]=new short[32768];
|
|
|
|
bbInLen=32768;
|
|
|
|
|
|
|
|
switch (sys) {
|
2022-01-13 06:03:57 +00:00
|
|
|
case DIV_SYSTEM_YM2612:
|
2022-01-08 21:03:32 +00:00
|
|
|
dispatch=new DivPlatformGenesis;
|
2022-02-03 04:08:45 +00:00
|
|
|
((DivPlatformGenesis*)dispatch)->setYMFM(eng->getConfInt("ym2612Core",0));
|
2022-01-08 21:03:32 +00:00
|
|
|
break;
|
2022-02-23 07:52:30 +00:00
|
|
|
case DIV_SYSTEM_YM2612_EXT:
|
2022-01-08 21:03:32 +00:00
|
|
|
dispatch=new DivPlatformGenesisExt;
|
2022-02-03 04:08:45 +00:00
|
|
|
((DivPlatformGenesisExt*)dispatch)->setYMFM(eng->getConfInt("ym2612Core",0));
|
2022-01-08 21:03:32 +00:00
|
|
|
break;
|
|
|
|
case DIV_SYSTEM_SMS:
|
|
|
|
dispatch=new DivPlatformSMS;
|
|
|
|
break;
|
|
|
|
case DIV_SYSTEM_GB:
|
|
|
|
dispatch=new DivPlatformGB;
|
|
|
|
break;
|
|
|
|
case DIV_SYSTEM_PCE:
|
|
|
|
dispatch=new DivPlatformPCE;
|
|
|
|
break;
|
|
|
|
case DIV_SYSTEM_NES:
|
|
|
|
dispatch=new DivPlatformNES;
|
|
|
|
break;
|
|
|
|
case DIV_SYSTEM_C64_6581:
|
|
|
|
dispatch=new DivPlatformC64;
|
|
|
|
((DivPlatformC64*)dispatch)->setChipModel(true);
|
|
|
|
break;
|
|
|
|
case DIV_SYSTEM_C64_8580:
|
|
|
|
dispatch=new DivPlatformC64;
|
|
|
|
((DivPlatformC64*)dispatch)->setChipModel(false);
|
|
|
|
break;
|
2022-01-13 06:03:57 +00:00
|
|
|
case DIV_SYSTEM_YM2151:
|
2022-01-08 21:03:32 +00:00
|
|
|
dispatch=new DivPlatformArcade;
|
2022-01-17 21:27:57 +00:00
|
|
|
((DivPlatformArcade*)dispatch)->setYMFM(eng->getConfInt("arcadeCore",0)==0);
|
2022-01-08 21:03:32 +00:00
|
|
|
break;
|
|
|
|
case DIV_SYSTEM_YM2610:
|
2022-02-10 08:35:08 +00:00
|
|
|
case DIV_SYSTEM_YM2610_FULL:
|
2022-01-08 21:03:32 +00:00
|
|
|
dispatch=new DivPlatformYM2610;
|
|
|
|
break;
|
|
|
|
case DIV_SYSTEM_YM2610_EXT:
|
2022-02-10 08:35:08 +00:00
|
|
|
case DIV_SYSTEM_YM2610_FULL_EXT:
|
2022-01-08 21:03:32 +00:00
|
|
|
dispatch=new DivPlatformYM2610Ext;
|
|
|
|
break;
|
2022-01-15 22:28:33 +00:00
|
|
|
case DIV_SYSTEM_AMIGA:
|
|
|
|
dispatch=new DivPlatformAmiga;
|
|
|
|
break;
|
2022-01-13 07:52:19 +00:00
|
|
|
case DIV_SYSTEM_AY8910:
|
|
|
|
dispatch=new DivPlatformAY8910;
|
|
|
|
break;
|
2022-01-14 05:02:10 +00:00
|
|
|
case DIV_SYSTEM_AY8930:
|
|
|
|
dispatch=new DivPlatformAY8930;
|
|
|
|
break;
|
2022-01-14 08:37:36 +00:00
|
|
|
case DIV_SYSTEM_TIA:
|
|
|
|
dispatch=new DivPlatformTIA;
|
|
|
|
break;
|
2022-02-13 22:49:24 +00:00
|
|
|
case DIV_SYSTEM_SAA1099: {
|
|
|
|
int saaCore=eng->getConfInt("saaCore",0);
|
|
|
|
if (saaCore<0 || saaCore>2) saaCore=0;
|
2022-01-14 21:29:27 +00:00
|
|
|
dispatch=new DivPlatformSAA1099;
|
2022-02-13 22:49:24 +00:00
|
|
|
((DivPlatformSAA1099*)dispatch)->setCore((DivSAACores)saaCore);
|
2022-01-14 21:29:27 +00:00
|
|
|
break;
|
2022-02-13 22:49:24 +00:00
|
|
|
}
|
2022-02-20 17:15:15 +00:00
|
|
|
case DIV_SYSTEM_LYNX:
|
2022-02-22 23:21:57 +00:00
|
|
|
dispatch=new DivPlatformLynx;
|
|
|
|
break;
|
2022-02-22 09:01:57 +00:00
|
|
|
case DIV_SYSTEM_QSOUND:
|
|
|
|
dispatch=new DivPlatformQSound;
|
2022-02-20 17:15:15 +00:00
|
|
|
break;
|
2022-02-23 07:52:30 +00:00
|
|
|
case DIV_SYSTEM_SEGAPCM:
|
|
|
|
case DIV_SYSTEM_SEGAPCM_COMPAT:
|
|
|
|
dispatch=new DivPlatformSegaPCM;
|
|
|
|
break;
|
2022-01-08 21:03:32 +00:00
|
|
|
default:
|
|
|
|
logW("this system is not supported yet! using dummy platform.\n");
|
|
|
|
dispatch=new DivPlatformDummy;
|
|
|
|
break;
|
|
|
|
}
|
2022-02-04 22:04:36 +00:00
|
|
|
dispatch->init(eng,chanCount,gotRate,flags);
|
2022-01-08 21:03:32 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
void DivDispatchContainer::quit() {
|
|
|
|
if (dispatch==NULL) return;
|
|
|
|
dispatch->quit();
|
|
|
|
delete dispatch;
|
|
|
|
dispatch=NULL;
|
|
|
|
|
|
|
|
delete[] bbOut[0];
|
|
|
|
delete[] bbOut[1];
|
|
|
|
delete[] bbIn[0];
|
|
|
|
delete[] bbIn[1];
|
|
|
|
bbInLen=0;
|
|
|
|
blip_delete(bb[0]);
|
|
|
|
blip_delete(bb[1]);
|
|
|
|
}
|