Merge branch 'tildearrow:master' into master
This commit is contained in:
commit
6daf9b3d18
32 changed files with 1050 additions and 141 deletions
|
|
@ -78,6 +78,7 @@
|
|||
#include "platform/ga20.h"
|
||||
#include "platform/sm8521.h"
|
||||
#include "platform/pv1000.h"
|
||||
#include "platform/k053260.h"
|
||||
#include "platform/pcmdac.h"
|
||||
#include "platform/dummy.h"
|
||||
#include "../ta-log.h"
|
||||
|
|
@ -503,6 +504,9 @@ void DivDispatchContainer::init(DivSystem sys, DivEngine* eng, int chanCount, do
|
|||
case DIV_SYSTEM_PV1000:
|
||||
dispatch=new DivPlatformPV1000;
|
||||
break;
|
||||
case DIV_SYSTEM_K053260:
|
||||
dispatch=new DivPlatformK053260;
|
||||
break;
|
||||
case DIV_SYSTEM_PCM_DAC:
|
||||
dispatch=new DivPlatformPCMDAC;
|
||||
break;
|
||||
|
|
|
|||
|
|
@ -929,6 +929,10 @@ void DivInstrument::putInsData2(SafeWriter* w, bool fui, const DivSong* song) {
|
|||
break;
|
||||
case DIV_INS_PV1000:
|
||||
break;
|
||||
case DIV_INS_K053260:
|
||||
featureSM=true;
|
||||
featureSL=true;
|
||||
break;
|
||||
|
||||
case DIV_INS_MAX:
|
||||
break;
|
||||
|
|
|
|||
|
|
@ -80,6 +80,7 @@ enum DivInstrumentType: unsigned short {
|
|||
DIV_INS_POKEMINI=47,
|
||||
DIV_INS_SM8521=48,
|
||||
DIV_INS_PV1000=49,
|
||||
DIV_INS_K053260=50,
|
||||
DIV_INS_MAX,
|
||||
DIV_INS_NULL
|
||||
};
|
||||
|
|
|
|||
513
src/engine/platform/k053260.cpp
Normal file
513
src/engine/platform/k053260.cpp
Normal file
|
|
@ -0,0 +1,513 @@
|
|||
/**
|
||||
* Furnace Tracker - multi-system chiptune tracker
|
||||
* Copyright (C) 2021-2023 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.
|
||||
*/
|
||||
|
||||
#include "k053260.h"
|
||||
#include "../engine.h"
|
||||
#include "../../ta-log.h"
|
||||
#include <math.h>
|
||||
|
||||
#define rWrite(a,v) {if(!skipRegisterWrites) {k053260.write(a,v); regPool[a]=v; if(dumpWrites) addWrite(a,v);}}
|
||||
|
||||
#define CHIP_DIVIDER 16
|
||||
#define TICK_DIVIDER 64 // for match to YM3012 output rate
|
||||
|
||||
const char* regCheatSheetK053260[]={
|
||||
"MainToSub0", "00",
|
||||
"MainToSub1", "01",
|
||||
"SubToMain0", "02",
|
||||
"SubToMain1", "03",
|
||||
"CHx_FreqL", "08+x*8",
|
||||
"CHx_FreqH", "09+x*8",
|
||||
"CHx_LengthL", "0A+x*8",
|
||||
"CHx_LengthH", "0B+x*8",
|
||||
"CHx_StartL", "0C+x*8",
|
||||
"CHx_StartM", "0D+x*8",
|
||||
"CHx_StartH", "0E+x*8",
|
||||
"CHx_Volume", "0F+x*8",
|
||||
"KeyOn", "28",
|
||||
"Status", "29",
|
||||
"LoopFormat", "2A",
|
||||
"Test", "2B",
|
||||
"CH01_Pan", "2C",
|
||||
"CH23_Pan", "2D",
|
||||
"ROMReadback", "2E",
|
||||
"Control", "2F",
|
||||
NULL
|
||||
};
|
||||
|
||||
const char** DivPlatformK053260::getRegisterSheet() {
|
||||
return regCheatSheetK053260;
|
||||
}
|
||||
|
||||
inline void DivPlatformK053260::chWrite(unsigned char ch, unsigned int addr, unsigned char val) {
|
||||
if (!skipRegisterWrites) {
|
||||
rWrite(8+((ch<<3)|(addr&7)),val);
|
||||
}
|
||||
}
|
||||
|
||||
u8 DivPlatformK053260::read_sample(u32 address) {
|
||||
if ((sampleMem!=NULL) && (address<getSampleMemCapacity())) {
|
||||
return sampleMem[address&0x1fffff];
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
void DivPlatformK053260::acquire(short** buf, size_t len) {
|
||||
for (size_t i=0; i<len; i++) {
|
||||
k053260.tick(TICK_DIVIDER);
|
||||
int lout=(k053260.output(0)); // scale to 16 bit
|
||||
int rout=(k053260.output(1)); // scale to 16 bit
|
||||
if (lout>32767) lout=32767;
|
||||
if (lout<-32768) lout=-32768;
|
||||
if (rout>32767) rout=32767;
|
||||
if (rout<-32768) rout=-32768;
|
||||
buf[0][i]=lout;
|
||||
buf[1][i]=rout;
|
||||
|
||||
for (int i=0; i<4; i++) {
|
||||
oscBuf[i]->data[oscBuf[i]->needle++]=(k053260.voice_out(i,0)+k053260.voice_out(i,1))>>2;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void DivPlatformK053260::tick(bool sysTick) {
|
||||
unsigned char panMask=0;
|
||||
for (int i=0; i<4; i++) {
|
||||
chan[i].std.next();
|
||||
if (chan[i].std.vol.had) {
|
||||
chan[i].outVol=((chan[i].vol&0x7f)*MIN(chan[i].macroVolMul,chan[i].std.vol.val))/chan[i].macroVolMul;
|
||||
chWrite(i,7,chan[i].outVol);
|
||||
}
|
||||
if (NEW_ARP_STRAT) {
|
||||
chan[i].handleArp();
|
||||
} else if (chan[i].std.arp.had) {
|
||||
if (!chan[i].inPorta) {
|
||||
chan[i].baseFreq=NOTE_PERIODIC(parent->calcArp(chan[i].note,chan[i].std.arp.val));
|
||||
}
|
||||
chan[i].freqChanged=true;
|
||||
}
|
||||
if (chan[i].std.pitch.had) {
|
||||
if (chan[i].std.pitch.mode) {
|
||||
chan[i].pitch2+=chan[i].std.pitch.val;
|
||||
CLAMP_VAR(chan[i].pitch2,-32768,32767);
|
||||
} else {
|
||||
chan[i].pitch2=chan[i].std.pitch.val;
|
||||
}
|
||||
chan[i].freqChanged=true;
|
||||
}
|
||||
if (chan[i].std.panL.had) { // panning
|
||||
chan[i].panning=4+chan[i].std.panL.val;
|
||||
if (!isMuted[i]) {
|
||||
panMask|=1<<i;
|
||||
}
|
||||
}
|
||||
if (chan[i].std.phaseReset.had) {
|
||||
if (chan[i].std.phaseReset.val==1 && chan[i].active) {
|
||||
chan[i].audPos=0;
|
||||
chan[i].setPos=true;
|
||||
}
|
||||
}
|
||||
if (chan[i].setPos) {
|
||||
// force keyon
|
||||
chan[i].keyOn=true;
|
||||
chan[i].setPos=false;
|
||||
} else {
|
||||
chan[i].audPos=0;
|
||||
}
|
||||
if (chan[i].freqChanged || chan[i].keyOn || chan[i].keyOff) {
|
||||
unsigned char keyon=regPool[0x28]|(1<<i);
|
||||
unsigned char keyoff=keyon&~(17<<i);
|
||||
unsigned char loopon=regPool[0x2a]|(1<<i);
|
||||
unsigned char loopoff=loopon&~(1<<i);
|
||||
double off=1.0;
|
||||
int sample=chan[i].sample;
|
||||
if (sample>=0 && sample<parent->song.sampleLen) {
|
||||
DivSample* s=parent->getSample(sample);
|
||||
if (s->centerRate<1) {
|
||||
off=1.0;
|
||||
} else {
|
||||
off=8363.0/s->centerRate;
|
||||
}
|
||||
}
|
||||
DivSample* s=parent->getSample(chan[i].sample);
|
||||
chan[i].freq=0x1000-(int)(off*parent->calcFreq(chan[i].baseFreq,chan[i].pitch,chan[i].fixedArp?chan[i].baseNoteOverride:chan[i].arpOff,chan[i].fixedArp,true,0,chan[i].pitch2,chipClock,CHIP_DIVIDER));
|
||||
if (chan[i].freq>4095) chan[i].freq=4095;
|
||||
if (chan[i].freq<0) chan[i].freq=0;
|
||||
if (chan[i].keyOn) {
|
||||
unsigned int start=0;
|
||||
unsigned int length=0;
|
||||
if (chan[i].sample>=0 && chan[i].sample<parent->song.sampleLen) {
|
||||
start=sampleOffK053260[chan[i].sample];
|
||||
length=s->length8;
|
||||
if (chan[i].reverse) {
|
||||
start+=length;
|
||||
keyon|=(16<<i);
|
||||
}
|
||||
}
|
||||
if (chan[i].audPos>0) {
|
||||
if (chan[i].reverse) {
|
||||
start=start-MIN(chan[i].audPos,s->length8);
|
||||
}
|
||||
else {
|
||||
start=start+MIN(chan[i].audPos,s->length8);
|
||||
}
|
||||
length=MAX(1,length-chan[i].audPos);
|
||||
}
|
||||
start=MIN(start,getSampleMemCapacity());
|
||||
length=MIN(65535,MIN(length,getSampleMemCapacity()));
|
||||
rWrite(0x28,keyoff); // force keyoff first
|
||||
rWrite(0x2a,loopoff);
|
||||
chWrite(i,2,length&0xff);
|
||||
chWrite(i,3,length>>8);
|
||||
chWrite(i,4,start&0xff);
|
||||
chWrite(i,5,start>>8);
|
||||
chWrite(i,6,start>>16);
|
||||
if (!chan[i].std.vol.had) {
|
||||
chan[i].outVol=chan[i].vol;
|
||||
chWrite(i,7,chan[i].outVol);
|
||||
}
|
||||
rWrite(0x28,keyon);
|
||||
if (s->isLoopable()) {
|
||||
rWrite(0x2a,loopon);
|
||||
}
|
||||
chan[i].keyOn=false;
|
||||
}
|
||||
if (chan[i].keyOff) {
|
||||
rWrite(0x28,keyoff);
|
||||
rWrite(0x2a,loopoff);
|
||||
chan[i].keyOff=false;
|
||||
}
|
||||
if (chan[i].freqChanged) {
|
||||
chWrite(i,0,chan[i].freq&0xff);
|
||||
chWrite(i,1,chan[i].freq>>8);
|
||||
chan[i].freqChanged=false;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (panMask) {
|
||||
updatePanning(panMask);
|
||||
}
|
||||
}
|
||||
|
||||
void DivPlatformK053260::updatePanning(unsigned char mask) {
|
||||
if (mask&3) {
|
||||
rWrite(0x2c,
|
||||
(isMuted[0]?0:chan[0].panning)|
|
||||
(isMuted[1]?0:chan[1].panning<<3));
|
||||
}
|
||||
if (mask&0xc) {
|
||||
rWrite(0x2d,
|
||||
(isMuted[2]?0:chan[2].panning)|
|
||||
(isMuted[3]?0:chan[3].panning<<3));
|
||||
}
|
||||
}
|
||||
|
||||
int DivPlatformK053260::dispatch(DivCommand c) {
|
||||
switch (c.cmd) {
|
||||
case DIV_CMD_NOTE_ON: {
|
||||
DivInstrument* ins=parent->getIns(chan[c.chan].ins,DIV_INS_AMIGA);
|
||||
chan[c.chan].macroVolMul=ins->type==DIV_INS_AMIGA?64:127;
|
||||
if (c.value!=DIV_NOTE_NULL) {
|
||||
chan[c.chan].sample=ins->amiga.getSample(c.value);
|
||||
c.value=ins->amiga.getFreq(c.value);
|
||||
}
|
||||
if (c.value!=DIV_NOTE_NULL) {
|
||||
chan[c.chan].baseFreq=NOTE_PERIODIC(c.value);
|
||||
}
|
||||
if (chan[c.chan].sample<0 || chan[c.chan].sample>=parent->song.sampleLen) {
|
||||
chan[c.chan].sample=-1;
|
||||
}
|
||||
if (c.value!=DIV_NOTE_NULL) {
|
||||
chan[c.chan].freqChanged=true;
|
||||
chan[c.chan].note=c.value;
|
||||
}
|
||||
chan[c.chan].active=true;
|
||||
chan[c.chan].keyOn=true;
|
||||
chan[c.chan].macroInit(ins);
|
||||
if (!parent->song.brokenOutVol && !chan[c.chan].std.vol.will) {
|
||||
chan[c.chan].outVol=chan[c.chan].vol;
|
||||
}
|
||||
break;
|
||||
}
|
||||
case DIV_CMD_NOTE_OFF:
|
||||
chan[c.chan].sample=-1;
|
||||
chan[c.chan].active=false;
|
||||
chan[c.chan].keyOff=true;
|
||||
chan[c.chan].macroInit(NULL);
|
||||
break;
|
||||
case DIV_CMD_NOTE_OFF_ENV:
|
||||
case DIV_CMD_ENV_RELEASE:
|
||||
chan[c.chan].std.release();
|
||||
break;
|
||||
case DIV_CMD_INSTRUMENT:
|
||||
if (chan[c.chan].ins!=c.value || c.value2==1) {
|
||||
chan[c.chan].ins=c.value;
|
||||
}
|
||||
break;
|
||||
case DIV_CMD_VOLUME:
|
||||
if (chan[c.chan].vol!=c.value) {
|
||||
chan[c.chan].vol=c.value;
|
||||
if (!chan[c.chan].std.vol.has) {
|
||||
chan[c.chan].outVol=c.value;
|
||||
chWrite(c.chan,7,chan[c.chan].outVol);
|
||||
}
|
||||
}
|
||||
break;
|
||||
case DIV_CMD_GET_VOLUME:
|
||||
if (chan[c.chan].std.vol.has) {
|
||||
return chan[c.chan].vol;
|
||||
}
|
||||
return chan[c.chan].outVol;
|
||||
break;
|
||||
case DIV_CMD_PANNING:
|
||||
chan[c.chan].panning=MIN(parent->convertPanSplitToLinearLR(c.value,c.value2,7)+1,7);
|
||||
if (!isMuted[c.chan]) {
|
||||
updatePanning(1<<c.chan);
|
||||
}
|
||||
break;
|
||||
case DIV_CMD_PITCH:
|
||||
chan[c.chan].pitch=c.value;
|
||||
chan[c.chan].freqChanged=true;
|
||||
break;
|
||||
case DIV_CMD_NOTE_PORTA: {
|
||||
int destFreq=NOTE_PERIODIC(c.value2);
|
||||
bool return2=false;
|
||||
if (destFreq>chan[c.chan].baseFreq) {
|
||||
chan[c.chan].baseFreq+=c.value;
|
||||
if (chan[c.chan].baseFreq>=destFreq) {
|
||||
chan[c.chan].baseFreq=destFreq;
|
||||
return2=true;
|
||||
}
|
||||
} else {
|
||||
chan[c.chan].baseFreq-=c.value;
|
||||
if (chan[c.chan].baseFreq<=destFreq) {
|
||||
chan[c.chan].baseFreq=destFreq;
|
||||
return2=true;
|
||||
}
|
||||
}
|
||||
chan[c.chan].freqChanged=true;
|
||||
if (return2) {
|
||||
chan[c.chan].inPorta=false;
|
||||
return 2;
|
||||
}
|
||||
break;
|
||||
}
|
||||
case DIV_CMD_LEGATO: {
|
||||
chan[c.chan].baseFreq=NOTE_PERIODIC(c.value+((HACKY_LEGATO_MESS)?(chan[c.chan].std.arp.val-12):(0)));
|
||||
chan[c.chan].freqChanged=true;
|
||||
chan[c.chan].note=c.value;
|
||||
break;
|
||||
}
|
||||
case DIV_CMD_PRE_PORTA:
|
||||
if (chan[c.chan].active && c.value2) {
|
||||
if (parent->song.resetMacroOnPorta) chan[c.chan].macroInit(parent->getIns(chan[c.chan].ins,DIV_INS_AMIGA));
|
||||
}
|
||||
if (!chan[c.chan].inPorta && c.value && !parent->song.brokenPortaArp && chan[c.chan].std.arp.will && !NEW_ARP_STRAT) chan[c.chan].baseFreq=NOTE_PERIODIC(chan[c.chan].note);
|
||||
chan[c.chan].inPorta=c.value;
|
||||
break;
|
||||
case DIV_CMD_SAMPLE_POS:
|
||||
chan[c.chan].audPos=c.value;
|
||||
chan[c.chan].setPos=true;
|
||||
break;
|
||||
case DIV_CMD_SAMPLE_DIR: {
|
||||
if (chan[c.chan].reverse!=(bool)(c.value&1)) {
|
||||
chan[c.chan].reverse=c.value&1;
|
||||
}
|
||||
break;
|
||||
}
|
||||
case DIV_CMD_GET_VOLMAX:
|
||||
return 127;
|
||||
break;
|
||||
case DIV_CMD_MACRO_OFF:
|
||||
chan[c.chan].std.mask(c.value,true);
|
||||
break;
|
||||
case DIV_CMD_MACRO_ON:
|
||||
chan[c.chan].std.mask(c.value,false);
|
||||
break;
|
||||
case DIV_ALWAYS_SET_VOLUME:
|
||||
return 1;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
void DivPlatformK053260::muteChannel(int ch, bool mute) {
|
||||
isMuted[ch]=mute;
|
||||
updatePanning(1<<ch);
|
||||
}
|
||||
|
||||
void DivPlatformK053260::forceIns() {
|
||||
for (int i=0; i<4; i++) {
|
||||
chan[i].insChanged=true;
|
||||
chan[i].freqChanged=true;
|
||||
chan[i].sample=-1;
|
||||
chWrite(i,1,isMuted[i]?0:chan[i].panning);
|
||||
}
|
||||
}
|
||||
|
||||
void* DivPlatformK053260::getChanState(int ch) {
|
||||
return &chan[ch];
|
||||
}
|
||||
|
||||
DivMacroInt* DivPlatformK053260::getChanMacroInt(int ch) {
|
||||
return &chan[ch].std;
|
||||
}
|
||||
|
||||
DivDispatchOscBuffer* DivPlatformK053260::getOscBuffer(int ch) {
|
||||
return oscBuf[ch];
|
||||
}
|
||||
|
||||
void DivPlatformK053260::reset() {
|
||||
memset(regPool,0,64);
|
||||
k053260.reset();
|
||||
rWrite(0x28,0); // keyoff all channels
|
||||
for (int i=0; i<4; i++) {
|
||||
chan[i]=DivPlatformK053260::Channel();
|
||||
chan[i].std.setEngine(parent);
|
||||
}
|
||||
updatePanning(0xf);
|
||||
rWrite(0x2f,2); // sound enable
|
||||
}
|
||||
|
||||
int DivPlatformK053260::getOutputCount() {
|
||||
return 2;
|
||||
}
|
||||
|
||||
void DivPlatformK053260::notifyInsChange(int ins) {
|
||||
for (int i=0; i<4; i++) {
|
||||
if (chan[i].ins==ins) {
|
||||
chan[i].insChanged=true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void DivPlatformK053260::notifyWaveChange(int wave) {
|
||||
// TODO when wavetables are added
|
||||
// TODO they probably won't be added unless the samples reside in RAM
|
||||
}
|
||||
|
||||
void DivPlatformK053260::notifyInsDeletion(void* ins) {
|
||||
for (int i=0; i<4; i++) {
|
||||
chan[i].std.notifyInsDeletion((DivInstrument*)ins);
|
||||
}
|
||||
}
|
||||
|
||||
void DivPlatformK053260::setFlags(const DivConfig& flags) {
|
||||
switch (flags.getInt("clockSel",0)) {
|
||||
case 1: chipClock=4000000; break;
|
||||
default: chipClock=COLOR_NTSC; break;
|
||||
}
|
||||
CHECK_CUSTOM_CLOCK;
|
||||
rate=chipClock/TICK_DIVIDER;
|
||||
for (int i=0; i<4; i++) {
|
||||
oscBuf[i]->rate=rate;
|
||||
}
|
||||
}
|
||||
|
||||
void DivPlatformK053260::poke(unsigned int addr, unsigned short val) {
|
||||
rWrite(addr&0x3f,val);
|
||||
}
|
||||
|
||||
void DivPlatformK053260::poke(std::vector<DivRegWrite>& wlist) {
|
||||
for (DivRegWrite& i: wlist) rWrite(i.addr&0x3f,i.val);
|
||||
}
|
||||
|
||||
unsigned char* DivPlatformK053260::getRegisterPool() {
|
||||
regPool[0x29]=k053260.read(0x29); // dynamically updated
|
||||
return regPool;
|
||||
}
|
||||
|
||||
int DivPlatformK053260::getRegisterPoolSize() {
|
||||
return 64;
|
||||
}
|
||||
|
||||
const void* DivPlatformK053260::getSampleMem(int index) {
|
||||
return index == 0 ? sampleMem : NULL;
|
||||
}
|
||||
|
||||
size_t DivPlatformK053260::getSampleMemCapacity(int index) {
|
||||
return index == 0 ? 2097152 : 0;
|
||||
}
|
||||
|
||||
size_t DivPlatformK053260::getSampleMemUsage(int index) {
|
||||
return index == 0 ? sampleMemLen : 0;
|
||||
}
|
||||
|
||||
bool DivPlatformK053260::isSampleLoaded(int index, int sample) {
|
||||
if (index!=0) return false;
|
||||
if (sample<0 || sample>255) return false;
|
||||
return sampleLoaded[sample];
|
||||
}
|
||||
|
||||
void DivPlatformK053260::renderSamples(int sysID) {
|
||||
memset(sampleMem,0,getSampleMemCapacity());
|
||||
memset(sampleOffK053260,0,256*sizeof(unsigned int));
|
||||
memset(sampleLoaded,0,256*sizeof(bool));
|
||||
|
||||
size_t memPos=1; // for avoid silence
|
||||
for (int i=0; i<parent->song.sampleLen; i++) {
|
||||
DivSample* s=parent->song.sample[i];
|
||||
if (!s->renderOn[0][sysID]) {
|
||||
sampleOffK053260[i]=0;
|
||||
continue;
|
||||
}
|
||||
|
||||
int length=MIN(65535,s->getEndPosition(DIV_SAMPLE_DEPTH_8BIT));
|
||||
int actualLength=MIN((int)(getSampleMemCapacity()-memPos-1),length);
|
||||
if (actualLength>0) {
|
||||
sampleOffK053260[i]=memPos-1;
|
||||
for (int j=0; j<actualLength; j++) {
|
||||
sampleMem[memPos++]=s->data8[j];
|
||||
}
|
||||
sampleMem[memPos++]=0; // Silence for avoid popping noise
|
||||
}
|
||||
if (actualLength<length) {
|
||||
logW("out of K053260 PCM memory for sample %d!",i);
|
||||
break;
|
||||
}
|
||||
sampleLoaded[i]=true;
|
||||
}
|
||||
sampleMemLen=memPos;
|
||||
}
|
||||
|
||||
int DivPlatformK053260::init(DivEngine* p, int channels, int sugRate, const DivConfig& flags) {
|
||||
parent=p;
|
||||
dumpWrites=false;
|
||||
skipRegisterWrites=false;
|
||||
|
||||
for (int i=0; i<4; i++) {
|
||||
isMuted[i]=false;
|
||||
oscBuf[i]=new DivDispatchOscBuffer;
|
||||
}
|
||||
sampleMem=new unsigned char[getSampleMemCapacity()];
|
||||
sampleMemLen=0;
|
||||
setFlags(flags);
|
||||
reset();
|
||||
|
||||
return 4;
|
||||
}
|
||||
|
||||
void DivPlatformK053260::quit() {
|
||||
delete[] sampleMem;
|
||||
for (int i=0; i<4; i++) {
|
||||
delete oscBuf[i];
|
||||
}
|
||||
}
|
||||
97
src/engine/platform/k053260.h
Normal file
97
src/engine/platform/k053260.h
Normal file
|
|
@ -0,0 +1,97 @@
|
|||
/**
|
||||
* Furnace Tracker - multi-system chiptune tracker
|
||||
* Copyright (C) 2021-2023 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.
|
||||
*/
|
||||
|
||||
#ifndef _K053260_H
|
||||
#define _K053260_H
|
||||
|
||||
#include "../dispatch.h"
|
||||
#include <queue>
|
||||
#include "vgsound_emu/src/k053260/k053260.hpp"
|
||||
|
||||
class DivPlatformK053260: public DivDispatch, public k053260_intf {
|
||||
struct Channel: public SharedChannel<int> {
|
||||
unsigned int audPos;
|
||||
int sample, wave;
|
||||
int panning;
|
||||
bool setPos, reverse;
|
||||
int macroVolMul;
|
||||
Channel():
|
||||
SharedChannel<int>(127),
|
||||
audPos(0),
|
||||
sample(-1),
|
||||
wave(-1),
|
||||
panning(4),
|
||||
setPos(false),
|
||||
reverse(false),
|
||||
macroVolMul(64) {}
|
||||
};
|
||||
Channel chan[4];
|
||||
DivDispatchOscBuffer* oscBuf[4];
|
||||
bool isMuted[4];
|
||||
int chipType;
|
||||
unsigned char curChan;
|
||||
unsigned int sampleOffK053260[256];
|
||||
bool sampleLoaded[256];
|
||||
|
||||
unsigned char* sampleMem;
|
||||
size_t sampleMemLen;
|
||||
k053260_core k053260;
|
||||
unsigned char regPool[64];
|
||||
void updatePanning(unsigned char mask);
|
||||
|
||||
friend void putDispatchChip(void*,int);
|
||||
friend void putDispatchChan(void*,int,int);
|
||||
|
||||
public:
|
||||
virtual u8 read_sample(u32 address) override;
|
||||
virtual void acquire(short** buf, size_t len) override;
|
||||
virtual int dispatch(DivCommand c) override;
|
||||
virtual void* getChanState(int chan) override;
|
||||
virtual DivMacroInt* getChanMacroInt(int ch) override;
|
||||
virtual DivDispatchOscBuffer* getOscBuffer(int chan) override;
|
||||
virtual unsigned char* getRegisterPool() override;
|
||||
virtual int getRegisterPoolSize() override;
|
||||
virtual void reset() override;
|
||||
virtual void forceIns() override;
|
||||
virtual void tick(bool sysTick=true) override;
|
||||
virtual void muteChannel(int ch, bool mute) override;
|
||||
virtual int getOutputCount() override;
|
||||
virtual void notifyInsChange(int ins) override;
|
||||
virtual void notifyWaveChange(int wave) override;
|
||||
virtual void notifyInsDeletion(void* ins) override;
|
||||
virtual void setFlags(const DivConfig& flags) override;
|
||||
virtual void poke(unsigned int addr, unsigned short val) override;
|
||||
virtual void poke(std::vector<DivRegWrite>& wlist) override;
|
||||
virtual const char** getRegisterSheet() override;
|
||||
virtual const void* getSampleMem(int index = 0) override;
|
||||
virtual size_t getSampleMemCapacity(int index = 0) override;
|
||||
virtual size_t getSampleMemUsage(int index = 0) override;
|
||||
virtual bool isSampleLoaded(int index, int sample) override;
|
||||
virtual void renderSamples(int chipID) override;
|
||||
virtual int init(DivEngine* parent, int channels, int sugRate, const DivConfig& flags) override;
|
||||
virtual void quit() override;
|
||||
DivPlatformK053260():
|
||||
DivDispatch(),
|
||||
k053260_intf(),
|
||||
k053260(*this) {}
|
||||
private:
|
||||
void chWrite(unsigned char ch, unsigned int addr, unsigned char val);
|
||||
};
|
||||
|
||||
#endif
|
||||
|
|
@ -127,7 +127,8 @@ enum DivSystem {
|
|||
DIV_SYSTEM_YM2203_CSM,
|
||||
DIV_SYSTEM_YM2608_CSM,
|
||||
DIV_SYSTEM_SM8521,
|
||||
DIV_SYSTEM_PV1000
|
||||
DIV_SYSTEM_PV1000,
|
||||
DIV_SYSTEM_K053260
|
||||
};
|
||||
|
||||
enum DivEffectType: unsigned short {
|
||||
|
|
|
|||
|
|
@ -1864,6 +1864,19 @@ void DivEngine::registerSystems() {
|
|||
}
|
||||
);
|
||||
|
||||
sysDefs[DIV_SYSTEM_K053260]=new DivSysDef(
|
||||
"Konami K053260", NULL, 0xcc, 0, 4, false, true, 0x161, false, 1U<<DIV_SAMPLE_DEPTH_8BIT,
|
||||
"this PCM chip was widely used at Konami arcade boards in 1990-1992.",
|
||||
{"Channel 1", "Channel 2", "Channel 3", "Channel 4"},
|
||||
{"CH1", "CH2", "CH3", "CH4"},
|
||||
{DIV_CH_PCM, DIV_CH_PCM, DIV_CH_PCM, DIV_CH_PCM},
|
||||
{DIV_INS_K053260, DIV_INS_K053260, DIV_INS_K053260, DIV_INS_K053260},
|
||||
{DIV_INS_AMIGA, DIV_INS_AMIGA, DIV_INS_AMIGA, DIV_INS_AMIGA},
|
||||
{
|
||||
{0xdf, {DIV_CMD_SAMPLE_DIR, "DFxx: Set sample playback direction (0: normal; 1: reverse)"}}
|
||||
}
|
||||
);
|
||||
|
||||
sysDefs[DIV_SYSTEM_DUMMY]=new DivSysDef(
|
||||
"Dummy System", NULL, 0xfd, 0, 8, false, true, 0, false, 0,
|
||||
"this is a system designed for testing purposes.",
|
||||
|
|
|
|||
|
|
@ -564,7 +564,7 @@ void DivEngine::performVGMWrite(SafeWriter* w, DivSystem sys, DivRegWrite& write
|
|||
w->writeC(0xff);
|
||||
break;
|
||||
case DIV_SYSTEM_GA20:
|
||||
for (int i=0; i<3; i++) {
|
||||
for (int i=0; i<4; i++) {
|
||||
w->writeC(0xbf); // mute
|
||||
w->writeC((baseAddr2|5)+(i*8));
|
||||
w->writeC(0);
|
||||
|
|
@ -573,6 +573,16 @@ void DivEngine::performVGMWrite(SafeWriter* w, DivSystem sys, DivRegWrite& write
|
|||
w->writeC(0);
|
||||
}
|
||||
break;
|
||||
case DIV_SYSTEM_K053260:
|
||||
for (int i=0; i<4; i++) {
|
||||
w->writeC(0xba); // mute
|
||||
w->writeC(baseAddr2|0x2f);
|
||||
w->writeC(0);
|
||||
w->writeC(0xba); // keyoff
|
||||
w->writeC(baseAddr2|0x28);
|
||||
w->writeC(0);
|
||||
}
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
|
@ -1029,6 +1039,11 @@ void DivEngine::performVGMWrite(SafeWriter* w, DivSystem sys, DivRegWrite& write
|
|||
w->writeC(baseAddr2|(write.addr&0x7f));
|
||||
w->writeC(write.val);
|
||||
break;
|
||||
case DIV_SYSTEM_K053260:
|
||||
w->writeC(0xba);
|
||||
w->writeC(baseAddr2|(write.addr&0x3f));
|
||||
w->writeC(write.val&0xff);
|
||||
break;
|
||||
default:
|
||||
logW("write not handled!");
|
||||
break;
|
||||
|
|
@ -1201,6 +1216,7 @@ SafeWriter* DivEngine::saveVGM(bool* sysToExport, bool loop, int version, bool p
|
|||
DivDispatch* writeRF5C68[2]={NULL,NULL};
|
||||
DivDispatch* writeMSM6295[2]={NULL,NULL};
|
||||
DivDispatch* writeGA20[2]={NULL,NULL};
|
||||
DivDispatch* writeK053260[2]={NULL,NULL};
|
||||
DivDispatch* writeNES[2]={NULL,NULL};
|
||||
|
||||
int writeNESIndex[2]={0,0};
|
||||
|
|
@ -1725,6 +1741,21 @@ SafeWriter* DivEngine::saveVGM(bool* sysToExport, bool loop, int version, bool p
|
|||
howManyChips++;
|
||||
}
|
||||
break;
|
||||
case DIV_SYSTEM_K053260:
|
||||
if (!hasK053260) {
|
||||
hasK053260=disCont[i].dispatch->chipClock;
|
||||
CHIP_VOL(29,0.4);
|
||||
willExport[i]=true;
|
||||
writeK053260[0]=disCont[i].dispatch;
|
||||
} else if (!(hasK053260&0x40000000)) {
|
||||
isSecond[i]=true;
|
||||
CHIP_VOL_SECOND(29,0.4);
|
||||
willExport[i]=true;
|
||||
writeK053260[1]=disCont[i].dispatch;
|
||||
hasK053260|=0x40000000;
|
||||
howManyChips++;
|
||||
}
|
||||
break;
|
||||
case DIV_SYSTEM_T6W28:
|
||||
if (!hasSN) {
|
||||
hasSN=0xc0000000|disCont[i].dispatch->chipClock;
|
||||
|
|
@ -2086,6 +2117,15 @@ SafeWriter* DivEngine::saveVGM(bool* sysToExport, bool loop, int version, bool p
|
|||
w->writeI(0);
|
||||
w->write(writeGA20[i]->getSampleMem(),writeGA20[i]->getSampleMemUsage());
|
||||
}
|
||||
if (writeK053260[i]!=NULL && writeK053260[i]->getSampleMemUsage()>0) {
|
||||
w->writeC(0x67);
|
||||
w->writeC(0x66);
|
||||
w->writeC(0x8e);
|
||||
w->writeI((writeK053260[i]->getSampleMemUsage()+8)|(i*0x80000000));
|
||||
w->writeI(writeK053260[i]->getSampleMemCapacity());
|
||||
w->writeI(0);
|
||||
w->write(writeK053260[i]->getSampleMem(),writeK053260[i]->getSampleMemUsage());
|
||||
}
|
||||
if (writeNES[i]!=NULL && writeNES[i]->getSampleMemUsage()>0) {
|
||||
size_t howMuchWillBeWritten=writeNES[i]->getSampleMemUsage();
|
||||
w->writeC(0x67);
|
||||
|
|
|
|||
|
|
@ -279,6 +279,10 @@ void FurnaceGUI::insListItem(int i, int dir, int asset) {
|
|||
ImGui::PushStyleColor(ImGuiCol_Text,uiColors[GUI_COLOR_INSTR_PV1000]);
|
||||
name=fmt::sprintf(ICON_FA_GAMEPAD "##_INS%d",i);
|
||||
break;
|
||||
case DIV_INS_K053260:
|
||||
ImGui::PushStyleColor(ImGuiCol_Text,uiColors[GUI_COLOR_INSTR_K053260]);
|
||||
name=fmt::sprintf(ICON_FA_BAR_CHART "##_INS%d",i);
|
||||
break;
|
||||
default:
|
||||
ImGui::PushStyleColor(ImGuiCol_Text,uiColors[GUI_COLOR_INSTR_UNKNOWN]);
|
||||
name=fmt::sprintf(ICON_FA_QUESTION "##_INS%d",i);
|
||||
|
|
|
|||
|
|
@ -53,6 +53,7 @@
|
|||
#include "../engine/platform/ga20.h"
|
||||
#include "../engine/platform/sm8521.h"
|
||||
#include "../engine/platform/pv1000.h"
|
||||
#include "../engine/platform/k053260.h"
|
||||
#include "../engine/platform/dummy.h"
|
||||
|
||||
#define COMMON_CHIP_DEBUG \
|
||||
|
|
@ -544,6 +545,13 @@ void putDispatchChip(void* data, int type) {
|
|||
COMMON_CHIP_DEBUG_BOOL;
|
||||
break;
|
||||
}
|
||||
case DIV_SYSTEM_K053260: {
|
||||
DivPlatformK053260* ch=(DivPlatformK053260*)data;
|
||||
ImGui::Text("> K053260");
|
||||
COMMON_CHIP_DEBUG;
|
||||
COMMON_CHIP_DEBUG_BOOL;
|
||||
break;
|
||||
}
|
||||
default:
|
||||
ImGui::Text("Unimplemented chip! Help!");
|
||||
break;
|
||||
|
|
@ -1082,6 +1090,19 @@ void putDispatchChan(void* data, int chanNum, int type) {
|
|||
COMMON_CHAN_DEBUG_BOOL;
|
||||
break;
|
||||
}
|
||||
case DIV_SYSTEM_K053260: {
|
||||
DivPlatformK053260::Channel* ch=(DivPlatformK053260::Channel*)data;
|
||||
ImGui::Text("> K053260");
|
||||
COMMON_CHAN_DEBUG;
|
||||
ImGui::Text("* Sample: %d",ch->sample);
|
||||
ImGui::Text(" - pos: %d",ch->audPos);
|
||||
ImGui::Text("- panning: %d",ch->panning);
|
||||
ImGui::Text("- macroVolMul: %.2x",ch->macroVolMul);
|
||||
COMMON_CHAN_DEBUG_BOOL;
|
||||
ImGui::TextColored(ch->setPos?colorOn:colorOff,">> SetPos");
|
||||
ImGui::TextColored(ch->reverse?colorOn:colorOff,">> Reverse");
|
||||
break;
|
||||
}
|
||||
default:
|
||||
ImGui::Text("Unimplemented chip! Help!");
|
||||
break;
|
||||
|
|
|
|||
|
|
@ -1378,7 +1378,8 @@ void FurnaceGUI::doAction(int what) {
|
|||
i==DIV_INS_SNES ||
|
||||
i==DIV_INS_ES5506 ||
|
||||
i==DIV_INS_K007232 ||
|
||||
i==DIV_INS_GA20) {
|
||||
i==DIV_INS_GA20 ||
|
||||
i==DIV_INS_K053260) {
|
||||
makeInsTypeList.push_back(i);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -39,7 +39,7 @@ const char* queryReplaceModes[GUI_QUERY_REPLACE_MAX]={
|
|||
"set",
|
||||
"add",
|
||||
"add (overflow)",
|
||||
"scale",
|
||||
"scale %",
|
||||
"clear"
|
||||
};
|
||||
|
||||
|
|
|
|||
|
|
@ -1418,6 +1418,7 @@ void FurnaceGUI::keyDown(SDL_Event& ev) {
|
|||
try {
|
||||
int num=valueKeys.at(ev.key.keysym.sym);
|
||||
if (orderCursor>=0 && orderCursor<e->getTotalChannelCount()) {
|
||||
prepareUndo(GUI_UNDO_CHANGE_ORDER);
|
||||
e->lockSave([this,num]() {
|
||||
e->curOrders->ord[orderCursor][curOrder]=((e->curOrders->ord[orderCursor][curOrder]<<4)|num);
|
||||
});
|
||||
|
|
@ -1436,6 +1437,7 @@ void FurnaceGUI::keyDown(SDL_Event& ev) {
|
|||
}
|
||||
}
|
||||
e->walkSong(loopOrder,loopRow,loopEnd);
|
||||
makeUndo(GUI_UNDO_CHANGE_ORDER);
|
||||
}
|
||||
} catch (std::out_of_range& e) {
|
||||
}
|
||||
|
|
@ -4848,6 +4850,7 @@ bool FurnaceGUI::loop() {
|
|||
case GUI_FILE_SAMPLE_OPEN_RAW:
|
||||
case GUI_FILE_SAMPLE_OPEN_REPLACE_RAW:
|
||||
pendingRawSample=copyOfName;
|
||||
pendingRawSampleReplace=(curFileDialog==GUI_FILE_SAMPLE_OPEN_REPLACE_RAW);
|
||||
displayPendingRawSample=true;
|
||||
break;
|
||||
case GUI_FILE_SAMPLE_SAVE:
|
||||
|
|
@ -5715,10 +5718,26 @@ bool FurnaceGUI::loop() {
|
|||
if (s==NULL) {
|
||||
showError(e->getLastError());
|
||||
} else {
|
||||
if (e->addSamplePtr(s)==-1) {
|
||||
showError(e->getLastError());
|
||||
if (pendingRawSampleReplace) {
|
||||
if (curSample>=0 && curSample<(int)e->song.sample.size()) {
|
||||
e->lockEngine([this,s]() {
|
||||
// if it crashes here please tell me...
|
||||
DivSample* oldSample=e->song.sample[curSample];
|
||||
e->song.sample[curSample]=s;
|
||||
delete oldSample;
|
||||
e->renderSamples();
|
||||
MARK_MODIFIED;
|
||||
});
|
||||
} else {
|
||||
showError("...but you haven't selected a sample!");
|
||||
delete s;
|
||||
}
|
||||
} else {
|
||||
MARK_MODIFIED;
|
||||
if (e->addSamplePtr(s)==-1) {
|
||||
showError(e->getLastError());
|
||||
} else {
|
||||
MARK_MODIFIED;
|
||||
}
|
||||
}
|
||||
}
|
||||
ImGui::CloseCurrentPopup();
|
||||
|
|
@ -6756,6 +6775,7 @@ FurnaceGUI::FurnaceGUI():
|
|||
pendingRawSampleUnsigned(false),
|
||||
pendingRawSampleBigEndian(false),
|
||||
pendingRawSampleSwapNibbles(false),
|
||||
pendingRawSampleReplace(false),
|
||||
globalWinFlags(0),
|
||||
curFileDialog(GUI_FILE_OPEN),
|
||||
warnAction(GUI_WARN_OPEN),
|
||||
|
|
|
|||
|
|
@ -239,6 +239,7 @@ enum FurnaceGUIColors {
|
|||
GUI_COLOR_INSTR_POKEMINI,
|
||||
GUI_COLOR_INSTR_SM8521,
|
||||
GUI_COLOR_INSTR_PV1000,
|
||||
GUI_COLOR_INSTR_K053260,
|
||||
GUI_COLOR_INSTR_UNKNOWN,
|
||||
|
||||
GUI_COLOR_CHANNEL_BG,
|
||||
|
|
@ -1334,7 +1335,7 @@ class FurnaceGUI {
|
|||
|
||||
String pendingRawSample;
|
||||
int pendingRawSampleDepth, pendingRawSampleChannels;
|
||||
bool pendingRawSampleUnsigned, pendingRawSampleBigEndian, pendingRawSampleSwapNibbles;
|
||||
bool pendingRawSampleUnsigned, pendingRawSampleBigEndian, pendingRawSampleSwapNibbles, pendingRawSampleReplace;
|
||||
|
||||
ImGuiWindowFlags globalWinFlags;
|
||||
|
||||
|
|
|
|||
|
|
@ -131,6 +131,7 @@ const char* insTypes[DIV_INS_MAX+1]={
|
|||
"Pokémon Mini/QuadTone",
|
||||
"SM8521",
|
||||
"PV-1000",
|
||||
"K053260",
|
||||
NULL
|
||||
};
|
||||
|
||||
|
|
@ -851,6 +852,7 @@ const FurnaceGUIColorDef guiColors[GUI_COLOR_MAX]={
|
|||
D(GUI_COLOR_INSTR_POKEMINI,"",ImVec4(1.0f,1.0f,0.3f,1.0f)),
|
||||
D(GUI_COLOR_INSTR_SM8521,"",ImVec4(0.5f,0.55f,0.6f,1.0f)),
|
||||
D(GUI_COLOR_INSTR_PV1000,"",ImVec4(0.4f,0.6f,0.7f,1.0f)),
|
||||
D(GUI_COLOR_INSTR_K053260,"",ImVec4(1.0f,0.8f,0.1f,1.0f)),
|
||||
D(GUI_COLOR_INSTR_UNKNOWN,"",ImVec4(0.3f,0.3f,0.3f,1.0f)),
|
||||
|
||||
D(GUI_COLOR_CHANNEL_BG,"",ImVec4(0.4f,0.6f,0.8f,1.0f)),
|
||||
|
|
@ -1034,6 +1036,7 @@ const int availableSystems[]={
|
|||
DIV_SYSTEM_GA20,
|
||||
DIV_SYSTEM_SM8521,
|
||||
DIV_SYSTEM_PV1000,
|
||||
DIV_SYSTEM_K053260,
|
||||
DIV_SYSTEM_PCM_DAC,
|
||||
DIV_SYSTEM_PONG,
|
||||
0 // don't remove this last one!
|
||||
|
|
@ -1142,6 +1145,7 @@ const int chipsSample[]={
|
|||
DIV_SYSTEM_GA20,
|
||||
DIV_SYSTEM_PCM_DAC,
|
||||
DIV_SYSTEM_ES5506,
|
||||
DIV_SYSTEM_K053260,
|
||||
0 // don't remove this last one!
|
||||
};
|
||||
|
||||
|
|
|
|||
|
|
@ -4409,7 +4409,8 @@ void FurnaceGUI::drawInsEdit() {
|
|||
ins->type==DIV_INS_SNES ||
|
||||
ins->type==DIV_INS_ES5506 ||
|
||||
ins->type==DIV_INS_K007232 ||
|
||||
ins->type==DIV_INS_GA20) {
|
||||
ins->type==DIV_INS_GA20 ||
|
||||
ins->type==DIV_INS_K053260) {
|
||||
if (ImGui::BeginTabItem((ins->type==DIV_INS_SU)?"Sound Unit":"Sample")) {
|
||||
String sName;
|
||||
bool wannaOpenSMPopup=false;
|
||||
|
|
@ -5316,7 +5317,8 @@ void FurnaceGUI::drawInsEdit() {
|
|||
}
|
||||
if (ins->type==DIV_INS_FM || ins->type==DIV_INS_SEGAPCM || ins->type==DIV_INS_MIKEY ||
|
||||
ins->type==DIV_INS_MULTIPCM || ins->type==DIV_INS_SU || ins->type==DIV_INS_OPZ ||
|
||||
ins->type==DIV_INS_OPM || ins->type==DIV_INS_SNES || ins->type==DIV_INS_MSM5232) {
|
||||
ins->type==DIV_INS_OPM || ins->type==DIV_INS_SNES || ins->type==DIV_INS_MSM5232 ||
|
||||
ins->type==DIV_INS_K053260) {
|
||||
volMax=127;
|
||||
}
|
||||
if (ins->type==DIV_INS_GB) {
|
||||
|
|
@ -5405,7 +5407,7 @@ void FurnaceGUI::drawInsEdit() {
|
|||
if (ins->type==DIV_INS_TIA || ins->type==DIV_INS_AMIGA || ins->type==DIV_INS_SCC ||
|
||||
ins->type==DIV_INS_PET || ins->type==DIV_INS_SEGAPCM ||
|
||||
ins->type==DIV_INS_FM || ins->type==DIV_INS_K007232 || ins->type==DIV_INS_GA20 ||
|
||||
ins->type==DIV_INS_SM8521 || ins->type==DIV_INS_PV1000) {
|
||||
ins->type==DIV_INS_SM8521 || ins->type==DIV_INS_PV1000 || ins->type==DIV_INS_K053260) {
|
||||
dutyMax=0;
|
||||
}
|
||||
if (ins->type==DIV_INS_VBOY) {
|
||||
|
|
@ -5505,6 +5507,7 @@ void FurnaceGUI::drawInsEdit() {
|
|||
if (ins->type==DIV_INS_SEGAPCM) waveMax=0;
|
||||
if (ins->type==DIV_INS_K007232) waveMax=0;
|
||||
if (ins->type==DIV_INS_GA20) waveMax=0;
|
||||
if (ins->type==DIV_INS_K053260) waveMax=0;
|
||||
if (ins->type==DIV_INS_POKEMINI) waveMax=0;
|
||||
if (ins->type==DIV_INS_SU || ins->type==DIV_INS_POKEY) waveMax=7;
|
||||
if (ins->type==DIV_INS_PET) {
|
||||
|
|
@ -5623,6 +5626,11 @@ void FurnaceGUI::drawInsEdit() {
|
|||
panMax=7;
|
||||
panSingleNoBit=true;
|
||||
}
|
||||
if (ins->type==DIV_INS_K053260) {
|
||||
panMin=-3;
|
||||
panMax=3;
|
||||
panSingleNoBit=true;
|
||||
}
|
||||
if (ins->type==DIV_INS_SU) {
|
||||
panMin=-127;
|
||||
panMax=127;
|
||||
|
|
@ -5713,7 +5721,8 @@ void FurnaceGUI::drawInsEdit() {
|
|||
ins->type==DIV_INS_VBOY ||
|
||||
(ins->type==DIV_INS_X1_010 && ins->amiga.useSample) ||
|
||||
ins->type==DIV_INS_K007232 ||
|
||||
ins->type==DIV_INS_GA20) {
|
||||
ins->type==DIV_INS_GA20 ||
|
||||
ins->type==DIV_INS_K053260) {
|
||||
macroList.push_back(FurnaceGUIMacroDesc("Phase Reset",&ins->std.phaseResetMacro,0,1,32,uiColors[GUI_COLOR_MACRO_OTHER],false,NULL,NULL,true));
|
||||
}
|
||||
if (ex1Max>0) {
|
||||
|
|
|
|||
|
|
@ -1262,6 +1262,42 @@ void FurnaceGUI::initSystemPresets() {
|
|||
CH(DIV_SYSTEM_K007232, 1.0f, 0, "") // ""
|
||||
}
|
||||
);
|
||||
ENTRY(
|
||||
"Konami Rollergames", {
|
||||
CH(DIV_SYSTEM_OPL2, 1.0f, 0, ""), // 3.58MHz
|
||||
CH(DIV_SYSTEM_K053260, 1.0f, 0, ""), // ""
|
||||
}
|
||||
);
|
||||
ENTRY(
|
||||
"Konami Rollergames (drums mode)", {
|
||||
CH(DIV_SYSTEM_OPL2_DRUMS, 1.0f, 0, ""), // 3.58MHz
|
||||
CH(DIV_SYSTEM_K053260, 1.0f, 0, ""), // ""
|
||||
}
|
||||
);
|
||||
ENTRY(
|
||||
"Konami Golfing Greats", {
|
||||
CH(DIV_SYSTEM_K053260, 1.0f, 0, ""), // 3.58MHz
|
||||
}
|
||||
);
|
||||
ENTRY(
|
||||
"Konami Lightning Fighters", {
|
||||
CH(DIV_SYSTEM_YM2151, 1.0f, 0, ""), // 3.58MHz
|
||||
CH(DIV_SYSTEM_K053260, 1.0f, 0, ""), // ""
|
||||
}
|
||||
);
|
||||
ENTRY(
|
||||
"Konami Over Drive", {
|
||||
CH(DIV_SYSTEM_YM2151, 1.0f, 0, ""), // 3.58MHz
|
||||
CH(DIV_SYSTEM_K053260, 1.0f, 0, ""), // ""
|
||||
CH(DIV_SYSTEM_K053260, 1.0f, 0, ""), // ""
|
||||
}
|
||||
);
|
||||
ENTRY(
|
||||
"Konami Asterix", {
|
||||
CH(DIV_SYSTEM_YM2151, 1.0f, 0, "clockSel=2"), // 4MHz
|
||||
CH(DIV_SYSTEM_K053260, 1.0f, 0, "clockSel=1"), // ""
|
||||
}
|
||||
);
|
||||
ENTRY(
|
||||
"Konami Hexion", {
|
||||
CH(DIV_SYSTEM_SCC, 1.0f, 0, "clockSel=2"), // 1.5MHz (3MHz input)
|
||||
|
|
@ -2466,6 +2502,11 @@ void FurnaceGUI::initSystemPresets() {
|
|||
CH(DIV_SYSTEM_ES5506, 1.0f, 0, "channels=31")
|
||||
}
|
||||
);
|
||||
ENTRY(
|
||||
"Konami K053260", {
|
||||
CH(DIV_SYSTEM_K053260, 1.0f, 0, "")
|
||||
}
|
||||
);
|
||||
CATEGORY_END;
|
||||
|
||||
CATEGORY_BEGIN("Wavetable","chips which use user-specified waveforms to generate sound.");
|
||||
|
|
|
|||
|
|
@ -267,6 +267,16 @@ void FurnaceGUI::drawSampleEdit() {
|
|||
SAMPLE_WARN(warnLength,"SegaPCM: maximum sample length is 65280");
|
||||
}
|
||||
break;
|
||||
case DIV_SYSTEM_K053260:
|
||||
if (sample->loop) {
|
||||
if (sample->loopStart!=0 || sample->loopEnd!=(int)(sample->samples)) {
|
||||
SAMPLE_WARN(warnLoopPos,"K053260: loop point ignored (may only loop entire sample)");
|
||||
}
|
||||
}
|
||||
if (sample->samples>65535) {
|
||||
SAMPLE_WARN(warnLength,"K053260: maximum sample length is 65535");
|
||||
}
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -2102,6 +2102,7 @@ void FurnaceGUI::drawSettings() {
|
|||
UI_COLOR_CONFIG(GUI_COLOR_INSTR_POKEMINI,"Pokémon Mini");
|
||||
UI_COLOR_CONFIG(GUI_COLOR_INSTR_SM8521,"SM8521");
|
||||
UI_COLOR_CONFIG(GUI_COLOR_INSTR_PV1000,"PV-1000");
|
||||
UI_COLOR_CONFIG(GUI_COLOR_INSTR_K053260,"K053260");
|
||||
UI_COLOR_CONFIG(GUI_COLOR_INSTR_UNKNOWN,"Other/Unknown");
|
||||
ImGui::TreePop();
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1882,6 +1882,26 @@ bool FurnaceGUI::drawSysConf(int chan, DivSystem type, DivConfig& flags, bool mo
|
|||
}
|
||||
break;
|
||||
}*/
|
||||
case DIV_SYSTEM_K053260: {
|
||||
int clockSel=flags.getInt("clockSel",0);
|
||||
|
||||
ImGui::Text("Clock rate:");
|
||||
if (ImGui::RadioButton("3.58MHz (NTSC)",clockSel==0)) {
|
||||
clockSel=0;
|
||||
altered=true;
|
||||
}
|
||||
if (ImGui::RadioButton("4MHz",clockSel==1)) {
|
||||
clockSel=1;
|
||||
altered=true;
|
||||
}
|
||||
|
||||
if (altered) {
|
||||
e->lockSave([&]() {
|
||||
flags.set("clockSel",clockSel);
|
||||
});
|
||||
}
|
||||
break;
|
||||
}
|
||||
case DIV_SYSTEM_SWAN:
|
||||
case DIV_SYSTEM_BUBSYS_WSG:
|
||||
case DIV_SYSTEM_PET:
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue