This commit is contained in:
Eknous-P 2023-07-16 11:50:20 +04:00
commit 1fcbc603e1
91 changed files with 514 additions and 333 deletions

Binary file not shown.

View File

@ -1,113 +1,114 @@
# instrument list
![instrument list](list.png)
click on an instrument to select it.
double-click to open the instrument editor.
# instrument editor
every instrument can be renamed and have its type changed.
depending on the instrument type, there are many different types of instrument editor:
- [FM synthesis](fm.md) - for use with YM2612, YM2151 and FM block portion of YM2610.
- [Standard](standard.md) - for use with NES and Sega Master System's PSG sound source and its derivatives.
- [Game Boy](game-boy.md) - for use with Game Boy APU.
- [PC Engine / TurboGrafx-16](pce.md) - for use with PC Engine's wavetable synthesizer.
- [WonderSwan](wonderswan.md) - for use with WonderSwan's wavetable synthesizer.
- [AY8930](8930.md) - for use with Microchip AY8930 E-PSG sound source.
- [Commodore 64](c64.md) - for use with Commodore 64 SID.
- [SAA1099](saa.md) - for use with Philips SAA1099 PSG sound source.
- [TIA](tia.md) - for use with Atari 2600 chip.
- [AY-3-8910](ay8910.md) - for use with AY-3-8910 PSG sound source and SSG portion in YM2610.
- [Amiga / sample](amiga.md) for controlling Amiga and other sample based synthsizers like YM2612's Channel 6 PCM mode, NES channel 5, Sega PCM, X1-010 and PC Engine's sample playback mode.
- [Atari Lynx](lynx.md) - for use with Atari Lynx handheld console.
- [VERA](vera.md) - for use with Commander X16 VERA.
- [Seta/Allumer X1-010](x1_010.md) - for use with Wavetable portion in Seta/Allumer X1-010.
- [Konami SCC / Bubble System WSG](scc.md) - for use with Konami SCC and Wavetable portion in Bubble System's sound hardware.
- [Namco 163](n163.md) - for use with Namco 163.
- [Konami VRC6](vrc6.md) - for use with VRC6's PSG sound source.
- [SNES](snes.md) - for use with SNES S-APU.
- [Casio PV-1000](pv1000.md) - for use with Casio PV-1000.
# macros
Macros are incredibly versatile tools for automating instrument parameters.
After creating an instrument, open the Instrument Editor and select the "Macros" tab. There may be multiple macro tabs to control individual FM operators and such.
![macro view](macroview.png)
The very first numeric entry sets the visible width of the bars in sequence-type macros. The scrollbar affects the view of all macros at once. There's a matching scrollbar at the bottom underneath all the macros.
Each macro has two buttons on the left.
- Macro type (explained below).
- Timing editor, which pops up a small dialog:
- Step Length (ticks): Determines how many ticks pass before each change of value.
- Delay: Delays the start of the macro until this many ticks have passed.
## macro types
Every macro can be defined though one of three methods, selectable with the leftmost button under the macro type label:
- ![](macro-button-seq.png) **Sequence:** displayed as a bar graph, this is a sequence of numeric values.
- ![](macro-button-ADSR.png) **ADSR:** this is a traditional ADSR envelope, defined by the rate of increase and decrease of value over time.
- ![](macro-button-LFO.png) **LFO:** the Low Frequency Oscillator generates a repeating wave of values.
Some macros are "bitmap" style. They represent a number of "bits" that can be toggled individually, and the values listed represent the sum of which bits are turned on.
### sequence
![sequence macro editor](macro-seq.png)
The number between the macro type label and the macro type button is the macro length in steps. The `-` and `+` buttons change the length of the macro. Start out by adding at least a few steps.
The values of the macro can be drawn in the "bar graph box". Just beneath the box is shorter bar graph.
- Click to set the start point of a loop; the end point is the last value or release point. Right-click to remove the loop.
- Shift-click to set the release point. When played, the macro will hold here until the note is released. Right-click to remove the release point.
Finally, the sequence of values can be directly edited in the text box at the bottom.
- The loop start is entered as a `|`.
- The release point is entered as a `/`.
- In arpeggio macros, a value starting with a `@` is an absolute note (instead of a relative shift). No matter the note played, `@` values will be played at that exact note. This is especially useful for noise instruments with preset periods.
### ADSR
![ADSR macro editor](macro-ADSR.png)
- **Bottom** and **Top** determine the range of outputs generated by the macro. (Bottom can be larger than Top to invert the envelope!) All outputs will be between these two values.
- Attack, Decay, Sustain, SusDecay, and Release accept inputs between 0 to 255. These are scaled to the distance between Bottom and Top.
- **Attack** is how much the value moves toward Top with each tick.
- **Hold** sets how many ticks to stay at Top before Decay.
- **Decay** is how much the value moves to the Sustain level.
- **Sustain** is how far from Bottom the value stays while the note is held.
- **SusTime** is how many ticks to stay at Sustain until SusDecay.
- **SusDecay** is how much the value moves toward Bottom with each tick while the note is held.
- **Release** is how much the value moves toward Bottom with each tick after the note is released.
![macro ADSR chart](macro-ADSRchart.png)
### LFO
![LFO macro editor](macro-LFO.png)
- **Bottom** and **Top** determine the range of values generated by the macro. (Bottom can be larger than Top to invert the waveform!)
- **Speed** is how quickly the values change - the frequency of the oscillator.
- **Phase** is which part of the waveform the macro will start at, measured in 1/1024 increments.
- **Shape** is the waveform used. Triangle is the default, and Saw and Square are exactly as they say.
# samples
This tab appears for Generic PCM, SNES, Amiga, and other sample-based instruments.
![](sample-map.png)
- **Initial Sample**: the sample that the instrument will use.
- **Use wavetable**: instead of samples, use wavetables. this causes the [Wavetables](../5-wave/README.md) tab to appear next to Sample.
- depending on the system and use of the wavetable synthesizer, this may or may not be reproducible on hardware.
- **Use sample map**: assigns a sample to each note.
- samples will be played at their default pitch.
- to set a note's sample, click the list entry in the `#` column then type the number of the sample.
# instrument list
![instrument list](list.png)
click on an instrument to select it.
double-click to open the instrument editor.
# instrument editor
every instrument can be renamed and have its type changed.
depending on the instrument type, there are many different types of instrument editor:
- [FM synthesis](fm.md) - for use with YM2612, YM2151 and FM block portion of YM2610.
- [PSG](psg.md) - for use with TI SN76489 and derivatives like Sega Master System's PSG.
- [NES](nes.md) - for use with NES.
- [Game Boy](game-boy.md) - for use with Game Boy APU.
- [PC Engine / TurboGrafx-16](pce.md) - for use with PC Engine's wavetable synthesizer.
- [WonderSwan](wonderswan.md) - for use with WonderSwan's wavetable synthesizer.
- [AY8930](8930.md) - for use with Microchip AY8930 E-PSG sound source.
- [Commodore 64](c64.md) - for use with Commodore 64 SID.
- [SAA1099](saa.md) - for use with Philips SAA1099 PSG sound source.
- [TIA](tia.md) - for use with Atari 2600 chip.
- [AY-3-8910](ay8910.md) - for use with AY-3-8910 PSG sound source and SSG portion in YM2610.
- [Amiga / sample](amiga.md) for controlling Amiga and other sample based synthsizers like YM2612's Channel 6 PCM mode, NES channel 5, Sega PCM, X1-010 and PC Engine's sample playback mode.
- [Atari Lynx](lynx.md) - for use with Atari Lynx handheld console.
- [VERA](vera.md) - for use with Commander X16 VERA.
- [Seta/Allumer X1-010](x1_010.md) - for use with Wavetable portion in Seta/Allumer X1-010.
- [Konami SCC / Bubble System WSG](scc.md) - for use with Konami SCC and Wavetable portion in Bubble System's sound hardware.
- [Namco 163](n163.md) - for use with Namco 163.
- [Konami VRC6](vrc6.md) - for use with VRC6's PSG sound source.
- [SNES](snes.md) - for use with SNES S-APU.
- [Casio PV-1000](pv1000.md) - for use with Casio PV-1000.
# macros
Macros are incredibly versatile tools for automating instrument parameters.
After creating an instrument, open the Instrument Editor and select the "Macros" tab. There may be multiple macro tabs to control individual FM operators and such.
![macro view](macroview.png)
The very first numeric entry sets the visible width of the bars in sequence-type macros. The scrollbar affects the view of all macros at once. There's a matching scrollbar at the bottom underneath all the macros.
Each macro has two buttons on the left.
- Macro type (explained below).
- Timing editor, which pops up a small dialog:
- Step Length (ticks): Determines how many ticks pass before each change of value.
- Delay: Delays the start of the macro until this many ticks have passed.
## macro types
Every macro can be defined though one of three methods, selectable with the leftmost button under the macro type label:
- ![](macro-button-seq.png) **Sequence:** displayed as a bar graph, this is a sequence of numeric values.
- ![](macro-button-ADSR.png) **ADSR:** this is a traditional ADSR envelope, defined by the rate of increase and decrease of value over time.
- ![](macro-button-LFO.png) **LFO:** the Low Frequency Oscillator generates a repeating wave of values.
Some macros are "bitmap" style. They represent a number of "bits" that can be toggled individually, and the values listed represent the sum of which bits are turned on.
### sequence
![sequence macro editor](macro-seq.png)
The number between the macro type label and the macro type button is the macro length in steps. The `-` and `+` buttons change the length of the macro. Start out by adding at least a few steps.
The values of the macro can be drawn in the "bar graph box". Just beneath the box is shorter bar graph.
- Click to set the start point of a loop; the end point is the last value or release point. Right-click to remove the loop.
- Shift-click to set the release point. When played, the macro will hold here until the note is released. Right-click to remove the release point.
Finally, the sequence of values can be directly edited in the text box at the bottom.
- The loop start is entered as a `|`.
- The release point is entered as a `/`.
- In arpeggio macros, a value starting with a `@` is an absolute note (instead of a relative shift). No matter the note played, `@` values will be played at that exact note. This is especially useful for noise instruments with preset periods.
### ADSR
![ADSR macro editor](macro-ADSR.png)
- **Bottom** and **Top** determine the range of outputs generated by the macro. (Bottom can be larger than Top to invert the envelope!) All outputs will be between these two values.
- Attack, Decay, Sustain, SusDecay, and Release accept inputs between 0 to 255. These are scaled to the distance between Bottom and Top.
- **Attack** is how much the value moves toward Top with each tick.
- **Hold** sets how many ticks to stay at Top before Decay.
- **Decay** is how much the value moves to the Sustain level.
- **Sustain** is how far from Bottom the value stays while the note is held.
- **SusTime** is how many ticks to stay at Sustain until SusDecay.
- **SusDecay** is how much the value moves toward Bottom with each tick while the note is held.
- **Release** is how much the value moves toward Bottom with each tick after the note is released.
![macro ADSR chart](macro-ADSRchart.png)
### LFO
![LFO macro editor](macro-LFO.png)
- **Bottom** and **Top** determine the range of values generated by the macro. (Bottom can be larger than Top to invert the waveform!)
- **Speed** is how quickly the values change - the frequency of the oscillator.
- **Phase** is which part of the waveform the macro will start at, measured in 1/1024 increments.
- **Shape** is the waveform used. Triangle is the default, and Saw and Square are exactly as they say.
# samples
This tab appears for Generic PCM, SNES, Amiga, and other sample-based instruments.
![](sample-map.png)
- **Initial Sample**: the sample that the instrument will use.
- **Use wavetable**: instead of samples, use wavetables. this causes the [Wavetables](../5-wave/README.md) tab to appear next to Sample.
- depending on the system and use of the wavetable synthesizer, this may or may not be reproducible on hardware.
- **Use sample map**: assigns a sample to each note.
- samples will be played at their default pitch.
- to set a note's sample, click the list entry in the `#` column then type the number of the sample.

18
doc/4-instrument/nes.md Normal file
View File

@ -0,0 +1,18 @@
# Standard instrument editor
The instrument editor for NES consists of these macros:
- **Volume**: volume.
- **Arpeggio**: pitch in half-steps.
- **Duty**: duty cycle and noise mode.
- pulse duty cycles:
- `0`: 12.5%
- `1`: 25%
- `2`: 50%
- `3`: 75%
- noise modes:
- `0`: long noise.
- `1`: short noise.
- **Panning**: output for left and right channels.
- **Pitch**: fine pitch.
- **Phase Reset**: trigger restart of waveform.

14
doc/4-instrument/psg.md Normal file
View File

@ -0,0 +1,14 @@
# PSG instrument editor
The instrument editor for PSG (SMS, MSX, and other TI SN76489 derivatives) consists of these macros:
- **Volume**: volume.
- **Arpeggio**: pitch in half-steps.
- **Duty**: noise mode.
- `0`: short noise, preset frequencies.
- `1`: long noise, preset frequencies.
- `2`: short noise, use channel 3 for frequency.
- `3`: long noise, use channel 3 for frequency.
- **Panning**: output for left and right channels.
- **Pitch**: fine pitch.
- **Phase Reset**: trigger restart of waveform.

View File

@ -1,10 +0,0 @@
# Standard instrument editor
The instrument editor for NES and PSG (SMS, MSX, and such) consists of these macros:
- **Volume**: volume
- **Arpeggio**: pitch in half-steps
- **Duty**: duty cycle and noise mode for NES channels. _Note:_ This has no effect on Sega Master System.
- **Panning**: output for left and right channels
- **Pitch**: fine pitch
- **Phase Reset**: trigger restart of waveform

View File

@ -295,6 +295,8 @@ struct DivRegWrite {
*/
unsigned int addr;
unsigned int val;
DivRegWrite():
addr(0), val(0) {}
DivRegWrite(unsigned int a, unsigned int v):
addr(a), val(v) {}
};

View File

@ -2598,6 +2598,8 @@ void DivEngine::stepOne(int row) {
}
stepPlay=2;
ticks=1;
prevOrder=curOrder;
prevRow=curRow;
BUSY_END;
}
@ -4320,9 +4322,7 @@ void DivEngine::autoNoteOn(int ch, int ins, int note, int vol) {
void DivEngine::autoNoteOff(int ch, int note, int vol) {
if (!playing) {
reset();
freelance=true;
playing=true;
return;
}
//if (ch<0 || ch>=chans) return;
for (int i=0; i<chans; i++) {
@ -4335,9 +4335,7 @@ void DivEngine::autoNoteOff(int ch, int note, int vol) {
void DivEngine::autoNoteOffAll() {
if (!playing) {
reset();
freelance=true;
playing=true;
return;
}
for (int i=0; i<chans; i++) {
if (chan[i].midiNote!=-1) {

140
src/engine/fixedQueue.h Normal file
View File

@ -0,0 +1,140 @@
/**
* 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 _FIXED_QUEUE_H
#define _FIXED_QUEUE_H
#include <stdint.h>
#include "../ta-log.h"
template<typename T, size_t items> struct FixedQueue {
size_t readPos, writePos;
T data[items];
T& front();
T& back();
bool pop();
bool push(const T& item);
bool pop_front();
bool pop_back();
bool push_front(const T& item);
bool push_back(const T& item);
void clear();
bool empty();
size_t size();
FixedQueue():
readPos(0),
writePos(0) {}
};
template <typename T, size_t items> T& FixedQueue<T,items>::front() {
return data[readPos];
}
template <typename T, size_t items> T& FixedQueue<T,items>::back() {
if (writePos==0) return data[items-1];
return data[writePos-1];
}
template <typename T, size_t items> bool FixedQueue<T,items>::pop() {
if (readPos==writePos) return false;
if (++readPos>=items) readPos=0;
return true;
}
template <typename T, size_t items> bool FixedQueue<T,items>::push(const T& item) {
if (writePos==(readPos-1)) {
logW("queue overflow!");
return false;
}
if (writePos==items-1 && readPos==0) {
logW("queue overflow!");
return false;
}
data[writePos]=item;
if (++writePos>=items) writePos=0;
return true;
}
template <typename T, size_t items> bool FixedQueue<T,items>::pop_front() {
if (readPos==writePos) return false;
if (++readPos>=items) readPos=0;
return true;
}
template <typename T, size_t items> bool FixedQueue<T,items>::push_back(const T& item) {
if (writePos==(readPos-1)) {
logW("queue overflow!");
return false;
}
if (writePos==items-1 && readPos==0) {
logW("queue overflow!");
return false;
}
data[writePos]=item;
if (++writePos>=items) writePos=0;
return true;
}
template <typename T, size_t items> bool FixedQueue<T,items>::pop_back() {
if (readPos==writePos) return false;
if (writePos>0) {
writePos--;
} else {
writePos=items-1;
}
return true;
}
template <typename T, size_t items> bool FixedQueue<T,items>::push_front(const T& item) {
if (readPos==(writePos+1)) {
logW("stack overflow!");
return false;
}
if (readPos==0 && writePos==items-1) {
logW("stack overflow!");
return false;
}
if (readPos>0) {
readPos--;
} else {
readPos=items-1;
}
data[readPos]=item;
return true;
}
template <typename T, size_t items> void FixedQueue<T,items>::clear() {
readPos=0;
writePos=0;
}
template <typename T, size_t items> bool FixedQueue<T,items>::empty() {
return (readPos==writePos);
}
template <typename T, size_t items> size_t FixedQueue<T,items>::size() {
if (readPos>writePos) {
return items+writePos-readPos;
}
return writePos-readPos;
}
#endif

View File

@ -21,7 +21,6 @@
#define _AMIGA_H
#include "../dispatch.h"
#include <queue>
#include "../waveSynth.h"
class DivPlatformAmiga: public DivDispatch {

View File

@ -878,7 +878,7 @@ void DivPlatformArcade::poke(std::vector<DivRegWrite>& wlist) {
}
void DivPlatformArcade::reset() {
while (!writes.empty()) writes.pop_front();
writes.clear();
memset(regPool,0,256);
if (useYMFM) {
fm_ymfm->reset();

View File

@ -20,7 +20,6 @@
#ifndef _ARCADE_H
#define _ARCADE_H
#include "fmshared_OPM.h"
#include <queue>
#include "../../../extern/opm/opm.h"
#include "sound/ymfm/ymfm_opm.h"

View File

@ -25,7 +25,7 @@
#include <math.h>
#define rWrite(a,v) if (!skipRegisterWrites) {pendingWrites[a]=v;}
#define immWrite(a,v) if (!skipRegisterWrites) {writes.emplace(regRemap(a),v); if (dumpWrites) {addWrite(regRemap(a),v);} }
#define immWrite(a,v) if (!skipRegisterWrites) {writes.push(QueuedWrite(regRemap(a),v)); if (dumpWrites) {addWrite(regRemap(a),v);} }
#define CHIP_DIVIDER (extMode?extDiv:((sunsoft||clockSel)?16:8))

View File

@ -20,7 +20,7 @@
#ifndef _AY_H
#define _AY_H
#include "../dispatch.h"
#include <queue>
#include "../fixedQueue.h"
#include "sound/ay8910.h"
class DivPlatformAY8910: public DivDispatch {
@ -89,9 +89,10 @@ class DivPlatformAY8910: public DivDispatch {
unsigned short addr;
unsigned char val;
bool addrOrVal;
QueuedWrite(): addr(0), val(0), addrOrVal(false) {}
QueuedWrite(unsigned short a, unsigned char v): addr(a), val(v), addrOrVal(false) {}
};
std::queue<QueuedWrite> writes;
FixedQueue<QueuedWrite,128> writes;
ay8910_device* ay;
DivDispatchOscBuffer* oscBuf[3];
unsigned char regPool[16];

View File

@ -25,7 +25,7 @@
#include <math.h>
#define rWrite(a,v) if (!skipRegisterWrites) {pendingWrites[a]=v;}
#define immWrite2(a,v) if (!skipRegisterWrites) {writes.emplace(a,v); if (dumpWrites) {addWrite(a,v);} }
#define immWrite2(a,v) if (!skipRegisterWrites) {writes.push(QueuedWrite(a,v)); if (dumpWrites) {addWrite(a,v);} }
#define CHIP_DIVIDER (clockSel?8:4)

View File

@ -20,7 +20,7 @@
#ifndef _AY8930_H
#define _AY8930_H
#include "../dispatch.h"
#include <queue>
#include "../fixedQueue.h"
#include "sound/ay8910.h"
class DivPlatformAY8930: public DivDispatch {
@ -99,9 +99,10 @@ class DivPlatformAY8930: public DivDispatch {
unsigned short addr;
unsigned char val;
bool addrOrVal;
QueuedWrite(): addr(0), val(0), addrOrVal(false) {}
QueuedWrite(unsigned short a, unsigned char v): addr(a), val(v), addrOrVal(false) {}
};
std::queue<QueuedWrite> writes;
FixedQueue<QueuedWrite,128> writes;
ay8930_device* ay;
DivDispatchOscBuffer* oscBuf[3];
unsigned char regPool[32];

View File

@ -21,7 +21,6 @@
#define _K005289_H
#include "../dispatch.h"
#include <queue>
#include "../waveSynth.h"
#include "vgsound_emu/src/k005289/k005289.hpp"

View File

@ -23,7 +23,7 @@
#include <math.h>
#include "../../ta-log.h"
#define rWrite(a,v) if (!skipRegisterWrites) {writes.emplace(a,v); if (dumpWrites) {addWrite(a,v);} }
#define rWrite(a,v) if (!skipRegisterWrites) {writes.push(QueuedWrite(a,v)); if (dumpWrites) {addWrite(a,v);} }
#define CHIP_FREQBASE 524288

View File

@ -21,7 +21,7 @@
#define _C64_H
#include "../dispatch.h"
#include <queue>
#include "../fixedQueue.h"
#include "sound/c64/sid.h"
#include "sound/c64_fp/SID.h"
#include "sound/c64_d/dsid.h"
@ -62,9 +62,10 @@ class DivPlatformC64: public DivDispatch {
struct QueuedWrite {
unsigned char addr;
unsigned char val;
QueuedWrite(): addr(0), val(0) {}
QueuedWrite(unsigned char a, unsigned char v): addr(a), val(v) {}
};
std::queue<QueuedWrite> writes;
FixedQueue<QueuedWrite,128> writes;
unsigned char filtControl, filtRes, vol;
unsigned char writeOscBuf;

View File

@ -26,9 +26,8 @@
#define PITCH_OFFSET ((double)(16*2048*(chanMax+1)))
#define NOTE_ES5506(c,note) (parent->calcBaseFreq(chipClock,chan[c].pcm.freqOffs,note,false))
#define rWrite(a,...) {if(!skipRegisterWrites) {hostIntf32.emplace(4,(a),__VA_ARGS__); }}
//#define rRead(a,st,...) {hostIntf32.emplace(st,4,(a),__VA_ARGS__);}
#define immWrite(a,...) {hostIntf32.emplace(4,(a),__VA_ARGS__);}
#define rWrite(a,...) {if(!skipRegisterWrites) {hostIntf32.push_back(QueuedHostIntf(4,(a),__VA_ARGS__)); }}
#define immWrite(a,...) {hostIntf32.push_back(QueuedHostIntf(4,(a),__VA_ARGS__));}
#define pageWrite(p,a,...) \
if (!skipRegisterWrites) { \
if (curPage!=(p)) { \
@ -118,15 +117,15 @@ void DivPlatformES5506::acquire(short** buf, size_t len) {
while (!hostIntf32.empty()) {
QueuedHostIntf w=hostIntf32.front();
if (w.isRead && (w.read!=NULL)) {
hostIntf8.emplace(w.state,0,w.addr,w.read,w.mask);
hostIntf8.emplace(w.state,1,w.addr,w.read,w.mask);
hostIntf8.emplace(w.state,2,w.addr,w.read,w.mask);
hostIntf8.emplace(w.state,3,w.addr,w.read,w.mask,w.delay);
hostIntf8.push(QueuedHostIntf(w.state,0,w.addr,w.read,w.mask));
hostIntf8.push(QueuedHostIntf(w.state,1,w.addr,w.read,w.mask));
hostIntf8.push(QueuedHostIntf(w.state,2,w.addr,w.read,w.mask));
hostIntf8.push(QueuedHostIntf(w.state,3,w.addr,w.read,w.mask,w.delay));
} else {
hostIntf8.emplace(0,w.addr,w.val,w.mask);
hostIntf8.emplace(1,w.addr,w.val,w.mask);
hostIntf8.emplace(2,w.addr,w.val,w.mask);
hostIntf8.emplace(3,w.addr,w.val,w.mask,w.delay);
hostIntf8.push(QueuedHostIntf(0,w.addr,w.val,w.mask));
hostIntf8.push(QueuedHostIntf(1,w.addr,w.val,w.mask));
hostIntf8.push(QueuedHostIntf(2,w.addr,w.val,w.mask));
hostIntf8.push(QueuedHostIntf(3,w.addr,w.val,w.mask,w.delay));
}
hostIntf32.pop();
}
@ -1095,8 +1094,6 @@ DivMacroInt* DivPlatformES5506::getChanMacroInt(int ch) {
void DivPlatformES5506::reset() {
while (!hostIntf32.empty()) hostIntf32.pop();
while (!hostIntf8.empty()) hostIntf8.pop();
while (!queuedRead.empty()) queuedRead.pop();
while (!queuedReadState.empty()) queuedReadState.pop();
for (int i=0; i<32; i++) {
chan[i]=DivPlatformES5506::Channel();
chan[i].std.setEngine(parent);

View File

@ -22,7 +22,7 @@
#include "../dispatch.h"
#include "../engine.h"
#include <queue>
#include "../fixedQueue.h"
#include "../macroInt.h"
#include "../sample.h"
#include "vgsound_emu/src/es550x/es5506.hpp"
@ -238,6 +238,15 @@ class DivPlatformES5506: public DivDispatch, public es550x_intf {
unsigned int* read;
unsigned short delay;
bool isRead;
QueuedHostIntf():
state(0),
step(0),
addr(0),
val(0),
mask(0),
read(NULL),
delay(0),
isRead(false) {}
QueuedHostIntf(unsigned char s, unsigned char a, unsigned int v, unsigned int m=(unsigned int)(~0), unsigned short d=0):
state(0),
step(s),
@ -257,17 +266,8 @@ class DivPlatformES5506: public DivDispatch, public es550x_intf {
delay(d),
isRead(true) {}
};
struct QueuedReadState {
unsigned int* read;
unsigned char state;
QueuedReadState(unsigned int* r, unsigned char s):
read(r),
state(s) {}
};
std::queue<QueuedHostIntf> hostIntf32;
std::queue<QueuedHostIntf> hostIntf8;
std::queue<unsigned char> queuedRead;
std::queue<QueuedReadState> queuedReadState;
FixedQueue<QueuedHostIntf,2048> hostIntf32;
FixedQueue<QueuedHostIntf,2048> hostIntf8;
int cycle, curPage, volScale;
unsigned char maskedVal;
unsigned int irqv;

View File

@ -22,7 +22,7 @@
#include "../dispatch.h"
#include "../instrument.h"
#include <deque>
#include "../fixedQueue.h"
#define KVS(x,y) ((chan[x].state.op[y].kvs==2 && isOutput[chan[x].state.alg][y]) || chan[x].state.op[y].kvs==1)
@ -79,9 +79,10 @@ class DivPlatformFMBase: public DivDispatch {
unsigned short addr;
unsigned char val;
bool addrOrVal;
QueuedWrite(): addr(0), val(0), addrOrVal(false) {}
QueuedWrite(unsigned short a, unsigned char v): addr(a), val(v), addrOrVal(false) {}
};
std::deque<QueuedWrite> writes;
FixedQueue<QueuedWrite,2048> writes;
unsigned char lastBusy;
int delay;

View File

@ -22,7 +22,7 @@
#include "../../ta-log.h"
#include <math.h>
#define rWrite(a,v) {if(!skipRegisterWrites) {writes.emplace(a,v); if(dumpWrites) addWrite(a,v);}}
#define rWrite(a,v) {if(!skipRegisterWrites) {writes.push(QueuedWrite(a,v)); if(dumpWrites) addWrite(a,v);}}
#define CHIP_DIVIDER 64
@ -68,7 +68,7 @@ void DivPlatformGA20::acquire(short** buf, size_t len) {
ga20.write(w.addr,w.val);
regPool[w.addr]=w.val;
writes.pop();
delay=w.delay;
delay=1;
}
}
short *buffer[4]={
@ -361,9 +361,7 @@ DivDispatchOscBuffer* DivPlatformGA20::getOscBuffer(int ch) {
}
void DivPlatformGA20::reset() {
while (!writes.empty()) {
writes.pop();
}
writes.clear();
memset(regPool,0,32);
ga20.device_reset();
delay=0;

View File

@ -21,7 +21,7 @@
#define _GA20_H
#include "../dispatch.h"
#include <queue>
#include "../fixedQueue.h"
#include "../macroInt.h"
#include "sound/ga20/iremga20.h"
@ -47,15 +47,14 @@ class DivPlatformGA20: public DivDispatch, public iremga20_intf {
DivDispatchOscBuffer* oscBuf[4];
bool isMuted[4];
struct QueuedWrite {
unsigned short addr;
unsigned char addr;
unsigned char val;
unsigned short delay;
QueuedWrite(unsigned short a, unsigned char v, unsigned short d=1):
QueuedWrite(): addr(0), val(0) {}
QueuedWrite(unsigned char a, unsigned char v):
addr(a),
val(v),
delay(d) {}
val(v) {}
};
std::queue<QueuedWrite> writes;
FixedQueue<QueuedWrite,256> writes;
unsigned int sampleOffGA20[256];
bool sampleLoaded[256];

View File

@ -22,8 +22,8 @@
#include "../../ta-log.h"
#include <math.h>
#define rWrite(a,v) if (!skipRegisterWrites) {writes.emplace(a,v); regPool[(a)&0x7f]=v; if (dumpWrites) {addWrite(a,v);} }
#define immWrite(a,v) {writes.emplace(a,v); regPool[(a)&0x7f]=v; if (dumpWrites) {addWrite(a,v);} }
#define rWrite(a,v) if (!skipRegisterWrites) {writes.push(QueuedWrite(a,v)); regPool[(a)&0x7f]=v; if (dumpWrites) {addWrite(a,v);} }
#define immWrite(a,v) {writes.push(QueuedWrite(a,v)); regPool[(a)&0x7f]=v; if (dumpWrites) {addWrite(a,v);} }
#define CHIP_DIVIDER 16

View File

@ -23,7 +23,7 @@
#include "../dispatch.h"
#include "../waveSynth.h"
#include "sound/gb/gb.h"
#include <queue>
#include "../fixedQueue.h"
class DivPlatformGB: public DivDispatch {
struct Channel: public SharedChannel<signed char> {
@ -62,11 +62,12 @@ class DivPlatformGB: public DivDispatch {
unsigned char lastPan;
DivWaveSynth ws;
struct QueuedWrite {
unsigned char addr;
unsigned char val;
QueuedWrite(unsigned char a, unsigned char v): addr(a), val(v) {}
unsigned char addr;
unsigned char val;
QueuedWrite(): addr(0), val(0) {}
QueuedWrite(unsigned char a, unsigned char v): addr(a), val(v) {}
};
std::queue<QueuedWrite> writes;
FixedQueue<QueuedWrite,256> writes;
int antiClickPeriodCount, antiClickWavePos;

View File

@ -284,7 +284,7 @@ void DivPlatformGenesis::acquire(short** buf, size_t len) {
}
void DivPlatformGenesis::fillStream(std::vector<DivDelayedWrite>& stream, int sRate, size_t len) {
while (!writes.empty()) writes.pop_front();
writes.clear();
for (size_t i=0; i<len; i++) {
processDAC(sRate);
@ -1282,7 +1282,7 @@ float DivPlatformGenesis::getPostAmp() {
}
void DivPlatformGenesis::reset() {
while (!writes.empty()) writes.pop_front();
writes.clear();
memset(regPool,0,512);
if (useYMFM) {
fm_ymfm->reset();

View File

@ -22,7 +22,7 @@
#include "../../ta-log.h"
#include <math.h>
#define rWrite(a,v) {if(!skipRegisterWrites) {writes.emplace(a,v); if(dumpWrites) addWrite(a,v);}}
#define rWrite(a,v) {if(!skipRegisterWrites) {writes.push(QueuedWrite(a,v)); if(dumpWrites) addWrite(a,v);}}
#define CHIP_DIVIDER 64

View File

@ -21,7 +21,7 @@
#define _K007232_H
#include "../dispatch.h"
#include <queue>
#include "../fixedQueue.h"
#include "../macroInt.h"
#include "vgsound_emu/src/k007232/k007232.hpp"
@ -57,12 +57,13 @@ class DivPlatformK007232: public DivDispatch, public k007232_intf {
unsigned short addr;
unsigned char val;
unsigned short delay;
QueuedWrite(): addr(0), val(0), delay(1) {}
QueuedWrite(unsigned short a, unsigned char v, unsigned short d=1):
addr(a),
val(v),
delay(d) {}
};
std::queue<QueuedWrite> writes;
FixedQueue<QueuedWrite,256> writes;
unsigned int sampleOffK007232[256];
bool sampleLoaded[256];

View File

@ -23,7 +23,7 @@
#include <math.h>
//#define rWrite(a,v) pendingWrites[a]=v;
#define rWrite(a,v) if (!skipRegisterWrites) {writes.emplace(a,v); if (dumpWrites) {addWrite(a,v);} }
#define rWrite(a,v) if (!skipRegisterWrites) {writes.push(QueuedWrite(a,v)); if (dumpWrites) {addWrite(a,v);} }
#define NOTE_LINEAR(x) ((x)<<7)

View File

@ -21,7 +21,7 @@
#define _MSM5232_H
#include "../dispatch.h"
#include <queue>
#include "../fixedQueue.h"
#include "sound/oki/msm5232.h"
class DivPlatformMSM5232: public DivDispatch {
@ -46,11 +46,12 @@ class DivPlatformMSM5232: public DivDispatch {
unsigned char groupAR[2];
unsigned char groupDR[2];
struct QueuedWrite {
unsigned char addr;
unsigned char val;
QueuedWrite(unsigned char a, unsigned char v): addr(a), val(v) {}
unsigned char addr;
unsigned char val;
QueuedWrite(): addr(0), val(0) {}
QueuedWrite(unsigned char a, unsigned char v): addr(a), val(v) {}
};
std::queue<QueuedWrite> writes;
FixedQueue<QueuedWrite,256> writes;
int cycles, curChan, delay, detune, clockDriftAccum;
unsigned int clockDriftLFOPos, clockDriftLFOSpeed;

View File

@ -24,7 +24,7 @@
#include <string.h>
#include <math.h>
#define rWrite(a,v) if (!skipRegisterWrites) {writes.emplace(a,v); if (dumpWrites) {addWrite(a,v);} }
#define rWrite(a,v) if (!skipRegisterWrites) {writes.push(QueuedWrite(a,v)); if (dumpWrites) {addWrite(a,v);} }
const char** DivPlatformMSM6258::getRegisterSheet() {
return NULL;

View File

@ -21,7 +21,7 @@
#define _MSM6258_H
#include "../dispatch.h"
#include <queue>
#include "../fixedQueue.h"
#include "sound/oki/okim6258.h"
class DivPlatformMSM6258: public DivDispatch {
@ -42,9 +42,10 @@ class DivPlatformMSM6258: public DivDispatch {
struct QueuedWrite {
unsigned short addr;
unsigned char val;
QueuedWrite(): addr(0), val(0) {}
QueuedWrite(unsigned short a, unsigned char v): addr(a), val(v) {}
};
std::queue<QueuedWrite> writes;
FixedQueue<QueuedWrite,256> writes;
okim6258_device* msm;
unsigned char lastBusy;

View File

@ -23,8 +23,8 @@
#include <string.h>
#include <math.h>
#define rWrite(a,v) if (!skipRegisterWrites) {writes.emplace(a,v); if (dumpWrites) {addWrite(a,v);} }
#define rWriteDelay(a,v,d) if (!skipRegisterWrites) {writes.emplace(a,v,d); if (dumpWrites) {addWrite(a,v);} }
#define rWrite(a,v) if (!skipRegisterWrites) {writes.push(QueuedWrite(a,v)); if (dumpWrites) {addWrite(a,v);} }
#define rWriteDelay(a,v,d) if (!skipRegisterWrites) {writes.push(QueuedWrite(a,v,d)); if (dumpWrites) {addWrite(a,v);} }
const char** DivPlatformMSM6295::getRegisterSheet() {
return NULL;

View File

@ -21,7 +21,7 @@
#define _MSM6295_H
#include "../dispatch.h"
#include <queue>
#include "../fixedQueue.h"
#include "vgsound_emu/src/msm6295/msm6295.hpp"
class DivPlatformMSM6295: public DivDispatch, public vgsound_emu_mem_intf {
@ -41,12 +41,13 @@ class DivPlatformMSM6295: public DivDispatch, public vgsound_emu_mem_intf {
unsigned short addr;
unsigned char val;
unsigned short delay;
QueuedWrite(): addr(0), val(0), delay(96) {}
QueuedWrite(unsigned short a, unsigned char v, unsigned short d=96):
addr(a),
val(v),
delay(d) {}
};
std::queue<QueuedWrite> writes;
FixedQueue<QueuedWrite,256> writes;
msm6295_core msm;
unsigned char lastBusy;

View File

@ -23,8 +23,8 @@
#include <math.h>
#define rRead(a,v) n163.addr_w(a); n163.data_r(v);
#define rWrite(a,v) if (!skipRegisterWrites) {writes.emplace(a,v); if (dumpWrites) {addWrite(a,v);} }
#define rWriteMask(a,v,m) if (!skipRegisterWrites) {writes.emplace(a,v,m); if (dumpWrites) {addWrite(a,v);} }
#define rWrite(a,v) if (!skipRegisterWrites) {writes.push(QueuedWrite(a,v)); if (dumpWrites) {addWrite(a,v);} }
#define rWriteMask(a,v,m) if (!skipRegisterWrites) {writes.push(QueuedWrite(a,v,m)); if (dumpWrites) {addWrite(a,v);} }
#define chWrite(c,a,v) \
if (c<=chanMax) { \
rWrite(0x78-(c<<3)+(a&7),v) \

View File

@ -21,7 +21,7 @@
#define _N163_H
#include "../dispatch.h"
#include <queue>
#include "../fixedQueue.h"
#include "../waveSynth.h"
#include "vgsound_emu/src/n163/n163.hpp"
@ -54,12 +54,13 @@ class DivPlatformN163: public DivDispatch {
DivDispatchOscBuffer* oscBuf[8];
bool isMuted[8];
struct QueuedWrite {
unsigned char addr;
unsigned char val;
unsigned char mask;
QueuedWrite(unsigned char a, unsigned char v, unsigned char m=~0): addr(a), val(v), mask(m) {}
unsigned char addr;
unsigned char val;
unsigned char mask;
QueuedWrite(): addr(0), val(0), mask(~0) {}
QueuedWrite(unsigned char a, unsigned char v, unsigned char m=~0): addr(a), val(v), mask(m) {}
};
std::queue<QueuedWrite> writes;
FixedQueue<QueuedWrite,2048> writes;
unsigned char initChanMax;
unsigned char chanMax;
short loadWave, loadPos, loadLen;

View File

@ -22,7 +22,7 @@
#include <math.h>
//#define rWrite(a,v) pendingWrites[a]=v;
#define rWrite(a,v) if (!skipRegisterWrites) {writes.emplace(a,v); if (dumpWrites) {addWrite(a,v);} }
#define rWrite(a,v) if (!skipRegisterWrites) {writes.push(QueuedWrite(a,v)); if (dumpWrites) {addWrite(a,v);} }
#define CHIP_FREQBASE 4194304

View File

@ -21,7 +21,7 @@
#define _NAMCOWSG_H
#include "../dispatch.h"
#include <queue>
#include "../fixedQueue.h"
#include "../waveSynth.h"
#include "sound/namco.h"
@ -41,11 +41,12 @@ class DivPlatformNamcoWSG: public DivDispatch {
DivDispatchOscBuffer* oscBuf[8];
bool isMuted[8];
struct QueuedWrite {
unsigned short addr;
unsigned char val;
QueuedWrite(unsigned short a, unsigned char v): addr(a), val(v) {}
unsigned short addr;
unsigned char val;
QueuedWrite(): addr(0), val(0) {}
QueuedWrite(unsigned short a, unsigned char v): addr(a), val(v) {}
};
std::queue<QueuedWrite> writes;
FixedQueue<QueuedWrite,256> writes;
namco_audio_device* namco;
int devType, chans;

View File

@ -24,7 +24,7 @@
#include <math.h>
#define rWrite(a,v) if (!skipRegisterWrites) {pendingWrites[a]=v;}
#define immWrite(a,v) if (!skipRegisterWrites) {writes.emplace(a,v); if (dumpWrites) {addWrite(a,v);} }
#define immWrite(a,v) if (!skipRegisterWrites) {writes.push(QueuedWrite(a,v)); if (dumpWrites) {addWrite(a,v);} }
#define KVSL(x,y) ((chan[x].state.op[orderedOpsL1[ops==4][y]].kvs==2 && isOutputL[ops==4][chan[x].state.alg][y]) || chan[x].state.op[orderedOpsL1[ops==4][y]].kvs==1)

View File

@ -21,7 +21,7 @@
#define _OPL_H
#include "../dispatch.h"
#include <queue>
#include "../fixedQueue.h"
#include "../../../extern/opl/opl3.h"
#include "sound/ymfm/ymfm_adpcm.h"
@ -64,9 +64,10 @@ class DivPlatformOPL: public DivDispatch {
unsigned short addr;
unsigned char val;
bool addrOrVal;
QueuedWrite(): addr(0), val(0), addrOrVal(false) {}
QueuedWrite(unsigned short a, unsigned char v): addr(a), val(v), addrOrVal(false) {}
};
std::queue<QueuedWrite> writes;
FixedQueue<QueuedWrite,2048> writes;
opl3_chip fm;
unsigned char* adpcmBMem;
size_t adpcmBMemLen;

View File

@ -24,7 +24,7 @@
#include <math.h>
#define rWrite(a,v) if (!skipRegisterWrites) {pendingWrites[a]=v;}
#define immWrite(a,v) if (!skipRegisterWrites) {writes.emplace(a,v); if (dumpWrites) {addWrite(a,v);} }
#define immWrite(a,v) if (!skipRegisterWrites) {writes.push(QueuedWrite(a,v)); if (dumpWrites) {addWrite(a,v);} }
#define CHIP_FREQBASE 1180068

View File

@ -21,7 +21,7 @@
#define _OPLL_H
#include "../dispatch.h"
#include <queue>
#include "../fixedQueue.h"
extern "C" {
#include "../../../extern/Nuked-OPLL/opll.h"
@ -50,9 +50,10 @@ class DivPlatformOPLL: public DivDispatch {
unsigned short addr;
unsigned char val;
bool addrOrVal;
QueuedWrite(): addr(0), val(0), addrOrVal(false) {}
QueuedWrite(unsigned short a, unsigned char v): addr(a), val(v), addrOrVal(false) {}
};
std::queue<QueuedWrite> writes;
FixedQueue<QueuedWrite,512> writes;
opll_t fm;
int delay, lastCustomMemory;
unsigned char lastBusy;

View File

@ -22,7 +22,7 @@
#include <math.h>
//#define rWrite(a,v) pendingWrites[a]=v;
#define rWrite(a,v) if (!skipRegisterWrites) {writes.emplace(a,v); if (dumpWrites) {addWrite(a,v);} }
#define rWrite(a,v) if (!skipRegisterWrites) {writes.push(QueuedWrite(a,v)); if (dumpWrites) {addWrite(a,v);} }
#define chWrite(c,a,v) \
if (!skipRegisterWrites) { \
if (curChan!=c) { \
@ -531,7 +531,7 @@ int DivPlatformPCE::getRegisterPoolSize() {
}
void DivPlatformPCE::reset() {
while (!writes.empty()) writes.pop();
writes.clear();
memset(regPool,0,128);
for (int i=0; i<6; i++) {
chan[i]=DivPlatformPCE::Channel();

View File

@ -21,7 +21,7 @@
#define _PCE_H
#include "../dispatch.h"
#include <queue>
#include "../fixedQueue.h"
#include "../waveSynth.h"
#include "sound/pce_psg.h"
@ -60,11 +60,12 @@ class DivPlatformPCE: public DivDispatch {
bool antiClickEnabled;
bool updateLFO;
struct QueuedWrite {
unsigned char addr;
unsigned char val;
QueuedWrite(unsigned char a, unsigned char v): addr(a), val(v) {}
unsigned char addr;
unsigned char val;
QueuedWrite(): addr(0), val(9) {}
QueuedWrite(unsigned char a, unsigned char v): addr(a), val(v) {}
};
std::queue<QueuedWrite> writes;
FixedQueue<QueuedWrite,512> writes;
unsigned char lastPan;
int cycles, curChan, delay;

View File

@ -21,7 +21,6 @@
#define _PCM_DAC_H
#include "../dispatch.h"
#include <queue>
#include "../waveSynth.h"
class DivPlatformPCMDAC: public DivDispatch {

View File

@ -21,7 +21,7 @@
#define _PCSPKR_H
#include "../dispatch.h"
#include <queue>
#include "../fixedQueue.h"
#include <thread>
#include <mutex>
#include <condition_variable>
@ -40,12 +40,16 @@ class DivPlatformPCSpeaker: public DivDispatch {
struct RealQueueVal {
int tv_sec, tv_nsec;
unsigned short val;
RealQueueVal():
tv_sec(0),
tv_nsec(0),
val(0) {}
RealQueueVal(int sec, int nsec, unsigned short v):
tv_sec(sec),
tv_nsec(nsec),
val(v) {}
};
std::queue<RealQueueVal> realQueue;
FixedQueue<RealQueueVal,2048> realQueue;
std::mutex realQueueLock;
bool isMuted[1];
bool on, flip, lastOn, realOutEnabled;

View File

@ -21,7 +21,7 @@
#include "../engine.h"
#include "../../ta-log.h"
#define rWrite(a,v) if (!skipRegisterWrites) {writes.emplace(a,v); if (dumpWrites) {addWrite(a,v);} }
#define rWrite(a,v) if (!skipRegisterWrites) {writes.push(QueuedWrite(a,v)); if (dumpWrites) {addWrite(a,v);} }
#define CHIP_DIVIDER 1

View File

@ -21,7 +21,7 @@
#define _POKEY_H
#include "../dispatch.h"
#include <queue>
#include "../fixedQueue.h"
extern "C" {
#include "sound/pokey/mzpokeysnd.h"
@ -43,11 +43,12 @@ class DivPlatformPOKEY: public DivDispatch {
DivDispatchOscBuffer* oscBuf[4];
bool isMuted[4];
struct QueuedWrite {
unsigned char addr;
unsigned char val;
QueuedWrite(unsigned char a, unsigned char v): addr(a), val(v) {}
unsigned char addr;
unsigned char val;
QueuedWrite(): addr(0), val(0) {}
QueuedWrite(unsigned char a, unsigned char v): addr(a), val(v) {}
};
std::queue<QueuedWrite> writes;
FixedQueue<QueuedWrite,128> writes;
unsigned char audctl, skctl;
bool audctlChanged, skctlChanged;
unsigned char oscBufDelay;

View File

@ -22,7 +22,6 @@
#include "../dispatch.h"
#include "sound/d65modified.h"
#include <queue>
class DivPlatformPV1000: public DivDispatch {
struct Channel: public SharedChannel<int> {

View File

@ -21,7 +21,6 @@
#define _QSOUND_H
#include "../dispatch.h"
#include <queue>
#include "sound/qsound.h"
class DivPlatformQSound: public DivDispatch {

View File

@ -21,7 +21,6 @@
#define _RF5C68_H
#include "../dispatch.h"
#include <queue>
#include "sound/rf5c68.h"
class DivPlatformRF5C68: public DivDispatch {

View File

@ -23,7 +23,7 @@
#include <string.h>
#include <math.h>
#define rWrite(a,v) if (!skipRegisterWrites) {writes.emplace(a,v); if (dumpWrites) {addWrite(a,v);} }
#define rWrite(a,v) if (!skipRegisterWrites) {writes.push(QueuedWrite(a,v)); if (dumpWrites) {addWrite(a,v);} }
#define CHIP_DIVIDER 2

View File

@ -21,7 +21,7 @@
#define _SAA_H
#include "../dispatch.h"
#include <queue>
#include "../fixedQueue.h"
#include "../../../extern/SAASound/src/SAASound.h"
class DivPlatformSAA1099: public DivDispatch {
@ -44,9 +44,10 @@ class DivPlatformSAA1099: public DivDispatch {
unsigned short addr;
unsigned char val;
bool addrOrVal;
QueuedWrite(): addr(0), val(0), addrOrVal(false) {}
QueuedWrite(unsigned short a, unsigned char v): addr(a), val(v), addrOrVal(false) {}
};
std::queue<QueuedWrite> writes;
FixedQueue<QueuedWrite,256> writes;
CSAASound* saa_saaSound;
unsigned char regPool[32];
unsigned char lastBusy;

View File

@ -21,7 +21,6 @@
#define _SCC_H
#include "../dispatch.h"
#include <queue>
#include "../waveSynth.h"
#include "vgsound_emu/src/scc/scc.hpp"

View File

@ -23,7 +23,7 @@
#include <string.h>
#include <math.h>
#define rWrite(a,v) if (!skipRegisterWrites) {writes.emplace(a,v); if (dumpWrites) {addWrite(a,v);} }
#define rWrite(a,v) if (!skipRegisterWrites) {writes.push(QueuedWrite(a,v)); if (dumpWrites) {addWrite(a,v);} }
#define chWrite(c,a,v) rWrite(((c)<<3)+(a),v)
void DivPlatformSegaPCM::acquire(short** buf, size_t len) {

View File

@ -23,7 +23,7 @@
#include "../dispatch.h"
#include "../instrument.h"
#include "sound/segapcm.h"
#include <queue>
#include "../fixedQueue.h"
class DivPlatformSegaPCM: public DivDispatch {
protected:
@ -59,9 +59,10 @@ class DivPlatformSegaPCM: public DivDispatch {
unsigned short addr;
unsigned char val;
bool addrOrVal;
QueuedWrite(): addr(0), val(0), addrOrVal(false) {}
QueuedWrite(unsigned short a, unsigned char v): addr(a), val(v), addrOrVal(false) {}
};
std::queue<QueuedWrite> writes;
FixedQueue<QueuedWrite,1024> writes;
segapcm_device pcm;
int delay;
int pcmL, pcmR, pcmCycles;

View File

@ -22,7 +22,7 @@
#include <math.h>
//#define rWrite(a,v) pendingWrites[a]=v;
#define rWrite(a,v) if (!skipRegisterWrites) {writes.emplace(a,v); if (dumpWrites) {addWrite(a,v);} }
#define rWrite(a,v) if (!skipRegisterWrites) {writes.push(QueuedWrite(a,v)); if (dumpWrites) {addWrite(a,v);} }
#define CHIP_DIVIDER 64

View File

@ -21,7 +21,7 @@
#define _SM8521_H
#include "../dispatch.h"
#include <queue>
#include "../fixedQueue.h"
#include "../waveSynth.h"
#include "sound/sm8521.h"
@ -46,11 +46,12 @@ class DivPlatformSM8521: public DivDispatch {
DivDispatchOscBuffer* oscBuf[3];
bool isMuted[3];
struct QueuedWrite {
unsigned short addr;
unsigned char val;
QueuedWrite(unsigned short a, unsigned char v): addr(a), val(v) {}
unsigned short addr;
unsigned char val;
QueuedWrite(): addr(0), val(0) {}
QueuedWrite(unsigned short a, unsigned char v): addr(a), val(v) {}
};
std::queue<QueuedWrite> writes;
FixedQueue<QueuedWrite,128> writes;
bool antiClickEnabled;
struct sm8521_t sm8521;

View File

@ -22,7 +22,7 @@
#include "../../ta-log.h"
#include <math.h>
#define rWrite(a,v) {if (!skipRegisterWrites) {writes.emplace(a,v); if (dumpWrites) {addWrite(a,v);}}}
#define rWrite(a,v) {if (!skipRegisterWrites) {writes.push(QueuedWrite(a,v)); if (dumpWrites) {addWrite(a,v);}}}
const char* regCheatSheetSN[]={
"DATA", "0",

View File

@ -25,7 +25,7 @@
extern "C" {
#include "../../../extern/Nuked-PSG/ympsg.h"
}
#include <queue>
#include "../fixedQueue.h"
class DivPlatformSMS: public DivDispatch {
struct Channel: public SharedChannel<signed char> {
@ -59,9 +59,10 @@ class DivPlatformSMS: public DivDispatch {
unsigned short addr;
unsigned char val;
bool addrOrVal;
QueuedWrite(): addr(0), val(0), addrOrVal(false) {}
QueuedWrite(unsigned short a, unsigned char v): addr(a), val(v), addrOrVal(false) {}
};
std::queue<QueuedWrite> writes;
FixedQueue<QueuedWrite,128> writes;
friend void putDispatchChip(void*,int);
friend void putDispatchChan(void*,int,int);

View File

@ -22,7 +22,7 @@
#include "../dispatch.h"
#include "../waveSynth.h"
#include <queue>
#include "../fixedQueue.h"
#include "sound/snes/SPC_DSP.h"
class DivPlatformSNES: public DivDispatch {
@ -81,9 +81,10 @@ class DivPlatformSNES: public DivDispatch {
struct QueuedWrite {
unsigned char addr;
unsigned char val;
QueuedWrite(): addr(0), val(0) {}
QueuedWrite(unsigned char a, unsigned char v): addr(a), val(v) {}
};
std::queue<QueuedWrite> writes;
FixedQueue<QueuedWrite,256> writes;
signed char sampleMem[65536];
signed char copyOfSampleMem[65536];

View File

@ -351,7 +351,7 @@ void SID::write(int offset, unsigned char value)
break;
case 0x04: // Voice #1 control register
voice[0]->writeCONTROL_REG(muted[0] ? 0 : value);
voice[0]->writeCONTROL_REG(value);
break;
case 0x05: // Voice #1 Attack and Decay length
@ -379,7 +379,7 @@ void SID::write(int offset, unsigned char value)
break;
case 0x0b: // Voice #2 control register
voice[1]->writeCONTROL_REG(muted[1] ? 0 : value);
voice[1]->writeCONTROL_REG(value);
break;
case 0x0c: // Voice #2 Attack and Decay length
@ -407,7 +407,7 @@ void SID::write(int offset, unsigned char value)
break;
case 0x12: // Voice #3 control register
voice[2]->writeCONTROL_REG(muted[2] ? 0 : value);
voice[2]->writeCONTROL_REG(value);
break;
case 0x13: // Voice #3 Attack and Decay length

View File

@ -320,11 +320,11 @@ int SID::output()
const int v2 = voice[1]->output(voice[0]->wave());
const int v3 = voice[2]->output(voice[1]->wave());
lastChanOut[0]=v1;
lastChanOut[1]=v2;
lastChanOut[2]=v3;
lastChanOut[0]=muted[0]?0:v1;
lastChanOut[1]=muted[1]?0:v2;
lastChanOut[2]=muted[2]?0:v3;
return externalFilter->clock(filter->clock(v1, v2, v3));
return externalFilter->clock(filter->clock(muted[0]?0:v1, muted[1]?0:v2, muted[2]?0:v3));
}

View File

@ -137,7 +137,7 @@ void okim6258_device::device_reset()
void okim6258_device::sound_stream_update(short** outputs, int len)
{
auto &buffer = outputs[0];
short* buffer = outputs[0];
if (m_status & STATUS_PLAYING)
{

View File

@ -23,7 +23,7 @@
#include <math.h>
//#define rWrite(a,v) pendingWrites[a]=v;
#define rWrite(a,v) if (!skipRegisterWrites) {writes.emplace(a,v); if (dumpWrites) {addWrite(a,v);} }
#define rWrite(a,v) if (!skipRegisterWrites) {writes.push(QueuedWrite(a,v)); if (dumpWrites) {addWrite(a,v);} }
#define chWrite(c,a,v) rWrite(((c)<<5)|(a),v);
#define CHIP_DIVIDER 2

View File

@ -21,7 +21,7 @@
#define _SU_H
#include "../dispatch.h"
#include <queue>
#include "../fixedQueue.h"
#include "sound/su.h"
class DivPlatformSoundUnit: public DivDispatch {
@ -72,11 +72,12 @@ class DivPlatformSoundUnit: public DivDispatch {
DivDispatchOscBuffer* oscBuf[8];
bool isMuted[8];
struct QueuedWrite {
unsigned char addr;
unsigned char val;
QueuedWrite(unsigned char a, unsigned char v): addr(a), val(v) {}
unsigned char addr;
unsigned char val;
QueuedWrite(): addr(0), val(0) {}
QueuedWrite(unsigned char a, unsigned char v): addr(a), val(v) {}
};
std::queue<QueuedWrite> writes;
FixedQueue<QueuedWrite,512> writes;
unsigned char lastPan;
bool sampleMemSize;
unsigned char ilCtrl, ilSize, fil1;

View File

@ -21,8 +21,8 @@
#include "../engine.h"
#include <math.h>
#define rWrite(a,v) if (!skipRegisterWrites) {writes.emplace(a,v); if (dumpWrites) {addWrite(a,v);}}
#define postWrite(a,v) postDACWrites.emplace(a,v);
#define rWrite(a,v) if (!skipRegisterWrites) {writes.push(QueuedWrite(a,v)); if (dumpWrites) {addWrite(a,v);}}
#define postWrite(a,v) postDACWrites.push(DivRegWrite(a,v));
#define CHIP_DIVIDER 32

View File

@ -23,7 +23,7 @@
#include "../dispatch.h"
#include "../waveSynth.h"
#include "sound/swan.h"
#include <queue>
#include "../fixedQueue.h"
class DivPlatformSwan: public DivDispatch {
struct Channel: public SharedChannel<int> {
@ -46,12 +46,13 @@ class DivPlatformSwan: public DivDispatch {
unsigned char regPool[0x80];
struct QueuedWrite {
unsigned char addr;
unsigned char val;
QueuedWrite(unsigned char a, unsigned char v): addr(a), val(v) {}
unsigned char addr;
unsigned char val;
QueuedWrite(): addr(0), val(0) {}
QueuedWrite(unsigned char a, unsigned char v): addr(a), val(v) {}
};
std::queue<QueuedWrite> writes;
std::queue<DivRegWrite> postDACWrites;
FixedQueue<QueuedWrite,256> writes;
FixedQueue<DivRegWrite,2048> postDACWrites;
WSwan* ws;
void updateWave(int ch);
friend void putDispatchChip(void*,int);

View File

@ -23,7 +23,7 @@
#include <math.h>
//#define rWrite(a,v) pendingWrites[a]=v;
#define rWrite(a,v) if (!skipRegisterWrites) {writes.emplace(a,v); if (dumpWrites) {addWrite(a,v);} }
#define rWrite(a,v) if (!skipRegisterWrites) {writes.push(QueuedWrite(a,v)); if (dumpWrites) {addWrite(a,v);} }
const char* regCheatSheetT6W28[]={
"Data0", "0",

View File

@ -21,7 +21,7 @@
#define _T6W28_H
#include "../dispatch.h"
#include <queue>
#include "../fixedQueue.h"
#include "sound/t6w28/T6W28_Apu.h"
class DivPlatformT6W28: public DivDispatch {
@ -38,11 +38,12 @@ class DivPlatformT6W28: public DivDispatch {
bool isMuted[4];
bool easyNoise;
struct QueuedWrite {
unsigned char addr;
unsigned char val;
QueuedWrite(unsigned char a, unsigned char v): addr(a), val(v) {}
unsigned char addr;
unsigned char val;
QueuedWrite(): addr(0), val(0) {}
QueuedWrite(unsigned char a, unsigned char v): addr(a), val(v) {}
};
std::queue<QueuedWrite> writes;
FixedQueue<QueuedWrite,256> writes;
unsigned char lastPan;
int cycles, curChan, delay;

View File

@ -21,7 +21,6 @@
#define _TIA_H
#include "../dispatch.h"
#include <queue>
#include "sound/tia/Audio.h"
class DivPlatformTIA: public DivDispatch {

View File

@ -986,7 +986,7 @@ void DivPlatformTX81Z::poke(std::vector<DivRegWrite>& wlist) {
}
void DivPlatformTX81Z::reset() {
while (!writes.empty()) writes.pop_front();
writes.clear();
memset(regPool,0,330);
fm_ymfm->reset();
if (dumpWrites) {

View File

@ -21,7 +21,7 @@
#define _TX81Z_H
#include "fmshared_OPM.h"
#include <queue>
#include "../fixedQueue.h"
#include "sound/ymfm/ymfm_opz.h"
class DivTXInterface: public ymfm::ymfm_interface {

View File

@ -22,7 +22,7 @@
#include <math.h>
//#define rWrite(a,v) pendingWrites[a]=v;
#define rWrite(a,v) if (!skipRegisterWrites) {writes.emplace(a,v); if (dumpWrites) {addWrite(a,v);} }
#define rWrite(a,v) if (!skipRegisterWrites) {writes.push(QueuedWrite(a,v)); if (dumpWrites) {addWrite(a,v);} }
#define chWrite(c,a,v) rWrite(0x400+((c)<<6)+((a)<<2),v);
#define CHIP_DIVIDER 16

View File

@ -21,7 +21,7 @@
#define _PLATFORM_VB_H
#include "../dispatch.h"
#include <queue>
#include "../fixedQueue.h"
#include "../waveSynth.h"
#include "sound/vsu.h"
@ -44,11 +44,12 @@ class DivPlatformVB: public DivDispatch {
DivDispatchOscBuffer* oscBuf[6];
bool isMuted[6];
struct QueuedWrite {
unsigned short addr;
unsigned char val;
QueuedWrite(unsigned short a, unsigned char v): addr(a), val(v) {}
unsigned short addr;
unsigned char val;
QueuedWrite(): addr(0), val(0) {}
QueuedWrite(unsigned short a, unsigned char v): addr(a), val(v) {}
};
std::queue<QueuedWrite> writes;
FixedQueue<QueuedWrite,2048> writes;
unsigned char lastPan;
int cycles, curChan, delay;

View File

@ -22,7 +22,6 @@
#include "../dispatch.h"
#include "sound/vic20sound.h"
#include <queue>
class DivPlatformVIC20: public DivDispatch {
struct Channel: public SharedChannel<int> {

View File

@ -22,7 +22,7 @@
#include <cstddef>
#include <math.h>
#define rWrite(a,v) if (!skipRegisterWrites) {writes.emplace(a,v); if (dumpWrites) {addWrite(a,v);} }
#define rWrite(a,v) if (!skipRegisterWrites) {writes.push(QueuedWrite(a,v)); if (dumpWrites) {addWrite(a,v);} }
#define chWrite(c,a,v) rWrite(0x9000+(c<<12)+(a&3),v)
const char* regCheatSheetVRC6[]={

View File

@ -20,7 +20,7 @@
#ifndef _VRC6_H
#define _VRC6_H
#include <queue>
#include "../fixedQueue.h"
#include "../dispatch.h"
#include "vgsound_emu/src/vrcvi/vrcvi.hpp"
@ -47,11 +47,12 @@ class DivPlatformVRC6: public DivDispatch, public vrcvi_intf {
DivDispatchOscBuffer* oscBuf[3];
bool isMuted[3];
struct QueuedWrite {
unsigned short addr;
unsigned char val;
QueuedWrite(unsigned short a, unsigned char v): addr(a), val(v) {}
unsigned short addr;
unsigned char val;
QueuedWrite(): addr(0), val(0) {}
QueuedWrite(unsigned short a, unsigned char v): addr(a), val(v) {}
};
std::queue<QueuedWrite> writes;
FixedQueue<QueuedWrite,64> writes;
unsigned char sampleBank;
unsigned char writeOscBuf;
vrcvi_core vrc6;

View File

@ -974,7 +974,7 @@ void DivPlatformYM2203::poke(std::vector<DivRegWrite>& wlist) {
}
void DivPlatformYM2203::reset() {
while (!writes.empty()) writes.pop_front();
writes.clear();
memset(regPool,0,256);
if (dumpWrites) {
addWrite(0xffffffff,0);

View File

@ -1481,7 +1481,7 @@ void DivPlatformYM2608::poke(std::vector<DivRegWrite>& wlist) {
}
void DivPlatformYM2608::reset() {
while (!writes.empty()) writes.pop_front();
writes.clear();
memset(regPool,0,512);
if (dumpWrites) {
addWrite(0xffffffff,0);

View File

@ -1441,7 +1441,7 @@ void DivPlatformYM2610::poke(std::vector<DivRegWrite>& wlist) {
}
void DivPlatformYM2610::reset() {
while (!writes.empty()) writes.pop_front();
writes.clear();
memset(regPool,0,512);
if (dumpWrites) {
addWrite(0xffffffff,0);

View File

@ -1508,7 +1508,7 @@ void DivPlatformYM2610B::poke(std::vector<DivRegWrite>& wlist) {
}
void DivPlatformYM2610B::reset() {
while (!writes.empty()) writes.pop_front();
writes.clear();
memset(regPool,0,512);
if (dumpWrites) {
addWrite(0xffffffff,0);

View File

@ -21,7 +21,6 @@
#define _YMZ280B_H
#include "../dispatch.h"
#include <queue>
#include "sound/ymz280b.h"
class DivPlatformYMZ280B: public DivDispatch {

View File

@ -260,7 +260,6 @@ int DivPlatformZXBeeper::getRegisterPoolSize() {
}
void DivPlatformZXBeeper::reset() {
while (!writes.empty()) writes.pop();
memset(regPool,0,128);
for (int i=0; i<6; i++) {
chan[i]=DivPlatformZXBeeper::Channel();

View File

@ -21,7 +21,6 @@
#define _ZXBEEPER_H
#include "../dispatch.h"
#include <queue>
class DivPlatformZXBeeper: public DivDispatch {
struct Channel: public SharedChannel<signed char> {
@ -35,12 +34,6 @@ class DivPlatformZXBeeper: public DivDispatch {
Channel chan[6];
DivDispatchOscBuffer* oscBuf[6];
bool isMuted[6];
struct QueuedWrite {
unsigned char addr;
unsigned char val;
QueuedWrite(unsigned char a, unsigned char v): addr(a), val(v) {}
};
std::queue<QueuedWrite> writes;
unsigned char lastPan, ulaOut;
int cycles, curChan, sOffTimer, delay, curSample, curSamplePeriod;

View File

@ -1130,8 +1130,10 @@ void DivEngine::nextRow() {
}
}
prevOrder=curOrder;
prevRow=curRow;
if (!stepPlay) {
prevOrder=curOrder;
prevRow=curRow;
}
for (int i=0; i<chans; i++) {
if (song.delayBehavior!=2) {
@ -1337,7 +1339,11 @@ bool DivEngine::nextTick(bool noAccum, bool inhibitLowLat) {
}
}
endOfSong=false;
if (stepPlay==2) stepPlay=1;
if (stepPlay==2) {
stepPlay=1;
prevOrder=curOrder;
prevRow=curRow;
}
nextRow();
break;
}

View File

@ -111,6 +111,7 @@ void FurnaceGUI::doAction(int what) {
break;
case GUI_ACTION_STEP_ONE:
e->stepOne(cursor.y);
pendingStepUpdate=1;
break;
case GUI_ACTION_OCTAVE_UP:
if (++curOctave>7) {

View File

@ -374,7 +374,7 @@ void FurnaceGUI::drawMobileControls() {
if (portrait) ImGui::SameLine();
if (ImGui::Button(ICON_FA_ARROW_DOWN "##StepOne",buttonSize)) {
e->stepOne(cursor.y);
pendingStepUpdate=true;
pendingStepUpdate=1;
}
bool repeatPattern=e->getRepeatPattern();
@ -730,7 +730,7 @@ void FurnaceGUI::drawEditControls() {
ImGui::SameLine();
if (ImGui::Button(ICON_FA_ARROW_DOWN "##StepOne")) {
e->stepOne(cursor.y);
pendingStepUpdate=true;
pendingStepUpdate=1;
}
if (ImGui::IsItemHovered()) {
ImGui::SetTooltip("Step one row");
@ -770,7 +770,7 @@ void FurnaceGUI::drawEditControls() {
ImGui::SameLine();
if (ImGui::Button(ICON_FA_ARROW_DOWN "##StepOne")) {
e->stepOne(cursor.y);
pendingStepUpdate=true;
pendingStepUpdate=1;
}
if (ImGui::IsItemHovered()) {
ImGui::SetTooltip("Step one row");
@ -875,7 +875,7 @@ void FurnaceGUI::drawEditControls() {
}
if (ImGui::Button(ICON_FA_ARROW_DOWN "##StepOne",buttonSize)) {
e->stepOne(cursor.y);
pendingStepUpdate=true;
pendingStepUpdate=1;
}
if (ImGui::IsItemHovered()) {
ImGui::SetTooltip("Step one row");
@ -1009,7 +1009,7 @@ void FurnaceGUI::drawEditControls() {
ImGui::SameLine();
if (ImGui::Button(ICON_FA_ARROW_DOWN "##StepOne")) {
e->stepOne(cursor.y);
pendingStepUpdate=true;
pendingStepUpdate=1;
}
if (ImGui::IsItemHovered()) {
ImGui::SetTooltip("Step one row");

View File

@ -2419,7 +2419,7 @@ void FurnaceGUI::processDrags(int dragX, int dragY) {
if (y>waveDragMax) y=waveDragMax;
if (y<waveDragMin) y=waveDragMin;
waveDragTarget[x]=y;
e->notifyWaveChange(curWave);
notifyWaveChange=true;
MARK_MODIFIED;
}
}
@ -3746,6 +3746,11 @@ bool FurnaceGUI::loop() {
midiLock.unlock();
}
if (notifyWaveChange) {
notifyWaveChange=false;
e->notifyWaveChange(curWave);
}
eventTimeEnd=SDL_GetPerformanceCounter();
if (SDL_GetWindowFlags(sdlWin)&SDL_WINDOW_MINIMIZED) {
@ -6718,6 +6723,7 @@ FurnaceGUI::FurnaceGUI():
preserveChanPos(false),
wantScrollList(false),
noteInputPoly(true),
notifyWaveChange(false),
displayPendingIns(false),
pendingInsSingle(false),
displayPendingRawSample(false),
@ -7015,7 +7021,7 @@ FurnaceGUI::FurnaceGUI():
fadeMode(false),
randomMode(false),
haveHitBounds(false),
pendingStepUpdate(false),
pendingStepUpdate(0),
oldOrdersLen(0),
sampleZoom(1.0),
prevSampleZoom(1.0),

View File

@ -1310,7 +1310,7 @@ class FurnaceGUI {
bool vgmExportDirectStream, displayInsTypeList;
bool portrait, injectBackUp, mobileMenuOpen, warnColorPushed;
bool wantCaptureKeyboard, oldWantCaptureKeyboard, displayMacroMenu;
bool displayNew, fullScreen, preserveChanPos, wantScrollList, noteInputPoly;
bool displayNew, fullScreen, preserveChanPos, wantScrollList, noteInputPoly, notifyWaveChange;
bool displayPendingIns, pendingInsSingle, displayPendingRawSample, snesFilterHex, modTableHex, displayEditString;
bool mobileEdit;
bool killGraphics;
@ -1913,7 +1913,8 @@ class FurnaceGUI {
int dummyRows, demandX;
int transposeAmount, randomizeMin, randomizeMax, fadeMin, fadeMax, collapseAmount;
float scaleMax;
bool fadeMode, randomMode, haveHitBounds, pendingStepUpdate;
bool fadeMode, randomMode, haveHitBounds;
signed char pendingStepUpdate;
int oldOrdersLen;
DivOrders oldOrders;

View File

@ -446,7 +446,7 @@ void FurnaceGUI::drawPattern() {
float lineHeight=(ImGui::GetTextLineHeight()+2*dpiScale);
int curRow=e->getRow();
if (e->isPlaying() && followPattern && (!e->isStepping() || pendingStepUpdate)) updateScroll(curRow);
pendingStepUpdate=false;
if (--pendingStepUpdate<0) pendingStepUpdate=0;
if (nextScroll>-0.5f) {
ImGui::SetScrollY(nextScroll);
nextScroll=-1.0f;