mirror of
https://github.com/tildearrow/furnace.git
synced 2024-11-22 20:45:11 +00:00
parent
aefe4938fd
commit
fc4397f644
12 changed files with 454 additions and 8246 deletions
|
@ -485,7 +485,6 @@ src/engine/playback.cpp
|
||||||
src/engine/sample.cpp
|
src/engine/sample.cpp
|
||||||
src/engine/song.cpp
|
src/engine/song.cpp
|
||||||
src/engine/sysDef.cpp
|
src/engine/sysDef.cpp
|
||||||
src/engine/watermark.cpp
|
|
||||||
src/engine/wavetable.cpp
|
src/engine/wavetable.cpp
|
||||||
src/engine/waveSynth.cpp
|
src/engine/waveSynth.cpp
|
||||||
src/engine/vgmOps.cpp
|
src/engine/vgmOps.cpp
|
||||||
|
|
|
@ -1,3 +1,99 @@
|
||||||
# Contributing
|
# Contributing
|
||||||
|
|
||||||
contributions to Furnace Pro are not welcome. try applying for a job at Furnace Headquarters instead?
|
contributions to Furnace are welcome!
|
||||||
|
|
||||||
|
# Getting ready
|
||||||
|
|
||||||
|
log into your Github account, and click the Fork button in the header of the project's page.
|
||||||
|
|
||||||
|
then open a terminal and clone your fork:
|
||||||
|
|
||||||
|
```
|
||||||
|
git clone git@github.com:USERNAME/furnace.git
|
||||||
|
```
|
||||||
|
|
||||||
|
(replace `USERNAME` with your username)
|
||||||
|
|
||||||
|
# Working
|
||||||
|
|
||||||
|
## Code
|
||||||
|
|
||||||
|
bug fixes, improvements and several other things accepted.
|
||||||
|
|
||||||
|
the coding style is described here:
|
||||||
|
|
||||||
|
- indentation: two spaces. **strictly** spaces. do NOT use tabs.
|
||||||
|
- modified 1TBS style:
|
||||||
|
- no spaces in function calls
|
||||||
|
- spaces between arguments in function declarations
|
||||||
|
- no spaces in operations except for `||` and `&&`
|
||||||
|
- no space between variable name and assignment
|
||||||
|
- space between macro in string literals
|
||||||
|
- space after comment delimiter
|
||||||
|
- C++ pointer style: `void* variable` rather than `void *variable`
|
||||||
|
- indent switch cases
|
||||||
|
- preprocessor directives not intended
|
||||||
|
- if macro comprises more than one line, indent
|
||||||
|
- no new line after `template<>`
|
||||||
|
- prefer built-in types:
|
||||||
|
- `bool`
|
||||||
|
- `signed char` or `unsigned char` are 8-bit
|
||||||
|
- when the type is `char`, **always** specify whether it is signed or not.
|
||||||
|
- unspecified `char` is signed on x86 and unsigned on ARM, so yeah.
|
||||||
|
- the only situation in where unspecified `char` is allowed is for C strings (`const char*`).
|
||||||
|
- `short` or `unsigned short` are 16-bit
|
||||||
|
- `int` or `unsigned int` are 32-bit
|
||||||
|
- `float` is 32-bit
|
||||||
|
- `double` is 64-bit
|
||||||
|
- `long long int` or `unsigned long long int` are 64-bit
|
||||||
|
- avoid using 64-bit numbers as I still build for 32-bit systems.
|
||||||
|
- two `long`s are required to make Windows happy.
|
||||||
|
- `size_t` are 32-bit or 64-bit, depending on architecture.
|
||||||
|
- in float/double operations, always use decimal and `f` if single-precision.
|
||||||
|
- e.g. `1.0f` or `1.0` instead of `1`.
|
||||||
|
- prefer `NULL` over `nullptr` or any other proprietary null.
|
||||||
|
- don't use `auto` unless needed.
|
||||||
|
- use `String` for `std::string` (this is typedef'd in ta-utils.h).
|
||||||
|
- prefer using operator for String (std::string) comparisons (a=="").
|
||||||
|
- if you have to work with C strings, only use safe C string operations:
|
||||||
|
- snprintf
|
||||||
|
- strncpy
|
||||||
|
- strncat
|
||||||
|
- any other operation which specifies a limit
|
||||||
|
|
||||||
|
some files (particularly the ones in `src/engine/platform/sound` and `extern/`) don't follow this style.
|
||||||
|
|
||||||
|
you don't have to follow this style. I will fix it after I accept your contribution.
|
||||||
|
|
||||||
|
additional guidelines:
|
||||||
|
|
||||||
|
- in general **strongly** avoid breaking compatibility.
|
||||||
|
- do not touch loadFur/saveFur unless you know what you're doing!
|
||||||
|
- new fields must be at the end of each block to ensure forward compatibility
|
||||||
|
- likewise, the instrument read/write functions in DivInstrument have to be handled carefully
|
||||||
|
- any change to the format requires a version bump (see `src/engine/engine.h`).
|
||||||
|
- do not bump the version number under any circumstances!
|
||||||
|
- if you are making major changes to the playback routine, make sure to test with older songs to ensure nothing breaks.
|
||||||
|
- I will run a test suite to make sure this is the case.
|
||||||
|
- if something breaks, you might want to add a compatibility flag (this requires changing the format though).
|
||||||
|
- do not use `#pragma once`.
|
||||||
|
- do not memcmp() structs.
|
||||||
|
- on a switch block, **always** put `default` last and not in any other position.
|
||||||
|
- I have fear of some C/C++ compilers ignoring the rest of cases upon hitting default.
|
||||||
|
|
||||||
|
## Demo Songs
|
||||||
|
|
||||||
|
just put your demo song in `demos/`! be noted there are some guidelines:
|
||||||
|
|
||||||
|
- avoid Nintendo song covers.
|
||||||
|
- avoid big label song covers.
|
||||||
|
- low effort compositions/covers may not be accepted at all.
|
||||||
|
|
||||||
|
# Finishing
|
||||||
|
|
||||||
|
after you've done your modifications, commit the changes and push.
|
||||||
|
then open your fork on GitHub and send a pull request.
|
||||||
|
|
||||||
|
# I don't know how to use Git but I want to contribute with a demo song
|
||||||
|
|
||||||
|
you can also contact me directly! [find me here.](https://tildearrow.org/?p=contact)
|
||||||
|
|
293
README.md
293
README.md
|
@ -1,27 +1,117 @@
|
||||||
# Furnace Pro (chiptune tracker)
|
# Furnace (chiptune tracker)
|
||||||
|
|
||||||
![screenshot](papers/screenshot2.png)
|
![screenshot](papers/screenshot2.png)
|
||||||
|
|
||||||
the ultimate chiptune tracker for pro usage.
|
the biggest multi-system chiptune tracker ever made!
|
||||||
|
|
||||||
[downloads](#downloads) | [discussion/help](#quick-references) | [developer info](#developer-info) | [unofficial packages](#unofficial-packages) | [FAQ](#frequently-asked-questions)
|
[downloads](#downloads) | [discussion/help](#quick-references) | [developer info](#developer-info) | [unofficial packages](#unofficial-packages) | [FAQ](#frequently-asked-questions)
|
||||||
|
|
||||||
---
|
---
|
||||||
## downloads
|
## downloads
|
||||||
|
|
||||||
Furnace Pro is shareware. this means you can use and share it, but you gotta register in order to unlock all of its features.
|
|
||||||
|
|
||||||
check out the [Releases](https://github.com/tildearrow/furnace/releases) page. available for Windows, macOS and Linux (AppImage).
|
check out the [Releases](https://github.com/tildearrow/furnace/releases) page. available for Windows, macOS and Linux (AppImage).
|
||||||
|
|
||||||
|
[see here](https://nightly.link/tildearrow/furnace/workflows/build/master) for unstable developer builds.
|
||||||
|
|
||||||
## features
|
## features
|
||||||
|
|
||||||
- over 60 sound chips, and counting. we strive to add the best of the best.
|
- over 50 sound chips - and counting:
|
||||||
- thousands of instruments, wavetables and samples built-in, made by our talented designers at Furnace Headquarters.
|
- Yamaha FM chips:
|
||||||
- 128-bit audio processing for maximum quality.
|
- YM2151 (OPM)
|
||||||
- Bonus Pack contains:
|
- YM2203 (OPN)
|
||||||
- MIDISlap Ultimate: automatically imports MIDI files and uses the latest AI-powered technology to convert them into masterpieces!
|
- YM2413 (OPLL)
|
||||||
- UltraExport: exports any song to a ROM and/or PCB that plays on every hardware without limitations
|
- YM2414 (OPZ) used in Yamaha TX81Z
|
||||||
- Dummy System II with a low-pass filter
|
- YM2608 (OPNA) used in PC-98
|
||||||
|
- YM2610 (OPNB) used in Neo Geo
|
||||||
|
- YM2610B (OPNB2)
|
||||||
|
- YM2612 (OPN2) used in Sega Genesis and FM Towns
|
||||||
|
- YM3526 (OPL) used in C64 Sound Expander
|
||||||
|
- YM3812 (OPL2)
|
||||||
|
- YMF262 (OPL3) with full 4-op support!
|
||||||
|
- Y8950 (OPL with ADPCM)
|
||||||
|
- square wave chips:
|
||||||
|
- AY-3-8910/YM2149(F) used in several computers and game consoles
|
||||||
|
- Commodore VIC used in the VIC-20
|
||||||
|
- Microchip AY8930
|
||||||
|
- TI SN76489 used in Sega Master System and BBC Micro
|
||||||
|
- PC Speaker
|
||||||
|
- Philips SAA1099 used in SAM Coupé
|
||||||
|
- OKI MSM5232 used in some arcade boards
|
||||||
|
- sample chips:
|
||||||
|
- SNES
|
||||||
|
- Amiga
|
||||||
|
- SegaPCM - all 16 channels
|
||||||
|
- Capcom QSound
|
||||||
|
- Yamaha YMZ280B (PCMD8)
|
||||||
|
- Ricoh RF5C68 used in Sega CD and FM Towns
|
||||||
|
- OKI MSM6258 and MSM6295
|
||||||
|
- Konami K007232
|
||||||
|
- Irem GA20
|
||||||
|
- Ensoniq ES5506
|
||||||
|
- wavetable chips:
|
||||||
|
- HuC6280 used in PC Engine
|
||||||
|
- Konami Bubble System WSG
|
||||||
|
- Konami SCC/SCC+
|
||||||
|
- Namco arcade chips (WSG/C15/C30)
|
||||||
|
- WonderSwan
|
||||||
|
- Seta/Allumer X1-010
|
||||||
|
- Sharp SM8521 used in Tiger Game.com
|
||||||
|
- NES (Ricoh 2A03/2A07), with additional expansion sound support:
|
||||||
|
- Konami VRC6
|
||||||
|
- Konami VRC7
|
||||||
|
- MMC5
|
||||||
|
- Famicom Disk System
|
||||||
|
- Sunsoft 5B
|
||||||
|
- Namco 163
|
||||||
|
- Family Noraebang (OPLL)
|
||||||
|
- SID (6581/8580) used in Commodore 64
|
||||||
|
- Mikey used in Atari Lynx
|
||||||
|
- ZX Spectrum beeper (SFX-like engine)
|
||||||
|
- Pokémon Mini
|
||||||
|
- Commodore PET
|
||||||
|
- TIA used in Atari 2600
|
||||||
|
- POKEY used in Atari 8-bit computers
|
||||||
|
- Game Boy
|
||||||
|
- Virtual Boy
|
||||||
|
- modern/fantasy:
|
||||||
|
- Commander X16 VERA
|
||||||
|
- tildearrow Sound Unit
|
||||||
|
- mix and match sound chips!
|
||||||
|
- over 200 ready to use presets from computers, game consoles and arcade boards...
|
||||||
|
- ...or create your own - up to 32 of them or a total of 128 channels!
|
||||||
|
- DefleMask compatibility
|
||||||
|
- loads .dmf modules from all versions (beta 1 to 1.1.7)
|
||||||
|
- saves .dmf modules - both modern and legacy
|
||||||
|
- Furnace doubles as a module downgrader
|
||||||
|
- loads/saves .dmp instruments and .dmw wavetables as well
|
||||||
|
- clean-room design (guesswork and ABX tests only, no decompilation involved)
|
||||||
|
- some bug/quirk implementation for increased playback accuracy through compatibility flags
|
||||||
|
- VGM export
|
||||||
|
- modular layout that you may adapt to your needs
|
||||||
|
- audio file export - entire song, per chip or per channel
|
||||||
|
- quality emulation cores (Nuked, MAME, SameBoy, Mednafen PCE, NSFplay, puNES, reSID, Stella, SAASound, vgsound_emu and ymfm)
|
||||||
|
- wavetable synthesizer
|
||||||
|
- available on wavetable chips
|
||||||
|
- create complex sounds with ease - provide up to two wavetables, select and effect and let go!
|
||||||
|
- MIDI input support
|
||||||
|
- additional features:
|
||||||
|
- FM macros!
|
||||||
|
- negative octaves
|
||||||
|
- advanced arp macros
|
||||||
|
- arbitrary pitch samples
|
||||||
|
- sample loop points
|
||||||
|
- SSG envelopes and ADPCM-B in Neo Geo
|
||||||
|
- pitchable OPLL drums
|
||||||
|
- full duty/cutoff range in C64
|
||||||
|
- full 16-channel SegaPCM
|
||||||
|
- ability to change tempo mid-song
|
||||||
|
- decimal tempo/tick rate
|
||||||
|
- multiple sub-songs in a module
|
||||||
|
- per-channel oscilloscope with waveform centering
|
||||||
|
- built-in sample editor
|
||||||
|
- chip mixing settings
|
||||||
|
- built-in visualizer in pattern view
|
||||||
|
- open-source under GPLv2 or later.
|
||||||
|
|
||||||
---
|
---
|
||||||
# quick references
|
# quick references
|
||||||
|
@ -29,28 +119,183 @@ check out the [Releases](https://github.com/tildearrow/furnace/releases) page. a
|
||||||
- **discussion**: see the [Discussions](https://github.com/tildearrow/furnace/discussions) section, or (preferably) the [official Discord server](https://discord.gg/EfrwT2wq7z).
|
- **discussion**: see the [Discussions](https://github.com/tildearrow/furnace/discussions) section, or (preferably) the [official Discord server](https://discord.gg/EfrwT2wq7z).
|
||||||
- **help**: check out the [documentation](papers/doc/README.md). it's mostly incomplete, but has details on effects.
|
- **help**: check out the [documentation](papers/doc/README.md). it's mostly incomplete, but has details on effects.
|
||||||
|
|
||||||
|
## unofficial packages
|
||||||
|
|
||||||
|
[![Packaging status](https://repology.org/badge/tiny-repos/furnace.svg)](https://repology.org/project/furnace/versions)
|
||||||
|
|
||||||
|
some people have provided packages for Unix/Unix-like distributions. here's a list.
|
||||||
|
- **Arch Linux**: [furnace](https://archlinux.org/packages/community/x86_64/furnace/) is now in the community repo!
|
||||||
|
- **FreeBSD**: [a package in ports](https://www.freshports.org/audio/furnace/) is available courtesy of ehaupt.
|
||||||
|
- **Nix**: [package](https://search.nixos.org/packages?channel=unstable&show=furnace&from=0&size=50&sort=relevance&type=packages&query=furnace) thanks to OPNA2608.
|
||||||
|
- **openSUSE**: [a package](https://software.opensuse.org/package/furnace) is available, courtesy of fpesari.
|
||||||
|
|
||||||
|
---
|
||||||
|
# developer info
|
||||||
|
|
||||||
|
[![Build furnace](https://github.com/tildearrow/furnace/actions/workflows/build.yml/badge.svg)](https://github.com/tildearrow/furnace/actions/workflows/build.yml)
|
||||||
|
|
||||||
|
if you can't download these artifacts (because GitHub requires you to be logged in), [go here](https://nightly.link/tildearrow/furnace/workflows/build/master) instead.
|
||||||
|
|
||||||
|
**NOTE: do not download the project's source as a .zip or .tar.gz as these do not include the project's submodules which are necessary to proceed with building. please instead use Git as shown below.**
|
||||||
|
|
||||||
|
## dependencies
|
||||||
|
|
||||||
|
- CMake
|
||||||
|
- JACK (optional, macOS/Linux only)
|
||||||
|
|
||||||
|
if building under Windows or macOS, no additional dependencies are required.
|
||||||
|
otherwise, you may also need the following:
|
||||||
|
|
||||||
|
- libpulse
|
||||||
|
- libx11
|
||||||
|
- libasound
|
||||||
|
- libGL
|
||||||
|
|
||||||
|
some Linux distributions (e.g. Ubuntu or openSUSE) will require you to install the `-dev` versions of these.
|
||||||
|
|
||||||
|
## getting the source
|
||||||
|
|
||||||
|
type the following on a terminal/console: (make sure Git is installed)
|
||||||
|
|
||||||
|
```
|
||||||
|
git clone --recursive https://github.com/tildearrow/furnace.git
|
||||||
|
cd furnace
|
||||||
|
```
|
||||||
|
|
||||||
|
(the `--recursive` parameter ensures submodules are fetched as well)
|
||||||
|
|
||||||
|
## compilation
|
||||||
|
|
||||||
|
your typical CMake project.
|
||||||
|
|
||||||
|
### Windows using MSVC
|
||||||
|
|
||||||
|
as of now tildearrow uses MinGW for Windows builds, but thanks to OPNA2608 this works again!
|
||||||
|
|
||||||
|
from the developer tools command prompt:
|
||||||
|
|
||||||
|
```
|
||||||
|
mkdir build
|
||||||
|
cd build
|
||||||
|
cmake ..
|
||||||
|
msbuild ALL_BUILD.vcxproj
|
||||||
|
```
|
||||||
|
|
||||||
|
### macOS and Linux
|
||||||
|
|
||||||
|
```
|
||||||
|
mkdir build
|
||||||
|
cd build
|
||||||
|
cmake ..
|
||||||
|
make
|
||||||
|
```
|
||||||
|
Alternatively, build scripts are provided in the `scripts/` folder in the root of the repository.
|
||||||
|
|
||||||
|
### CMake options
|
||||||
|
|
||||||
|
To add an option from the command-line: `-D<NAME>=<VALUE>`
|
||||||
|
Example: `cmake -DBUILD_GUI=OFF -DWARNINGS_ARE_ERRORS=ON ..`
|
||||||
|
|
||||||
|
Available options:
|
||||||
|
|
||||||
|
| Name | Default | Description |
|
||||||
|
| :--: | :-----: | ----------- |
|
||||||
|
| `BUILD_GUI` | `ON` | Build the tracker (disable to build only a headless player) |
|
||||||
|
| `USE_RTMIDI` | `ON` | Build with MIDI support using RtMidi |
|
||||||
|
| `USE_SDL2` | `ON` | Build with SDL2 (required to build with GUI) |
|
||||||
|
| `USE_SNDFILE` | `ON` | Build with libsndfile (required in order to work with audio files) |
|
||||||
|
| `USE_BACKWARD` | `ON` | Use backward-cpp to print a backtrace on crash/abort |
|
||||||
|
| `WITH_JACK` | `ON` if system-installed JACK detected, otherwise `OFF` | Whether to build with JACK support. Auto-detects if JACK is available |
|
||||||
|
| `SYSTEM_FFTW` | `OFF` | Use a system-installed version of FFTW instead of the vendored one |
|
||||||
|
| `SYSTEM_FMT` | `OFF` | Use a system-installed version of fmt instead of the vendored one |
|
||||||
|
| `SYSTEM_LIBSNDFILE` | `OFF` | Use a system-installed version of libsndfile instead of the vendored one |
|
||||||
|
| `SYSTEM_RTMIDI` | `OFF` | Use a system-installed version of RtMidi instead of the vendored one |
|
||||||
|
| `SYSTEM_ZLIB` | `OFF` | Use a system-installed version of zlib instead of the vendored one |
|
||||||
|
| `SYSTEM_SDL2` | `OFF` | Use a system-installed version of SDL2 instead of the vendored one |
|
||||||
|
| `SUPPORT_XP` | `OFF` | Build a Windows XP-compatible binary |
|
||||||
|
| `WARNINGS_ARE_ERRORS` | `OFF` (but consider enabling this & reporting any errors that arise from it!) | Whether warnings in furnace's C++ code should be treated as errors |
|
||||||
|
| `WITH_DEMOS` | `ON` | Install demo songs on `make install` |
|
||||||
|
| `WITH_INSTRUMENTS` | `ON` | Install demo instruments on `make install` |
|
||||||
|
| `WITH_WAVETABLES` | `ON` | Install wavetables on `make install` |
|
||||||
|
|
||||||
|
## console usage
|
||||||
|
|
||||||
|
```
|
||||||
|
./furnace
|
||||||
|
```
|
||||||
|
|
||||||
|
this opens the program.
|
||||||
|
|
||||||
|
```
|
||||||
|
./furnace -console <file>
|
||||||
|
```
|
||||||
|
|
||||||
|
this will play a compatible file.
|
||||||
|
|
||||||
|
```
|
||||||
|
./furnace -console -view commands <file>
|
||||||
|
```
|
||||||
|
|
||||||
|
this will play a compatible file and enable the commands view.
|
||||||
|
|
||||||
|
**note that these commands only actually work in Linux environments. on other command lines, such as Windows' Command Prompt, or MacOS Terminal, it may not work correctly.**
|
||||||
|
|
||||||
---
|
---
|
||||||
# frequently asked questions
|
# frequently asked questions
|
||||||
|
|
||||||
> why does the cursor move randomly?
|
> woah! 50 sound chips?! I can't believe it!
|
||||||
|
|
||||||
who knows? it must be a glitch, or maybe intentional...
|
yup, it's real.
|
||||||
|
|
||||||
> can you help me get rid of the nag screens?
|
> where's the manual?
|
||||||
|
|
||||||
Furnace Pro is now shareware. please register it in order to disable the nag screens.
|
see [papers/](papers/doc/README.md). it's kind of incomplete, but at least the sound chips section is there.
|
||||||
|
|
||||||
> shareware? are you serious?
|
|
||||||
|
|
||||||
well, we need money for development and stuff. you gotta pay.
|
|
||||||
|
|
||||||
don't wanna pay? there's still one way...
|
|
||||||
|
|
||||||
> it doesn't open under macOS!
|
> it doesn't open under macOS!
|
||||||
|
|
||||||
check your pipes. there must be a hammer that is damaging the app.
|
this is due to Apple's application signing policy. a workaround is to right click on the Furnace app icon and select Open.
|
||||||
|
|
||||||
if that still doesn't work, move your computer to the trash.
|
**as of Monterey, this workaround no longer works (especially on ARM).** yeah, Apple has decided to be strict on the matter.
|
||||||
|
if you happen to be on that version, use this workaround instead (on a Terminal):
|
||||||
|
|
||||||
|
```
|
||||||
|
xattr -d com.apple.quarantine /path/to/Furnace.app
|
||||||
|
```
|
||||||
|
|
||||||
|
(replace /path/to/ with the path where Furnace.app is located)
|
||||||
|
|
||||||
|
you may need to log out and/or reboot after doing this.
|
||||||
|
|
||||||
|
> .spc export?
|
||||||
|
|
||||||
|
**not yet!** coming in 0.7 though, eventually...
|
||||||
|
|
||||||
|
> how do I use C64 absolute filter/duty?
|
||||||
|
|
||||||
|
on Instrument Editor in the C64 tab there are two options to toggle these.
|
||||||
|
also provided are two effects:
|
||||||
|
|
||||||
|
- `3xxx`: set fine duty.
|
||||||
|
- `4xxx`: set fine cutoff. `xxx` range is 000-7ff.
|
||||||
|
additionally, you can change the cutoff and/or duty as a macro inside an instrument by clicking the `absolute cutoff macro` and/or `absolute duty macro` checkbox at the bottom of the instrument. (for the filter, you also need to click the checkbox that says `volume macro is cutoff macro`.)
|
||||||
|
|
||||||
|
> how do I use PCM on a PCM-capable chip?
|
||||||
|
|
||||||
|
two possibilities:
|
||||||
|
- the recommended way is by creating the "Sample" type instrument and assigning a sample to it.
|
||||||
|
- otherwise you may employ the DefleMask-compatible method, using `17xx` effect.
|
||||||
|
|
||||||
|
> my .dmf song sounds odd at a certain point
|
||||||
|
|
||||||
|
Furnace's .dmf compatibility isn't perfect and it's mostly because DefleMask does things different.
|
||||||
|
|
||||||
|
> my song sounds terrible after saving as .dmf!
|
||||||
|
|
||||||
|
you should only save as .dmf if you're really sure, because the DefleMask format has several limitations. save in Furnace song format instead (.fur).
|
||||||
|
|
||||||
|
> how do I solo channels?
|
||||||
|
|
||||||
|
right click on the channel name.
|
||||||
|
|
||||||
---
|
---
|
||||||
# footnotes
|
# footnotes
|
||||||
|
@ -65,5 +310,3 @@ You should have received a copy of the GNU General Public License along with thi
|
||||||
|
|
||||||
|
|
||||||
despite the fact this program works with the .dmf, .dmp and .dmw file formats (besides its native .fur format), it is NOT affiliated with Delek or DefleMask in any way, nor it is a replacement for the original program.
|
despite the fact this program works with the .dmf, .dmp and .dmw file formats (besides its native .fur format), it is NOT affiliated with Delek or DefleMask in any way, nor it is a replacement for the original program.
|
||||||
|
|
||||||
we didn't say free as in free beer.
|
|
||||||
|
|
Binary file not shown.
|
@ -39,8 +39,6 @@
|
||||||
#endif
|
#endif
|
||||||
#include <fmt/printf.h>
|
#include <fmt/printf.h>
|
||||||
|
|
||||||
#include "watermark.h"
|
|
||||||
|
|
||||||
void process(void* u, float** in, float** out, int inChans, int outChans, unsigned int size) {
|
void process(void* u, float** in, float** out, int inChans, int outChans, unsigned int size) {
|
||||||
((DivEngine*)u)->nextBuf(in,out,inChans,outChans,size);
|
((DivEngine*)u)->nextBuf(in,out,inChans,outChans,size);
|
||||||
}
|
}
|
||||||
|
@ -819,7 +817,6 @@ void DivEngine::runExportThread() {
|
||||||
size_t fadeOutSamples=got.rate*exportFadeOut;
|
size_t fadeOutSamples=got.rate*exportFadeOut;
|
||||||
size_t curFadeOutSample=0;
|
size_t curFadeOutSample=0;
|
||||||
bool isFadingOut=false;
|
bool isFadingOut=false;
|
||||||
int watermarkPos=-((rand()%120)*4410);
|
|
||||||
switch (exportMode) {
|
switch (exportMode) {
|
||||||
case DIV_EXPORT_MODE_ONE: {
|
case DIV_EXPORT_MODE_ONE: {
|
||||||
SNDFILE* sf;
|
SNDFILE* sf;
|
||||||
|
@ -856,26 +853,17 @@ void DivEngine::runExportThread() {
|
||||||
}
|
}
|
||||||
for (int i=0; i<(int)totalProcessed; i++) {
|
for (int i=0; i<(int)totalProcessed; i++) {
|
||||||
total++;
|
total++;
|
||||||
float nextWaterSample=0;
|
|
||||||
watermarkPos++;
|
|
||||||
if (dejarteArriba && watermarkPos>=0 && watermarkPos<(int)watermark_size) {
|
|
||||||
nextWaterSample=(signed char)watermark[watermarkPos];
|
|
||||||
nextWaterSample/=128;
|
|
||||||
}
|
|
||||||
if (watermarkPos>=(int)watermark_size) {
|
|
||||||
watermarkPos=-((rand()%120)*4410);
|
|
||||||
}
|
|
||||||
if (isFadingOut) {
|
if (isFadingOut) {
|
||||||
double mul=(1.0-((double)curFadeOutSample/(double)fadeOutSamples));
|
double mul=(1.0-((double)curFadeOutSample/(double)fadeOutSamples));
|
||||||
outBuf[2][i<<1]=MAX(-1.0f,MIN(1.0f,outBuf[0][i]+nextWaterSample))*mul;
|
outBuf[2][i<<1]=MAX(-1.0f,MIN(1.0f,outBuf[0][i]))*mul;
|
||||||
outBuf[2][1+(i<<1)]=MAX(-1.0f,MIN(1.0f,outBuf[1][i]+nextWaterSample))*mul;
|
outBuf[2][1+(i<<1)]=MAX(-1.0f,MIN(1.0f,outBuf[1][i]))*mul;
|
||||||
if (++curFadeOutSample>=fadeOutSamples) {
|
if (++curFadeOutSample>=fadeOutSamples) {
|
||||||
playing=false;
|
playing=false;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
outBuf[2][i<<1]=MAX(-1.0f,MIN(1.0f,outBuf[0][i]+nextWaterSample));
|
outBuf[2][i<<1]=MAX(-1.0f,MIN(1.0f,outBuf[0][i]));
|
||||||
outBuf[2][1+(i<<1)]=MAX(-1.0f,MIN(1.0f,outBuf[1][i]+nextWaterSample));
|
outBuf[2][1+(i<<1)]=MAX(-1.0f,MIN(1.0f,outBuf[1][i]));
|
||||||
if (lastLoopPos>-1 && i>=lastLoopPos && totalLoops>=exportLoopCount) {
|
if (lastLoopPos>-1 && i>=lastLoopPos && totalLoops>=exportLoopCount) {
|
||||||
logD("start fading out...");
|
logD("start fading out...");
|
||||||
isFadingOut=true;
|
isFadingOut=true;
|
||||||
|
|
|
@ -29,13 +29,6 @@ constexpr int MASTER_CLOCK_PREC=(sizeof(void*)==8)?8:0;
|
||||||
|
|
||||||
void DivEngine::nextOrder() {
|
void DivEngine::nextOrder() {
|
||||||
curRow=0;
|
curRow=0;
|
||||||
|
|
||||||
if (dejarteArriba) {
|
|
||||||
if (!(rand()%3)) for (int i=0; i<chans; i++) {
|
|
||||||
dispatchCmd(DivCommand(DIV_CMD_NOTE_ON,i,0x4a+(rand()%12)));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (repeatPattern) return;
|
if (repeatPattern) return;
|
||||||
if (++curOrder>=curSubSong->ordersLen) {
|
if (++curOrder>=curSubSong->ordersLen) {
|
||||||
logV("end of orders reached");
|
logV("end of orders reached");
|
||||||
|
@ -368,24 +361,6 @@ int DivEngine::dispatchCmd(DivCommand c) {
|
||||||
|
|
||||||
c.chan=dispatchChanOfChan[c.dis];
|
c.chan=dispatchChanOfChan[c.dis];
|
||||||
|
|
||||||
if (dejarteArriba) {
|
|
||||||
if (c.cmd==DIV_CMD_NOTE_ON) {
|
|
||||||
if (c.value!=DIV_NOTE_NULL) {
|
|
||||||
if (!(rand()%5)) {
|
|
||||||
c.value+=(rand()%17)-8;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (c.cmd==DIV_CMD_NOTE_OFF) {
|
|
||||||
if (!(rand()%4)) return 0;
|
|
||||||
}
|
|
||||||
if (c.cmd==DIV_CMD_INSTRUMENT) {
|
|
||||||
if (!(rand()%3)) {
|
|
||||||
c.value+=rand()%3;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return disCont[dispatchOfChan[c.dis]].dispatch->dispatch(c);
|
return disCont[dispatchOfChan[c.dis]].dispatch->dispatch(c);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
File diff suppressed because it is too large
Load diff
|
@ -1,2 +0,0 @@
|
||||||
extern const unsigned char watermark[];
|
|
||||||
extern const unsigned int watermark_size;
|
|
170
src/gui/gui.cpp
170
src/gui/gui.cpp
|
@ -3658,18 +3658,10 @@ bool FurnaceGUI::loop() {
|
||||||
openFileDialog(GUI_FILE_EXPORT_AUDIO_ONE);
|
openFileDialog(GUI_FILE_EXPORT_AUDIO_ONE);
|
||||||
}
|
}
|
||||||
if (ImGui::MenuItem("multiple files (one per chip)")) {
|
if (ImGui::MenuItem("multiple files (one per chip)")) {
|
||||||
if (dejarteArriba) {
|
openFileDialog(GUI_FILE_EXPORT_AUDIO_PER_SYS);
|
||||||
showError("not available in UNREGISTERED version!");
|
|
||||||
} else {
|
|
||||||
openFileDialog(GUI_FILE_EXPORT_AUDIO_PER_SYS);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
if (ImGui::MenuItem("multiple files (one per channel)")) {
|
if (ImGui::MenuItem("multiple files (one per channel)")) {
|
||||||
if (dejarteArriba) {
|
openFileDialog(GUI_FILE_EXPORT_AUDIO_PER_CHANNEL);
|
||||||
showError("not available in UNREGISTERED version. oscilloscope view is a no for today.");
|
|
||||||
} else {
|
|
||||||
openFileDialog(GUI_FILE_EXPORT_AUDIO_PER_CHANNEL);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
if (ImGui::InputInt("Loops",&exportLoops,1,2)) {
|
if (ImGui::InputInt("Loops",&exportLoops,1,2)) {
|
||||||
if (exportLoops<0) exportLoops=0;
|
if (exportLoops<0) exportLoops=0;
|
||||||
|
@ -3680,90 +3672,86 @@ bool FurnaceGUI::loop() {
|
||||||
ImGui::EndMenu();
|
ImGui::EndMenu();
|
||||||
}
|
}
|
||||||
if (ImGui::BeginMenu("export VGM...")) {
|
if (ImGui::BeginMenu("export VGM...")) {
|
||||||
if (dejarteArriba) {
|
ImGui::Text("settings:");
|
||||||
ImGui::Text("VGM export not available in unregistered version.");
|
if (ImGui::BeginCombo("format version",fmt::sprintf("%d.%.2x",vgmExportVersion>>8,vgmExportVersion&0xff).c_str())) {
|
||||||
} else {
|
for (int i=0; i<7; i++) {
|
||||||
ImGui::Text("settings:");
|
if (ImGui::Selectable(fmt::sprintf("%d.%.2x",vgmVersions[i]>>8,vgmVersions[i]&0xff).c_str(),vgmExportVersion==vgmVersions[i])) {
|
||||||
if (ImGui::BeginCombo("format version",fmt::sprintf("%d.%.2x",vgmExportVersion>>8,vgmExportVersion&0xff).c_str())) {
|
vgmExportVersion=vgmVersions[i];
|
||||||
for (int i=0; i<7; i++) {
|
|
||||||
if (ImGui::Selectable(fmt::sprintf("%d.%.2x",vgmVersions[i]>>8,vgmVersions[i]&0xff).c_str(),vgmExportVersion==vgmVersions[i])) {
|
|
||||||
vgmExportVersion=vgmVersions[i];
|
|
||||||
}
|
|
||||||
}
|
|
||||||
ImGui::EndCombo();
|
|
||||||
}
|
|
||||||
ImGui::Checkbox("loop",&vgmExportLoop);
|
|
||||||
if (vgmExportLoop && e->song.loopModality==2) {
|
|
||||||
ImGui::Text("trailing ticks:");
|
|
||||||
if (ImGui::RadioButton("auto-detect",vgmExportTrailingTicks==-1)) {
|
|
||||||
vgmExportTrailingTicks=-1;
|
|
||||||
}
|
|
||||||
if (ImGui::RadioButton("one loop",vgmExportTrailingTicks==-2)) {
|
|
||||||
vgmExportTrailingTicks=-2;
|
|
||||||
}
|
|
||||||
if (ImGui::RadioButton("custom",vgmExportTrailingTicks>=0)) {
|
|
||||||
vgmExportTrailingTicks=0;
|
|
||||||
}
|
|
||||||
if (vgmExportTrailingTicks>=0) {
|
|
||||||
ImGui::SameLine();
|
|
||||||
if (ImGui::InputInt("##TrailTicks",&vgmExportTrailingTicks,1,100)) {
|
|
||||||
if (vgmExportTrailingTicks<0) vgmExportTrailingTicks=0;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
ImGui::Checkbox("add pattern change hints",&vgmExportPatternHints);
|
ImGui::EndCombo();
|
||||||
if (ImGui::IsItemHovered()) {
|
}
|
||||||
ImGui::SetTooltip(
|
ImGui::Checkbox("loop",&vgmExportLoop);
|
||||||
"inserts data blocks on pattern changes.\n"
|
if (vgmExportLoop && e->song.loopModality==2) {
|
||||||
"useful if you are writing a playback routine.\n\n"
|
ImGui::Text("trailing ticks:");
|
||||||
|
if (ImGui::RadioButton("auto-detect",vgmExportTrailingTicks==-1)) {
|
||||||
|
vgmExportTrailingTicks=-1;
|
||||||
|
}
|
||||||
|
if (ImGui::RadioButton("one loop",vgmExportTrailingTicks==-2)) {
|
||||||
|
vgmExportTrailingTicks=-2;
|
||||||
|
}
|
||||||
|
if (ImGui::RadioButton("custom",vgmExportTrailingTicks>=0)) {
|
||||||
|
vgmExportTrailingTicks=0;
|
||||||
|
}
|
||||||
|
if (vgmExportTrailingTicks>=0) {
|
||||||
|
ImGui::SameLine();
|
||||||
|
if (ImGui::InputInt("##TrailTicks",&vgmExportTrailingTicks,1,100)) {
|
||||||
|
if (vgmExportTrailingTicks<0) vgmExportTrailingTicks=0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
ImGui::Checkbox("add pattern change hints",&vgmExportPatternHints);
|
||||||
|
if (ImGui::IsItemHovered()) {
|
||||||
|
ImGui::SetTooltip(
|
||||||
|
"inserts data blocks on pattern changes.\n"
|
||||||
|
"useful if you are writing a playback routine.\n\n"
|
||||||
|
|
||||||
"the format of a pattern change data block is:\n"
|
"the format of a pattern change data block is:\n"
|
||||||
"67 66 FE ll ll ll ll 01 oo rr pp pp pp ...\n"
|
"67 66 FE ll ll ll ll 01 oo rr pp pp pp ...\n"
|
||||||
"- ll: length, a 32-bit little-endian number\n"
|
"- ll: length, a 32-bit little-endian number\n"
|
||||||
"- oo: order\n"
|
"- oo: order\n"
|
||||||
"- rr: initial row (a 0Dxx effect is able to select a different row)\n"
|
"- rr: initial row (a 0Dxx effect is able to select a different row)\n"
|
||||||
"- pp: pattern index (one per channel)\n\n"
|
"- pp: pattern index (one per channel)\n\n"
|
||||||
|
|
||||||
"pattern indexes are ordered as they appear in the song."
|
"pattern indexes are ordered as they appear in the song."
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
ImGui::Checkbox("direct stream mode",&vgmExportDirectStream);
|
ImGui::Checkbox("direct stream mode",&vgmExportDirectStream);
|
||||||
if (ImGui::IsItemHovered()) {
|
if (ImGui::IsItemHovered()) {
|
||||||
ImGui::SetTooltip(
|
ImGui::SetTooltip(
|
||||||
"required for DualPCM and MSM6258 export.\n\n"
|
"required for DualPCM and MSM6258 export.\n\n"
|
||||||
"allows for volume/direction changes when playing samples,\n"
|
"allows for volume/direction changes when playing samples,\n"
|
||||||
"at the cost of a massive increase in file size."
|
"at the cost of a massive increase in file size."
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
ImGui::Text("chips to export:");
|
ImGui::Text("chips to export:");
|
||||||
bool hasOneAtLeast=false;
|
bool hasOneAtLeast=false;
|
||||||
for (int i=0; i<e->song.systemLen; i++) {
|
for (int i=0; i<e->song.systemLen; i++) {
|
||||||
int minVersion=e->minVGMVersion(e->song.system[i]);
|
int minVersion=e->minVGMVersion(e->song.system[i]);
|
||||||
ImGui::BeginDisabled(minVersion>vgmExportVersion || minVersion==0);
|
ImGui::BeginDisabled(minVersion>vgmExportVersion || minVersion==0);
|
||||||
ImGui::Checkbox(fmt::sprintf("%d. %s##_SYSV%d",i+1,getSystemName(e->song.system[i]),i).c_str(),&willExport[i]);
|
ImGui::Checkbox(fmt::sprintf("%d. %s##_SYSV%d",i+1,getSystemName(e->song.system[i]),i).c_str(),&willExport[i]);
|
||||||
ImGui::EndDisabled();
|
ImGui::EndDisabled();
|
||||||
if (minVersion>vgmExportVersion) {
|
if (minVersion>vgmExportVersion) {
|
||||||
if (ImGui::IsItemHovered(ImGuiHoveredFlags_AllowWhenDisabled)) {
|
if (ImGui::IsItemHovered(ImGuiHoveredFlags_AllowWhenDisabled)) {
|
||||||
ImGui::SetTooltip("this chip is only available in VGM %d.%.2x and higher!",minVersion>>8,minVersion&0xff);
|
ImGui::SetTooltip("this chip is only available in VGM %d.%.2x and higher!",minVersion>>8,minVersion&0xff);
|
||||||
}
|
|
||||||
} else if (minVersion==0) {
|
|
||||||
if (ImGui::IsItemHovered(ImGuiHoveredFlags_AllowWhenDisabled)) {
|
|
||||||
ImGui::SetTooltip("this chip is not supported by the VGM format!");
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
if (willExport[i]) hasOneAtLeast=true;
|
|
||||||
}
|
}
|
||||||
}
|
} else if (minVersion==0) {
|
||||||
ImGui::Text("select the chip you wish to export,");
|
if (ImGui::IsItemHovered(ImGuiHoveredFlags_AllowWhenDisabled)) {
|
||||||
ImGui::Text("but only up to %d of each type.",(vgmExportVersion>=0x151)?2:1);
|
ImGui::SetTooltip("this chip is not supported by the VGM format!");
|
||||||
if (hasOneAtLeast) {
|
|
||||||
if (ImGui::MenuItem("click to export")) {
|
|
||||||
openFileDialog(GUI_FILE_EXPORT_VGM);
|
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
ImGui::Text("nothing to export");
|
if (willExport[i]) hasOneAtLeast=true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
ImGui::Text("select the chip you wish to export,");
|
||||||
|
ImGui::Text("but only up to %d of each type.",(vgmExportVersion>=0x151)?2:1);
|
||||||
|
if (hasOneAtLeast) {
|
||||||
|
if (ImGui::MenuItem("click to export")) {
|
||||||
|
openFileDialog(GUI_FILE_EXPORT_VGM);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
ImGui::Text("nothing to export");
|
||||||
|
}
|
||||||
ImGui::EndMenu();
|
ImGui::EndMenu();
|
||||||
}
|
}
|
||||||
int numZSMCompat=0;
|
int numZSMCompat=0;
|
||||||
|
@ -3821,7 +3809,7 @@ bool FurnaceGUI::loop() {
|
||||||
ImGui::EndMenu();
|
ImGui::EndMenu();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (!dejarteArriba) if (ImGui::BeginMenu("export command stream...")) {
|
if (ImGui::BeginMenu("export command stream...")) {
|
||||||
ImGui::Text(
|
ImGui::Text(
|
||||||
"this option exports a text or binary file which\n"
|
"this option exports a text or binary file which\n"
|
||||||
"contains a dump of the internal command stream\n"
|
"contains a dump of the internal command stream\n"
|
||||||
|
@ -4906,7 +4894,6 @@ bool FurnaceGUI::loop() {
|
||||||
}
|
}
|
||||||
if (!e->isExporting()) {
|
if (!e->isExporting()) {
|
||||||
ImGui::CloseCurrentPopup();
|
ImGui::CloseCurrentPopup();
|
||||||
if (dejarteArriba) showError("Thanks for using Furnace Pro!\nregister Furnace Pro now and unlock tons of features, including removal of the UNREGISTERED watermark!");
|
|
||||||
}
|
}
|
||||||
ImGui::EndPopup();
|
ImGui::EndPopup();
|
||||||
}
|
}
|
||||||
|
@ -4914,7 +4901,7 @@ bool FurnaceGUI::loop() {
|
||||||
ImVec2 regMinSize=mobileUI?ImVec2(canvasW-(portrait?0:(60.0*dpiScale)),canvasH-60.0*dpiScale):ImVec2(400.0f*dpiScale,200.0f*dpiScale);
|
ImVec2 regMinSize=mobileUI?ImVec2(canvasW-(portrait?0:(60.0*dpiScale)),canvasH-60.0*dpiScale):ImVec2(400.0f*dpiScale,200.0f*dpiScale);
|
||||||
ImVec2 regMaxSize=ImVec2(canvasW-((mobileUI && !portrait)?(60.0*dpiScale):0),canvasH-(mobileUI?(60.0*dpiScale):0));
|
ImVec2 regMaxSize=ImVec2(canvasW-((mobileUI && !portrait)?(60.0*dpiScale):0),canvasH-(mobileUI?(60.0*dpiScale):0));
|
||||||
ImGui::SetNextWindowSizeConstraints(regMinSize,regMaxSize);
|
ImGui::SetNextWindowSizeConstraints(regMinSize,regMaxSize);
|
||||||
if (ImGui::BeginPopupModal("Register",NULL,ImGuiWindowFlags_NoMove)) {
|
if (ImGui::BeginPopupModal("Register",NULL,ImGuiWindowFlags_NoMove|ImGuiWindowFlags_NoScrollWithMouse|ImGuiWindowFlags_NoScrollbar)) {
|
||||||
ImGui::SetWindowPos(ImVec2(((canvasW)-ImGui::GetWindowSize().x)*0.5,((canvasH)-ImGui::GetWindowSize().y)*0.5));
|
ImGui::SetWindowPos(ImVec2(((canvasW)-ImGui::GetWindowSize().x)*0.5,((canvasH)-ImGui::GetWindowSize().y)*0.5));
|
||||||
if (ImGui::GetWindowSize().x<regMinSize.x || ImGui::GetWindowSize().y<regMinSize.y) {
|
if (ImGui::GetWindowSize().x<regMinSize.x || ImGui::GetWindowSize().y<regMinSize.y) {
|
||||||
ImGui::SetWindowSize(regMinSize,ImGuiCond_Always);
|
ImGui::SetWindowSize(regMinSize,ImGuiCond_Always);
|
||||||
|
@ -5768,13 +5755,6 @@ bool FurnaceGUI::loop() {
|
||||||
introPos=12.0;
|
introPos=12.0;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (dejarteArriba) {
|
|
||||||
ImDrawList* urdl=ImGui::GetForegroundDrawList();
|
|
||||||
ImVec2 textSize=ImGui::CalcTextSize("Unregistered Furnace Pro");
|
|
||||||
urdl->AddRectFilled(ImVec2(0,0),textSize,0xffffffff);
|
|
||||||
urdl->AddText(ImVec2(0,0),0xff000000,"Unregistered Furnace Pro");
|
|
||||||
}
|
|
||||||
|
|
||||||
layoutTimeEnd=SDL_GetPerformanceCounter();
|
layoutTimeEnd=SDL_GetPerformanceCounter();
|
||||||
|
|
||||||
// backup trigger
|
// backup trigger
|
||||||
|
|
|
@ -1135,18 +1135,3 @@ const char* chipCategoryNames[]={
|
||||||
"Sample",
|
"Sample",
|
||||||
NULL
|
NULL
|
||||||
};
|
};
|
||||||
|
|
||||||
const int demoChips[]={
|
|
||||||
DIV_SYSTEM_YM2612,
|
|
||||||
DIV_SYSTEM_PCE,
|
|
||||||
DIV_SYSTEM_NES,
|
|
||||||
DIV_SYSTEM_C64_8580,
|
|
||||||
DIV_SYSTEM_YM2151,
|
|
||||||
DIV_SYSTEM_AY8910,
|
|
||||||
DIV_SYSTEM_AMIGA,
|
|
||||||
DIV_SYSTEM_OPL,
|
|
||||||
DIV_SYSTEM_VIC20,
|
|
||||||
DIV_SYSTEM_NAMCO,
|
|
||||||
DIV_SYSTEM_PONG,
|
|
||||||
0 // don't remove this last one!
|
|
||||||
};
|
|
||||||
|
|
|
@ -50,10 +50,9 @@ extern const int chipsSquare[];
|
||||||
extern const int chipsWavetable[];
|
extern const int chipsWavetable[];
|
||||||
extern const int chipsSpecial[];
|
extern const int chipsSpecial[];
|
||||||
extern const int chipsSample[];
|
extern const int chipsSample[];
|
||||||
extern const int demoChips[];
|
|
||||||
extern const int* chipCategories[];
|
extern const int* chipCategories[];
|
||||||
extern const FurnaceGUIActionDef guiActions[];
|
extern const FurnaceGUIActionDef guiActions[];
|
||||||
extern const FurnaceGUIColorDef guiColors[];
|
extern const FurnaceGUIColorDef guiColors[];
|
||||||
extern const int altValues[24];
|
extern const int altValues[24];
|
||||||
extern const int vgmVersions[7];
|
extern const int vgmVersions[7];
|
||||||
extern const FurnaceGUIColors fxColors[256];
|
extern const FurnaceGUIColors fxColors[256];
|
|
@ -22,7 +22,6 @@
|
||||||
#include "IconsFontAwesome4.h"
|
#include "IconsFontAwesome4.h"
|
||||||
#include "guiConst.h"
|
#include "guiConst.h"
|
||||||
#include <imgui.h>
|
#include <imgui.h>
|
||||||
#include "../ta-log.h"
|
|
||||||
|
|
||||||
DivSystem FurnaceGUI::systemPicker() {
|
DivSystem FurnaceGUI::systemPicker() {
|
||||||
DivSystem ret=DIV_SYSTEM_NULL;
|
DivSystem ret=DIV_SYSTEM_NULL;
|
||||||
|
@ -34,21 +33,17 @@ DivSystem FurnaceGUI::systemPicker() {
|
||||||
|
|
||||||
ImGui::SetNextItemWidth(ImGui::GetContentRegionAvail().x);
|
ImGui::SetNextItemWidth(ImGui::GetContentRegionAvail().x);
|
||||||
if (ImGui::InputTextWithHint("##SysSearch","Search...",&sysSearchQuery)) reissueSearch=true;
|
if (ImGui::InputTextWithHint("##SysSearch","Search...",&sysSearchQuery)) reissueSearch=true;
|
||||||
if (dejarteArriba) {
|
if (ImGui::BeginTabBar("SysCats")) {
|
||||||
curSysSection=demoChips;
|
for (int i=0; chipCategories[i]; i++) {
|
||||||
} else {
|
if (ImGui::BeginTabItem(chipCategoryNames[i])) {
|
||||||
if (ImGui::BeginTabBar("SysCats")) {
|
if (ImGui::IsItemActive()) {
|
||||||
for (int i=0; chipCategories[i]; i++) {
|
reissueSearch=true;
|
||||||
if (ImGui::BeginTabItem(chipCategoryNames[i])) {
|
|
||||||
if (ImGui::IsItemActive()) {
|
|
||||||
reissueSearch=true;
|
|
||||||
}
|
|
||||||
curSysSection=chipCategories[i];
|
|
||||||
ImGui::EndTabItem();
|
|
||||||
}
|
}
|
||||||
|
curSysSection=chipCategories[i];
|
||||||
|
ImGui::EndTabItem();
|
||||||
}
|
}
|
||||||
ImGui::EndTabBar();
|
|
||||||
}
|
}
|
||||||
|
ImGui::EndTabBar();
|
||||||
}
|
}
|
||||||
if (reissueSearch) {
|
if (reissueSearch) {
|
||||||
String lowerCase=sysSearchQuery;
|
String lowerCase=sysSearchQuery;
|
||||||
|
@ -95,10 +90,8 @@ DivSystem FurnaceGUI::systemPicker() {
|
||||||
if (hoveredSys!=DIV_SYSTEM_NULL) {
|
if (hoveredSys!=DIV_SYSTEM_NULL) {
|
||||||
const DivSysDef* sysDef=e->getSystemDef(hoveredSys);
|
const DivSysDef* sysDef=e->getSystemDef(hoveredSys);
|
||||||
ImGui::TextWrapped("%s",sysDef->description);
|
ImGui::TextWrapped("%s",sysDef->description);
|
||||||
} else {
|
|
||||||
ImGui::TextWrapped("register NOW and unlock over 50 chips!");
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
ImGui::EndChild();
|
ImGui::EndChild();
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
Loading…
Reference in a new issue