From 8235f6ee66868712f81ec30b5e9e2e257f9bec19 Mon Sep 17 00:00:00 2001 From: tildearrow Date: Wed, 11 Oct 2023 02:48:39 -0500 Subject: [PATCH] C140: add bank types --- CMakeLists.txt | 1 + src/engine/engine.cpp | 3 ++- src/engine/engine.h | 2 +- src/engine/pitchTable.cpp | 23 +++++++++++++++++ src/engine/platform/c140.cpp | 27 ++++++++++++++++--- src/engine/platform/c140.h | 1 + src/engine/platform/sound/c140_c219.c | 16 +++++++++++- src/engine/platform/sound/c140_c219.h | 5 +++- src/engine/vgmOps.cpp | 1 + src/gui/sysConf.cpp | 37 +++++++++++++++++++++++++-- 10 files changed, 107 insertions(+), 9 deletions(-) create mode 100644 src/engine/pitchTable.cpp diff --git a/CMakeLists.txt b/CMakeLists.txt index 2aeae78c7f..6278184b57 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -585,6 +585,7 @@ src/engine/filter.cpp src/engine/instrument.cpp src/engine/macroInt.cpp src/engine/pattern.cpp +src/engine/pitchTable.cpp src/engine/playback.cpp src/engine/sample.cpp src/engine/song.cpp diff --git a/src/engine/engine.cpp b/src/engine/engine.cpp index 353ba71edc..b9209b9651 100644 --- a/src/engine/engine.cpp +++ b/src/engine/engine.cpp @@ -3212,10 +3212,11 @@ void DivEngine::setOrder(unsigned char order) { BUSY_END; } -void DivEngine::updateSysFlags(int system, bool restart) { +void DivEngine::updateSysFlags(int system, bool restart, bool render) { BUSY_BEGIN_SOFT; disCont[system].dispatch->setFlags(song.systemFlags[system]); disCont[system].setRates(got.rate); + if (render) renderSamples(); // patchbay if (song.patchbayAuto) { diff --git a/src/engine/engine.h b/src/engine/engine.h index 1c6012bd75..4bae9db9e7 100644 --- a/src/engine/engine.h +++ b/src/engine/engine.h @@ -996,7 +996,7 @@ class DivEngine { void setOrder(unsigned char order); // update system flags - void updateSysFlags(int system, bool restart); + void updateSysFlags(int system, bool restart, bool render); // set Hz void setSongRate(float hz); diff --git a/src/engine/pitchTable.cpp b/src/engine/pitchTable.cpp new file mode 100644 index 0000000000..818a97dce2 --- /dev/null +++ b/src/engine/pitchTable.cpp @@ -0,0 +1,23 @@ +/** + * 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 "dispatch.h" + + + \ No newline at end of file diff --git a/src/engine/platform/c140.cpp b/src/engine/platform/c140.cpp index 9e144c6637..09d08e304a 100644 --- a/src/engine/platform/c140.cpp +++ b/src/engine/platform/c140.cpp @@ -271,6 +271,14 @@ void DivPlatformC140::tick(bool sysTick) { } } } else { + switch (bankType) { + case 0: + bank=((bank&8)<<2)|(bank&7); + break; + case 1: + bank=((bank&0x18)<<1)|(bank&7); + break; + } rWrite(0x04+(i<<4),bank); } rWrite(0x06+(i<<4),(start>>8)&0xff); @@ -548,7 +556,15 @@ const void* DivPlatformC140::getSampleMem(int index) { } size_t DivPlatformC140::getSampleMemCapacity(int index) { - return index == 0 ? (is219?524288:16777216) : 0; + if (index!=0) return 0; + if (is219) return 524288; + switch (bankType) { + case 0: + return 2097152; + case 1: + return 4194304; + } + return 16777216; } size_t DivPlatformC140::getSampleMemUsage(int index) { @@ -562,7 +578,7 @@ bool DivPlatformC140::isSampleLoaded(int index, int sample) { } void DivPlatformC140::renderSamples(int sysID) { - memset(sampleMem,0,getSampleMemCapacity()); + memset(sampleMem,0,is219?524288:16777216); memset(sampleOff,0,256*sizeof(unsigned int)); memset(sampleLoaded,0,256*sizeof(bool)); @@ -701,6 +717,10 @@ void DivPlatformC140::setFlags(const DivConfig& flags) { CHECK_CUSTOM_CLOCK; rate=chipClock/192; } + bankType=flags.getInt("bankType",0); + if (!is219) { + c140_bank_type(&c140,bankType); + } for (int i=0; irate=rate; } @@ -710,12 +730,13 @@ int DivPlatformC140::init(DivEngine* p, int channels, int sugRate, const DivConf parent=p; dumpWrites=false; skipRegisterWrites=false; + bankType=2; for (int i=0; ibank_type = type; +} + void c140_write(struct c140_t *c140, const unsigned short addr, const unsigned char data) { // voice register @@ -345,7 +350,16 @@ void c140_write(struct c140_t *c140, const unsigned short addr, const unsigned c case 0x1: voice->lvol = data; break; case 0x2: voice->freq = (voice->freq & ~0xff00) | (unsigned int)(data << 8); break; case 0x3: voice->freq = (voice->freq & ~0x00ff) | data; break; - case 0x4: voice->bank = data; break; + case 0x4: { // TILDEARROW + if (c140->bank_type == 0) { + voice->bank = ((data&0x20)>>2)|data&7; + } else if (c140->bank_type == 1) { + voice->bank = ((data&0x30)>>1)|data&7; + } else { + voice->bank = data; + } + break; + } case 0x5: voice->compressed = c140_bit(data, 3); voice->loop = c140_bit(data, 4); diff --git a/src/engine/platform/sound/c140_c219.h b/src/engine/platform/sound/c140_c219.h index fb19125a39..ac443b8db6 100644 --- a/src/engine/platform/sound/c140_c219.h +++ b/src/engine/platform/sound/c140_c219.h @@ -5,7 +5,7 @@ MODIFIED Namco C140/C219 sound emulator - MODIFIED VERSION by cam900 -MODIFICATION by tildearrow - adds muting function +MODIFICATION by tildearrow - adds muting function AND VGM banking THIS IS NOT THE ORIGINAL VERSION - you can find the original one in commit 72d04777c013988ed8cf6da27c62a9d784a59dff @@ -78,6 +78,7 @@ struct c140_t signed int lout, rout; signed short mulaw[256]; signed short *sample_mem; + unsigned char bank_type; }; struct c219_t @@ -106,6 +107,8 @@ void c140_write(struct c140_t *c140, const unsigned short addr, const unsigned c void c219_write(struct c219_t *c219, const unsigned short addr, const unsigned char data); +void c140_bank_type(struct c140_t *c140, unsigned char type); + void c140_init(struct c140_t *c140); void c219_init(struct c219_t *c219); diff --git a/src/engine/vgmOps.cpp b/src/engine/vgmOps.cpp index 599f568766..c8c6cef79f 100644 --- a/src/engine/vgmOps.cpp +++ b/src/engine/vgmOps.cpp @@ -1834,6 +1834,7 @@ SafeWriter* DivEngine::saveVGM(bool* sysToExport, bool loop, int version, bool p CHIP_VOL(40,1.0); willExport[i]=true; writeC140[0]=disCont[i].dispatch; + c140Type=(song.systemFlags[i].getInt("bankType",0)==1)?1:0; } else if (!(hasC140&0x40000000)) { isSecond[i]=true; CHIP_VOL_SECOND(40,1.0); diff --git a/src/gui/sysConf.cpp b/src/gui/sysConf.cpp index 10a6c76e58..b8caa73904 100644 --- a/src/gui/sysConf.cpp +++ b/src/gui/sysConf.cpp @@ -24,6 +24,7 @@ bool FurnaceGUI::drawSysConf(int chan, int sysPos, DivSystem type, DivConfig& flags, bool modifyOnChange, bool fromMenu) { bool altered=false; + bool mustRender=false; bool restart=modifyOnChange; bool supportsCustomRate=true; @@ -896,18 +897,22 @@ bool FurnaceGUI::drawSysConf(int chan, int sysPos, DivSystem type, DivConfig& fl if (ImGui::RadioButton("2MB (ECS/AGA max)",chipMem==21)) { chipMem=21; altered=true; + mustRender=true; } if (ImGui::RadioButton("1MB",chipMem==20)) { chipMem=20; altered=true; + mustRender=true; } if (ImGui::RadioButton("512KB (OCS max)",chipMem==19)) { chipMem=19; altered=true; + mustRender=true; } if (ImGui::RadioButton("256KB",chipMem==18)) { chipMem=18; altered=true; + mustRender=true; } ImGui::Unindent(); @@ -2181,6 +2186,35 @@ bool FurnaceGUI::drawSysConf(int chan, int sysPos, DivSystem type, DivConfig& fl } break; } + case DIV_SYSTEM_C140: { + int bankType=flags.getInt("bankType",0); + + ImGui::Text("Banking style:"); + ImGui::Indent(); + if (ImGui::RadioButton("Namco System 2 (2MB)",bankType==0)) { + bankType=0; + altered=true; + mustRender=true; + } + if (ImGui::RadioButton("Namco System 21 (4MB)",bankType==1)) { + bankType=1; + altered=true; + mustRender=true; + } + if (ImGui::RadioButton("Raw (16MB; no VGM export!)",bankType==2)) { + bankType=2; + altered=true; + mustRender=true; + } + ImGui::Unindent(); + + if (altered) { + e->lockSave([&]() { + flags.set("bankType",bankType); + }); + } + break; + } case DIV_SYSTEM_SWAN: case DIV_SYSTEM_BUBSYS_WSG: case DIV_SYSTEM_PET: @@ -2188,7 +2222,6 @@ bool FurnaceGUI::drawSysConf(int chan, int sysPos, DivSystem type, DivConfig& fl case DIV_SYSTEM_GA20: case DIV_SYSTEM_PV1000: case DIV_SYSTEM_VERA: - case DIV_SYSTEM_C140: case DIV_SYSTEM_C219: break; case DIV_SYSTEM_YMU759: @@ -2241,7 +2274,7 @@ bool FurnaceGUI::drawSysConf(int chan, int sysPos, DivSystem type, DivConfig& fl if (altered) { if (chan>=0) { - e->updateSysFlags(chan,restart); + e->updateSysFlags(chan,restart,mustRender); if (e->song.autoSystem) { autoDetectSystem(); }