diff --git a/CMakeLists.txt b/CMakeLists.txt index f4460c9..b42dc8a 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -118,6 +118,7 @@ set(SOURCES "src/formats_sup.cpp" "src/importer.cpp" "src/latency.cpp" + "src/hardware.cpp" "src/ins_names.cpp" "src/main.cpp" "src/opl/generator.cpp" diff --git a/FMBankEdit.pro b/FMBankEdit.pro index 40091fb..e73b065 100644 --- a/FMBankEdit.pro +++ b/FMBankEdit.pro @@ -122,6 +122,7 @@ SOURCES += \ src/formats_sup.cpp \ src/importer.cpp \ src/latency.cpp \ + src/hardware.cpp \ src/ins_names.cpp \ src/main.cpp \ src/opl/generator.cpp \ @@ -162,6 +163,7 @@ HEADERS += \ src/formats_sup.h \ src/importer.h \ src/latency.h \ + src/hardware.h \ src/ins_names.h \ src/main.h \ src/opl/generator.h \ diff --git a/build.bat b/build.bat index b9d95de..5fcefa4 100644 --- a/build.bat +++ b/build.bat @@ -33,8 +33,10 @@ IF NOT -%1-==-win9x- ( SET DEST_ARCHIVE=opl3-bank-editor-dev-win32.zip SET DEPLOY_FILES=.\bin-release\* IF -%1-==-win9x- ( - SET DEPLOY_FILES=%DEPLOY_FILES% .\opl_proxy\liboplproxy.dll + SET DEPLOY_FILES=%DEPLOY_FILES% .\opl_proxy\win9x\liboplproxy.dll SET DEST_ARCHIVE=opl3-bank-editor-dev-win9x.zip +) ELSE ( + SET DEPLOY_FILES=%DEPLOY_FILES% .\opl_proxy\modern\liboplproxy.dll ) SET DEPLOY_FILES=%DEPLOY_FILES% Bank_Examples SET DEPLOY_FILES=%DEPLOY_FILES% .\formats_info.htm .\license.txt .\changelog.txt diff --git a/opl_proxy/.gitignore b/opl_proxy/modern/.gitignore similarity index 100% rename from opl_proxy/.gitignore rename to opl_proxy/modern/.gitignore diff --git a/opl_proxy/Readme.txt b/opl_proxy/modern/Readme.txt similarity index 100% rename from opl_proxy/Readme.txt rename to opl_proxy/modern/Readme.txt diff --git a/opl_proxy/liboplproxy.dll b/opl_proxy/modern/liboplproxy.dll similarity index 100% rename from opl_proxy/liboplproxy.dll rename to opl_proxy/modern/liboplproxy.dll diff --git a/opl_proxy/liboplproxy.tgt b/opl_proxy/modern/liboplproxy.tgt similarity index 100% rename from opl_proxy/liboplproxy.tgt rename to opl_proxy/modern/liboplproxy.tgt diff --git a/opl_proxy/liboplproxy_exports.txt b/opl_proxy/modern/liboplproxy_exports.txt similarity index 100% rename from opl_proxy/liboplproxy_exports.txt rename to opl_proxy/modern/liboplproxy_exports.txt diff --git a/opl_proxy/modern/oplproxy.c b/opl_proxy/modern/oplproxy.c new file mode 100644 index 0000000..f1ad480 --- /dev/null +++ b/opl_proxy/modern/oplproxy.c @@ -0,0 +1,50 @@ +/* + * OPL3 chip interface proxy for OPL Bank Editor by Wohlstand, + * a part of free tool for music bank editing + * + * Copyright (c) 2016-2018 Vitaly Novichkov + * + * 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 3 of the License, or + * 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, see . + */ + +/* + Can be built by mingw-w64 + */ + +#include "InpOut32Helper.h" + +#define DLLExport __declspec(dllexport) +#define STDCall __stdcall +typedef unsigned short uint16_t; + +static uint16_t OPLBase = 0x388; + +DLLExport void STDCall chipInit(void) +{ OpenInpOut32(); } + +DLLExport void STDCall chipSetPort(uint16_t port) +{ OPLBase = port; } + +DLLExport void STDCall chipUnInit(void) +{ CloseInpOut32(); } + +DLLExport void STDCall chipPoke(uint16_t index, uint16_t value) +{ + uint16_t c, o = (index >> 8), port = (OPLBase + o * 2); + outportb(port, index); + for(c = 0; c < 6; ++c) inportb(port); + outportb(port + 1, value); + for(c = 0; c < 35; ++c) inportb(port); +} + diff --git a/opl_proxy/modern/oplproxy.dll b/opl_proxy/modern/oplproxy.dll new file mode 100644 index 0000000..d3ec100 Binary files /dev/null and b/opl_proxy/modern/oplproxy.dll differ diff --git a/opl_proxy/oplproxy.wpj b/opl_proxy/modern/oplproxy.wpj similarity index 100% rename from opl_proxy/oplproxy.wpj rename to opl_proxy/modern/oplproxy.wpj diff --git a/opl_proxy/update_exports.bat b/opl_proxy/modern/update_exports.bat similarity index 100% rename from opl_proxy/update_exports.bat rename to opl_proxy/modern/update_exports.bat diff --git a/opl_proxy/win9x/.gitignore b/opl_proxy/win9x/.gitignore new file mode 100644 index 0000000..7597e38 --- /dev/null +++ b/opl_proxy/win9x/.gitignore @@ -0,0 +1,8 @@ +*.lib +!liboplproxy.dll +*.map +*.lk1 +*.mk1 +*.sym +*.mk +*.obj diff --git a/opl_proxy/win9x/Readme.txt b/opl_proxy/win9x/Readme.txt new file mode 100644 index 0000000..a86d744 --- /dev/null +++ b/opl_proxy/win9x/Readme.txt @@ -0,0 +1,6 @@ +OPL Proxy - a small backend tool created for OPL Bank Editor by Wohlstand +to provide ability to test instruments on real OPL3 chip by running under Windows 98. + +On Windows NT family operating system this trick will not work. + +Build this tool by OpenWatcom diff --git a/opl_proxy/win9x/liboplproxy.dll b/opl_proxy/win9x/liboplproxy.dll new file mode 100644 index 0000000..0656b99 Binary files /dev/null and b/opl_proxy/win9x/liboplproxy.dll differ diff --git a/opl_proxy/win9x/liboplproxy.tgt b/opl_proxy/win9x/liboplproxy.tgt new file mode 100644 index 0000000..8aaa9e9 --- /dev/null +++ b/opl_proxy/win9x/liboplproxy.tgt @@ -0,0 +1,150 @@ +40 +targetIdent +0 +MProject +1 +MComponent +0 +2 +WString +4 +NDLL +3 +WString +5 +n_2d9 +1 +0 +1 +4 +MCommand +0 +5 +MCommand +0 +6 +MItem +15 +liboplproxy.dll +7 +WString +4 +NDLL +8 +WVList +4 +9 +MRState +10 +WString +5 +WLINK +11 +WString +25 +?????No debug information +1 +1 +12 +MRState +13 +WString +5 +WLINK +14 +WString +14 +?????Debug all +1 +0 +15 +MCState +16 +WString +5 +WLINK +17 +WString +13 +?????Map file +1 +0 +18 +MCState +19 +WString +5 +WLINK +20 +WString +24 +?????Eliminate dead code +1 +1 +21 +WVList +1 +22 +ActionStates +23 +WString +5 +&Make +24 +WVList +0 +-1 +1 +1 +0 +25 +WPickList +2 +26 +MItem +3 +*.c +27 +WString +4 +COBJ +28 +WVList +0 +29 +WVList +0 +-1 +1 +1 +0 +30 +MItem +10 +oplproxy.c +31 +WString +4 +COBJ +32 +WVList +1 +33 +MCState +34 +WString +3 +WCC +35 +WString +26 +?????Force ANSI compliance +1 +1 +36 +WVList +0 +26 +1 +1 +0 diff --git a/opl_proxy/win9x/liboplproxy_exports.txt b/opl_proxy/win9x/liboplproxy_exports.txt new file mode 100644 index 0000000..2959c2e --- /dev/null +++ b/opl_proxy/win9x/liboplproxy_exports.txt @@ -0,0 +1,30 @@ +Microsoft (R) COFF/PE Dumper Version 14.00.24215.1 +Copyright (C) Microsoft Corporation. All rights reserved. + + +Dump of file liboplproxy.dll + +File Type: DLL + + Section contains the following exports for liboplproxy.dll + + 00000000 characteristics + 0 time date stamp + 0.00 version + 1 ordinal base + 3 number of functions + 3 number of names + + ordinal hint RVA name + + 1 0 00001010 _chipInit@0 + 3 1 0000104A _chipPoke@8 + 2 2 0000102D _chipUnInit@0 + + Summary + + 1000 .edata + 1000 .idata + 1000 .reloc + 6000 AUTO + 3000 DGROUP diff --git a/opl_proxy/oplproxy.c b/opl_proxy/win9x/oplproxy.c similarity index 100% rename from opl_proxy/oplproxy.c rename to opl_proxy/win9x/oplproxy.c diff --git a/opl_proxy/win9x/oplproxy.wpj b/opl_proxy/win9x/oplproxy.wpj new file mode 100644 index 0000000..5d69d5d --- /dev/null +++ b/opl_proxy/win9x/oplproxy.wpj @@ -0,0 +1,43 @@ +40 +projectIdent +0 +VpeMain +1 +WRect +232 +110 +7872 +8400 +2 +MProject +3 +MCommand +0 +4 +MCommand +0 +1 +5 +WFileName +15 +liboplproxy.tgt +6 +WVList +1 +7 +VComponent +8 +WRect +416 +410 +5712 +4360 +0 +0 +9 +WFileName +15 +liboplproxy.tgt +0 +1 +7 diff --git a/opl_proxy/win9x/update_exports.bat b/opl_proxy/win9x/update_exports.bat new file mode 100644 index 0000000..76ea25b --- /dev/null +++ b/opl_proxy/win9x/update_exports.bat @@ -0,0 +1 @@ +"C:\Program Files (x86)\Microsoft Visual Studio 14.0\VC\bin\dumpbin.exe" /exports liboplproxy.dll > liboplproxy_exports.txt diff --git a/src/bank_editor.cpp b/src/bank_editor.cpp index c141af7..6fd7801 100644 --- a/src/bank_editor.cpp +++ b/src/bank_editor.cpp @@ -34,11 +34,15 @@ #include "bank_editor.h" #include "ui_bank_editor.h" #include "latency.h" +#include "hardware.h" #include "ins_names.h" #include "main.h" #if defined(ENABLE_PLOTS) #include "delay_analysis.h" #endif +#ifdef ENABLE_WIN9X_OPL_PROXY // to set hardware port +#include "opl/chips/win9x_opl_proxy.h" +#endif #include "FileFormats/ffmt_factory.h" #include "FileFormats/ffmt_enums.h" @@ -113,6 +117,10 @@ BankEditor::BankEditor(QWidget *parent) : ui->actionWin9xOPLProxy->setVisible(false); #endif +#ifndef ENABLE_WIN9X_OPL_PROXY + ui->actionHardware_OPL->setVisible(false); +#endif + ui->instruments->installEventFilter(this); ui->pitchBendSlider->setTracking(true); @@ -1209,6 +1217,32 @@ void BankEditor::on_actionLatency_triggered() delete dlg; } +#ifdef ENABLE_WIN9X_OPL_PROXY +void BankEditor::on_actionHardware_OPL_triggered() +{ + Win9x_OPL_Proxy proxy; + bool supportsChangeAddress = proxy.canSetOplAddress(); + + HardwareDialog *dlg = new HardwareDialog; + + dlg->setOplAddress(m_proxyOplAddress); + dlg->setCanChangeOplAddress(supportsChangeAddress); + dlg->exec(); + + if(supportsChangeAddress) + { + unsigned newAddress = dlg->oplAddress(); + if(newAddress != m_proxyOplAddress) + { + proxy.setOplAddress(newAddress); + m_proxyOplAddress = newAddress; + } + } + + delete dlg; +} +#endif + void BankEditor::onActionLanguageTriggered() { QAction *act = static_cast(sender()); diff --git a/src/bank_editor.h b/src/bank_editor.h index 06c2031..250b09c 100644 --- a/src/bank_editor.h +++ b/src/bank_editor.h @@ -119,6 +119,11 @@ class BankEditor : public QMainWindow QAction *m_midiInAction = nullptr; #endif +#ifdef ENABLE_WIN9X_OPL_PROXY + /* ********** OPL proxy stuff ********** */ + unsigned m_proxyOplAddress = 0x388; +#endif + /*! * \brief Initializes audio subsystem and FM generator */ @@ -433,6 +438,12 @@ private slots: * @brief Opens the latency setting dialog */ void on_actionLatency_triggered(); +#ifdef ENABLE_WIN9X_OPL_PROXY + /** + * @brief Opens the hardware OPL dialog + */ + void on_actionHardware_OPL_triggered(); +#endif /** * @brief Changes the current language */ diff --git a/src/bank_editor.ui b/src/bank_editor.ui index bc29365..fbe15bd 100644 --- a/src/bank_editor.ui +++ b/src/bank_editor.ui @@ -3544,6 +3544,7 @@ of second voice + @@ -3763,6 +3764,11 @@ of second voice Run delay analysis + + + Hardware OPL... + + diff --git a/src/hardware.cpp b/src/hardware.cpp new file mode 100644 index 0000000..694782a --- /dev/null +++ b/src/hardware.cpp @@ -0,0 +1,91 @@ +/* + * OPL Bank Editor by Wohlstand, a free tool for music bank editing + * Copyright (c) 2018 Vitaly Novichkov + * + * 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 3 of the License, or + * 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, see . + */ + +#include "hardware.h" +#include "bank_editor.h" +#include +#include +#include +#include +#include + +HardwareDialog::HardwareDialog(QWidget *parent) + : QDialog(parent) +{ + setupUi(); +} + +HardwareDialog::~HardwareDialog() +{ +} + +unsigned HardwareDialog::oplAddress() const +{ + return m_ctlAddressEdit->text().toUInt(nullptr, 16); +} + +void HardwareDialog::setOplAddress(unsigned address) +{ + m_ctlAddressEdit->setText(QString::number(address, 16)); +} + +void HardwareDialog::setCanChangeOplAddress(bool can) +{ + m_ctlAddressEdit->setEnabled(can); + updateInfoLabel(); +} + +void HardwareDialog::setupUi() +{ + setWindowTitle(tr("Hardware OPL")); + + QVBoxLayout *vl = new QVBoxLayout; + setLayout(vl); + + vl->addWidget(new QLabel(tr("Define the hardware address."))); + + QLabel *infoLabel = m_infoLabel = new QLabel; + vl->addWidget(infoLabel); + updateInfoLabel(); + + QHBoxLayout *ctlBox = new QHBoxLayout; + vl->addLayout(ctlBox); + + ctlBox->addWidget(new QLabel(tr("Hexadecimal address: "))); + + QLineEdit *ctlAddressEdit = m_ctlAddressEdit = new QLineEdit; + ctlBox->addWidget(ctlAddressEdit); + ctlAddressEdit->setInputMask("hhh"); + + QDialogButtonBox *bbox = new QDialogButtonBox(QDialogButtonBox::Ok); + vl->addWidget(bbox); + connect(bbox, SIGNAL(accepted()), this, SLOT(accept())); + connect(bbox, SIGNAL(rejected()), this, SLOT(reject())); + + adjustSize(); + setFixedSize(size()); +} + +void HardwareDialog::updateInfoLabel() +{ + if(m_ctlAddressEdit && m_ctlAddressEdit->isEnabled()) + m_infoLabel->setText(tr("Usually $388, varies depending on card.")); + else + m_infoLabel->setText(tr("Impossible to set the hardware address.\n" + "Make sure you installed the latest OPL proxy.")); +} diff --git a/src/hardware.h b/src/hardware.h new file mode 100644 index 0000000..6665bfc --- /dev/null +++ b/src/hardware.h @@ -0,0 +1,45 @@ +/* + * OPL Bank Editor by Wohlstand, a free tool for music bank editing + * Copyright (c) 2018 Vitaly Novichkov + * + * 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 3 of the License, or + * 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, see . + */ + +#ifndef HARDWARE_H +#define HARDWARE_H + +#include +class QLineEdit; +class QLabel; + +class HardwareDialog : public QDialog +{ + Q_OBJECT + +public: + HardwareDialog(QWidget *parent = nullptr); + ~HardwareDialog(); + + unsigned oplAddress() const; + void setOplAddress(unsigned address); + void setCanChangeOplAddress(bool can); + +private: + void setupUi(); + void updateInfoLabel(); + QLabel *m_infoLabel = nullptr; + QLineEdit *m_ctlAddressEdit = nullptr; +}; + +#endif // HARDWARE_H diff --git a/src/opl/chips/win9x_opl_proxy.cpp b/src/opl/chips/win9x_opl_proxy.cpp index 412785b..cc202c7 100644 --- a/src/opl/chips/win9x_opl_proxy.cpp +++ b/src/opl/chips/win9x_opl_proxy.cpp @@ -28,6 +28,7 @@ extern "C" typedef void (_stdcall *opl_poke)(uint16_t index, uint16_t value); typedef void (_stdcall *opl_init)(void); typedef void (_stdcall *opl_unInit)(void); + typedef void (_stdcall *opl_setPort)(uint16_t port); } struct OPLProxyDriver @@ -35,15 +36,18 @@ struct OPLProxyDriver opl_poke chip_oplPoke = nullptr; opl_init chip_oplInit = nullptr; opl_unInit chip_oplUninit = nullptr; + opl_setPort chip_oplSetPort = nullptr; HINSTANCE chip_lib = 0; }; template -void initOplFunction(HINSTANCE &chip_lib, FunkPtr &ptr, const char *procName) +void initOplFunction(HINSTANCE &chip_lib, FunkPtr &ptr, const char *procName, bool required = true) { ptr = (FunkPtr)GetProcAddress(chip_lib, procName); - if(!ptr) + static bool shownWarning = false; + if(!ptr && required && !shownWarning) { + shownWarning = true; QMessageBox::warning(nullptr, "liboplproxy.dll error", QString("Oops... I have failed to load %1 function:\n" @@ -70,6 +74,7 @@ void Win9x_OPL_Proxy::initChip() initOplFunction(chip_r->chip_lib, chip_r->chip_oplInit, "_chipInit@0"); initOplFunction(chip_r->chip_lib, chip_r->chip_oplPoke, "_chipPoke@8"); initOplFunction(chip_r->chip_lib, chip_r->chip_oplUninit, "_chipUnInit@0"); + initOplFunction(chip_r->chip_lib, chip_r->chip_oplSetPort, "_chipSetPort@4", false); if(chip_r->chip_oplInit) chip_r->chip_oplInit(); } @@ -88,9 +93,23 @@ void Win9x_OPL_Proxy::closeChip() chip_r->chip_oplInit = nullptr; chip_r->chip_oplPoke = nullptr; chip_r->chip_oplUninit = nullptr; + chip_r->chip_oplSetPort = nullptr; } } +bool Win9x_OPL_Proxy::canSetOplAddress() const +{ + OPLProxyDriver *chip_r = reinterpret_cast(m_chip); + return chip_r->chip_oplSetPort != nullptr; +} + +void Win9x_OPL_Proxy::setOplAddress(uint16_t address) +{ + OPLProxyDriver *chip_r = reinterpret_cast(m_chip); + if(chip_r->chip_oplSetPort) + chip_r->chip_oplSetPort(address); +} + Win9x_OPL_Proxy::Win9x_OPL_Proxy() { m_chip = new OPLProxyDriver; diff --git a/src/opl/chips/win9x_opl_proxy.h b/src/opl/chips/win9x_opl_proxy.h index 86ad967..dec74b6 100644 --- a/src/opl/chips/win9x_opl_proxy.h +++ b/src/opl/chips/win9x_opl_proxy.h @@ -12,6 +12,9 @@ class Win9x_OPL_Proxy : public OPLChipBaseT Win9x_OPL_Proxy(); virtual ~Win9x_OPL_Proxy() override; + bool canSetOplAddress() const; + void setOplAddress(uint16_t address); + bool canRunAtPcmRate() const override { return false; } void setRate(uint32_t rate) override {} void reset() override {}