Merge pull request #1014 from tildearrow/pv1000

Add NEC D65010G031 support
This commit is contained in:
tildearrow 2023-03-06 03:16:44 -05:00 committed by GitHub
commit c2b2cade94
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
18 changed files with 568 additions and 4 deletions

View File

@ -459,6 +459,8 @@ src/engine/platform/sound/ga20/iremga20.cpp
src/engine/platform/sound/sm8521.c
src/engine/platform/sound/d65010g031.c
src/engine/platform/oplAInterface.cpp
src/engine/platform/ym2608Interface.cpp
src/engine/platform/ym2610Interface.cpp
@ -544,6 +546,7 @@ src/engine/platform/snes.cpp
src/engine/platform/k007232.cpp
src/engine/platform/ga20.cpp
src/engine/platform/sm8521.cpp
src/engine/platform/pv1000.cpp
src/engine/platform/pcmdac.cpp
src/engine/platform/dummy.cpp
)

View File

@ -76,6 +76,7 @@
#include "platform/k007232.h"
#include "platform/ga20.h"
#include "platform/sm8521.h"
#include "platform/pv1000.h"
#include "platform/pcmdac.h"
#include "platform/dummy.h"
#include "../ta-log.h"
@ -493,6 +494,9 @@ void DivDispatchContainer::init(DivSystem sys, DivEngine* eng, int chanCount, do
case DIV_SYSTEM_SM8521:
dispatch=new DivPlatformSM8521;
break;
case DIV_SYSTEM_PV1000:
dispatch=new DivPlatformPV1000;
break;
case DIV_SYSTEM_PCM_DAC:
dispatch=new DivPlatformPCMDAC;
break;

View File

@ -928,6 +928,8 @@ void DivInstrument::putInsData2(SafeWriter* w, bool fui, const DivSong* song) {
checkForWL=true;
if (ws.enabled) featureWS=true;
break;
case DIV_INS_PV1000:
break;
case DIV_INS_MAX:
break;

View File

@ -79,6 +79,7 @@ enum DivInstrumentType: unsigned short {
DIV_INS_GA20=46,
DIV_INS_POKEMINI=47,
DIV_INS_SM8521=48,
DIV_INS_PV1000=49,
DIV_INS_MAX,
DIV_INS_NULL
};

View File

@ -0,0 +1,286 @@
/**
* 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 "pv1000.h"
#include "../engine.h"
#include <math.h>
#define rWrite(a,v) {regPool[(a)]=(v)&0xff; d65010g031_write(&d65010g031,a,v);}
#define CHIP_DIVIDER 1024
const char* regCheatSheetPV1000[]={
"CH1_Pitch", "00",
"CH2_Pitch", "01",
"CH3_Pitch", "02",
NULL
};
const char** DivPlatformPV1000::getRegisterSheet() {
return regCheatSheetPV1000;
}
void DivPlatformPV1000::acquire(short** buf, size_t len) {
for (size_t h=0; h<len; h++) {
short samp;
samp=d65010g031_sound_tick(&d65010g031,1);
buf[0][h]=samp<<12;
for (int i=0; i<3; i++) {
oscBuf[i]->data[oscBuf[i]->needle++]=(d65010g031.square[i].out<<12);
}
}
}
void DivPlatformPV1000::tick(bool sysTick) {
for (int i=0; i<3; i++) {
chan[i].std.next();
if (chan[i].std.vol.had) {
chan[i].outVol=(chan[i].vol && chan[i].std.vol.val);
chan[i].freqChanged=true;
}
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].freqChanged || chan[i].keyOn || chan[i].keyOff) {
chan[i].freq=0x3f-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<1) chan[i].freq=1;
if (chan[i].freq>62) chan[i].freq=62;
if (isMuted[i]) chan[i].keyOn=false;
if (chan[i].keyOn) {
rWrite(i,(isMuted[i] || (chan[i].outVol<=0)) ? 0 : chan[i].freq);
chan[i].keyOn=false;
} else if (chan[i].freqChanged && chan[i].active && !isMuted[i]) {
rWrite(i,(isMuted[i] || (chan[i].outVol<=0)) ? 0 : chan[i].freq);
}
if (chan[i].keyOff) {
rWrite(i,0);
chan[i].keyOff=false;
}
chan[i].freqChanged=false;
}
}
}
int DivPlatformPV1000::dispatch(DivCommand c) {
switch (c.cmd) {
case DIV_CMD_NOTE_ON: {
DivInstrument* ins=parent->getIns(chan[c.chan].ins,DIV_INS_PV1000);
if (c.value!=DIV_NOTE_NULL) {
chan[c.chan].baseFreq=NOTE_PERIODIC(c.value);
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);
break;
}
case DIV_CMD_NOTE_OFF:
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;
}
if (chan[c.chan].active) {
chan[c.chan].freqChanged=true;
}
}
break;
case DIV_CMD_GET_VOLUME:
return chan[c.chan].vol;
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):(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_PV1000));
}
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_GET_VOLMAX:
return 1;
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 DivPlatformPV1000::muteChannel(int ch, bool mute) {
isMuted[ch]=mute;
if (mute) {
chan[ch].keyOff=true;
} else if (chan[ch].active) {
chan[ch].keyOn=true;
chan[ch].freqChanged=true;
}
}
void DivPlatformPV1000::forceIns() {
for (int i=0; i<3; i++) {
chan[i].insChanged=true;
chan[i].freqChanged=true;
}
}
void* DivPlatformPV1000::getChanState(int ch) {
return &chan[ch];
}
DivMacroInt* DivPlatformPV1000::getChanMacroInt(int ch) {
return &chan[ch].std;
}
DivDispatchOscBuffer* DivPlatformPV1000::getOscBuffer(int ch) {
return oscBuf[ch];
}
unsigned char* DivPlatformPV1000::getRegisterPool() {
return regPool;
}
int DivPlatformPV1000::getRegisterPoolSize() {
return 3;
}
void DivPlatformPV1000::reset() {
memset(regPool,0,3);
for (int i=0; i<3; i++) {
chan[i]=Channel();
chan[i].std.setEngine(parent);
}
d65010g031_reset(&d65010g031);
}
int DivPlatformPV1000::getOutputCount() {
return 1;
}
void DivPlatformPV1000::notifyInsDeletion(void* ins) {
for (int i=0; i<3; i++) {
chan[i].std.notifyInsDeletion((DivInstrument*)ins);
}
}
void DivPlatformPV1000::setFlags(const DivConfig& flags) {
chipClock=COLOR_NTSC*5.0;
CHECK_CUSTOM_CLOCK;
rate=chipClock/1024;
for (int i=0; i<3; i++) {
oscBuf[i]->rate=rate;
}
}
void DivPlatformPV1000::poke(unsigned int addr, unsigned short val) {
rWrite(addr,val);
}
void DivPlatformPV1000::poke(std::vector<DivRegWrite>& wlist) {
for (DivRegWrite& i: wlist) rWrite(i.addr,i.val);
}
int DivPlatformPV1000::init(DivEngine* p, int channels, int sugRate, const DivConfig& flags) {
parent=p;
dumpWrites=false;
skipRegisterWrites=false;
for (int i=0; i<3; i++) {
isMuted[i]=false;
oscBuf[i]=new DivDispatchOscBuffer;
}
setFlags(flags);
reset();
return 4;
}
void DivPlatformPV1000::quit() {
for (int i=0; i<3; i++) {
delete oscBuf[i];
}
}
DivPlatformPV1000::~DivPlatformPV1000() {
}

View File

@ -0,0 +1,63 @@
/**
* 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 _PV1000_H
#define _PV1000_H
#include "../dispatch.h"
#include "sound/d65010g031.h"
#include <queue>
class DivPlatformPV1000: public DivDispatch {
struct Channel: public SharedChannel<int> {
Channel():
SharedChannel<int>(1) {}
};
Channel chan[3];
DivDispatchOscBuffer* oscBuf[3];
bool isMuted[3];
unsigned char regPool[3];
d65010g031_t d65010g031;
friend void putDispatchChip(void*,int);
friend void putDispatchChan(void*,int,int);
public:
void acquire(short** buf, size_t len);
int dispatch(DivCommand c);
void* getChanState(int chan);
DivMacroInt* getChanMacroInt(int ch);
DivDispatchOscBuffer* getOscBuffer(int chan);
unsigned char* getRegisterPool();
int getRegisterPoolSize();
void reset();
void forceIns();
void tick(bool sysTick=true);
void muteChannel(int ch, bool mute);
void setFlags(const DivConfig& flags);
void notifyInsDeletion(void* ins);
int getOutputCount();
void poke(unsigned int addr, unsigned short val);
void poke(std::vector<DivRegWrite>& wlist);
const char** getRegisterSheet();
int init(DivEngine* parent, int channels, int sugRate, const DivConfig& flags);
void quit();
~DivPlatformPV1000();
};
#endif

View File

@ -0,0 +1,86 @@
/*
============================================================================
NEC D65010G031 sound emulator
by cam900
This file is licensed under zlib license.
============================================================================
zlib License
(C) 2023-present cam900 and contributors
This software is provided 'as-is', without any express or implied
warranty. In no event will the authors be held liable for any damages
arising from the use of this software.
Permission is granted to anyone to use this software for any purpose,
including commercial applications, and to alter it and redistribute it
freely, subject to the following restrictions:
1. The origin of this software must not be misrepresented; you must not
claim that you wrote the original software. If you use this software
in a product, an acknowledgment in the product documentation would be
appreciated but is not required.
2. Altered source versions must be plainly marked as such, and must not be
misrepresented as being the original software.
3. This notice may not be removed or altered from any source distribution.
============================================================================
TODO:
- needs hardware test
*/
#include "d65010g031.h"
#include <stdlib.h>
static int d65010g031_max(int a, int b) { return (a > b) ? a : b; }
int d65010g031_square_tick(struct d65010g031_square_t *square, const int cycle)
{
if (square->period > 0)
{
int period = d65010g031_max(1, (0x3f - square->period));
square->counter += cycle;
while (square->counter >= period)
{
square->counter -= period;
square->out ^= 1;
}
return square->out;
}
return 0;
}
int d65010g031_sound_tick(struct d65010g031_t *d65010g031, const int cycle)
{
int out = 0;
for (int i = 0; i < 3; i++)
{
out += d65010g031_square_tick(&d65010g031->square[i], cycle);
}
return out;
}
void d65010g031_reset(struct d65010g031_t *d65010g031)
{
for (int i = 0; i < 3; i++)
{
d65010g031->square[i].period = 0;
d65010g031->square[i].counter = 0;
d65010g031->square[i].out = 0;
}
}
void d65010g031_write(struct d65010g031_t *d65010g031, const unsigned char a, const unsigned char d)
{
if (a < 3)
{
d65010g031->square[a].period = d & 0x3f;
}
}

View File

@ -0,0 +1,71 @@
/*
============================================================================
NEC D65010G031 sound emulator
by cam900
This file is licensed under zlib license.
============================================================================
zlib License
(C) 2023-present cam900 and contributors
This software is provided 'as-is', without any express or implied
warranty. In no event will the authors be held liable for any damages
arising from the use of this software.
Permission is granted to anyone to use this software for any purpose,
including commercial applications, and to alter it and redistribute it
freely, subject to the following restrictions:
1. The origin of this software must not be misrepresented; you must not
claim that you wrote the original software. If you use this software
in a product, an acknowledgment in the product documentation would be
appreciated but is not required.
2. Altered source versions must be plainly marked as such, and must not be
misrepresented as being the original software.
3. This notice may not be removed or altered from any source distribution.
============================================================================
TODO:
- needs hardware test
*/
#ifndef _D65010G031_EMU_H
#define _D65010G031_EMU_H
#ifdef __cplusplus
extern "C"
{
#endif
struct d65010g031_square_t
{
unsigned char period; // Period (0 = Off)
int counter; // clock counter
signed short out; // output
};
struct d65010g031_t
{
struct d65010g031_square_t square[3];
};
int d65010g031_square_tick(struct d65010g031_square_t *square, const int cycle);
int d65010g031_sound_tick(struct d65010g031_t *d65010g031, const int cycle);
void d65010g031_reset(struct d65010g031_t *d65010g031);
void d65010g031_write(struct d65010g031_t *d65010g031, const unsigned char a, const unsigned char d);
#ifdef __cplusplus
} // extern "C"
#endif
#endif // _D65010G031_EMU_H

View File

@ -125,7 +125,8 @@ enum DivSystem {
DIV_SYSTEM_YM2610B_CSM,
DIV_SYSTEM_YM2203_CSM,
DIV_SYSTEM_YM2608_CSM,
DIV_SYSTEM_SM8521
DIV_SYSTEM_SM8521,
DIV_SYSTEM_PV1000
};
struct DivGroovePattern {

View File

@ -1833,6 +1833,15 @@ void DivEngine::registerSystems() {
waveOnlyEffectHandlerMap
);
sysDefs[DIV_SYSTEM_PV1000]=new DivSysDef(
"Casio PV-1000", NULL, 0xcb, 0, 3, false, true, 0, false, 0,
"a game console with 3 channels of square wave. it's what happens after fusing TIA and VIC together.",
{"Square 1", "Square 2", "Square 3"},
{"S1", "S2", "S3"},
{DIV_CH_PULSE, DIV_CH_PULSE, DIV_CH_PULSE},
{DIV_INS_PV1000, DIV_INS_PV1000, DIV_INS_PV1000}
);
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.",

View File

@ -434,6 +434,10 @@ void FurnaceGUI::drawInsList(bool asChild) {
ImGui::PushStyleColor(ImGuiCol_Text,uiColors[GUI_COLOR_INSTR_SM8521]);
name=fmt::sprintf(ICON_FA_GAMEPAD "##_INS%d",i);
break;
case DIV_INS_PV1000:
ImGui::PushStyleColor(ImGuiCol_Text,uiColors[GUI_COLOR_INSTR_PV1000]);
name=fmt::sprintf(ICON_FA_GAMEPAD "##_INS%d",i);
break;
default:
ImGui::PushStyleColor(ImGuiCol_Text,uiColors[GUI_COLOR_INSTR_UNKNOWN]);
name=fmt::sprintf(ICON_FA_QUESTION "##_INS%d",i);

View File

@ -52,6 +52,7 @@
#include "../engine/platform/k007232.h"
#include "../engine/platform/ga20.h"
#include "../engine/platform/sm8521.h"
#include "../engine/platform/pv1000.h"
#include "../engine/platform/dummy.h"
#define COMMON_CHIP_DEBUG \
@ -537,6 +538,13 @@ void putDispatchChip(void* data, int type) {
ImGui::TextColored(ch->antiClickEnabled?colorOn:colorOff,">> AntiClickEnabled");
break;
}
case DIV_SYSTEM_PV1000: {
DivPlatformPV1000* ch=(DivPlatformPV1000*)data;
ImGui::Text("> PV1000");
COMMON_CHIP_DEBUG;
COMMON_CHIP_DEBUG_BOOL;
break;
}
default:
ImGui::Text("Unimplemented chip! Help!");
break;
@ -1068,6 +1076,13 @@ void putDispatchChan(void* data, int chanNum, int type) {
ImGui::TextColored(ch->volumeChanged?colorOn:colorOff,">> VolumeChanged");
break;
}
case DIV_SYSTEM_PV1000: {
DivPlatformPV1000::Channel* ch=(DivPlatformPV1000::Channel*)data;
ImGui::Text("> PV1000");
COMMON_CHAN_DEBUG;
COMMON_CHAN_DEBUG_BOOL;
break;
}
default:
ImGui::Text("Unimplemented chip! Help!");
break;

View File

@ -190,6 +190,7 @@ enum FurnaceGUIColors {
GUI_COLOR_INSTR_GA20,
GUI_COLOR_INSTR_POKEMINI,
GUI_COLOR_INSTR_SM8521,
GUI_COLOR_INSTR_PV1000,
GUI_COLOR_INSTR_UNKNOWN,
GUI_COLOR_CHANNEL_BG,

View File

@ -130,6 +130,7 @@ const char* insTypes[DIV_INS_MAX+1]={
"GA20",
"Pokémon Mini",
"SM8521",
"PV-1000",
NULL
};
@ -820,6 +821,7 @@ const FurnaceGUIColorDef guiColors[GUI_COLOR_MAX]={
D(GUI_COLOR_INSTR_GA20,"",ImVec4(0.1f,1.0f,0.4f,1.0f)),
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_UNKNOWN,"",ImVec4(0.3f,0.3f,0.3f,1.0f)),
D(GUI_COLOR_CHANNEL_BG,"",ImVec4(0.4f,0.6f,0.8f,1.0f)),
@ -1001,6 +1003,7 @@ const int availableSystems[]={
DIV_SYSTEM_K007232,
DIV_SYSTEM_GA20,
DIV_SYSTEM_SM8521,
DIV_SYSTEM_PV1000,
DIV_SYSTEM_PCM_DAC,
DIV_SYSTEM_PONG,
0 // don't remove this last one!
@ -1050,6 +1053,7 @@ const int chipsSquare[]={
DIV_SYSTEM_VIC20,
DIV_SYSTEM_MSM5232,
DIV_SYSTEM_T6W28,
DIV_SYSTEM_PV1000,
0 // don't remove this last one!
};

View File

@ -5039,7 +5039,7 @@ void FurnaceGUI::drawInsEdit() {
volMax=0;
}
}
if (ins->type==DIV_INS_PET || ins->type==DIV_INS_BEEPER) {
if (ins->type==DIV_INS_PET || ins->type==DIV_INS_BEEPER || ins->type==DIV_INS_PV1000) {
volMax=1;
}
if (ins->type==DIV_INS_FDS) {
@ -5118,7 +5118,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_VIC || 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_SM8521 || ins->type==DIV_INS_PV1000) {
dutyMax=0;
}
if (ins->type==DIV_INS_VBOY) {
@ -5190,7 +5190,9 @@ void FurnaceGUI::drawInsEdit() {
if (ins->type==DIV_INS_C64 || ins->type==DIV_INS_SAA1099) {
waveBitMode=true;
}
if (ins->type==DIV_INS_STD || ins->type==DIV_INS_VRC6_SAW || ins->type==DIV_INS_NES || ins->type==DIV_INS_T6W28) waveMax=0;
if (ins->type==DIV_INS_STD || ins->type==DIV_INS_VRC6_SAW || ins->type==DIV_INS_NES ||
ins->type==DIV_INS_T6W28 || ins->type==DIV_INS_PV1000)
waveMax=0;
if (ins->type==DIV_INS_TIA || ins->type==DIV_INS_VIC || ins->type==DIV_INS_OPLL) waveMax=15;
if (ins->type==DIV_INS_C64) waveMax=4;
if (ins->type==DIV_INS_SAA1099) waveMax=2;

View File

@ -261,6 +261,11 @@ void FurnaceGUI::initSystemPresets() {
CH(DIV_SYSTEM_SM8521, 1.0f, 0, "")
}
);
ENTRY(
"Casio PV-1000", {
CH(DIV_SYSTEM_PV1000, 1.0f, 0, "")
}
);
CATEGORY_END;
CATEGORY_BEGIN("Computers","let's get to work on chiptune today.");
@ -2370,6 +2375,11 @@ void FurnaceGUI::initSystemPresets() {
CH(DIV_SYSTEM_PONG, 1.0f, 0, "")
}
);
ENTRY(
"NEC D65010G031", {
CH(DIV_SYSTEM_PV1000, 1.0f, 0, "")
}
);
CATEGORY_END;
CATEGORY_BEGIN("Sample","chips/systems which use PCM or ADPCM samples for sound synthesis.");

View File

@ -1929,6 +1929,7 @@ void FurnaceGUI::drawSettings() {
UI_COLOR_CONFIG(GUI_COLOR_INSTR_GA20,"GA20");
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_UNKNOWN,"Other/Unknown");
ImGui::TreePop();
}

View File

@ -1723,6 +1723,7 @@ bool FurnaceGUI::drawSysConf(int chan, DivSystem type, DivConfig& flags, bool mo
case DIV_SYSTEM_PET:
case DIV_SYSTEM_VBOY:
case DIV_SYSTEM_GA20:
case DIV_SYSTEM_PV1000:
ImGui::Text("nothing to configure");
break;
case DIV_SYSTEM_VERA: